--- /Users/jcovert/Desktop/Gtalk/res_jabber.c.1.6.1.head.c 2009-10-13 13:01:22.000000000 -0400 +++ /Users/jcovert/Desktop/Gtalk/res_jabber.c.1.6.1.gtalk-web.c 2009-10-13 18:15:57.000000000 -0400 @@ -59,18 +59,139 @@ #include "asterisk/astdb.h" #include "asterisk/manager.h" +/*** DOCUMENTATION + + + Send a Jabber Message + + + + Client or transport Asterisk uses to connect to Jabber. + + + XMPP/Jabber JID (Name) of recipient. + + + Message to be sent to the buddy. + + + + Allows user to send a message to a receipent via XMPP. + + + + + Retrieve the status of a jabber list member + + + + Client or transport Asterisk users to connect to Jabber. + + + XMPP/Jabber JID (Name) of recipient. + + + Variable to store the status of requested user. + + + + This application is deprecated. Please use the JABBER_STATUS() function instead. + Retrieves the numeric status associated with the specified buddy JID. + The return value in the Variablewill be one of the following. + + + Online. + + + Chatty. + + + Away. + + + Extended Away. + + + Do Not Disturb. + + + Offline. + + + Not In Roster. + + + + + + + Retrieve the status of a jabber list member + + + + XMPP/Jabber ID (Name) of sender. + + + XMPP/Jabber JID (Name) of recipient. + + + Client or transport Asterisk users to connect to Jabber. + + + + Retrieves the numeric status associated with the specified buddy JID. + The return value will be one of the following. + + + Online. + + + Chatty. + + + Away. + + + Extended Away. + + + Do Not Disturb. + + + Offline. + + + Not In Roster. + + + + + + + Sends a message to a Jabber Client. + + + + + Client or transport Asterisk uses to connect to JABBER. + + + XMPP/Jabber JID (Name) of recipient. + + + Message to be sent to the buddy. + + + + Sends a message to a Jabber Client. + + + ***/ + /*! \todo This should really be renamed to xmpp.conf. For backwards compatibility, we need to read both files */ #define JABBER_CONFIG "jabber.conf" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - /*-- Forward declarations */ static void aji_buddy_destroy(struct aji_buddy *obj); static void aji_client_destroy(struct aji_client *obj); @@ -96,7 +217,6 @@ static int aji_initialize(struct aji_client *client); static int aji_client_connect(void *data, ikspak *pak); static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc); -static char *aji_do_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static char *aji_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static char *aji_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static char *aji_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); @@ -123,9 +243,8 @@ static int aji_register_transport2(void *data, ikspak *pak); */ -static struct ast_cli_entry cli_aji_do_debug_deprecated = AST_CLI_DEFINE(aji_do_debug_deprecated, "Enable/disable jabber debugging"); static struct ast_cli_entry aji_cli[] = { - AST_CLI_DEFINE(aji_do_set_debug, "Enable/Disable Jabber debug", .deprecate_cmd = &cli_aji_do_debug_deprecated), + AST_CLI_DEFINE(aji_do_set_debug, "Enable/Disable Jabber debug"), AST_CLI_DEFINE(aji_do_reload, "Reload Jabber configuration"), AST_CLI_DEFINE(aji_show_clients, "Show state of clients and components"), AST_CLI_DEFINE(aji_show_buddies, "Show buddy lists of our clients"), @@ -155,8 +274,8 @@ " If not in roster variable will be set to 7\n\n" "Note: This application is deprecated. Please use the JABBER_STATUS() function instead.\n"; -struct aji_client_container clients; -struct aji_capabilities *capabilities = NULL; +static struct aji_client_container clients; +static struct aji_capabilities *capabilities = NULL; /*! \brief Global flags, initialized to default values */ static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER }; @@ -212,7 +331,7 @@ * \param pak struct The XML stanza we're processing * \return a pointer to the added or found aji_version structure */ -static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak) +static struct aji_version *aji_find_version(char *node, char *version, char *ext, ikspak *pak) { struct aji_capabilities *list = NULL; struct aji_version *res = NULL; @@ -227,8 +346,9 @@ if(!strcasecmp(list->node, node)) { res = list->versions; while(res) { - if(!strcasecmp(res->version, version)) + if(!strcasecmp(res->version, version)) { return res; + } res = res->next; } /* Specified version not found. Let's add it to @@ -242,6 +362,7 @@ res->jingle = 0; res->parent = list; ast_copy_string(res->version, version, sizeof(res->version)); + ast_copy_string(res->ext, ext ? ext : "none", sizeof(res->ext)); res->next = list->versions; list->versions = res; return res; @@ -264,6 +385,7 @@ } ast_copy_string(list->node, node, sizeof(list->node)); ast_copy_string(res->version, version, sizeof(res->version)); + ast_copy_string(res->ext, ext ? ext : "none", sizeof(res->ext)); res->jingle = 0; res->parent = list; res->next = NULL; @@ -301,8 +423,16 @@ */ static int gtalk_yuck(iks *node) { - if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) + if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { + ast_debug(1, "Found resource with Googletalk voice capabilities\n"); + return 1; + } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { + ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); + return 1; + } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { + ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); return 1; + } return 0; } @@ -364,7 +494,7 @@ ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); if (!data) { - ast_log(LOG_ERROR, "Usage: JabberStatus(,[/],\n"); + ast_log(LOG_ERROR, "Usage: JabberStatus(,[/],\n"); return 0; } s = ast_strdupa(data); @@ -880,6 +1010,21 @@ } pak = iks_packet(node); + /* work around iksemel's impossibility to recognize node names + * containing a semicolon. Set the namespace of the corresponding + * node accordingly. */ + if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) { + char *node_ns = NULL; + char attr[AJI_MAX_ATTRLEN]; + char *node_name = iks_name(iks_child(node)); + char *aux = strchr(node_name, ':') + 1; + snprintf(attr, strlen("xmlns:") + aux - node_name, "xmlns:%s", node_name); + node_ns = iks_find_attrib(iks_child(node), attr); + if (node_ns) { + pak->ns = node_ns; + pak->query = iks_child(node); + } + } if (!client->component) { /*client */ switch (type) { @@ -1527,7 +1672,8 @@ struct aji_buddy *buddy; struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; char *ver, *node, *descrip, *type; - + char *ext = NULL; + if(client->state != AJI_CONNECTED) aji_create_buddy(pak->from->partial, client); @@ -1663,19 +1809,23 @@ node = iks_find_attrib(iks_find(pak->x, "c"), "node"); ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); + ext = iks_find_attrib(iks_find(pak->x, "c"), "ext"); /* handle gmail client's special caps:c tag */ - if (!node && !ver) { + if (!node && !ver && !ext) { node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); + ext = iks_find_attrib(iks_find(pak->x, "caps:c"), "ext"); } /* retrieve capabilites of the new resource */ if(status !=6 && found && !found->cap) { - found->cap = aji_find_version(node, ver, pak); - if(gtalk_yuck(pak->x)) /* gtalk should do discover */ + found->cap = aji_find_version(node, ver, ext, pak); + if(gtalk_yuck(pak->x)) {/* gtalk should do discover */ found->cap->jingle = 1; - if(found->cap->jingle && option_debug > 4) { + } + + if(found->cap->jingle) { ast_debug(1,"Special case for google till they support discover.\n"); } else { @@ -2081,7 +2231,7 @@ ASTOBJ_RDLOCK(iterator); /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never * be called at the same time */ - if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { + if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ res = ast_aji_send(client, 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")); @@ -2331,7 +2481,7 @@ iks *presence = iks_make_pres(level, desc); iks *cnode = iks_new("c"); iks *priority = iks_new("priority"); - char priorityS[10]; + char priorityS[AJI_MAX_ATTRLEN]; if (presence && cnode && client && priority) { if(to) @@ -2343,7 +2493,9 @@ iks_insert_node(presence, priority); 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"); + if (ast_module_check("chan_gtalk.so") || ast_module_check("chan_gtalk")) { + iks_insert_attrib(cnode, "ext", "camera-v1 video-v1 voice-v1"); + } iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); iks_insert_node(presence, cnode); res = ast_aji_send(client, presence); @@ -2396,46 +2548,6 @@ } /*! - * \brief Turn on/off console debugging (deprecated, use aji_do_set_debug). - * \return CLI_SUCCESS. - */ -static char *aji_do_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) -{ - - switch (cmd) { - case CLI_INIT: - e->command = "jabber debug [off]"; - e->usage = - "Usage: jabber debug [off]\n" - " Enables/disables dumping of Jabber packets for debugging purposes.\n"; - return NULL; - case CLI_GENERATE: - return NULL; - } - - if (a->argc == 2) { - ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { - ASTOBJ_RDLOCK(iterator); - iterator->debug = 1; - ASTOBJ_UNLOCK(iterator); - }); - ast_cli(a->fd, "Jabber Debugging Enabled.\n"); - return CLI_SUCCESS; - } else if (a->argc == 3) { - if (!strncasecmp(a->argv[2], "off", 3)) { - ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { - ASTOBJ_RDLOCK(iterator); - iterator->debug = 0; - ASTOBJ_UNLOCK(iterator); - }); - ast_cli(a->fd, "Jabber Debugging Disabled.\n"); - return CLI_SUCCESS; - } - } - return CLI_SHOWUSAGE; /* defaults to invalid */ -} - -/*! * \brief Reload jabber module. * \return CLI_SUCCESS. */ @@ -2774,14 +2886,6 @@ } else { iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); } - if (!strchr(client->user, '/') && !client->component) { /*client */ - resource = NULL; - if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { - client->jid = iks_id_new(client->stack, resource); - ast_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); @@ -3028,7 +3132,7 @@ static int unload_module(void) { - ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); + ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); ast_unregister_application(app_ajisend); ast_unregister_application(app_ajistatus); ast_manager_unregister("JabberSend");