--- /Users/jcovert/Desktop/Gtalk/chan_gtalk.c.1.6.1.head.c 2009-10-09 12:24:15.000000000 -0400 +++ /Users/jcovert/Desktop/Gtalk/chan_gtalk.c.1.6.1.gtalk-web.c 2009-10-13 19:23:29.000000000 -0400 @@ -66,12 +66,10 @@ #include "asterisk/astobj.h" #include "asterisk/abstract_jb.h" #include "asterisk/jabber.h" +#include "asterisk/jingle.h" #define GOOGLE_CONFIG "gtalk.conf" -#define GOOGLE_NS "http://www.google.com/session" - - /*! Global jitterbuffer configuration - by default, jb is disabled */ static struct ast_jb_conf default_jbconf = { @@ -93,6 +91,12 @@ AJI_CONNECT_RELAY = 3, }; +enum gtalk_client_type { + AJI_CLIENT_UNKNOWN, + AJI_CLIENT_GTALK, /*!< Remote client type is GoogleTalk */ + AJI_CLIENT_GMAIL, /*!< Remote client type is Gmail */ +}; + struct gtalk_pvt { ast_mutex_t lock; /*!< Channel private lock */ time_t laststun; @@ -103,6 +107,7 @@ char ring[10]; /*!< Message ID of ring */ iksrule *ringrule; /*!< Rule for matching RING request */ int initiator; /*!< If we're the initiator */ + enum gtalk_client_type ctype; int alreadygone; int capability; struct ast_codec_pref prefs; @@ -428,7 +433,7 @@ iks_insert_attrib(iq, "id", client->connection->mid); ast_aji_increment_mid(client->connection->mid); - iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session"); + iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS); iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept"); /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ @@ -484,7 +489,7 @@ while (((c = *t) != '/') && (*t++ = tolower(c))); } iks_insert_attrib(session, "initiator", initiator ? from : lowerto); - iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); + iks_insert_attrib(session, "xmlns", GOOGLE_NS); iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p"); iks_insert_node(iq,session); iks_insert_node(session,transport); @@ -609,9 +614,17 @@ ast_log(LOG_DEBUG, "The client is %s\n", client->name); /* Make sure our new call doesn't exist yet */ - for (tmp = client->p; tmp; tmp = tmp->next) { - if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) - break; + char *ses, *seses[] = {"session", "ses:session", 0}; + for (ses = seses[0] ; ses ; ses++) { + for (tmp = client->p; tmp; tmp = tmp->next) { + if (iks_find_with_attrib(pak->x, ses, "id", tmp->sid)) + break; + } + if (tmp != 0) break; + } + if (tmp == 0) { + ast_log(LOG_WARNING, "Could not find session in iq\n"); + return -1; } /* codec points to the first tag */ @@ -752,7 +765,7 @@ ast_debug(1, "The client is %s\n", client->name); /* Make sure our new call doesn't exist yet */ for (tmp = client->p; tmp; tmp = tmp->next) { - if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) + if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid)) break; } from = iks_find_attrib(pak->x, "to"); @@ -774,7 +787,7 @@ struct gtalk_candidate *tmp; struct aji_client *c = client->connection; struct gtalk_candidate *ours1 = NULL, *ours2 = NULL; - struct sockaddr_in sin; + struct sockaddr_in sin = { 0, }; struct sockaddr_in dest; struct in_addr us; iks *iq, *gtalk, *candidate, *transport; @@ -797,9 +810,12 @@ iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p"); iks_insert_node(iq, gtalk); - iks_insert_node(gtalk,transport); - iks_insert_node(transport, candidate); - + if (p->ctype == AJI_CLIENT_GMAIL) { + iks_insert_node(gtalk,candidate); + } else { + iks_insert_node(gtalk,transport); + iks_insert_node(transport, candidate); + } for (; p; p = p->next) { if (!strcasecmp(p->sid, sid)) break; @@ -859,7 +875,18 @@ iks_insert_attrib(iq, "type", "set"); iks_insert_attrib(iq, "id", c->mid); ast_aji_increment_mid(c->mid); - iks_insert_attrib(gtalk, "type", "transport-info"); + switch (p->ctype) { + case AJI_CLIENT_GTALK: + iks_insert_attrib(gtalk, "type", "transport-info"); + break; + case AJI_CLIENT_GMAIL: + iks_insert_attrib(gtalk, "type", "candidates"); + break; + default: + ast_log(LOG_WARNING, "Client type is unknown\n"); + iks_insert_attrib(gtalk, "type", "transport-info"); + break; + } iks_insert_attrib(gtalk, "id", sid); /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ @@ -937,6 +964,8 @@ if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { return NULL; } + /* set client type to unknown until we have more info */ + tmp->ctype = AJI_CLIENT_UNKNOWN; memcpy(&tmp->prefs, &client->prefs, sizeof(struct ast_codec_pref)); @@ -1099,7 +1128,7 @@ while (((c = *t) != '/') && (*t++ = tolower(c))); } iks_insert_attrib(session, "initiator", p->initiator ? p->us : lowerthem); - iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); + iks_insert_attrib(session, "xmlns", GOOGLE_NS); iks_insert_node(request, session); ast_aji_send(client->connection, request); res = 0; @@ -1166,7 +1195,7 @@ from = client->connection->jid->full; while (tmp) { - if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { + if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid)) { ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); gtalk_response(client, from, pak, "out-of-order", NULL); return -1; @@ -1190,6 +1219,14 @@ return -1; } + /* if the node name of the query contains a semicolon, the remote peer + * is a gmail type client. If not, treat it as a regular GoogleTalk + * client */ + if (strchr(iks_name(pak->query), ':')) { + p->ctype = AJI_CLIENT_GMAIL; + } else { + p->ctype = AJI_CLIENT_GTALK; + } chan = gtalk_new(client, p, AST_STATE_DOWN, pak->from->user); if (!chan) { gtalk_free_pvt(client, p); @@ -1207,8 +1244,14 @@ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); while (codec) { - ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); - ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); + ast_log(LOG_NOTICE, "iks_name(codec) : %s\n", iks_name(codec)); + if (!strcmp(iks_name(codec), "vid:payload-type")) { + ast_rtp_set_m_type(p->vrtp, atoi(iks_find_attrib(codec, "id"))); + ast_rtp_set_rtpmap_type(p->vrtp, atoi(iks_find_attrib(codec, "id")), "video", iks_find_attrib(codec, "name"), 0); + } else { + ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); + ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); + } codec = iks_next_tag(codec); } @@ -1243,7 +1286,9 @@ break; case AST_PBX_SUCCESS: gtalk_response(client, from, pak, NULL, NULL); - gtalk_invite_response(p, p->them, p->us,p->sid, 0); + if (p->ctype == AJI_CLIENT_GTALK) { + gtalk_invite_response(p, p->them, p->us,p->sid, 0); + } gtalk_create_candidates(client, p, p->sid, p->them, p->us); /* nothing to do */ break; @@ -1257,8 +1302,8 @@ struct gtalk_candidate *tmp; struct hostent *hp; struct ast_hostent ahp; - struct sockaddr_in sin; - struct sockaddr_in aux; + struct sockaddr_in sin = { 0, }; + struct sockaddr_in aux = { 0, }; if (time(NULL) == p->laststun) return 0; @@ -1311,7 +1356,7 @@ from = c->jid->full; for (tmp = client->p; tmp; tmp = tmp->next) { - if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) { + if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || !strcmp(iks_find_attrib(pak->query, "id"), tmp->sid)) { p = tmp; break; } @@ -1326,11 +1371,15 @@ traversenodes = iks_first_tag(traversenodes); continue; } + if(!strcasecmp(iks_name(traversenodes), "ses:session")) { + traversenodes = iks_child(traversenodes); + continue; + } if(!strcasecmp(iks_name(traversenodes), "transport")) { traversenodes = iks_first_tag(traversenodes); continue; } - if(!strcasecmp(iks_name(traversenodes), "candidate")) { + if(!strcasecmp(iks_name(traversenodes), "candidate") || !strcasecmp(iks_name(traversenodes), "ses:candidate")) { newcandidate = ast_calloc(1, sizeof(*newcandidate)); if (!newcandidate) return 0; @@ -1763,26 +1812,31 @@ static int gtalk_parser(void *data, ikspak *pak) { struct gtalk *client = ASTOBJ_REF((struct gtalk *) data); + int res; if (iks_find_attrib(pak->x, "type") && !strcmp(iks_find_attrib (pak->x, "type"),"error")) { ast_log(LOG_NOTICE, "Remote peer reported an error, trying to establish the call anyway\n"); } - else if (iks_find_with_attrib(pak->x, "session", "type", "initiate")) { + else if (!strcmp(iks_find_attrib(pak->query, "type"), "initiate")) { /* New call */ gtalk_newcall(client, pak); - } else if (iks_find_with_attrib(pak->x, "session", "type", "candidates") || iks_find_with_attrib(pak->x, "session", "type", "transport-info")) { + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "candidates") || !strcmp(iks_find_attrib(pak->query, "type"), "transport-info")) { ast_debug(3, "About to add candidate!\n"); - gtalk_add_candidate(client, pak); - ast_debug(3, "Candidate Added!\n"); - } else if (iks_find_with_attrib(pak->x, "session", "type", "accept")) { + res = gtalk_add_candidate(client, pak); + if (!res) { + ast_log(LOG_WARNING, "Could not add any candidate\n"); + } else { + ast_debug(3, "Candidate Added!\n"); + } + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "accept")) { gtalk_is_answered(client, pak); - } else if (iks_find_with_attrib(pak->x, "session", "type", "transport-accept")) { + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "transport-accept")) { gtalk_is_accepted(client, pak); - } else if (iks_find_with_attrib(pak->x, "session", "type", "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "content-info") || iks_find_with_attrib(pak->x, "gtalk", "action", "session-info")) { gtalk_handle_dtmf(client, pak); - } else if (iks_find_with_attrib(pak->x, "session", "type", "terminate")) { + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "terminate")) { gtalk_hangup_farend(client, pak); - } else if (iks_find_with_attrib(pak->x, "session", "type", "reject")) { + } else if (!strcmp(iks_find_attrib(pak->query, "type"), "reject")) { gtalk_hangup_farend(client, pak); } ASTOBJ_UNREF(client, gtalk_member_destroy); @@ -1879,7 +1933,7 @@ iks_filter_add_rule(client->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_FROM_PARTIAL, member->user, - IKS_RULE_NS, "http://www.google.com/session", + IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE); } else { @@ -2000,7 +2054,7 @@ ASTOBJ_WRLOCK(iterator); ASTOBJ_WRLOCK(member); member->connection = NULL; - iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://www.google.com/session", IKS_RULE_DONE); + iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE); iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE); ASTOBJ_UNLOCK(member); ASTOBJ_UNLOCK(iterator);