| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1999 - 2006, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Matt O'Gorman <mogorman@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \file
 | 
					
						
							|  |  |  |  * \brief A resource for interfacing asterisk directly as a client | 
					
						
							|  |  |  |  * or a component to a jabber compliant server. | 
					
						
							| 
									
										
										
										
											2007-06-07 10:00:17 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \todo If you unload this module, chan_gtalk/jingle will be dead. How do we handle that? | 
					
						
							|  |  |  |  * \todo If you have TLS, you can't unload this module. See bug #9738. This needs to be fixed, | 
					
						
							|  |  |  |  *       but the bug is in the unmantained Iksemel library | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>iksemel</depend> | 
					
						
							| 
									
										
										
										
											2007-05-25 14:28:46 +00:00
										 |  |  | 	<use>gnutls</use> | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <iksemel.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/jabber.h"
 | 
					
						
							|  |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/callerid.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/logger.h"
 | 
					
						
							|  |  |  | #include "asterisk/options.h"
 | 
					
						
							|  |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/app.h"
 | 
					
						
							|  |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/md5.h"
 | 
					
						
							|  |  |  | #include "asterisk/acl.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/astobj.h"
 | 
					
						
							|  |  |  | #include "asterisk/astdb.h"
 | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | #include "asterisk/manager.h"
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define JABBER_CONFIG "jabber.conf"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | #ifndef FALSE
 | 
					
						
							|  |  |  | #define FALSE 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef TRUE
 | 
					
						
							|  |  |  | #define TRUE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | /*-- Forward declarations */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static int aji_highest_bit(int number); | 
					
						
							|  |  |  | static void aji_buddy_destroy(struct aji_buddy *obj); | 
					
						
							|  |  |  | static void aji_client_destroy(struct aji_client *obj); | 
					
						
							|  |  |  | static int aji_send_exec(struct ast_channel *chan, void *data); | 
					
						
							|  |  |  | static int aji_status_exec(struct ast_channel *chan, void *data); | 
					
						
							|  |  |  | static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming); | 
					
						
							|  |  |  | static int aji_act_hook(void *data, int type, iks *node); | 
					
						
							|  |  |  | static void aji_handle_iq(struct aji_client *client, iks *node); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | static void aji_handle_message(struct aji_client *client, ikspak *pak); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static void aji_handle_presence(struct aji_client *client, ikspak *pak); | 
					
						
							|  |  |  | static void aji_handle_subscribe(struct aji_client *client, ikspak *pak); | 
					
						
							|  |  |  | static void *aji_recv_loop(void *data); | 
					
						
							|  |  |  | static int aji_component_initialize(struct aji_client *client); | 
					
						
							|  |  |  | static int aji_client_initialize(struct aji_client *client); | 
					
						
							|  |  |  | static int aji_client_connect(void *data, ikspak *pak); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static int aji_do_debug(int fd, int argc, char *argv[]); | 
					
						
							|  |  |  | static int aji_do_reload(int fd, int argc, char *argv[]); | 
					
						
							|  |  |  | static int aji_no_debug(int fd, int argc, char *argv[]); | 
					
						
							|  |  |  | static int aji_test(int fd, int argc, char *argv[]); | 
					
						
							|  |  |  | static int aji_show_clients(int fd, int argc, char *argv[]); | 
					
						
							|  |  |  | static int aji_create_client(char *label, struct ast_variable *var, int debug); | 
					
						
							|  |  |  | static int aji_create_buddy(char *label, struct aji_client *client); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | static int aji_reload(void); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static int aji_load_config(void); | 
					
						
							|  |  |  | static void aji_pruneregister(struct aji_client *client); | 
					
						
							|  |  |  | static int aji_filter_roster(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_get_roster(struct aji_client *client); | 
					
						
							|  |  |  | static int aji_client_info_handler(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_dinfo_handler(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_ditems_handler(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_register_query_handler(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_register_approve_handler(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_reconnect(struct aji_client *client); | 
					
						
							|  |  |  | static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | /* No transports in this version */ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | static int aji_create_transport(char *label, struct aji_client *client); | 
					
						
							|  |  |  | static int aji_register_transport(void *data, ikspak *pak); | 
					
						
							|  |  |  | static int aji_register_transport2(void *data, ikspak *pak); | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char debug_usage[] =  | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "Usage: jabber debug\n"  | 
					
						
							|  |  |  | "       Enables dumping of Jabber packets for debugging purposes.\n"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char no_debug_usage[] =  | 
					
						
							| 
									
										
										
										
											2006-11-02 23:49:13 +00:00
										 |  |  | "Usage: jabber debug off\n"  | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "       Disables dumping of Jabber packets for debugging purposes.\n"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char reload_usage[] =  | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "Usage: jabber reload\n"  | 
					
						
							|  |  |  | "       Enables reloading of Jabber module.\n"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char test_usage[] =  | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "Usage: jabber test [client]\n"  | 
					
						
							| 
									
										
										
										
											2006-06-06 19:51:26 +00:00
										 |  |  | "       Sends test message for debugging purposes.  A specific client\n" | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | "       as configured in jabber.conf can be optionally specified.\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_cli_entry aji_cli[] = { | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | 	{ { "jabber", "debug", NULL}, | 
					
						
							|  |  |  | 	aji_do_debug, "Enable Jabber debugging", | 
					
						
							|  |  |  | 	debug_usage }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "jabber", "reload", NULL}, | 
					
						
							| 
									
										
										
										
											2007-02-07 05:24:31 +00:00
										 |  |  | 	aji_do_reload, "Reload Jabber configuration", | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | 	reload_usage }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "jabber", "show", "connected", NULL}, | 
					
						
							|  |  |  | 	aji_show_clients, "Show state of clients and components", | 
					
						
							|  |  |  | 	debug_usage }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-02 23:49:13 +00:00
										 |  |  | 	{ { "jabber", "debug", "off", NULL}, | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | 	aji_no_debug, "Disable Jabber debug", | 
					
						
							|  |  |  | 	no_debug_usage }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "jabber", "test", NULL}, | 
					
						
							|  |  |  | 	aji_test, "Shows roster, but is generally used for mog's debugging.", | 
					
						
							|  |  |  | 	test_usage }, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | static char *app_ajisend = "JabberSend"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | static char *ajisend_synopsis = "JabberSend(jabber,screenname,message)"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char *ajisend_descrip = | 
					
						
							| 
									
										
										
										
											2006-08-08 17:07:41 +00:00
										 |  |  | "JabberSend(Jabber,ScreenName,Message)\n" | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "  Jabber - Client or transport Asterisk uses to connect to Jabber\n"  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | "  ScreenName - User Name to message.\n"  | 
					
						
							|  |  |  | "  Message - Message to be sent to the buddy\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | static char *app_ajistatus = "JabberStatus"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | static char *ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char *ajistatus_descrip = | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | "JabberStatus(Jabber,ScreenName,Variable)\n" | 
					
						
							|  |  |  | "  Jabber - Client or transport Asterisk uses to connect to Jabber\n" | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | "  ScreenName - User Name to retrieve status from.\n" | 
					
						
							|  |  |  | "  Variable - Variable to store presence in will be 1-6.\n"  | 
					
						
							|  |  |  | "             In order, Online, Chatty, Away, XAway, DND, Offline\n"  | 
					
						
							|  |  |  | "             If not in roster variable will = 7\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct aji_client_container clients; | 
					
						
							| 
									
										
										
										
											2007-05-04 20:03:49 +00:00
										 |  |  | struct aji_capabilities *capabilities = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | /*! \brief Global flags, initialized to default values */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER }; | 
					
						
							| 
									
										
										
										
											2007-06-07 09:55:13 +00:00
										 |  |  | static int tls_initialized = FALSE; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Deletes the aji_client data structure. | 
					
						
							|  |  |  |  * \param obj is the structure we will delete. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_client_destroy(struct aji_client *obj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	struct aji_message *tmp; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_DESTROY(&obj->buddies); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	iks_filter_delete(obj->f); | 
					
						
							|  |  |  | 	iks_parser_delete(obj->p); | 
					
						
							|  |  |  | 	iks_stack_delete(obj->stack); | 
					
						
							| 
									
										
										
										
											2006-06-09 18:37:26 +00:00
										 |  |  | 	AST_LIST_LOCK(&obj->messages); | 
					
						
							|  |  |  | 	while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 		if (tmp->from) | 
					
						
							|  |  |  | 			free(tmp->from); | 
					
						
							|  |  |  | 		if (tmp->message) | 
					
						
							|  |  |  | 			free(tmp->message); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-09 18:37:26 +00:00
										 |  |  | 	AST_LIST_HEAD_DESTROY(&obj->messages); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	free(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Deletes the aji_buddy data structure. | 
					
						
							|  |  |  |  * \param obj is the structure we will delete. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_buddy_destroy(struct aji_buddy *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_resource *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((tmp = obj->resources)) { | 
					
						
							|  |  |  | 		obj->resources = obj->resources->next; | 
					
						
							| 
									
										
										
										
											2006-06-06 19:51:26 +00:00
										 |  |  | 		free(tmp->description); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		free(tmp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	free(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-04 20:03:49 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Find version in XML stream and populate our capabilities list | 
					
						
							|  |  |  |  * \param node the node attribute in the caps element we'll look for or add to  | 
					
						
							|  |  |  |  * our list | 
					
						
							|  |  |  |  * \param version the version attribute in the caps element we'll look for or  | 
					
						
							|  |  |  |  * add to our list | 
					
						
							|  |  |  |  * \param pak the XML stanza we're processing | 
					
						
							|  |  |  |  * \return a pointer to the added or found aji_version structure | 
					
						
							|  |  |  |  */  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_capabilities *list = NULL; | 
					
						
							|  |  |  | 	struct aji_version *res = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = capabilities; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(!node) | 
					
						
							|  |  |  | 		node = pak->from->full; | 
					
						
							|  |  |  | 	if(!version) | 
					
						
							|  |  |  | 		version = "none supplied."; | 
					
						
							|  |  |  | 	while(list) { | 
					
						
							|  |  |  | 		if(!strcasecmp(list->node, node)) { | 
					
						
							|  |  |  | 			res = list->versions; | 
					
						
							|  |  |  | 			while(res) { | 
					
						
							|  |  |  | 				 if(!strcasecmp(res->version, version)) | 
					
						
							|  |  |  | 					 return res; | 
					
						
							|  |  |  | 				 res = res->next; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2007-05-04 20:03:49 +00:00
										 |  |  | 			/* Specified version not found. Let's add it to 
 | 
					
						
							|  |  |  | 			   this node in our capabilities list */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			if(!res) { | 
					
						
							|  |  |  | 				res = (struct aji_version *)malloc(sizeof(struct aji_version)); | 
					
						
							|  |  |  | 				if(!res) { | 
					
						
							|  |  |  | 					ast_log(LOG_ERROR, "Out of memory!\n"); | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				res->jingle = 0; | 
					
						
							|  |  |  | 				res->parent = list; | 
					
						
							|  |  |  | 				ast_copy_string(res->version, version, sizeof(res->version)); | 
					
						
							|  |  |  | 				res->next = list->versions; | 
					
						
							|  |  |  | 				list->versions = res; | 
					
						
							|  |  |  | 				return res; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		list = list->next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-05-04 20:03:49 +00:00
										 |  |  | 	/* Specified node not found. Let's add it our capabilities list */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if(!list) { | 
					
						
							|  |  |  | 		list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities)); | 
					
						
							|  |  |  | 		if(!list) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory!\n"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		res = (struct aji_version *)malloc(sizeof(struct aji_version)); | 
					
						
							|  |  |  | 		if(!res) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory!\n"); | 
					
						
							| 
									
										
										
										
											2007-10-31 21:23:11 +00:00
										 |  |  | 			ast_free(list); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ast_copy_string(list->node, node, sizeof(list->node)); | 
					
						
							|  |  |  | 		ast_copy_string(res->version, version, sizeof(res->version)); | 
					
						
							|  |  |  | 		res->jingle = 0; | 
					
						
							|  |  |  | 		res->parent = list; | 
					
						
							| 
									
										
										
										
											2007-05-04 20:03:49 +00:00
										 |  |  | 		res->next = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		list->versions = res; | 
					
						
							|  |  |  | 		list->next = capabilities; | 
					
						
							|  |  |  | 		capabilities = list; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *name) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct aji_resource *res = NULL; | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	if (!buddy || !name) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		return res; | 
					
						
							|  |  |  | 	res = buddy->resources; | 
					
						
							|  |  |  | 	while (res) { | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 		if (!strcasecmp(res->resource, name)) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		res = res->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int gtalk_yuck(iks *node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Detects the highest bit in a number. | 
					
						
							|  |  |  |  * \param Number you want to have evaluated. | 
					
						
							|  |  |  |  * \return the highest power of 2 that can go into the number. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_highest_bit(int number) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int x = sizeof(number) * 8 - 1; | 
					
						
							|  |  |  | 	if (!number) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	for (; x > 0; x--) { | 
					
						
							|  |  |  | 		if (number & (1 << x)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (1 << x); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	iks *x, *y; | 
					
						
							|  |  |  | 	x = iks_new("iq"); | 
					
						
							|  |  |  | 	iks_insert_attrib(x, "type", "set"); | 
					
						
							|  |  |  | 	y = iks_insert(x, "query"); | 
					
						
							|  |  |  | 	iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); | 
					
						
							|  |  |  | 	iks_insert_cdata(iks_insert(y, "username"), id->user, 0); | 
					
						
							|  |  |  | 	iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); | 
					
						
							|  |  |  | 	if (sid) { | 
					
						
							|  |  |  | 		char buf[41]; | 
					
						
							|  |  |  | 		char sidpass[100]; | 
					
						
							|  |  |  | 		snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); | 
					
						
							|  |  |  | 		ast_sha1_hash(buf, sidpass); | 
					
						
							|  |  |  | 		iks_insert_cdata(iks_insert(y, "digest"), buf, 0); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		iks_insert_cdata(iks_insert(y, "password"), pass, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Dial plan function status(). puts the status of watched user  | 
					
						
							|  |  |  |    into a channel variable. | 
					
						
							|  |  |  |  * \param channel, and username,watched user, status var | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_status_exec(struct ast_channel *chan, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = NULL; | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 	struct aji_buddy *buddy = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	struct aji_resource *r = NULL; | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 	char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL; | 
					
						
							|  |  |  | 	int stat = 7; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	char status[2]; | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "This application requires arguments.\n"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-02-20 16:53:45 +00:00
										 |  |  | 	s = ast_strdupa(data); | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 	if (s) { | 
					
						
							|  |  |  | 		sender = strsep(&s, "|"); | 
					
						
							|  |  |  | 		if (sender && (sender[0] != '\0')) { | 
					
						
							|  |  |  | 			jid = strsep(&s, "|"); | 
					
						
							|  |  |  | 			if (jid && (jid[0] != '\0')) { | 
					
						
							|  |  |  | 				variable = s; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Bad arguments\n"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 	if(!strchr(jid, '/')) { | 
					
						
							| 
									
										
										
										
											2006-06-04 16:56:16 +00:00
										 |  |  | 		resource = NULL; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 		screenname = strsep(&jid, "/"); | 
					
						
							|  |  |  | 		resource = jid; | 
					
						
							| 
									
										
										
										
											2006-06-04 16:56:16 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	client = ast_aji_get_client(sender); | 
					
						
							|  |  |  | 	if (!client) { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-01 08:22:44 +00:00
										 |  |  | 	if(!&client->buddies) { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender); | 
					
						
							| 
									
										
										
										
											2006-06-01 08:22:44 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 	buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid); | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 	if (!buddy) { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 	r = aji_find_resource(buddy, resource); | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 	if(!r && buddy->resources)  | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 		r = buddy->resources; | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 	if(!r) | 
					
						
							| 
									
										
										
										
											2006-07-05 20:28:54 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname); | 
					
						
							| 
									
										
										
										
											2007-03-05 03:35:03 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		stat = r->status; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	sprintf(status, "%d", stat); | 
					
						
							|  |  |  | 	pbx_builtin_setvar_helper(chan, variable, status); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Dial plan function to send a message. | 
					
						
							|  |  |  |  * \param channel, and data, data is sender, reciever, message. | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_send_exec(struct ast_channel *chan, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-01 07:49:47 +00:00
										 |  |  | 	char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "This application requires arguments.\n"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-02-20 16:53:45 +00:00
										 |  |  | 	s = ast_strdupa(data); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (s) { | 
					
						
							|  |  |  | 		sender = strsep(&s, "|"); | 
					
						
							|  |  |  | 		if (sender && (sender[0] != '\0')) { | 
					
						
							|  |  |  | 			recipient = strsep(&s, "|"); | 
					
						
							|  |  |  | 			if (recipient && (recipient[0] != '\0')) { | 
					
						
							|  |  |  | 				message = s; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 				ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (!(client = ast_aji_get_client(sender))) { | 
					
						
							| 
									
										
										
										
											2007-02-19 21:12:55 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-01 07:49:47 +00:00
										 |  |  | 	if (strchr(recipient, '@') && message) | 
					
						
							|  |  |  | 		ast_aji_send(client, recipient, message); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief the debug loop. | 
					
						
							|  |  |  |  * \param aji_client structure, xml data as string, size of string, direction of packet, 1 for inbound 0 for outbound. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							| 
									
										
										
										
											2007-04-09 18:02:17 +00:00
										 |  |  | 	manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 	if (client->debug) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (is_incoming) | 
					
						
							|  |  |  | 			ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			if( strlen(xmpp) == 1) { | 
					
						
							|  |  |  | 				if(option_debug > 2  && xmpp[0] == ' ') | 
					
						
							|  |  |  | 				ast_verbose("\nJABBER: Keep alive packet\n"); | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief The action hook parses the inbound packets, constantly running. | 
					
						
							| 
									
										
										
										
											2007-06-07 09:00:44 +00:00
										 |  |  |  * \param data aji client structure  | 
					
						
							|  |  |  |  * \param type type of packet  | 
					
						
							|  |  |  |  * \param node the actual packet. | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  |  * \return IKS_OK or IKS_HOOK . | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_act_hook(void *data, int type, iks *node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	ikspak *pak = NULL; | 
					
						
							|  |  |  | 	iks *auth = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-08 17:07:41 +00:00
										 |  |  | 	if(!node) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 		ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							| 
									
										
										
										
											2006-08-08 17:07:41 +00:00
										 |  |  | 		return IKS_HOOK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 09:00:44 +00:00
										 |  |  | 	if (client->state == AJI_DISCONNECTING) { | 
					
						
							|  |  |  | 		ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 		return IKS_HOOK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	pak = iks_packet(node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if (!client->component) { /*client */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		switch (type) { | 
					
						
							|  |  |  | 		case IKS_NODE_START: | 
					
						
							|  |  |  | 			if (client->usetls && !iks_is_secure(client->p)) { | 
					
						
							| 
									
										
										
										
											2007-06-07 09:55:13 +00:00
										 |  |  | 				if (iks_has_tls()) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					iks_start_tls(client->p); | 
					
						
							| 
									
										
										
										
											2007-06-07 09:55:13 +00:00
										 |  |  | 					tls_initialized = TRUE; | 
					
						
							|  |  |  | 				} else | 
					
						
							|  |  |  | 					ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!client->usesasl) { | 
					
						
							|  |  |  | 				iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, IKS_RULE_DONE); | 
					
						
							|  |  |  | 				auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); | 
					
						
							|  |  |  | 				if (auth) { | 
					
						
							|  |  |  | 					iks_insert_attrib(auth, "id", client->mid); | 
					
						
							|  |  |  | 					iks_insert_attrib(auth, "to", client->jid->server); | 
					
						
							|  |  |  | 					ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 					iks_send(client->p, auth); | 
					
						
							|  |  |  | 					iks_delete(auth); | 
					
						
							|  |  |  | 				} else | 
					
						
							|  |  |  | 					ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case IKS_NODE_NORMAL: | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 			if (!strcmp("stream:features", iks_name(node))) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				int features = 0; | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 				features = iks_stream_features(node); | 
					
						
							|  |  |  | 				if (client->usesasl) { | 
					
						
							|  |  |  | 					if (client->usetls && !iks_is_secure(client->p)) | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					if (client->authorized) { | 
					
						
							|  |  |  | 						if (features & IKS_STREAM_BIND) { | 
					
						
							|  |  |  | 							iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE); | 
					
						
							|  |  |  | 							auth = iks_make_resource_bind(client->jid); | 
					
						
							|  |  |  | 							if (auth) { | 
					
						
							|  |  |  | 								iks_insert_attrib(auth, "id", client->mid); | 
					
						
							|  |  |  | 								ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 								iks_send(client->p, auth); | 
					
						
							|  |  |  | 								iks_delete(auth); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							| 
									
										
										
										
											2007-06-04 15:50:16 +00:00
										 |  |  | 								break; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						if (features & IKS_STREAM_SESSION) { | 
					
						
							|  |  |  | 							iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE); | 
					
						
							|  |  |  | 							auth = iks_make_session(); | 
					
						
							|  |  |  | 							if (auth) { | 
					
						
							|  |  |  | 								iks_insert_attrib(auth, "id", "auth"); | 
					
						
							|  |  |  | 								ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 								iks_send(client->p, auth); | 
					
						
							|  |  |  | 								iks_delete(auth); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						if (!client->jid->user) { | 
					
						
							|  |  |  | 							ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						features = aji_highest_bit(features); | 
					
						
							|  |  |  | 						if (features == IKS_STREAM_SASL_MD5) | 
					
						
							|  |  |  | 							iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password); | 
					
						
							|  |  |  | 						else { | 
					
						
							|  |  |  | 							if (features == IKS_STREAM_SASL_PLAIN) { | 
					
						
							|  |  |  | 								iks *x = NULL; | 
					
						
							|  |  |  | 								x = iks_new("auth"); | 
					
						
							|  |  |  | 								if (x) { | 
					
						
							|  |  |  | 									int len = strlen(client->jid->user) + strlen(client->password) + 3; | 
					
						
							|  |  |  | 									/* XXX Check return values XXX */ | 
					
						
							|  |  |  | 									char *s = ast_malloc(80 + len); | 
					
						
							|  |  |  | 									char *base64 = ast_malloc(80 + len * 2); | 
					
						
							|  |  |  | 									iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); | 
					
						
							|  |  |  | 									iks_insert_attrib(x, "mechanism", "PLAIN"); | 
					
						
							|  |  |  | 									sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password); | 
					
						
							| 
									
										
										
										
											2008-01-07 14:25:29 +00:00
										 |  |  | 										 | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 									/* exclude the NULL training byte from the base64 encoding operation
 | 
					
						
							|  |  |  | 									   as some XMPP servers will refuse it. | 
					
						
							|  |  |  | 									   The format for authentication is [authzid]\0authcid\0password | 
					
						
							|  |  |  | 									   not [authzid]\0authcid\0password\0 */ | 
					
						
							|  |  |  | 									ast_base64encode(base64, (const unsigned char *) s, len - 1, len * 2); | 
					
						
							|  |  |  | 									iks_insert_cdata(x, base64, 0); | 
					
						
							|  |  |  | 									iks_send(client->p, x); | 
					
						
							|  |  |  | 									iks_delete(x); | 
					
						
							|  |  |  | 									if (base64) | 
					
						
							|  |  |  | 										free(base64); | 
					
						
							|  |  |  | 									if (s) | 
					
						
							|  |  |  | 										free(s); | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 			} else if (!strcmp("failure", iks_name(node))) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); | 
					
						
							|  |  |  | 			} else if (!strcmp("success", iks_name(node))) { | 
					
						
							|  |  |  | 				client->authorized = 1; | 
					
						
							|  |  |  | 				iks_send_header(client->p, client->jid->server); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-01-07 14:34:36 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		case IKS_NODE_ERROR:  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				ast_log(LOG_ERROR, "JABBER: Node Error\n"); | 
					
						
							|  |  |  | 				ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 				return IKS_HOOK; | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		case IKS_NODE_STOP:  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				ast_log(LOG_WARNING, "JABBER: Disconnected\n"); | 
					
						
							|  |  |  | 				ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 				return IKS_HOOK; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	} else if (client->state != AJI_CONNECTED && client->component) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		switch (type) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		case IKS_NODE_START: | 
					
						
							|  |  |  | 			if (client->state == AJI_DISCONNECTED) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				char secret[160], shasum[320], *handshake; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				sprintf(secret, "%s%s", pak->id, client->password); | 
					
						
							|  |  |  | 				ast_sha1_hash(shasum, secret); | 
					
						
							|  |  |  | 				handshake = NULL; | 
					
						
							|  |  |  | 				asprintf(&handshake, "<handshake>%s</handshake>", shasum); | 
					
						
							|  |  |  | 				if (handshake) { | 
					
						
							|  |  |  | 					iks_send_raw(client->p, handshake); | 
					
						
							|  |  |  | 					free(handshake); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					handshake = NULL; | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 				client->state = AJI_CONNECTING; | 
					
						
							|  |  |  | 				if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ | 
					
						
							|  |  |  | 					client->state = AJI_CONNECTED; | 
					
						
							| 
									
										
										
										
											2006-09-20 00:39:44 +00:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 					ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n"); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		case IKS_NODE_NORMAL: | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		case IKS_NODE_ERROR: | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "JABBER: Node Error\n"); | 
					
						
							|  |  |  | 			ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 			return IKS_HOOK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case IKS_NODE_STOP: | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "JABBER: Disconnected\n"); | 
					
						
							|  |  |  | 			ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 			return IKS_HOOK; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (pak->type) { | 
					
						
							|  |  |  | 	case IKS_PAK_NONE: | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case IKS_PAK_MESSAGE: | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		aji_handle_message(client, pak); | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case IKS_PAK_PRESENCE: | 
					
						
							|  |  |  | 		aji_handle_presence(client, pak); | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case IKS_PAK_S10N: | 
					
						
							|  |  |  | 		aji_handle_subscribe(client, pak); | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case IKS_PAK_IQ: | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		aji_handle_iq(client, node); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2006-10-12 10:24:36 +00:00
										 |  |  | 		if (option_debug) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	iks_filter_packet(client->f, pak); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (node) | 
					
						
							|  |  |  | 		iks_delete(node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_register_approve_handler(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	iks *iq = NULL, *presence = NULL, *x = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	iq = iks_new("iq"); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	presence = iks_new("presence"); | 
					
						
							|  |  |  | 	x = iks_new("x"); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	if (client && iq && presence && x) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (!iks_find(pak->query, "remove")) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->jid->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "from", client->jid->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "to", pak->from->partial); | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "id", client->mid); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			ast_aji_increment_mid(client->mid); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 			iks_insert_attrib(presence, "type", "subscribe"); | 
					
						
							|  |  |  | 			iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); | 
					
						
							|  |  |  | 			iks_insert_node(presence, x); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 			iks_send(client->p, presence);  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (iq) | 
					
						
							|  |  |  | 		iks_delete(iq); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if(presence) | 
					
						
							|  |  |  | 		iks_delete(presence); | 
					
						
							|  |  |  | 	if (x) | 
					
						
							|  |  |  | 		iks_delete(x); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_register_query_handler(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	struct aji_buddy *buddy = NULL;  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	char *node = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	client = (struct aji_client *) data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); | 
					
						
							|  |  |  | 	if (!buddy) { | 
					
						
							|  |  |  | 		iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL; | 
					
						
							| 
									
										
										
										
											2007-06-29 04:43:15 +00:00
										 |  |  | 		ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		error = iks_new("error"); | 
					
						
							|  |  |  | 		notacceptable = iks_new("not-acceptable"); | 
					
						
							|  |  |  | 		if(iq && query && error && notacceptable) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "error"); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "jabber:iq:register"); | 
					
						
							|  |  |  | 			iks_insert_attrib(error, "code" , "406"); | 
					
						
							|  |  |  | 			iks_insert_attrib(error, "type", "modify"); | 
					
						
							|  |  |  | 			iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(iq, error); | 
					
						
							|  |  |  | 			iks_insert_node(error, notacceptable); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (error) | 
					
						
							|  |  |  | 			iks_delete(error); | 
					
						
							|  |  |  | 		if (notacceptable) | 
					
						
							|  |  |  | 			iks_delete(notacceptable); | 
					
						
							|  |  |  | 	} else 	if (!(node = iks_find_attrib(pak->query, "node"))) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks *iq = NULL, *query = NULL, *instructions = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		instructions = iks_new("instructions"); | 
					
						
							|  |  |  | 		if (iq && query && instructions && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "jabber:iq:register"); | 
					
						
							|  |  |  | 			iks_insert_cdata(instructions, explain, 0); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, instructions); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (instructions) | 
					
						
							|  |  |  | 			iks_delete(instructions); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_ditems_handler(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	char *node = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(node = iks_find_attrib(pak->query, "node"))) { | 
					
						
							|  |  |  | 		iks *iq = NULL, *query = NULL, *item = NULL; | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		item = iks_new("item"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iq && query && item) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); | 
					
						
							|  |  |  | 			iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); | 
					
						
							|  |  |  | 			iks_insert_attrib(item, "jid", client->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, item); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (item) | 
					
						
							|  |  |  | 			iks_delete(item); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { | 
					
						
							|  |  |  | 		iks *iq, *query, *confirm; | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		confirm = iks_new("item"); | 
					
						
							|  |  |  | 		if (iq && query && confirm && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "node", "confirmaccount"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "name", "Confirm AIM account"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "jid", "blog.astjab.org"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, confirm); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (confirm) | 
					
						
							|  |  |  | 			iks_delete(confirm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (!strcasecmp(node, "confirmaccount")) { | 
					
						
							|  |  |  | 		iks *iq = NULL, *query = NULL, *feature = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		feature = iks_new("feature"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iq && query && feature && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); | 
					
						
							|  |  |  | 			iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, feature); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (feature) | 
					
						
							|  |  |  | 			iks_delete(feature); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_client_info_handler(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	struct aji_resource *resource = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	resource = aji_find_resource(buddy, pak->from->resource); | 
					
						
							|  |  |  | 	if (pak->subtype == IKS_TYPE_RESULT) { | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		if (!resource) { | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); | 
					
						
							|  |  |  | 			ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 			return IKS_FILTER_EAT; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { | 
					
						
							|  |  |  | 			resource->cap->jingle = 1; | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			resource->cap->jingle = 0; | 
					
						
							|  |  |  | 	} else if (pak->subtype == IKS_TYPE_GET) { | 
					
						
							|  |  |  | 		iks *iq, *disco, *ident, *google, *query; | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		ident = iks_new("identity"); | 
					
						
							|  |  |  | 		disco = iks_new("feature"); | 
					
						
							|  |  |  | 		google = iks_new("feature"); | 
					
						
							|  |  |  | 		if (iq && ident && disco && google) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->jid->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			iks_insert_attrib(ident, "category", "client"); | 
					
						
							|  |  |  | 			iks_insert_attrib(ident, "type", "pc"); | 
					
						
							|  |  |  | 			iks_insert_attrib(ident, "name", "asterisk"); | 
					
						
							|  |  |  | 			iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); | 
					
						
							|  |  |  | 			iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, ident); | 
					
						
							|  |  |  | 			iks_insert_node(query, google); | 
					
						
							| 
									
										
										
										
											2006-06-06 19:18:44 +00:00
										 |  |  | 			iks_insert_node(query, disco); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of Memory.\n"); | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (ident) | 
					
						
							|  |  |  | 			iks_delete(ident); | 
					
						
							|  |  |  | 		if (google) | 
					
						
							|  |  |  | 			iks_delete(google); | 
					
						
							|  |  |  | 		if (disco) | 
					
						
							|  |  |  | 			iks_delete(disco); | 
					
						
							|  |  |  | 	} else if (pak->subtype == IKS_TYPE_ERROR) { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_dinfo_handler(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							| 
									
										
										
										
											2006-10-03 22:35:43 +00:00
										 |  |  | 	char *node = NULL; | 
					
						
							|  |  |  | 	struct aji_resource *resource = NULL; | 
					
						
							|  |  |  | 	struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resource = aji_find_resource(buddy, pak->from->resource); | 
					
						
							|  |  |  | 	if (pak->subtype == IKS_TYPE_ERROR) { | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n"); | 
					
						
							|  |  |  | 		return IKS_FILTER_EAT; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-03 22:35:43 +00:00
										 |  |  | 	if (pak->subtype == IKS_TYPE_RESULT) { | 
					
						
							|  |  |  | 		if (!resource) { | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); | 
					
						
							|  |  |  | 			ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 			return IKS_FILTER_EAT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { | 
					
						
							|  |  |  | 			resource->cap->jingle = 1; | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			resource->cap->jingle = 0; | 
					
						
							|  |  |  | 	} else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		identity = iks_new("identity"); | 
					
						
							|  |  |  | 		disco = iks_new("feature"); | 
					
						
							|  |  |  | 		reg = iks_new("feature"); | 
					
						
							|  |  |  | 		commands = iks_new("feature"); | 
					
						
							|  |  |  | 		gateway = iks_new("feature"); | 
					
						
							|  |  |  | 		version = iks_new("feature"); | 
					
						
							|  |  |  | 		vcard = iks_new("feature"); | 
					
						
							|  |  |  | 		search = iks_new("feature"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); | 
					
						
							|  |  |  | 			iks_insert_attrib(identity, "category", "gateway"); | 
					
						
							|  |  |  | 			iks_insert_attrib(identity, "type", "pstn"); | 
					
						
							|  |  |  | 			iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); | 
					
						
							|  |  |  | 			iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); | 
					
						
							|  |  |  | 			iks_insert_attrib(reg, "var", "jabber:iq:register"); | 
					
						
							|  |  |  | 			iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); | 
					
						
							|  |  |  | 			iks_insert_attrib(version, "var", "jabber:iq:version"); | 
					
						
							|  |  |  | 			iks_insert_attrib(vcard, "var", "vcard-temp"); | 
					
						
							|  |  |  | 			iks_insert_attrib(search, "var", "jabber:iq:search"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, identity); | 
					
						
							|  |  |  | 			iks_insert_node(query, disco); | 
					
						
							|  |  |  | 			iks_insert_node(query, reg); | 
					
						
							|  |  |  | 			iks_insert_node(query, commands); | 
					
						
							|  |  |  | 			iks_insert_node(query, gateway); | 
					
						
							|  |  |  | 			iks_insert_node(query, version); | 
					
						
							|  |  |  | 			iks_insert_node(query, vcard); | 
					
						
							|  |  |  | 			iks_insert_node(query, search); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (identity) | 
					
						
							|  |  |  | 			iks_delete(identity); | 
					
						
							|  |  |  | 		if (disco) | 
					
						
							|  |  |  | 			iks_delete(disco); | 
					
						
							|  |  |  | 		if (reg) | 
					
						
							|  |  |  | 			iks_delete(reg); | 
					
						
							|  |  |  | 		if (commands) | 
					
						
							|  |  |  | 			iks_delete(commands); | 
					
						
							|  |  |  | 		if (gateway) | 
					
						
							|  |  |  | 			iks_delete(gateway); | 
					
						
							|  |  |  | 		if (version) | 
					
						
							|  |  |  | 			iks_delete(version); | 
					
						
							|  |  |  | 		if (vcard) | 
					
						
							|  |  |  | 			iks_delete(vcard); | 
					
						
							|  |  |  | 		if (search) | 
					
						
							|  |  |  | 			iks_delete(search); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-03 22:35:43 +00:00
										 |  |  | 	} else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		iks *iq, *query, *confirm; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		confirm = iks_new("item"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iq && query && confirm && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "node", "confirmaccount"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "name", "Confirm AIM account"); | 
					
						
							|  |  |  | 			iks_insert_attrib(confirm, "jid", client->user); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, confirm); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (confirm) | 
					
						
							|  |  |  | 			iks_delete(confirm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-03 22:35:43 +00:00
										 |  |  | 	} else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		iks *iq, *query, *feature; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		iq = iks_new("iq"); | 
					
						
							|  |  |  | 		query = iks_new("query"); | 
					
						
							|  |  |  | 		feature = iks_new("feature"); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (iq && query && feature && client) { | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "from", client->user); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_attrib(iq, "type", "result"); | 
					
						
							|  |  |  | 			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); | 
					
						
							|  |  |  | 			iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); | 
					
						
							|  |  |  | 			iks_insert_node(iq, query); | 
					
						
							|  |  |  | 			iks_insert_node(query, feature); | 
					
						
							|  |  |  | 			iks_send(client->p, iq); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iq) | 
					
						
							|  |  |  | 			iks_delete(iq); | 
					
						
							|  |  |  | 		if (query) | 
					
						
							|  |  |  | 			iks_delete(query); | 
					
						
							|  |  |  | 		if (feature) | 
					
						
							|  |  |  | 			iks_delete(feature); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Handles <iq> tags. | 
					
						
							|  |  |  |  * \param client structure and the iq node. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_handle_iq(struct aji_client *client, iks *node) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-08-08 17:07:41 +00:00
										 |  |  | 	/*Nothing to see here */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Handles presence packets. | 
					
						
							|  |  |  |  * \param client structure and the node. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | static void aji_handle_message(struct aji_client *client, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	struct aji_message *insert, *tmp; | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	int flag = 0; | 
					
						
							| 
									
										
										
										
											2006-06-27 14:07:24 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-06-18 21:45:48 +00:00
										 |  |  | 	if (!(insert = ast_calloc(1, sizeof(struct aji_message)))) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	time(&insert->arrived); | 
					
						
							| 
									
										
										
										
											2006-06-27 15:53:27 +00:00
										 |  |  | 	if (iks_find_cdata(pak->x, "body")) | 
					
						
							| 
									
										
										
										
											2006-06-27 14:07:24 +00:00
										 |  |  | 		insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); | 
					
						
							|  |  |  | 	if(pak->id) | 
					
						
							|  |  |  | 		ast_copy_string(insert->id, pak->id, sizeof(insert->message)); | 
					
						
							| 
									
										
										
										
											2006-10-23 17:07:45 +00:00
										 |  |  | 	if (pak->from) | 
					
						
							|  |  |  | 		insert->from = ast_strdup(pak->from->full); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_LOCK(&client->messages); | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { | 
					
						
							| 
									
										
										
										
											2006-06-18 21:45:48 +00:00
										 |  |  | 		if (flag) { | 
					
						
							|  |  |  | 			AST_LIST_REMOVE_CURRENT(&client->messages, list); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 			if (tmp->from) | 
					
						
							|  |  |  | 				free(tmp->from); | 
					
						
							|  |  |  | 			if (tmp->message) | 
					
						
							|  |  |  | 				free(tmp->message); | 
					
						
							|  |  |  | 		} else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) { | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 			flag = 1; | 
					
						
							| 
									
										
										
										
											2006-06-18 21:45:48 +00:00
										 |  |  | 			AST_LIST_REMOVE_CURRENT(&client->messages, list); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 			if (tmp->from) | 
					
						
							|  |  |  | 				free(tmp->from); | 
					
						
							|  |  |  | 			if (tmp->message) | 
					
						
							|  |  |  | 				free(tmp->message); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_TRAVERSE_SAFE_END; | 
					
						
							| 
									
										
										
										
											2006-06-18 21:45:48 +00:00
										 |  |  | 	AST_LIST_INSERT_HEAD(&client->messages, insert, list); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_UNLOCK(&client->messages); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-06-18 21:45:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static void aji_handle_presence(struct aji_client *client, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int status, priority; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	struct aji_buddy *buddy; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	char *ver, *node, *descrip, *type; | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if(client->state != AJI_CONNECTED) | 
					
						
							|  |  |  | 		aji_create_buddy(pak->from->partial, client); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); | 
					
						
							| 
									
										
										
										
											2007-10-07 16:15:39 +00:00
										 |  |  | 	if (!buddy && pak->from->partial) { | 
					
						
							|  |  |  | 		/* allow our jid to be used to log in with another resource */ | 
					
						
							|  |  |  | 		if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) | 
					
						
							|  |  |  | 			aji_create_buddy(pak->from->partial, client); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	type = iks_find_attrib(pak->x, "type"); | 
					
						
							|  |  |  | 	if(client->component && type &&!strcasecmp("probe", type)) { | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage); | 
					
						
							|  |  |  | 		ast_verbose("what i was looking for \n"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 	ASTOBJ_WRLOCK(buddy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	status = (pak->show) ? pak->show : 6; | 
					
						
							|  |  |  | 	priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); | 
					
						
							|  |  |  | 	tmp = buddy->resources; | 
					
						
							| 
									
										
										
										
											2006-06-06 19:51:26 +00:00
										 |  |  | 	descrip = ast_strdup(iks_find_cdata(pak->x,"status")); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-07 15:52:44 +00:00
										 |  |  | 	while (tmp && pak->from->resource) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (!strcasecmp(tmp->resource, pak->from->resource)) { | 
					
						
							|  |  |  | 			tmp->status = status; | 
					
						
							| 
									
										
										
										
											2006-06-06 19:51:26 +00:00
										 |  |  | 			if (tmp->description) free(tmp->description); | 
					
						
							|  |  |  | 			tmp->description = descrip; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			found = tmp; | 
					
						
							|  |  |  | 			if (status == 6) {	/* Sign off Destroy resource */ | 
					
						
							|  |  |  | 				if (last && found->next) { | 
					
						
							|  |  |  | 					last->next = found->next; | 
					
						
							|  |  |  | 				} else if (!last) { | 
					
						
							|  |  |  | 					if (found->next) | 
					
						
							|  |  |  | 						buddy->resources = found->next; | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						buddy->resources = NULL; | 
					
						
							|  |  |  | 				} else if (!found->next) { | 
					
						
							|  |  |  | 					if (last) | 
					
						
							|  |  |  | 						last->next = NULL; | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						buddy->resources = NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				free(found); | 
					
						
							|  |  |  | 				found = NULL; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 			/* resource list is sorted by descending priority */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			if (tmp->priority != priority) { | 
					
						
							|  |  |  | 				found->priority = priority; | 
					
						
							|  |  |  | 				if (!last && !found->next) | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 					/* resource was found to be unique,
 | 
					
						
							|  |  |  | 					   leave loop */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 				/* search for resource in our list
 | 
					
						
							|  |  |  | 				   and take it out for the moment */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				if (last) | 
					
						
							|  |  |  | 					last->next = found->next; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					buddy->resources = found->next; | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				last = NULL; | 
					
						
							|  |  |  | 				tmp = buddy->resources; | 
					
						
							|  |  |  | 				if (!buddy->resources) | 
					
						
							|  |  |  | 					buddy->resources = found; | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 				/* priority processing */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				while (tmp) { | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 					/* insert resource back according to 
 | 
					
						
							|  |  |  | 					   its priority value */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					if (found->priority > tmp->priority) { | 
					
						
							|  |  |  | 						if (last) | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 							/* insert within list */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 							last->next = found; | 
					
						
							|  |  |  | 						found->next = tmp; | 
					
						
							|  |  |  | 						if (!last) | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 							/* insert on top */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 							buddy->resources = found; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (!tmp->next) { | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 						/* insert at the end of the list */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 						tmp->next = found; | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 						found->next = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					last = tmp; | 
					
						
							|  |  |  | 					tmp = tmp->next; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		last = tmp; | 
					
						
							|  |  |  | 		tmp = tmp->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 	/* resource not found in our list, create it */ | 
					
						
							| 
									
										
										
										
											2007-10-07 15:52:44 +00:00
										 |  |  | 	if (!found && status != 6 && pak->from->resource) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		found = (struct aji_resource *) malloc(sizeof(struct aji_resource)); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		memset(found, 0, sizeof(struct aji_resource)); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		if (!found) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory!\n"); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); | 
					
						
							|  |  |  | 		found->status = status; | 
					
						
							| 
									
										
										
										
											2006-06-06 19:51:26 +00:00
										 |  |  | 		found->description = descrip; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		found->priority = priority; | 
					
						
							|  |  |  | 		found->next = NULL; | 
					
						
							|  |  |  | 		last = NULL; | 
					
						
							|  |  |  | 		tmp = buddy->resources; | 
					
						
							|  |  |  | 		while (tmp) { | 
					
						
							|  |  |  | 			if (found->priority > tmp->priority) { | 
					
						
							|  |  |  | 				if (last) | 
					
						
							|  |  |  | 					last->next = found; | 
					
						
							|  |  |  | 				found->next = tmp; | 
					
						
							|  |  |  | 				if (!last) | 
					
						
							|  |  |  | 					buddy->resources = found; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!tmp->next) { | 
					
						
							|  |  |  | 				tmp->next = found; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			last = tmp; | 
					
						
							|  |  |  | 			tmp = tmp->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!tmp) | 
					
						
							|  |  |  | 			buddy->resources = found; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 	ASTOBJ_UNLOCK(buddy); | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(buddy, aji_buddy_destroy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	node = iks_find_attrib(iks_find(pak->x, "c"), "node"); | 
					
						
							|  |  |  | 	ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-16 09:37:10 +00:00
										 |  |  | 	/* handle gmail client's special caps:c tag */ | 
					
						
							|  |  |  | 	if (!node && !ver) { | 
					
						
							|  |  |  | 		node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); | 
					
						
							|  |  |  | 		ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-07 15:52:44 +00:00
										 |  |  | 	/* retrieve capabilites of the new resource */ | 
					
						
							|  |  |  | 	if(status !=6 && found && !found->cap) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		found->cap = aji_find_version(node, ver, pak); | 
					
						
							|  |  |  | 		if(gtalk_yuck(pak->x)) /* gtalk should do discover */ | 
					
						
							|  |  |  | 			found->cap->jingle = 1; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		if(found->cap->jingle && option_debug > 4) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			ast_log(LOG_DEBUG,"Special case for google till they support discover.\n"); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			iks *iq, *query; | 
					
						
							|  |  |  | 			iq = iks_new("iq"); | 
					
						
							|  |  |  | 			query = iks_new("query"); | 
					
						
							|  |  |  | 			if(query && iq)  { | 
					
						
							|  |  |  | 				iks_insert_attrib(iq, "type", "get"); | 
					
						
							|  |  |  | 				iks_insert_attrib(iq, "to", pak->from->full); | 
					
						
							| 
									
										
										
										
											2007-09-06 14:20:54 +00:00
										 |  |  | 				iks_insert_attrib(iq,"from", client->jid->full); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				iks_insert_attrib(iq, "id", client->mid); | 
					
						
							|  |  |  | 				ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 				iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); | 
					
						
							|  |  |  | 				iks_insert_node(iq, query); | 
					
						
							|  |  |  | 				iks_send(client->p, iq); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 			if(query) | 
					
						
							|  |  |  | 				iks_delete(query); | 
					
						
							|  |  |  | 			if(iq) | 
					
						
							|  |  |  | 				iks_delete(iq); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (option_verbose > 4) { | 
					
						
							| 
									
										
										
										
											2006-05-23 16:43:58 +00:00
										 |  |  | 		switch (pak->subtype) { | 
					
						
							|  |  |  | 		case IKS_TYPE_AVAILABLE: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am available ^_* %i\n", pak->subtype); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_TYPE_UNAVAILABLE: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am unavailable ^_* %i\n", pak->subtype); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); | 
					
						
							| 
									
										
										
										
											2006-05-23 16:43:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		switch (pak->show) { | 
					
						
							|  |  |  | 		case IKS_SHOW_UNAVAILABLE: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_SHOW_AVAILABLE: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is available\n"); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_SHOW_CHAT: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_SHOW_AWAY: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is away\n"); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_SHOW_XA: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IKS_SHOW_DND: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: Kinky! how did that happen %i\n", pak->show); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief handles subscription requests. | 
					
						
							|  |  |  |  * \param aji_client struct and xml packet. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_handle_subscribe(struct aji_client *client, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-02-29 13:05:15 +00:00
										 |  |  | 	iks *presence = NULL, *status = NULL; | 
					
						
							|  |  |  | 	struct aji_buddy* buddy = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (pak->subtype) {  | 
					
						
							|  |  |  | 	case IKS_TYPE_SUBSCRIBE: | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		presence = iks_new("presence"); | 
					
						
							|  |  |  | 		status = iks_new("status"); | 
					
						
							|  |  |  | 		if(presence && status) { | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "type", "subscribed"); | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "to", pak->from->full); | 
					
						
							| 
									
										
										
										
											2007-03-29 17:43:52 +00:00
										 |  |  | 			iks_insert_attrib(presence, "from", client->jid->full); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 			if(pak->id) | 
					
						
							|  |  |  | 				iks_insert_attrib(presence, "id", pak->id); | 
					
						
							|  |  |  | 			iks_insert_cdata(status, "Asterisk has approved subscription", 0); | 
					
						
							|  |  |  | 			iks_insert_node(presence, status); | 
					
						
							|  |  |  | 			iks_send(client->p, presence); | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Unable to allocate nodes\n"); | 
					
						
							|  |  |  | 		if(presence) | 
					
						
							|  |  |  | 			iks_delete(presence); | 
					
						
							|  |  |  | 		if(status) | 
					
						
							|  |  |  | 			iks_delete(status); | 
					
						
							|  |  |  | 		if(client->component) | 
					
						
							|  |  |  | 			aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage); | 
					
						
							| 
									
										
										
										
											2008-02-29 13:05:15 +00:00
										 |  |  | 	case IKS_TYPE_SUBSCRIBED: | 
					
						
							|  |  |  | 		buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); | 
					
						
							|  |  |  | 		if (!buddy && pak->from->partial) { | 
					
						
							|  |  |  | 			aji_create_buddy(pak->from->partial, client); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		if (option_verbose > 4) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); | 
					
						
							| 
									
										
										
										
											2006-05-23 16:43:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief sends messages. | 
					
						
							|  |  |  |  * \param aji_client struct , reciever, message. | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-01-05 22:16:33 +00:00
										 |  |  | int ast_aji_send(struct aji_client *client, const char *address, const char *message) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	iks *message_packet = NULL; | 
					
						
							|  |  |  | 	if (client->state == AJI_CONNECTED) { | 
					
						
							|  |  |  | 		message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); | 
					
						
							|  |  |  | 		if (message_packet) { | 
					
						
							|  |  |  | 			iks_insert_attrib(message_packet, "from", client->jid->full); | 
					
						
							|  |  |  | 			res = iks_send(client->p, message_packet); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (message_packet) | 
					
						
							|  |  |  | 			iks_delete(message_packet); | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief create a chatroom. | 
					
						
							|  |  |  |  * \param aji_client struct , room, server, topic for the room. | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ast_aji_create_chat(struct aji_client *client, char *room, char *server, char *topic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	iks *iq = NULL; | 
					
						
							|  |  |  | 	iq = iks_new("iq"); | 
					
						
							| 
									
										
										
										
											2008-02-29 14:47:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (iq && client) { | 
					
						
							|  |  |  | 		iks_insert_attrib(iq, "type", "get"); | 
					
						
							|  |  |  | 		iks_insert_attrib(iq, "to", server); | 
					
						
							|  |  |  | 		iks_insert_attrib(iq, "id", client->mid); | 
					
						
							|  |  |  | 		ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 		iks_send(client->p, iq); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							| 
									
										
										
										
											2008-02-29 14:47:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	iks_delete(iq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief join a chatroom. | 
					
						
							|  |  |  |  * \param aji_client struct , room. | 
					
						
							|  |  |  |  * \return res. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ast_aji_join_chat(struct aji_client *client, char *room) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	iks *presence = NULL, *priority = NULL; | 
					
						
							|  |  |  | 	presence = iks_new("presence"); | 
					
						
							|  |  |  | 	priority = iks_new("priority"); | 
					
						
							|  |  |  | 	if (presence && priority && client) { | 
					
						
							|  |  |  | 		iks_insert_cdata(priority, "0", 1); | 
					
						
							|  |  |  | 		iks_insert_attrib(presence, "to", room); | 
					
						
							|  |  |  | 		iks_insert_node(presence, priority); | 
					
						
							|  |  |  | 		res = iks_send(client->p, presence); | 
					
						
							|  |  |  | 		iks_insert_cdata(priority, "5", 1); | 
					
						
							|  |  |  | 		iks_insert_attrib(presence, "to", room); | 
					
						
							|  |  |  | 		res = iks_send(client->p, presence); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	if (presence) | 
					
						
							|  |  |  | 		iks_delete(presence); | 
					
						
							|  |  |  | 	if (priority) | 
					
						
							|  |  |  | 		iks_delete(priority); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief invite to a chatroom. | 
					
						
							|  |  |  |  * \param aji_client struct ,user, room, message. | 
					
						
							|  |  |  |  * \return res. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char *message) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	iks *invite, *body, *namespace; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	invite = iks_new("message"); | 
					
						
							|  |  |  | 	body = iks_new("body"); | 
					
						
							|  |  |  | 	namespace = iks_new("x"); | 
					
						
							|  |  |  | 	if (client && invite && body && namespace) { | 
					
						
							|  |  |  | 		iks_insert_attrib(invite, "to", user); | 
					
						
							|  |  |  | 		iks_insert_attrib(invite, "id", client->mid); | 
					
						
							|  |  |  | 		ast_aji_increment_mid(client->mid); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		iks_insert_cdata(body, message, 0); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); | 
					
						
							|  |  |  | 		iks_insert_attrib(namespace, "jid", room); | 
					
						
							|  |  |  | 		iks_insert_node(invite, body); | 
					
						
							|  |  |  | 		iks_insert_node(invite, namespace); | 
					
						
							|  |  |  | 		res = iks_send(client->p, invite); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	if (body) | 
					
						
							|  |  |  | 		iks_delete(body); | 
					
						
							|  |  |  | 	if (namespace) | 
					
						
							|  |  |  | 		iks_delete(namespace); | 
					
						
							|  |  |  | 	if (invite) | 
					
						
							|  |  |  | 		iks_delete(invite); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief receive message loop. | 
					
						
							|  |  |  |  * \param aji_client struct. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void *aji_recv_loop(void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 	int res = IKS_HOOK; | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		if (res != IKS_OK) { | 
					
						
							|  |  |  | 			while(res != IKS_OK) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 				if(option_verbose > 3) | 
					
						
							|  |  |  | 					ast_verbose("JABBER: reconnecting.\n"); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 				res = aji_reconnect(client); | 
					
						
							| 
									
										
										
										
											2006-05-23 21:18:07 +00:00
										 |  |  | 				sleep(4); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		res = iks_recv(client->p, 1); | 
					
						
							| 
									
										
										
										
											2007-06-07 09:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (client->state == AJI_DISCONNECTING) { | 
					
						
							|  |  |  | 			if (option_debug > 1) | 
					
						
							|  |  |  | 				ast_log(LOG_DEBUG, "Ending our Jabber client's thread due to a disconnect\n"); | 
					
						
							|  |  |  | 			pthread_exit(NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		client->timeout--; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		if (res == IKS_HOOK)  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		else if (res == IKS_NET_TLSFAIL) | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n"); | 
					
						
							|  |  |  | 		else if (client->timeout == 0 && client->state == AJI_CONNECTED) { | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 			res = iks_send_raw(client->p, " "); | 
					
						
							|  |  |  | 			if(res == IKS_OK) | 
					
						
							|  |  |  | 				client->timeout = 50; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "JABBER:  Network Timeout\n"); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		} else if (res == IKS_NET_RWERR) | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "JABBER: socket read error\n"); | 
					
						
							| 
									
										
										
										
											2006-05-23 21:18:07 +00:00
										 |  |  | 	} while (client); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief increments the mid field for messages and other events. | 
					
						
							|  |  |  |  * \param message id. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void ast_aji_increment_mid(char *mid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	for (i = strlen(mid) - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 		if (mid[i] != 'z') { | 
					
						
							|  |  |  | 			mid[i] = mid[i] + 1; | 
					
						
							|  |  |  | 			i = 0; | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			mid[i] = 'a'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief attempts to register to a transport. | 
					
						
							|  |  |  |  * \param aji_client struct, and xml packet. | 
					
						
							|  |  |  |  * \return IKS_FILTER_EAT. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | /*allows for registering to transport , was too sketch and is out for now. */ | 
					
						
							|  |  |  | /*static int aji_register_transport(void *data, ikspak *pak)
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	struct aji_buddy *buddy = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	iks *send = iks_make_iq(IKS_TYPE_GET, "jabber:iq:register"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (client && send) { | 
					
						
							|  |  |  | 		ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 			ASTOBJ_RDLOCK(iterator);  | 
					
						
							|  |  |  | 			if (iterator->btype == AJI_TRANS) { | 
					
						
							|  |  |  | 				  buddy = iterator; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 		iks_filter_remove_hook(client->f, aji_register_transport); | 
					
						
							|  |  |  | 		iks_filter_add_rule(client->f, aji_register_transport2, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS, IKS_NS_REGISTER, IKS_RULE_DONE); | 
					
						
							|  |  |  | 		iks_insert_attrib(send, "to", buddy->host); | 
					
						
							|  |  |  | 		iks_insert_attrib(send, "id", client->mid); | 
					
						
							|  |  |  | 		ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 		iks_insert_attrib(send, "from", client->user); | 
					
						
							|  |  |  | 		res = iks_send(client->p, send); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (send) | 
					
						
							|  |  |  | 		iks_delete(send); | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief attempts to register to a transport step 2. | 
					
						
							|  |  |  |  * \param aji_client struct, and xml packet. | 
					
						
							|  |  |  |  * \return IKS_FILTER_EAT. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | /* more of the same blob of code, too wonky for now*/ | 
					
						
							|  |  |  | /* static int aji_register_transport2(void *data, ikspak *pak)
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	struct aji_buddy *buddy = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	iks *regiq = iks_new("iq"); | 
					
						
							|  |  |  | 	iks *regquery = iks_new("query"); | 
					
						
							|  |  |  | 	iks *reguser = iks_new("username"); | 
					
						
							|  |  |  | 	iks *regpass = iks_new("password"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (client && regquery && reguser && regpass && regiq) { | 
					
						
							|  |  |  | 		ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 			ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 			if (iterator->btype == AJI_TRANS) | 
					
						
							|  |  |  | 				buddy = iterator; ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 		iks_filter_remove_hook(client->f, aji_register_transport2); | 
					
						
							|  |  |  | 		iks_insert_attrib(regiq, "to", buddy->host); | 
					
						
							|  |  |  | 		iks_insert_attrib(regiq, "type", "set"); | 
					
						
							|  |  |  | 		iks_insert_attrib(regiq, "id", client->mid); | 
					
						
							|  |  |  | 		ast_aji_increment_mid(client->mid); | 
					
						
							|  |  |  | 		iks_insert_attrib(regiq, "from", client->user); | 
					
						
							|  |  |  | 		iks_insert_attrib(regquery, "xmlns", "jabber:iq:register"); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		iks_insert_cdata(reguser, buddy->user, 0); | 
					
						
							|  |  |  | 		iks_insert_cdata(regpass, buddy->pass, 0); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks_insert_node(regiq, regquery); | 
					
						
							|  |  |  | 		iks_insert_node(regquery, reguser); | 
					
						
							|  |  |  | 		iks_insert_node(regquery, regpass); | 
					
						
							|  |  |  | 		res = iks_send(client->p, regiq); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	if (regiq) | 
					
						
							|  |  |  | 		iks_delete(regiq); | 
					
						
							|  |  |  | 	if (regquery) | 
					
						
							|  |  |  | 		iks_delete(regquery); | 
					
						
							|  |  |  | 	if (reguser) | 
					
						
							|  |  |  | 		iks_delete(reguser); | 
					
						
							|  |  |  | 	if (regpass) | 
					
						
							|  |  |  | 		iks_delete(regpass); | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief goes through roster and prunes users not needed in list, or adds them accordingly. | 
					
						
							|  |  |  |  * \param aji_client struct. | 
					
						
							|  |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void aji_pruneregister(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	iks *removeiq = iks_new("iq"); | 
					
						
							|  |  |  | 	iks *removequery = iks_new("query"); | 
					
						
							|  |  |  | 	iks *removeitem = iks_new("item"); | 
					
						
							|  |  |  | 	iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (client && removeiq && removequery && removeitem && send) { | 
					
						
							| 
									
										
										
										
											2006-06-01 07:49:47 +00:00
										 |  |  | 		iks_insert_node(removeiq, removequery); | 
					
						
							|  |  |  | 		iks_insert_node(removequery, removeitem); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 			ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 			/* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never
 | 
					
						
							|  |  |  | 			 * be called at the same time */ | 
					
						
							|  |  |  | 			if (ast_test_flag(iterator, AJI_AUTOPRUNE)) { | 
					
						
							|  |  |  | 				res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, | 
					
						
							|  |  |  | 						"GoodBye your status is no longer needed by Asterisk the Open Source PBX" | 
					
						
							|  |  |  | 						" so I am no longer subscribing to your presence.\n")); | 
					
						
							|  |  |  | 				res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, | 
					
						
							|  |  |  | 						"GoodBye you are no longer in the asterisk config file so I am removing" | 
					
						
							|  |  |  | 						" your access to my presence.\n")); | 
					
						
							|  |  |  | 				iks_insert_attrib(removeiq, "from", client->jid->full);  | 
					
						
							|  |  |  | 				iks_insert_attrib(removeiq, "type", "set");  | 
					
						
							|  |  |  | 				iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); | 
					
						
							|  |  |  | 				iks_insert_attrib(removeitem, "jid", iterator->name); | 
					
						
							|  |  |  | 				iks_insert_attrib(removeitem, "subscription", "remove"); | 
					
						
							|  |  |  | 				res = iks_send(client->p, removeiq); | 
					
						
							|  |  |  | 			} else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) { | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 				res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,  | 
					
						
							|  |  |  | 						"Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				ast_clear_flag(iterator, AJI_AUTOREGISTER); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	if (removeiq) | 
					
						
							|  |  |  | 		iks_delete(removeiq); | 
					
						
							|  |  |  | 	if (removequery) | 
					
						
							|  |  |  | 		iks_delete(removequery); | 
					
						
							|  |  |  | 	if (removeitem) | 
					
						
							|  |  |  | 		iks_delete(removeitem); | 
					
						
							|  |  |  | 	if (send) | 
					
						
							|  |  |  | 		iks_delete(send); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief filters the roster packet we get back from server. | 
					
						
							|  |  |  |  * \param aji_client struct, and xml packet. | 
					
						
							|  |  |  |  * \return IKS_FILTER_EAT. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_filter_roster(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	int flag = 0; | 
					
						
							|  |  |  | 	iks *x = NULL; | 
					
						
							|  |  |  | 	struct aji_buddy *buddy; | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	client->state = AJI_CONNECTED; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 		x = iks_child(pak->query); | 
					
						
							|  |  |  | 		flag = 0; | 
					
						
							|  |  |  | 		while (x) { | 
					
						
							|  |  |  | 			if (!iks_strcmp(iks_name(x), "item")) { | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 				if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { | 
					
						
							|  |  |  | 					flag = 1; | 
					
						
							|  |  |  | 					ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			x = iks_next(x); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!flag) | 
					
						
							|  |  |  | 			ast_copy_flags(iterator, client, AJI_AUTOREGISTER); | 
					
						
							|  |  |  | 		if (x) | 
					
						
							|  |  |  | 			iks_delete(x); | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	x = iks_child(pak->query); | 
					
						
							|  |  |  | 	while (x) { | 
					
						
							|  |  |  | 		flag = 0; | 
					
						
							|  |  |  | 		if (iks_strcmp(iks_name(x), "item") == 0) { | 
					
						
							|  |  |  | 			ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 				ASTOBJ_RDLOCK(iterator); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 				if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					flag = 1; | 
					
						
							|  |  |  | 				ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!flag) { | 
					
						
							| 
									
										
										
										
											2006-06-06 17:25:07 +00:00
										 |  |  | 				buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy)); | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 				if (!buddy) { | 
					
						
							| 
									
										
										
										
											2006-06-06 17:25:07 +00:00
										 |  |  | 					ast_log(LOG_WARNING, "Out of memory\n"); | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 					return 0; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2006-06-06 17:25:07 +00:00
										 |  |  | 				memset(buddy, 0, sizeof(struct aji_buddy)); | 
					
						
							|  |  |  | 				ASTOBJ_INIT(buddy); | 
					
						
							|  |  |  | 				ASTOBJ_WRLOCK(buddy); | 
					
						
							|  |  |  | 				ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); | 
					
						
							|  |  |  | 				ast_clear_flag(buddy, AST_FLAGS_ALL); | 
					
						
							|  |  |  | 				if(ast_test_flag(client, AJI_AUTOPRUNE)) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 					ast_set_flag(buddy, AJI_AUTOPRUNE); | 
					
						
							|  |  |  | 					buddy->objflags |= ASTOBJ_FLAG_MARKED; | 
					
						
							| 
									
										
										
										
											2006-06-06 17:25:07 +00:00
										 |  |  | 				} else | 
					
						
							|  |  |  | 					ast_set_flag(buddy, AJI_AUTOREGISTER); | 
					
						
							|  |  |  | 				ASTOBJ_UNLOCK(buddy); | 
					
						
							|  |  |  | 				if (buddy) { | 
					
						
							|  |  |  | 					ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); | 
					
						
							|  |  |  | 					ASTOBJ_UNREF(buddy, aji_buddy_destroy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		x = iks_next(x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (x) | 
					
						
							|  |  |  | 		iks_delete(x); | 
					
						
							|  |  |  | 	aji_pruneregister(client); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return IKS_FILTER_EAT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_reconnect(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (client->state) | 
					
						
							|  |  |  | 		client->state = AJI_DISCONNECTED; | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 	client->timeout=50; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (client->p) | 
					
						
							|  |  |  | 		iks_parser_reset(client->p); | 
					
						
							|  |  |  | 	if (client->authorized) | 
					
						
							|  |  |  | 		client->authorized = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if(client->component) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		res = aji_component_initialize(client); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		res = aji_client_initialize(client); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int aji_get_roster(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	iks *roster = NULL; | 
					
						
							|  |  |  | 	roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); | 
					
						
							|  |  |  | 	if(roster) { | 
					
						
							|  |  |  | 		iks_insert_attrib(roster, "id", "roster"); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks_send(client->p, roster); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (roster) | 
					
						
							|  |  |  | 		iks_delete(roster); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief connects as a client to jabber server. | 
					
						
							|  |  |  |  * \param aji_client struct, and xml packet. | 
					
						
							|  |  |  |  * \return res. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_client_connect(void *data, ikspak *pak) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (client) { | 
					
						
							|  |  |  | 		if (client->state == AJI_DISCONNECTED) { | 
					
						
							|  |  |  | 			iks_filter_add_rule(client->f, aji_filter_roster, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "roster", IKS_RULE_DONE); | 
					
						
							| 
									
										
										
										
											2006-06-06 18:51:37 +00:00
										 |  |  | 			client->state = AJI_CONNECTING; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; | 
					
						
							|  |  |  | 			iks_filter_remove_hook(client->f, aji_client_connect); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 			if(!client->component) /*client*/ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				aji_get_roster(client); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief prepares client for connect. | 
					
						
							|  |  |  |  * \param aji_client struct. | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_client_initialize(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int connected = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (connected == IKS_NET_NOCONN) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 		return IKS_HOOK; | 
					
						
							|  |  |  | 	} else 	if (connected == IKS_NET_NODNS) { | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server)); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 		return IKS_HOOK; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} else | 
					
						
							|  |  |  | 		iks_recv(client->p, 30); | 
					
						
							| 
									
										
										
										
											2006-05-23 20:25:23 +00:00
										 |  |  | 	return IKS_OK; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief prepares component for connect. | 
					
						
							|  |  |  |  * \param aji_client struct. | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_component_initialize(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int connected = 1; | 
					
						
							| 
									
										
										
										
											2007-05-24 14:38:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->user); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 	if (connected == IKS_NET_NOCONN) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 		return IKS_HOOK; | 
					
						
							|  |  |  | 	} else if (connected == IKS_NET_NODNS) { | 
					
						
							| 
									
										
										
										
											2007-05-24 14:38:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server)); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 		return IKS_HOOK; | 
					
						
							|  |  |  | 	} else if (!connected)  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks_recv(client->p, 30); | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 	return IKS_OK; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief disconnect from jabber server. | 
					
						
							|  |  |  |  * \param aji_client struct. | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ast_aji_disconnect(struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (client) { | 
					
						
							|  |  |  | 		if (option_verbose > 3) | 
					
						
							|  |  |  | 			ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n"); | 
					
						
							|  |  |  | 		iks_disconnect(client->p); | 
					
						
							|  |  |  | 		iks_parser_delete(client->p); | 
					
						
							|  |  |  | 		ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief set presence of client. | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  |  * \param aji_client struct, user to send it to, and from, level, description. | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  |  * \return void. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	iks *presence = iks_make_pres(level, desc); | 
					
						
							|  |  |  | 	iks *cnode = iks_new("c"); | 
					
						
							|  |  |  | 	iks *priority = iks_new("priority"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	iks_insert_cdata(priority, "0", 1); | 
					
						
							|  |  |  | 	if (presence && cnode && client) { | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 		if(to) | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "to", to); | 
					
						
							|  |  |  | 		if(from) | 
					
						
							|  |  |  | 			iks_insert_attrib(presence, "from", from); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); | 
					
						
							|  |  |  | 		iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); | 
					
						
							|  |  |  | 		iks_insert_attrib(cnode, "ext", "voice-v1"); | 
					
						
							|  |  |  | 		iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); | 
					
						
							|  |  |  | 		iks_insert_node(presence, cnode); | 
					
						
							|  |  |  | 		res = iks_send(client->p, presence); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Out of memory.\n"); | 
					
						
							|  |  |  | 	if (cnode) | 
					
						
							|  |  |  | 		iks_delete(cnode); | 
					
						
							|  |  |  | 	if (presence) | 
					
						
							|  |  |  | 		iks_delete(presence); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief turnon console debugging. | 
					
						
							|  |  |  |  * \param fd, number of args, args. | 
					
						
							|  |  |  |  * \return RESULT_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_do_debug(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator);  | 
					
						
							|  |  |  | 		iterator->debug = 1; | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	ast_cli(fd, "Jabber Debugging Enabled.\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief reload jabber module. | 
					
						
							|  |  |  |  * \param fd, number of args, args. | 
					
						
							|  |  |  |  * \return RESULT_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_do_reload(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	aji_reload(); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	ast_cli(fd, "Jabber Reloaded.\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief turnoff console debugging. | 
					
						
							|  |  |  |  * \param fd, number of args, args. | 
					
						
							|  |  |  |  * \return RESULT_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_no_debug(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 		iterator->debug = 0; | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	ast_cli(fd, "Jabber Debugging Disabled.\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief show client status. | 
					
						
							|  |  |  |  * \param fd, number of args, args. | 
					
						
							|  |  |  |  * \return RESULT_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_show_clients(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	char *status; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 	ast_cli(fd, "Jabber Users and their status:\n"); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		count++; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		switch (iterator->state) { | 
					
						
							|  |  |  | 		case AJI_DISCONNECTED: | 
					
						
							|  |  |  | 			status = "Disconnected"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AJI_CONNECTING: | 
					
						
							|  |  |  | 			status = "Connecting"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AJI_CONNECTED: | 
					
						
							|  |  |  | 			status = "Connected"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			status = "Unknown"; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		ast_cli(fd, "       User: %s     - %s\n", iterator->user, status); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	ast_cli(fd, "----\n"); | 
					
						
							|  |  |  | 	ast_cli(fd, "   Number of users: %d\n", count); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  |  * \brief send test message for debugging. | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  |  * \param fd, number of args, args. | 
					
						
							|  |  |  |  * \return RESULT_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_test(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client; | 
					
						
							|  |  |  | 	struct aji_resource *resource; | 
					
						
							|  |  |  | 	const char *name = "asterisk"; | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	struct aji_message *tmp; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	if (argc > 3) | 
					
						
							|  |  |  | 		return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 	else if (argc == 3) | 
					
						
							|  |  |  | 		name = argv[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { | 
					
						
							|  |  |  | 		ast_cli(fd, "Unable to find client '%s'!\n", name); | 
					
						
							|  |  |  | 		return RESULT_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-08 17:07:41 +00:00
										 |  |  | 	/* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ast_aji_send(client, "mogorman@astjab.org", "blahblah"); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 		ast_verbose("User: %s\n", iterator->name); | 
					
						
							|  |  |  | 		for (resource = iterator->resources; resource; resource = resource->next) { | 
					
						
							|  |  |  | 			ast_verbose("Resource: %s\n", resource->resource); | 
					
						
							|  |  |  | 			if(resource->cap) { | 
					
						
							|  |  |  | 				ast_verbose("   client: %s\n", resource->cap->parent->node); | 
					
						
							|  |  |  | 				ast_verbose("   version: %s\n", resource->cap->version); | 
					
						
							|  |  |  | 				ast_verbose("   Jingle Capable: %d\n", resource->cap->jingle); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ast_verbose("	Priority: %d\n", resource->priority); | 
					
						
							|  |  |  | 			ast_verbose("	Status: %d\n", resource->status);  | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 			ast_verbose("	Message: %s\n", S_OR(resource->description,""));  | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	ast_verbose("\nOooh a working message stack!\n"); | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_LOCK(&client->messages); | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE(&client->messages, tmp, list) { | 
					
						
							| 
									
										
										
										
											2006-06-27 14:07:24 +00:00
										 |  |  | 		ast_verbose("	Message from: %s with id %s @ %s	%s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_UNLOCK(&client->messages); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief creates aji_client structure. | 
					
						
							|  |  |  |  * \param label, ast_variable, debug, pruneregister, component/client, aji_client to dump into.  | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_create_client(char *label, struct ast_variable *var, int debug) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *resource; | 
					
						
							|  |  |  | 	struct aji_client *client = NULL; | 
					
						
							|  |  |  | 	int flag = 0; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	client = ASTOBJ_CONTAINER_FIND(&clients,label); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (!client) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		flag = 1; | 
					
						
							|  |  |  | 		client = (struct aji_client *) malloc(sizeof(struct aji_client)); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		if (!client) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			ast_log(LOG_ERROR, "Out of memory!\n"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		memset(client, 0, sizeof(struct aji_client)); | 
					
						
							|  |  |  | 		ASTOBJ_INIT(client); | 
					
						
							|  |  |  | 		ASTOBJ_WRLOCK(client); | 
					
						
							|  |  |  | 		ASTOBJ_CONTAINER_INIT(&client->buddies); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ASTOBJ_WRLOCK(client); | 
					
						
							|  |  |  | 		ASTOBJ_UNMARK(client); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_MARKALL(&client->buddies); | 
					
						
							|  |  |  | 	ast_copy_string(client->name, label, sizeof(client->name)); | 
					
						
							|  |  |  | 	ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | 	/* Set default values for the client object */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	client->debug = debug; | 
					
						
							|  |  |  | 	ast_copy_flags(client, &globalflags, AST_FLAGS_ALL); | 
					
						
							|  |  |  | 	client->port = 5222; | 
					
						
							|  |  |  | 	client->usetls = 1; | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	client->usesasl = 1; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	client->forcessl = 0; | 
					
						
							|  |  |  | 	client->keepalive = 1; | 
					
						
							| 
									
										
										
										
											2006-09-19 23:57:04 +00:00
										 |  |  | 	client->timeout = 50; | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	client->message_timeout = 100; | 
					
						
							| 
									
										
										
										
											2006-06-09 16:08:33 +00:00
										 |  |  | 	AST_LIST_HEAD_INIT(&client->messages); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	client->component = 0; | 
					
						
							| 
									
										
										
										
											2006-06-01 07:49:47 +00:00
										 |  |  | 	ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (flag) { | 
					
						
							|  |  |  | 		client->authorized = 0; | 
					
						
							|  |  |  | 		client->state = AJI_DISCONNECTED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	while (var) { | 
					
						
							|  |  |  | 		if (!strcasecmp(var->name, "username")) | 
					
						
							|  |  |  | 			ast_copy_string(client->user, var->value, sizeof(client->user)); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "serverhost")) | 
					
						
							|  |  |  | 			ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "secret")) | 
					
						
							|  |  |  | 			ast_copy_string(client->password, var->value, sizeof(client->password)); | 
					
						
							| 
									
										
										
										
											2006-06-01 07:49:47 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "statusmessage")) | 
					
						
							|  |  |  | 			ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "port")) | 
					
						
							|  |  |  | 			client->port = atoi(var->value); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "timeout")) | 
					
						
							|  |  |  | 			client->message_timeout = atoi(var->value); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "debug")) | 
					
						
							|  |  |  | 			client->debug = (ast_false(var->value)) ? 0 : 1; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "type")) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 			if (!strcasecmp(var->value, "component")) | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 				client->component = 1; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		} else if (!strcasecmp(var->name, "usetls")) { | 
					
						
							|  |  |  | 			client->usetls = (ast_false(var->value)) ? 0 : 1; | 
					
						
							|  |  |  | 		} else if (!strcasecmp(var->name, "usesasl")) { | 
					
						
							|  |  |  | 			client->usesasl = (ast_false(var->value)) ? 0 : 1; | 
					
						
							|  |  |  | 		} else if (!strcasecmp(var->name, "forceoldssl")) | 
					
						
							|  |  |  | 			client->forcessl = (ast_false(var->value)) ? 0 : 1; | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "keepalive")) | 
					
						
							|  |  |  | 			client->keepalive = (ast_false(var->value)) ? 0 : 1; | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "autoprune")) | 
					
						
							|  |  |  | 			ast_set2_flag(client, ast_true(var->value), AJI_AUTOPRUNE); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "autoregister")) | 
					
						
							|  |  |  | 			ast_set2_flag(client, ast_true(var->value), AJI_AUTOREGISTER); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "buddy")) | 
					
						
							|  |  |  | 				aji_create_buddy(var->value, client); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	/* no transport support in this version */ | 
					
						
							|  |  |  | 	/*	else if (!strcasecmp(var->name, "transport"))
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 				aji_create_transport(var->value, client); | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		var = var->next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (!flag) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ASTOBJ_UNLOCK(client); | 
					
						
							|  |  |  | 		ASTOBJ_UNREF(client, aji_client_destroy); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	if (!client->p) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	client->stack = iks_stack_new(8192, 8192); | 
					
						
							|  |  |  | 	if (!client->stack) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 	client->f = iks_filter_new(); | 
					
						
							|  |  |  | 	if (!client->f) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if (!strchr(client->user, '/') && !client->component) { /*client */ | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		resource = NULL; | 
					
						
							|  |  |  | 		asprintf(&resource, "%s/asterisk", client->user); | 
					
						
							|  |  |  | 		if (resource) { | 
					
						
							|  |  |  | 			client->jid = iks_id_new(client->stack, resource); | 
					
						
							|  |  |  | 			free(resource); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		client->jid = iks_id_new(client->stack, client->user); | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if (client->component) { | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); | 
					
						
							|  |  |  | 		iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); | 
					
						
							|  |  |  | 		iks_filter_add_rule(client->f, aji_register_query_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE); | 
					
						
							|  |  |  | 		iks_filter_add_rule(client->f, aji_register_approve_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-21 23:50:56 +00:00
										 |  |  | 	if (!strchr(client->user, '/') && !client->component) { /*client */ | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		resource = NULL; | 
					
						
							|  |  |  | 		asprintf(&resource, "%s/asterisk", client->user); | 
					
						
							|  |  |  | 		if (resource) { | 
					
						
							|  |  |  | 			client->jid = iks_id_new(client->stack, resource); | 
					
						
							|  |  |  | 			free(resource); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		client->jid = iks_id_new(client->stack, client->user); | 
					
						
							|  |  |  | 	iks_set_log_hook(client->p, aji_log_hook); | 
					
						
							|  |  |  | 	ASTOBJ_UNLOCK(client); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_LINK(&clients,client); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief creates transport. | 
					
						
							|  |  |  |  * \param label, buddy to dump it into.  | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | /* no connecting to transports today */ | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | static int aji_create_transport(char *label, struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *server = NULL, *buddyname = NULL, *user = NULL, *pass = NULL; | 
					
						
							|  |  |  | 	struct aji_buddy *buddy = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label); | 
					
						
							|  |  |  | 	if (!buddy) { | 
					
						
							|  |  |  | 		buddy = malloc(sizeof(struct aji_buddy)); | 
					
						
							|  |  |  | 		if(!buddy) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Out of memory\n"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		memset(buddy, 0, sizeof(struct aji_buddy)); | 
					
						
							|  |  |  | 		ASTOBJ_INIT(buddy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_WRLOCK(buddy); | 
					
						
							|  |  |  | 	server = label; | 
					
						
							|  |  |  | 	if ((buddyname = strchr(label, ','))) { | 
					
						
							|  |  |  | 		*buddyname = '\0'; | 
					
						
							|  |  |  | 		buddyname++; | 
					
						
							|  |  |  | 		if (buddyname && buddyname[0] != '\0') { | 
					
						
							|  |  |  | 			if ((user = strchr(buddyname, ','))) { | 
					
						
							|  |  |  | 				*user = '\0'; | 
					
						
							|  |  |  | 				user++; | 
					
						
							|  |  |  | 				if (user && user[0] != '\0') { | 
					
						
							|  |  |  | 					if ((pass = strchr(user, ','))) { | 
					
						
							|  |  |  | 						*pass = '\0'; | 
					
						
							|  |  |  | 						pass++; | 
					
						
							|  |  |  | 						ast_copy_string(buddy->pass, pass, sizeof(buddy->pass)); | 
					
						
							|  |  |  | 						ast_copy_string(buddy->user, user, sizeof(buddy->user)); | 
					
						
							|  |  |  | 						ast_copy_string(buddy->name, buddyname, sizeof(buddy->name)); | 
					
						
							|  |  |  | 						ast_copy_string(buddy->server, server, sizeof(buddy->server)); | 
					
						
							|  |  |  | 						return 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_UNLOCK(buddy); | 
					
						
							| 
									
										
										
										
											2006-06-01 08:22:44 +00:00
										 |  |  | 	ASTOBJ_UNMARK(buddy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-10-03 00:01:34 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief creates buddy. | 
					
						
							|  |  |  |  * \param label, buddy to dump it into.  | 
					
						
							|  |  |  |  * \return 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_create_buddy(char *label, struct aji_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct aji_buddy *buddy = NULL; | 
					
						
							|  |  |  | 	int flag = 0; | 
					
						
							|  |  |  | 	buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label); | 
					
						
							|  |  |  | 	if (!buddy) { | 
					
						
							|  |  |  | 		flag = 1; | 
					
						
							|  |  |  | 		buddy = malloc(sizeof(struct aji_buddy)); | 
					
						
							|  |  |  | 		if(!buddy) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Out of memory\n"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 		memset(buddy, 0, sizeof(struct aji_buddy)); | 
					
						
							|  |  |  | 		ASTOBJ_INIT(buddy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ASTOBJ_WRLOCK(buddy); | 
					
						
							|  |  |  | 	ast_copy_string(buddy->name, label, sizeof(buddy->name)); | 
					
						
							|  |  |  | 	ASTOBJ_UNLOCK(buddy); | 
					
						
							|  |  |  | 	if(flag) | 
					
						
							|  |  |  | 		ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); | 
					
						
							| 
									
										
										
										
											2006-06-01 08:22:44 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		ASTOBJ_UNMARK(buddy); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ASTOBJ_UNREF(buddy, aji_buddy_destroy); | 
					
						
							| 
									
										
										
										
											2006-06-01 08:22:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief load config file. | 
					
						
							|  |  |  |  * \param void.  | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int aji_load_config(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *cat = NULL; | 
					
						
							|  |  |  | 	int debug = 1; | 
					
						
							|  |  |  | 	struct ast_config *cfg = NULL; | 
					
						
							|  |  |  | 	struct ast_variable *var = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cfg = ast_config_load(JABBER_CONFIG); | 
					
						
							|  |  |  | 	if (!cfg) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cat = ast_category_browse(cfg, NULL); | 
					
						
							|  |  |  | 	for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { | 
					
						
							|  |  |  | 		if (!strcasecmp(var->name, "debug")) | 
					
						
							|  |  |  | 			debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "autoprune")) | 
					
						
							|  |  |  | 			ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "autoregister")) | 
					
						
							|  |  |  | 			ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (cat) { | 
					
						
							|  |  |  | 		if (strcasecmp(cat, "general")) { | 
					
						
							|  |  |  | 				var = ast_variable_browse(cfg, cat); | 
					
						
							|  |  |  | 				aji_create_client(cat, var, debug); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cat = ast_category_browse(cfg, cat); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-11-07 21:40:28 +00:00
										 |  |  | 	ast_config_destroy(cfg); /* or leak memory */ | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief grab a aji_client structure by label name. | 
					
						
							|  |  |  |  * \param void.  | 
					
						
							|  |  |  |  * \return 1. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-01-05 22:16:33 +00:00
										 |  |  | struct aji_client *ast_aji_get_client(const char *name) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = NULL; | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	client = ASTOBJ_CONTAINER_FIND(&clients, name); | 
					
						
							|  |  |  | 	if (!client && !strchr(name, '@')) | 
					
						
							|  |  |  | 		client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp); | 
					
						
							|  |  |  | 	return client; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct aji_client_container *ast_aji_get_clients(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return &clients; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | static char mandescr_jabber_send[] = | 
					
						
							|  |  |  | "Description: Sends a message to a Jabber Client.\n" | 
					
						
							|  |  |  | "Variables: \n" | 
					
						
							|  |  |  | "  Jabber:	Client or transport Asterisk uses to connect to JABBER.\n" | 
					
						
							|  |  |  | "  ScreenName:	User Name to message.\n" | 
					
						
							|  |  |  | "  Message:	Message to be sent to the buddy\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief  Send a Jabber Message via call from the Manager */ | 
					
						
							| 
									
										
										
										
											2007-01-05 22:16:33 +00:00
										 |  |  | static int manager_jabber_send(struct mansession *s, const struct message *m) | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct aji_client *client = NULL; | 
					
						
							| 
									
										
										
										
											2007-01-05 22:16:33 +00:00
										 |  |  | 	const char *id = astman_get_header(m,"ActionID"); | 
					
						
							|  |  |  | 	const char *jabber = astman_get_header(m,"Jabber"); | 
					
						
							|  |  |  | 	const char *screenname = astman_get_header(m,"ScreenName"); | 
					
						
							|  |  |  | 	const char *message = astman_get_header(m,"Message"); | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_strlen_zero(jabber)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No transport specified"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ast_strlen_zero(screenname)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No ScreenName specified"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ast_strlen_zero(message)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No Message specified"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	astman_send_ack(s, m, "Attempting to send Jabber Message"); | 
					
						
							|  |  |  | 	client = ast_aji_get_client(jabber); | 
					
						
							|  |  |  | 	if (!client) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "Could not find Sender"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	if (strchr(screenname, '@') && message){ | 
					
						
							|  |  |  | 		ast_aji_send(client, screenname, message);	 | 
					
						
							|  |  |  | 		if (!ast_strlen_zero(id)) | 
					
						
							|  |  |  | 			astman_append(s, "ActionID: %s\r\n",id); | 
					
						
							|  |  |  | 		astman_append(s, "Response: Success\r\n"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(id)) | 
					
						
							|  |  |  | 		astman_append(s, "ActionID: %s\r\n",id); | 
					
						
							|  |  |  | 	astman_append(s, "Response: Failure\r\n"); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | static int aji_reload() | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_MARKALL(&clients); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 	if (!aji_load_config()) { | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							|  |  |  | 		if(iterator->state == AJI_DISCONNECTED) { | 
					
						
							|  |  |  | 			if (!iterator->thread) | 
					
						
							| 
									
										
										
										
											2006-10-04 19:47:22 +00:00
										 |  |  | 				ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 		} else if (iterator->state == AJI_CONNECTING) | 
					
						
							|  |  |  | 			aji_get_roster(iterator); | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 09:55:13 +00:00
										 |  |  | 	/* Check if TLS is initialized. If that's the case, we can't unload this
 | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | 	   module due to a bug in the iksemel library that will cause a crash or | 
					
						
							|  |  |  | 	   a deadlock. We're trying to find a way to handle this, but in the meantime | 
					
						
							|  |  |  | 	   we will simply refuse to die...  | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2007-06-07 09:55:13 +00:00
										 |  |  | 	if (tls_initialized) { | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Module can't be unloaded due to a bug in the Iksemel library when using TLS.\n"); | 
					
						
							|  |  |  | 		return 1;	/* You need a forced unload to get rid of this module */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | 	ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); | 
					
						
							| 
									
										
										
										
											2006-06-07 22:43:20 +00:00
										 |  |  | 	ast_unregister_application(app_ajisend); | 
					
						
							| 
									
										
										
										
											2006-10-19 17:24:40 +00:00
										 |  |  | 	ast_unregister_application(app_ajistatus); | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | 	ast_manager_unregister("JabberSend"); | 
					
						
							| 
									
										
										
										
											2007-06-07 09:42:26 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { | 
					
						
							|  |  |  | 		ASTOBJ_RDLOCK(iterator); | 
					
						
							| 
									
										
										
										
											2007-06-07 09:00:44 +00:00
										 |  |  | 		if (option_debug > 2) | 
					
						
							|  |  |  | 			ast_log(LOG_DEBUG, "JABBER: Releasing and disconneing client: %s\n", iterator->name); | 
					
						
							|  |  |  | 		iterator->state = AJI_DISCONNECTING; | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 		ast_aji_disconnect(iterator); | 
					
						
							|  |  |  | 		pthread_join(iterator->thread, NULL); | 
					
						
							|  |  |  | 		ASTOBJ_UNLOCK(iterator); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_DESTROY(&clients); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ASTOBJ_CONTAINER_INIT(&clients); | 
					
						
							| 
									
										
										
										
											2006-08-31 21:00:20 +00:00
										 |  |  | 	if(!aji_reload()) | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2006-08-07 22:03:50 +00:00
										 |  |  | 	ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, | 
					
						
							|  |  |  | 			"Sends a message to a Jabber Client", mandescr_jabber_send); | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip); | 
					
						
							|  |  |  | 	ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip); | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | 	ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); | 
					
						
							| 
									
										
										
										
											2006-08-07 21:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int reload(void) | 
					
						
							| 
									
										
										
										
											2006-05-22 21:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	aji_reload(); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "AJI - Asterisk Jabber Interface", | 
					
						
							|  |  |  | 		.load = load_module, | 
					
						
							|  |  |  | 		.unload = unload_module, | 
					
						
							|  |  |  | 		.reload = reload, | 
					
						
							|  |  |  | 	       ); |