diff options
author | lmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-10-07 16:51:23 +0000 |
---|---|---|
committer | lmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-10-07 16:51:23 +0000 |
commit | 533e04bb23ff2d532ed9df6eeaf8bc4b6cc86209 (patch) | |
tree | b752d1dab2c00d256ae804c744d645b81d4e9d11 | |
parent | 06acc1b52254c01a885cb73f9e0b4af96e3f7543 (diff) | |
parent | 66afa1aec386d92340077b44a43f0e627ba8651a (diff) |
Creating tag for the release of asterisk-1.8.0-rc3
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.8.0-rc3@290745 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_dial.c | 3 | ||||
-rw-r--r-- | apps/app_directed_pickup.c | 28 | ||||
-rw-r--r-- | channels/chan_gtalk.c | 290 | ||||
-rw-r--r-- | channels/chan_iax2.c | 332 | ||||
-rw-r--r-- | include/asterisk/jabber.h | 1 | ||||
-rw-r--r-- | include/asterisk/jingle.h | 3 | ||||
-rw-r--r-- | main/file.c | 8 | ||||
-rw-r--r-- | main/pbx.c | 11 | ||||
-rw-r--r-- | res/res_jabber.c | 40 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 5 |
10 files changed, 455 insertions, 266 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index 51dacb6db..bb589a8ca 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1404,8 +1404,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, if ((f->subclass.integer == AST_CONTROL_HOLD) || (f->subclass.integer == AST_CONTROL_UNHOLD) || (f->subclass.integer == AST_CONTROL_VIDUPDATE) || - (f->subclass.integer == AST_CONTROL_SRCUPDATE) || - (f->subclass.integer == AST_CONTROL_REDIRECTING)) { + (f->subclass.integer == AST_CONTROL_SRCUPDATE)) { ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass.integer, outgoing->chan->name); ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) { diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index bcefb0661..3914e0d8e 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -179,18 +179,24 @@ static struct ast_channel *my_ast_get_channel_by_name_locked(const char *channam char *chkchan; struct pickup_by_name_args pickup_args; - pickup_args.len = strlen(channame) + 1; - - chkchan = alloca(pickup_args.len + 1); - - /* need to append a '-' for the comparison so we check full channel name, - * i.e SIP/hgc- , use a temporary variable so original stays the same for - * debugging. + /* Check if channel name contains a '-'. + * In this case the channel name will be interpreted as full channel name. */ - strcpy(chkchan, channame); - strcat(chkchan, "-"); - - pickup_args.name = chkchan; + if (strchr(channame, '-')) { + /* check full channel name */ + pickup_args.len = strlen(channame); + pickup_args.name = channame; + } else { + /* need to append a '-' for the comparison so we check full channel name, + * i.e SIP/hgc- , use a temporary variable so original stays the same for + * debugging. + */ + pickup_args.len = strlen(channame) + 1; + chkchan = alloca(pickup_args.len + 1); + strcpy(chkchan, channame); + strcat(chkchan, "-"); + pickup_args.name = chkchan; + } return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0); } diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 47eed7e08..011d21d80 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -21,7 +21,7 @@ * \author Matt O'Gorman <mogorman@digium.com> * * \brief Gtalk Channel Driver, until google/libjingle works with jingle spec - * + * * \ingroup channel_drivers */ @@ -67,12 +67,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #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 = { @@ -95,6 +93,12 @@ enum gtalk_connect_type { 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; @@ -105,6 +109,7 @@ struct gtalk_pvt { 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; @@ -168,7 +173,7 @@ AST_MUTEX_DEFINE_STATIC(gtalklock); /*!< Protect the interface list (of gtalk_pv /* Forward declarations */ static struct ast_channel *gtalk_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause); -static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration); +/*static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);*/ static int gtalk_sendtext(struct ast_channel *ast, const char *text); static int gtalk_digit_begin(struct ast_channel *ast, char digit); static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration); @@ -196,7 +201,10 @@ static const struct ast_channel_tech gtalk_tech = { .send_text = gtalk_sendtext, .send_digit_begin = gtalk_digit_begin, .send_digit_end = gtalk_digit_end, - .bridge = ast_rtp_instance_bridge, + /* XXX TODO native bridging is causing odd problems with DTMF pass-through with + * the gtalk servers. Enable native bridging once the source of this problem has + * been identified. + .bridge = ast_rtp_instance_bridge, */ .call = gtalk_call, .hangup = gtalk_hangup, .answer = gtalk_answer, @@ -243,7 +251,7 @@ static struct gtalk *find_gtalk(char *name, char *connection) if (!gtalk && strchr(name, '@')) gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp); - if (!gtalk) { + if (!gtalk) { /* guest call */ ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, { ASTOBJ_RDLOCK(iterator); @@ -270,7 +278,7 @@ static int add_codec_to_answer(const struct gtalk_pvt *p, int codec, iks *dcodec iks *payload_eg711u, *payload_pcmu; payload_pcmu = iks_new("payload-type"); payload_eg711u = iks_new("payload-type"); - + if(!payload_eg711u || !payload_pcmu) { iks_delete(payload_pcmu); iks_delete(payload_eg711u); @@ -387,11 +395,11 @@ static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, in iks_delete(dcodecs); iks_delete(transport); iks_delete(payload_telephone); - + ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n"); return 0; } - iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone"); + iks_insert_attrib(dcodecs, "xmlns", GOOGLE_AUDIO_NS); iks_insert_attrib(dcodecs, "xml:lang", "en"); for (x = 0; x < 64; x++) { @@ -404,24 +412,24 @@ static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, in codecs_num = add_codec_to_answer(p, pref_codec, dcodecs); alreadysent |= pref_codec; } - + if (codecs_num) { /* only propose DTMF within an audio session */ - iks_insert_attrib(payload_telephone, "id", "106"); + iks_insert_attrib(payload_telephone, "id", "101"); iks_insert_attrib(payload_telephone, "name", "telephone-event"); iks_insert_attrib(payload_telephone, "clockrate", "8000"); } - iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p"); - + iks_insert_attrib(transport,"xmlns",GOOGLE_TRANSPORT_NS); + iks_insert_attrib(iq, "type", "set"); iks_insert_attrib(iq, "to", to); iks_insert_attrib(iq, "from", from); 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 + /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ if (!initiator) { char c; @@ -467,7 +475,7 @@ static int gtalk_invite_response(struct gtalk_pvt *p, char *to , char *from, cha ast_aji_increment_mid(p->parent->connection->mid); iks_insert_attrib(session, "type", "transport-accept"); iks_insert_attrib(session, "id", sid); - /* put the initiator attribute to lower case if we receive the call + /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ if (!initiator) { char c; @@ -475,8 +483,8 @@ static int gtalk_invite_response(struct gtalk_pvt *p, char *to , char *from, cha 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(transport, "xmlns", "http://www.google.com/transport/p2p"); + iks_insert_attrib(session, "xmlns", GOOGLE_NS); + iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS); iks_insert_node(iq,session); iks_insert_node(session,transport); ast_aji_send(p->parent->connection, iq); @@ -504,11 +512,11 @@ static int gtalk_answer(struct ast_channel *ast) { struct gtalk_pvt *p = ast->tech_pvt; int res = 0; - + ast_debug(1, "Answer!\n"); ast_mutex_lock(&p->lock); gtalk_invite(p, p->them, p->us,p->sid, 0); - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", + manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", ast->name, "GTALK", p->sid); ast_mutex_unlock(&p->lock); return res; @@ -600,17 +608,26 @@ static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const c static int gtalk_is_answered(struct gtalk *client, ikspak *pak) { - struct gtalk_pvt *tmp; + struct gtalk_pvt *tmp = NULL; char *from; iks *codec; char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; int peernoncodeccapability; ast_log(LOG_DEBUG, "The client is %s\n", client->name); - /* Make sure our new call doesn't exist yet */ + + /* Make sure our new call does exist */ 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)) { + break; + } else if (iks_find_with_attrib(pak->x, "ses:session", "id", tmp->sid)) { break; + } + } + + if (tmp == 0) { + ast_log(LOG_WARNING, "Could not find session in iq\n"); + return -1; } /* codec points to the first <payload-type/> tag */ @@ -620,10 +637,10 @@ static int gtalk_is_answered(struct gtalk *client, ikspak *pak) ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); codec = iks_next_tag(codec); } - + /* Now gather all of the codecs that we are asked for */ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), &tmp->peercapability, &peernoncodeccapability); - + /* at this point, we received an awser from the remote Gtalk client, which allows us to compare capabilities */ tmp->jointcapability = tmp->capability & tmp->peercapability; @@ -636,8 +653,8 @@ static int gtalk_is_answered(struct gtalk *client, ikspak *pak) return -1; - } - + } + from = iks_find_attrib(pak->x, "to"); if(!from) from = client->connection->jid->full; @@ -751,7 +768,7 @@ static int gtalk_hangup_farend(struct gtalk *client, ikspak *pak) 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"); @@ -796,11 +813,14 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch if (!ours1 || !ours2) goto safeout; - iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p"); + iks_insert_attrib(transport, "xmlns",GOOGLE_TRANSPORT_NS); 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; @@ -863,9 +883,20 @@ static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, ch 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", "candidates"); + break; + } iks_insert_attrib(gtalk, "id", sid); - /* put the initiator attribute to lower case if we receive the call + /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ if (!p->initiator) { char c; @@ -922,19 +953,22 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const if (!sid && !strchr(them, '/')) { /* I started call! */ if (!strcasecmp(client->name, "guest")) { buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, them); - if (buddy) + if (buddy) { resources = buddy->resources; - } else if (client->buddy) + } + } else if (client->buddy) { resources = client->buddy->resources; + } + while (resources) { if (resources->cap->jingle) { break; } resources = resources->next; } - if (resources) + if (resources) { snprintf(idroster, sizeof(idroster), "%s/%s", them, resources->resource); - else { + } else { ast_log(LOG_ERROR, "no gtalk capable clients to talk to.\n"); return NULL; } @@ -942,6 +976,8 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const 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)); @@ -956,6 +992,7 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const tmp->initiator = 1; } /* clear codecs */ + bindaddr.sin_family = AF_INET; ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); if (!(tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL))) { ast_log(LOG_ERROR, "Failed to create a new RTP instance (possibly an invalid bindaddr?)\n"); @@ -963,6 +1000,8 @@ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const return NULL; } ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1); + ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_DTMF, 1); + ast_rtp_instance_dtmf_mode_set(tmp->rtp, AST_RTP_DTMF_MODE_RFC2833); ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp); /* add user configured codec capabilites */ @@ -1104,7 +1143,7 @@ static int gtalk_action(struct gtalk *client, struct gtalk_pvt *p, const char *a if (session) { iks_insert_attrib(session, "type", action); iks_insert_attrib(session, "id", p->sid); - /* put the initiator attribute to lower case if we receive the call + /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ if (!p->initiator) { char c; @@ -1112,7 +1151,7 @@ static int gtalk_action(struct gtalk *client, struct gtalk_pvt *p, const char *a 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; @@ -1177,9 +1216,9 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) from = iks_find_attrib(pak->x,"to"); if(!from) 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; @@ -1187,15 +1226,15 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) tmp = tmp->next; } - if (!strcasecmp(client->name, "guest")){ - /* the guest account is not tied to any configured XMPP client, - let's set it now */ - client->connection = ast_aji_get_client(from); - if (!client->connection) { - ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); - return -1; - } - } + if (!strcasecmp(client->name, "guest")){ + /* the guest account is not tied to any configured XMPP client, + let's set it now */ + client->connection = ast_aji_get_client(from); + if (!client->connection) { + ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); + return -1; + } + } p = gtalk_alloc(client, from, pak->from->full, iks_find_attrib(pak->query, "id")); if (!p) { @@ -1203,6 +1242,14 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) 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, NULL); if (!chan) { gtalk_free_pvt(client, p); @@ -1216,20 +1263,25 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) sizeof(p->sid)); } - /* codec points to the first <payload-type/> tag */ + /* codec points to the first <payload-type/> tag */ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x))); - + while (codec) { - ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); - ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); + if (!strcmp(iks_name(codec), "vid:payload-type") && p->vrtp) { + ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->vrtp), p->vrtp, atoi(iks_find_attrib(codec, "id"))); + ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->vrtp), p->vrtp, atoi(iks_find_attrib(codec, "id")), "video", iks_find_attrib(codec, "name"), 0); + } else { + ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); + ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); + } codec = iks_next_tag(codec); } - + /* Now gather all of the codecs that we are asked for */ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), &p->peercapability, &peernoncodeccapability); p->jointcapability = p->capability & p->peercapability; ast_mutex_unlock(&p->lock); - + ast_setstate(chan, AST_STATE_RING); if (!p->jointcapability) { ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->capability), @@ -1241,10 +1293,10 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) gtalk_hangup(chan); ast_channel_release(chan); return -1; - } + } res = ast_pbx_start(chan); - + switch (res) { case AST_PBX_FAILED: ast_log(LOG_WARNING, "Failed to start PBX :(\n"); @@ -1256,7 +1308,9 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak) 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; @@ -1288,9 +1342,8 @@ static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p) sin.sin_family = AF_INET; memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); sin.sin_port = htons(tmp->port); - snprintf(username, sizeof(username), "%s%s", tmp->username, - p->ourcandidates->username); - + snprintf(username, sizeof(username), "%s%s", tmp->username, p->ourcandidates->username); + /* Find out the result of the STUN */ ast_rtp_instance_get_remote_address(p->rtp, &aux_tmp); ast_sockaddr_to_sin(&aux_tmp, &aux); @@ -1298,12 +1351,12 @@ static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p) /* If the STUN result is different from the IP of the hostname, lock on the stun IP of the hostname advertised by the remote client */ - if (aux.sin_addr.s_addr && - aux.sin_addr.s_addr != sin.sin_addr.s_addr) + if (aux.sin_addr.s_addr && (aux.sin_addr.s_addr != sin.sin_addr.s_addr)) { ast_rtp_instance_stun_request(p->rtp, &aux_tmp, username); - else + } else { + ast_sockaddr_from_sin(&sin_tmp, &sin); ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username); - + } if (aux.sin_addr.s_addr) { ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip); ast_debug(4, "Sending STUN request to %s\n", tmp->ip); @@ -1327,26 +1380,30 @@ static int gtalk_add_candidate(struct gtalk *client, ikspak *pak) 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; } } - if (!p) + if (!p) { return -1; - + } traversenodes = pak->query; while(traversenodes) { if(!strcasecmp(iks_name(traversenodes), "session")) { 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; @@ -1364,7 +1421,7 @@ static int gtalk_add_candidate(struct gtalk *client, ikspak *pak) newcandidate->protocol = AJI_PROTOCOL_UDP; if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) newcandidate->protocol = AJI_PROTOCOL_SSLTCP; - + if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun")) newcandidate->type = AJI_CONNECT_STUN; if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local")) @@ -1375,7 +1432,7 @@ static int gtalk_add_candidate(struct gtalk *client, ikspak *pak) sizeof(newcandidate->network)); newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); newcandidate->next = NULL; - + newcandidate->next = p->theircandidates; p->theircandidates = newcandidate; p->laststun = 0; @@ -1384,7 +1441,7 @@ static int gtalk_add_candidate(struct gtalk *client, ikspak *pak) } traversenodes = iks_next_tag(traversenodes); } - + receipt = iks_new("iq"); iks_insert_attrib(receipt, "type", "result"); iks_insert_attrib(receipt, "from", from); @@ -1538,14 +1595,40 @@ static int gtalk_sendtext(struct ast_channel *chan, const char *text) static int gtalk_digit_begin(struct ast_channel *chan, char digit) { - return gtalk_digit(chan, digit, 0); + struct gtalk_pvt *p = chan->tech_pvt; + int res = 0; + + ast_mutex_lock(&p->lock); + if (p->rtp) { + ast_rtp_instance_dtmf_begin(p->rtp, digit); + } else { + res = -1; + } + ast_mutex_unlock(&p->lock); + + return res; } static int gtalk_digit_end(struct ast_channel *chan, char digit, unsigned int duration) { - return gtalk_digit(chan, digit, duration); + struct gtalk_pvt *p = chan->tech_pvt; + int res = 0; + + ast_mutex_lock(&p->lock); + if (p->rtp) { + ast_rtp_instance_dtmf_end_with_duration(p->rtp, digit, duration); + } else { + res = -1; + } + ast_mutex_unlock(&p->lock); + + return res; } +/* This function is of not in use at the moment, but I am choosing to leave this + * within the code base as a reference to how DTMF is possible through + * jingle signaling. However, google currently does DTMF through the RTP. */ +#if 0 static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration) { struct gtalk_pvt *p = ast->tech_pvt; @@ -1571,7 +1654,7 @@ static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duratio ast_aji_increment_mid(client->connection->mid); iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk"); iks_insert_attrib(gtalk, "action", "session-info"); - /* put the initiator attribute to lower case if we receive the call + /* put the initiator attribute to lower case if we receive the call * otherwise GoogleTalk won't establish the session */ if (!p->initiator) { char c; @@ -1599,6 +1682,7 @@ static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duratio ast_mutex_unlock(&p->lock); return 0; } +#endif static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen) { @@ -1625,8 +1709,8 @@ static int gtalk_auto_congest(void *nothing) } */ -/*! \brief Initiate new call, part of PBX interface - * dest is the dial string */ +/*!\brief Initiate new call, part of PBX interface + * dest is the dial string */ static int gtalk_call(struct ast_channel *ast, char *dest, int timeout) { struct gtalk_pvt *p = ast->tech_pvt; @@ -1670,7 +1754,7 @@ static int gtalk_hangup(struct ast_channel *ast) return 0; } -/*! \brief Part of PBX interface */ +/*!\brief Part of PBX interface */ static struct ast_channel *gtalk_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) { struct gtalk_pvt *p = NULL; @@ -1706,7 +1790,7 @@ static struct ast_channel *gtalk_request(const char *type, format_t format, cons return NULL; } } - + ASTOBJ_WRLOCK(client); p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL); if (p) @@ -1758,14 +1842,14 @@ static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl resource ++; } if (chan) - ast_cli(a->fd, FORMAT, + ast_cli(a->fd, FORMAT, chan->name, jid, resource, ast_getformatname(chan->readformat), - ast_getformatname(chan->writeformat) + ast_getformatname(chan->writeformat) ); - else + else ast_log(LOG_WARNING, "No available channel\n"); numchans ++; p = p->next; @@ -1792,8 +1876,8 @@ static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_ar return NULL; case CLI_GENERATE: return NULL; - } - + } + ast_verbose("IT DOES WORK!\n"); return CLI_SUCCESS; } @@ -1801,26 +1885,30 @@ static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_ar 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); @@ -1914,10 +2002,10 @@ static int gtalk_create_member(char *label, struct ast_variable *var, int allowg else if (!strcasecmp(var->name, "connection")) { if ((client = ast_aji_get_client(var->value))) { member->connection = client; - iks_filter_add_rule(client->f, gtalk_parser, member, - IKS_RULE_TYPE, IKS_PAK_IQ, + 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 { @@ -2042,7 +2130,7 @@ static int gtalk_load_config(void) 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); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 03e4b8b80..5f962155d 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -91,6 +91,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/taskprocessor.h" #include "asterisk/test.h" #include "asterisk/data.h" +#include "asterisk/netsock2.h" #include "iax2.h" #include "iax2-parser.h" @@ -502,7 +503,7 @@ struct iax2_peer { ); struct ast_codec_pref prefs; struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */ - struct sockaddr_in addr; + struct ast_sockaddr addr; int formats; int sockfd; /*!< Socket to use for transmission */ struct in_addr mask; @@ -593,7 +594,7 @@ enum iax_transfer_state { }; struct iax2_registry { - struct sockaddr_in addr; /*!< Who we connect to for registration purposes */ + struct ast_sockaddr addr; /*!< Who we connect to for registration purposes */ char username[80]; char secret[80]; /*!< Password or key name in []'s */ int expire; /*!< Sched ID of expiration */ @@ -1194,7 +1195,7 @@ static struct ast_channel *iax2_request(const char *type, format_t format, const static struct ast_frame *iax2_read(struct ast_channel *c); static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); -static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, time_t regtime); +static void realtime_update_peer(const char *peername, struct ast_sockaddr *sockaddr, time_t regtime); static void *iax2_dup_variable_datastore(void *); static void prune_peers(void); static void prune_users(void); @@ -1736,8 +1737,12 @@ static int iax2_getpeername(struct sockaddr_in sin, char *host, int len) i = ao2_iterator_init(peers, 0); while ((peer = ao2_iterator_next(&i))) { - if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && - (peer->addr.sin_port == sin.sin_port)) { + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + + if ((peer_addr.sin_addr.s_addr == sin.sin_addr.s_addr) && + (peer_addr.sin_port == sin.sin_port)) { ast_copy_string(host, peer->name, len); peer_unref(peer); res = 1; @@ -2288,13 +2293,18 @@ static int prune_addr_range_cb(void *obj, void *arg, int flags) * \internal * \brief modifies peercnt entry in peercnts table. Used to set custom limit or mark a registered ip */ -static void peercnt_modify(unsigned char reg, uint16_t limit, struct sockaddr_in *sin) +static void peercnt_modify(unsigned char reg, uint16_t limit, struct ast_sockaddr *sockaddr) { /* this function turns off and on custom callno limits set by peer registration */ struct peercnt *peercnt; struct peercnt tmp = { - .addr = sin->sin_addr.s_addr, + .addr = 0, }; + struct sockaddr_in sin; + + ast_sockaddr_to_sin(sockaddr, &sin); + + tmp.addr = sin.sin_addr.s_addr; if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { peercnt->reg = reg; @@ -2303,7 +2313,7 @@ static void peercnt_modify(unsigned char reg, uint16_t limit, struct sockaddr_in } else { set_peercnt_limit(peercnt); } - ast_debug(1, "peercnt entry %s modified limit:%d registered:%d", ast_inet_ntoa(sin->sin_addr), peercnt->limit, peercnt->reg); + ast_debug(1, "peercnt entry %s modified limit:%d registered:%d", ast_inet_ntoa(sin.sin_addr), peercnt->limit, peercnt->reg); ao2_ref(peercnt, -1); /* decrement ref from find */ } } @@ -2901,8 +2911,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s return res; } -static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) { - +static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) { return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); } @@ -3739,6 +3748,10 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct peer = find_peer(a->argv[3], load_realtime); if (peer) { + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + encmethods_to_str(peer->encmethods, encmethods); ast_cli(a->fd, "\n\n"); ast_cli(a->fd, " * Name : %s\n", peer->name); @@ -3754,7 +3767,7 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); ast_cli(a->fd, " Expire : %d\n", peer->expire); ast_cli(a->fd, " ACL : %s\n", (peer->ha ? "Yes" : "No")); - ast_cli(a->fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); + ast_cli(a->fd, " Addr->IP : %s Port %d\n", peer_addr.sin_addr.s_addr ? ast_inet_ntoa(peer_addr.sin_addr) : "(Unspecified)", ntohs(peer_addr.sin_port)); ast_cli(a->fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); ast_cli(a->fd, " Username : %s\n", peer->username); ast_cli(a->fd, " Codecs : "); @@ -4355,9 +4368,9 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in } else if (!strcasecmp(tmp->name, "regseconds")) { ast_get_time_t(tmp->value, ®seconds, 0, NULL); } else if (!strcasecmp(tmp->name, "ipaddr")) { - inet_aton(tmp->value, &(peer->addr.sin_addr)); + ast_sockaddr_parse(&peer->addr, tmp->value, PARSE_PORT_IGNORE); } else if (!strcasecmp(tmp->name, "port")) { - peer->addr.sin_port = htons(atoi(tmp->value)); + ast_sockaddr_set_port(&peer->addr, atoi(tmp->value)); } else if (!strcasecmp(tmp->name, "host")) { if (!strcasecmp(tmp->value, "dynamic")) dynamic = 1; @@ -4477,7 +4490,7 @@ static struct iax2_user *realtime_user(const char *username, struct sockaddr_in return user; } -static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, time_t regtime) +static void realtime_update_peer(const char *peername, struct ast_sockaddr *sockaddr, time_t regtime) { char port[10]; char regseconds[20]; @@ -4490,9 +4503,9 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, syslabel = "regserver"; snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); - snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); + snprintf(port, sizeof(port), "%d", ast_sockaddr_port(sockaddr)); ast_update_realtime("iaxpeers", "name", peername, - "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, + "ipaddr", ast_sockaddr_stringify_addr(sockaddr), "port", port, "regseconds", regseconds, syslabel, sysname, SENTINEL); /* note syslable can be NULL */ } @@ -4522,6 +4535,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka struct iax2_peer *peer; int res = -1; struct ast_codec_pref ourprefs; + struct sockaddr_in peer_addr; ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK); cai->sockfd = defaultsockfd; @@ -4549,10 +4563,13 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka } cai->found = 1; - + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + /* if the peer has no address (current or default), return failure */ - if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) + if (!(peer_addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) { goto return_unref; + } /* if the peer is being monitored and is currently unreachable, return failure */ if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) @@ -4596,9 +4613,9 @@ static int create_addr(const char *peername, struct ast_channel *c, struct socka } } - if (peer->addr.sin_addr.s_addr) { - sin->sin_addr = peer->addr.sin_addr; - sin->sin_port = peer->addr.sin_port; + if (peer_addr.sin_addr.s_addr) { + sin->sin_addr = peer_addr.sin_addr; + sin->sin_port = peer_addr.sin_port; } else { sin->sin_addr = peer->defaddr.sin_addr; sin->sin_port = peer->defaddr.sin_port; @@ -5641,8 +5658,12 @@ static int iax2_getpeertrunk(struct sockaddr_in sin) i = ao2_iterator_init(peers, 0); while ((peer = ao2_iterator_next(&i))) { - if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && - (peer->addr.sin_port == sin.sin_port)) { + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + + if ((peer_addr.sin_addr.s_addr == sin.sin_addr.s_addr) && + (peer_addr.sin_port == sin.sin_port)) { res = ast_test_flag64(peer, IAX_TRUNK); peer_unref(peer); break; @@ -6637,11 +6658,16 @@ static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int char nm[20]; char status[20]; int retstatus; + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); - if (registeredonly && !peer->addr.sin_addr.s_addr) + if (registeredonly && !peer_addr.sin_addr.s_addr) { continue; - if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) + } + if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { continue; + } if (!ast_strlen_zero(peer->username)) snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); @@ -6673,18 +6699,18 @@ static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int "Status: %s\r\n\r\n", idtext, name, - peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", - ntohs(peer->addr.sin_port), + ast_sockaddr_stringify_addr(&peer->addr), + ast_sockaddr_port(&peer->addr), ast_test_flag64(peer, IAX_DYNAMIC) ? "yes" : "no", ast_test_flag64(peer, IAX_TRUNK) ? "yes" : "no", peer->encmethods ? ast_str_buffer(encmethods) : "no", status); } else { ast_cli(fd, FORMAT, name, - peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", + ast_sockaddr_stringify_addr(&peer->addr), ast_test_flag64(peer, IAX_DYNAMIC) ? "(D)" : "(S)", nm, - ntohs(peer->addr.sin_port), + ast_sockaddr_port(&peer->addr), ast_test_flag64(peer, IAX_TRUNK) ? "(T)" : " ", peer->encmethods ? "(E)" : " ", status); @@ -6960,10 +6986,10 @@ static int manager_iax2_show_peer_list(struct mansession *s, const struct messag astman_append(s, "ObjectName: %s\r\n", peer->name); } astman_append(s, "ChanObjectType: peer\r\n"); - astman_append(s, "IPaddress: %s\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-"); + astman_append(s, "IPaddress: %s\r\n", ast_sockaddr_stringify_addr(&peer->addr)); ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); astman_append(s, "Mask: %s\r\n", nm); - astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port)); + astman_append(s, "Port: %d\r\n", ast_sockaddr_port(&peer->addr)); astman_append(s, "Dynamic: %s\r\n", ast_test_flag64(peer, IAX_DYNAMIC) ? "Yes" : "No"); astman_append(s, "Trunk: %s\r\n", ast_test_flag64(peer, IAX_TRUNK) ? "Yes" : "No"); astman_append(s, "Encryption: %s\r\n", peer->encmethods ? ast_str_buffer(encmethods) : "No"); @@ -7024,7 +7050,7 @@ static char *handle_cli_iax2_show_registry(struct ast_cli_entry *e, int cmd, str ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); AST_LIST_LOCK(®istrations); AST_LIST_TRAVERSE(®istrations, reg, entry) { - snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); + snprintf(host, sizeof(host), "%s", ast_sockaddr_stringify(®->addr)); if (reg->us.sin_addr.s_addr) snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); else @@ -7057,7 +7083,7 @@ static int manager_iax2_show_registry(struct mansession *s, const struct message AST_LIST_LOCK(®istrations); AST_LIST_TRAVERSE(®istrations, reg, entry) { - snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); + snprintf(host, sizeof(host), "%s", ast_sockaddr_stringify(®->addr)); if (reg->us.sin_addr.s_addr) { snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); @@ -7284,6 +7310,8 @@ static char *handle_cli_iax2_set_debug(struct ast_cli_entry *e, int cmd, struct if (!strcasecmp(a->argv[3], "peer")) { struct iax2_peer *peer; + struct sockaddr_in peer_addr; + if (a->argc != e->args + 1) return CLI_SHOWUSAGE; @@ -7295,8 +7323,10 @@ static char *handle_cli_iax2_set_debug(struct ast_cli_entry *e, int cmd, struct return CLI_FAILURE; } - debugaddr.sin_addr = peer->addr.sin_addr; - debugaddr.sin_port = peer->addr.sin_port; + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + + debugaddr.sin_addr = peer_addr.sin_addr; + debugaddr.sin_port = peer_addr.sin_port; ast_cli(a->fd, "IAX2 Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); @@ -8111,11 +8141,15 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, } else { struct ao2_iterator i = ao2_iterator_init(peers, 0); while ((peer = ao2_iterator_next(&i))) { + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) /* No peer specified at our end, or this is the peer */ && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) /* No username specified in peer rule, or this is the right username */ - && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr))) + && (!peer_addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer_addr.sin_addr.s_addr & peer->mask.s_addr))) /* No specified host, or this is our host */ ) { res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p); @@ -8369,6 +8403,7 @@ static int iax2_ack_registry(struct iax_ies *ies, struct sockaddr_in *sin, int c struct sockaddr_in oldus; struct sockaddr_in us; int oldmsgs; + struct sockaddr_in reg_addr; memset(&us, 0, sizeof(us)); if (ies->apparent_addr) @@ -8387,7 +8422,8 @@ static int iax2_ack_registry(struct iax_ies *ies, struct sockaddr_in *sin, int c } memcpy(&oldus, ®->us, sizeof(oldus)); oldmsgs = reg->messages; - if (inaddrcmp(®->addr, sin)) { + ast_sockaddr_to_sin(®->addr, ®_addr); + if (inaddrcmp(®_addr, sin)) { ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); return -1; } @@ -8421,18 +8457,14 @@ static int iax2_append_register(const char *hostname, const char *username, const char *secret, const char *porta) { struct iax2_registry *reg; - struct ast_sockaddr reg_addr_tmp; if (!(reg = ast_calloc(1, sizeof(*reg)))) return -1; - reg->addr.sin_family = AF_INET; - ast_sockaddr_from_sin(®_addr_tmp, ®->addr); - if (ast_dnsmgr_lookup(hostname, ®_addr_tmp, ®->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) { + if (ast_dnsmgr_lookup(hostname, ®->addr, ®->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) { ast_free(reg); return -1; } - ast_sockaddr_to_sin(®_addr_tmp, ®->addr); ast_copy_string(reg->username, username, sizeof(reg->username)); @@ -8441,8 +8473,7 @@ static int iax2_append_register(const char *hostname, const char *username, reg->expire = -1; reg->refresh = IAX_DEFAULT_REG_EXPIRE; - reg->addr.sin_family = AF_INET; - reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); + ast_sockaddr_set_port(®->addr, porta ? atoi(porta) : IAX_DEFAULT_PORTNO); AST_LIST_LOCK(®istrations); AST_LIST_INSERT_HEAD(®istrations, reg, entry); @@ -8571,44 +8602,48 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall); static void reg_source_db(struct iax2_peer *p) { char data[80]; - struct in_addr in; - char *c, *d; - if (!ast_test_flag64(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { - c = strchr(data, ':'); - if (c) { - *c = '\0'; - c++; - if (inet_aton(data, &in)) { - d = strchr(c, ':'); - if (d) { - *d = '\0'; - d++; - ast_verb(3, "Seeding '%s' at %s:%d for %d\n", p->name, - ast_inet_ntoa(in), atoi(c), atoi(d)); - iax2_poke_peer(p, 0); - p->expiry = atoi(d); - memset(&p->addr, 0, sizeof(p->addr)); - p->addr.sin_family = AF_INET; - p->addr.sin_addr = in; - p->addr.sin_port = htons(atoi(c)); - if (p->expire > -1) { - if (!ast_sched_thread_del(sched, p->expire)) { - p->expire = -1; - peer_unref(p); - } - } - ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ - p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); - if (p->expire == -1) - peer_unref(p); - if (iax2_regfunk) - iax2_regfunk(p->name, 1); - register_peer_exten(p, 1); - } - - } + char *expiry; + + if (ast_test_flag64(p, IAX_TEMPONLY) || ast_db_get("IAX/Registry", p->name, data, sizeof(data))) { + return; + } + + expiry = strrchr(data, ':'); + if (!expiry) { + ast_log(LOG_NOTICE, "IAX/Registry astdb entry missing expiry: '%s'\n", data); + } + *expiry++ = '\0'; + + if (ast_sockaddr_parse(&p->addr, data, PARSE_PORT_REQUIRE)) { + ast_log(LOG_NOTICE, "IAX/Registry astdb host:port invalid - '%s'\n", data); + return; + } + + p->expiry = atoi(expiry); + + ast_verb(3, "Seeding '%s' at %s for %d\n", p->name, + ast_sockaddr_stringify(&p->addr), p->expiry); + + iax2_poke_peer(p, 0); + if (p->expire > -1) { + if (!ast_sched_thread_del(sched, p->expire)) { + p->expire = -1; + peer_unref(p); } } + + ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ + + p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); + if (p->expire == -1) { + peer_unref(p); + } + + if (iax2_regfunk) { + iax2_regfunk(p->name, 1); + } + + register_peer_exten(p, 1); } /*! @@ -8620,15 +8655,18 @@ static void reg_source_db(struct iax2_peer *p) static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) { /* Called from IAX thread only, with proper iaxsl lock */ - struct iax_ie_data ied; + struct iax_ie_data ied = { + .pos = 0, + }; struct iax2_peer *p; int msgcount; char data[80]; int version; const char *peer_name; int res = -1; + struct ast_sockaddr sockaddr; - memset(&ied, 0, sizeof(ied)); + ast_sockaddr_from_sin(&sockaddr, sin); peer_name = ast_strdupa(iaxs[callno]->peer); @@ -8647,14 +8685,16 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i if (sin->sin_addr.s_addr) { time_t nowtime; time(&nowtime); - realtime_update_peer(peer_name, sin, nowtime); + realtime_update_peer(peer_name, &sockaddr, nowtime); } else { - realtime_update_peer(peer_name, sin, 0); + realtime_update_peer(peer_name, &sockaddr, 0); } } - if (inaddrcmp(&p->addr, sin)) { - if (iax2_regfunk) + + if (ast_sockaddr_cmp(&p->addr, &sockaddr)) { + if (iax2_regfunk) { iax2_regfunk(p->name, 1); + } /* modify entry in peercnts table as _not_ registered */ peercnt_modify(0, 0, &p->addr); @@ -8725,8 +8765,12 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); if (sin->sin_addr.s_addr) { + struct sockaddr_in peer_addr; + + ast_sockaddr_to_sin(&p->addr, &peer_addr); + iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); - iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); + iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &peer_addr); if (!ast_strlen_zero(p->mailbox)) { struct ast_event *event; int new, old; @@ -8842,31 +8886,35 @@ static int registry_rerequest(struct iax_ies *ies, int callno, struct sockaddr_i memset(&ied, 0, sizeof(ied)); reg = iaxs[callno]->reg; if (reg) { - if (inaddrcmp(®->addr, sin)) { - ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); - return -1; - } - if (ast_strlen_zero(reg->secret)) { - ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); - reg->regstate = REG_STATE_NOAUTH; - return -1; - } - iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); - iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); - if (reg->secret[0] == '[') { - char tmpkey[256]; - ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); - tmpkey[strlen(tmpkey) - 1] = '\0'; - res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); - } else - res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); - if (!res) { - reg->regstate = REG_STATE_AUTHSENT; - add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ - return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); - } else - return -1; - ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); + struct sockaddr_in reg_addr; + + ast_sockaddr_to_sin(®->addr, ®_addr); + + if (inaddrcmp(®_addr, sin)) { + ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); + return -1; + } + if (ast_strlen_zero(reg->secret)) { + ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); + reg->regstate = REG_STATE_NOAUTH; + return -1; + } + iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); + iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); + if (reg->secret[0] == '[') { + char tmpkey[256]; + ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); + tmpkey[strlen(tmpkey) - 1] = '\0'; + res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); + } else + res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); + if (!res) { + reg->regstate = REG_STATE_AUTHSENT; + add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */ + return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); + } else + return -1; + ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); } else ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); return -1; @@ -11633,7 +11681,7 @@ static int iax2_do_register(struct iax2_registry *reg) ast_debug(1, "Sending registration request for '%s'\n", reg->username); if (reg->dnsmgr && - ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { + ((reg->regstate == REG_STATE_TIMEOUT) || !ast_sockaddr_ipv4(®->addr))) { /* Maybe the IP has changed, force DNS refresh */ ast_dnsmgr_refresh(reg->dnsmgr); } @@ -11649,7 +11697,7 @@ static int iax2_do_register(struct iax2_registry *reg) ast_mutex_unlock(&iaxsl[callno]); reg->callno = 0; } - if (!reg->addr.sin_addr.s_addr) { + if (!ast_sockaddr_ipv4(®->addr)) { if (iaxdebug) ast_debug(1, "Unable to send registration request for '%s' without IP address\n", reg->username); /* Setup the next registration attempt */ @@ -11659,8 +11707,13 @@ static int iax2_do_register(struct iax2_registry *reg) } if (!reg->callno) { + struct sockaddr_in reg_addr; + ast_debug(3, "Allocate call number\n"); - reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); + + ast_sockaddr_to_sin(®->addr, ®_addr); + + reg->callno = find_callno_locked(0, 0, ®_addr, NEW_FORCE, defaultsockfd, 0); if (reg->callno < 1) { ast_log(LOG_WARNING, "Unable to create call for registration\n"); return -1; @@ -11849,7 +11902,9 @@ static int iax2_poke_peer_cb(void *obj, void *arg, int flags) static int iax2_poke_peer(struct iax2_peer *peer, int heldcall) { int callno; - if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { + struct sockaddr_in peer_addr; + + if (!peer->maxms || (!ast_sockaddr_ipv4(&peer->addr) && !peer->dnsmgr)) { /* IF we have no IP without dnsmgr, or this isn't to be monitored, return immediately after clearing things out */ peer->lastms = 0; @@ -11859,6 +11914,8 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall) return 0; } + ast_sockaddr_to_sin(&peer->addr, &peer_addr); + /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ if ((callno = peer->callno) > 0) { ast_log(LOG_NOTICE, "Still have a callno...\n"); @@ -11868,7 +11925,7 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall) } if (heldcall) ast_mutex_unlock(&iaxsl[heldcall]); - callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); + callno = peer->callno = find_callno(0, 0, &peer_addr, NEW_FORCE, peer->sockfd, 0); if (heldcall) ast_mutex_lock(&iaxsl[heldcall]); if (peer->callno < 1) { @@ -12235,7 +12292,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st ast_string_field_set(peer,secret,""); if (!found) { ast_string_field_set(peer, name, name); - peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); + ast_sockaddr_set_port(&peer->addr, IAX_DEFAULT_PORTNO); peer->expiry = min_reg_expire; } peer->prefs = prefs; @@ -12314,26 +12371,20 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st if (!found) { /* Initialize stuff iff we're not found, otherwise we keep going with what we had */ - memset(&peer->addr.sin_addr, 0, 4); - if (peer->addr.sin_port) { - /* If we've already got a port, make it the default rather than absolute */ - peer->defaddr.sin_port = peer->addr.sin_port; - peer->addr.sin_port = 0; + if (ast_sockaddr_port(&peer->addr)) { + peer->defaddr.sin_port = htons(ast_sockaddr_port(&peer->addr)); } + ast_sockaddr_setnull(&peer->addr); } } else { - struct ast_sockaddr peer_addr_tmp; - /* Non-dynamic. Make sure we become that way if we're not */ ast_sched_thread_del(sched, peer->expire); ast_clear_flag64(peer, IAX_DYNAMIC); - peer_addr_tmp.ss.ss_family = AF_INET; - if (ast_dnsmgr_lookup(v->value, &peer_addr_tmp, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL)) + if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL)) return peer_unref(peer); - ast_sockaddr_to_sin(&peer_addr_tmp, - &peer->addr); - if (!peer->addr.sin_port) - peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); + if (!ast_sockaddr_port(&peer->addr)) { + ast_sockaddr_set_port(&peer->addr, IAX_DEFAULT_PORTNO); + } } if (!maskfound) inet_aton("255.255.255.255", &peer->mask); @@ -12360,10 +12411,11 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st } else if (!strcasecmp(v->name, "peercontext")) { ast_string_field_set(peer, peercontext, v->value); } else if (!strcasecmp(v->name, "port")) { - if (ast_test_flag64(peer, IAX_DYNAMIC)) + if (ast_test_flag64(peer, IAX_DYNAMIC)) { peer->defaddr.sin_port = htons(atoi(v->value)); - else - peer->addr.sin_port = htons(atoi(v->value)); + } else { + ast_sockaddr_set_port(&peer->addr, atoi(v->value)); + } } else if (!strcasecmp(v->name, "username")) { ast_string_field_set(peer, username, v->value); } else if (!strcasecmp(v->name, "allow")) { @@ -12457,8 +12509,6 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st if (!peer->authmethods) peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; ast_clear_flag64(peer, IAX_DELME); - /* Make sure these are IPv4 addresses */ - peer->addr.sin_family = AF_INET; } if (oldha) @@ -13726,7 +13776,7 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat return -1; if (!strcasecmp(colname, "ip")) { - ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); + ast_copy_string(buf, ast_sockaddr_stringify_addr(&peer->addr), len); } else if (!strcasecmp(colname, "status")) { peer_status(peer, buf, len); } else if (!strcasecmp(colname, "mailbox")) { @@ -13831,9 +13881,9 @@ static int iax2_devicestate(void *data) res = AST_DEVICE_UNAVAILABLE; ast_debug(3, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", - pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); + pds.peer, ast_sockaddr_ipv4(&p->addr), p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); - if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && + if ((ast_sockaddr_ipv4(&p->addr) || p->defaddr.sin_addr.s_addr) && (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { /* Peer is registered, or have default IP address and a valid registration */ @@ -14381,11 +14431,11 @@ static int peers_data_provider_get(const struct ast_data_search *search, peer_status(peer, status, sizeof(status)); ast_data_add_str(data_peer, "status", status); - ast_data_add_str(data_peer, "host", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : ""); + ast_data_add_str(data_peer, "host", ast_sockaddr_stringify_host(&peer->addr)); ast_data_add_str(data_peer, "mask", ast_inet_ntoa(peer->mask)); - ast_data_add_int(data_peer, "port", ntohs(peer->addr.sin_port)); + ast_data_add_int(data_peer, "port", ast_sockaddr_port(&peer->addr)); ast_data_add_bool(data_peer, "trunk", ast_test_flag64(peer, IAX_TRUNK)); diff --git a/include/asterisk/jabber.h b/include/asterisk/jabber.h index 5f5dd14f3..3965f7a0f 100644 --- a/include/asterisk/jabber.h +++ b/include/asterisk/jabber.h @@ -72,6 +72,7 @@ */ #define AJI_MAX_JIDLEN 3071 #define AJI_MAX_RESJIDLEN 1023 +#define AJI_MAX_ATTRLEN 256 #define MUC_NS "http://jabber.org/protocol/muc" diff --git a/include/asterisk/jingle.h b/include/asterisk/jingle.h index 7442d9aca..bbe86c8f2 100644 --- a/include/asterisk/jingle.h +++ b/include/asterisk/jingle.h @@ -44,6 +44,9 @@ #define JINGLE_DTMF_NS "urn:xmpp:tmp:jingle:dtmf" #define GOOGLE_NS "http://www.google.com/session" +#define GOOGLE_AUDIO_NS "http://www.google.com/session/phone" +#define GOOGLE_VIDEO_NS "http://www.google.com/session/video" +#define GOOGLE_TRANSPORT_NS "http://www.google.com/transport/p2p" #define JINGLE_SID "sid" #define GOOGLE_SID "id" diff --git a/main/file.c b/main/file.c index 97e3720f1..76212d093 100644 --- a/main/file.c +++ b/main/file.c @@ -959,10 +959,12 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p * done this way because there is no where for ast_openstream_full to * return the file had no data. */ seekattempt = fseek(fs->f, -1, SEEK_END); - if (!seekattempt) - ast_seekstream(fs, 0, SEEK_SET); - else + if (seekattempt && errno == EINVAL) { + /* Zero-length file, as opposed to a pipe */ return 0; + } else { + ast_seekstream(fs, 0, SEEK_SET); + } vfs = ast_openvstream(chan, filename, preflang); if (vfs) { diff --git a/main/pbx.c b/main/pbx.c index 9b44306bf..87ebdd854 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -9550,11 +9550,18 @@ int pbx_builtin_setvar(struct ast_channel *chan, const char *data) mydata = ast_strdupa(data); name = strsep(&mydata, "="); value = mydata; - if (strchr(name, ' ')) + if (!value) { + ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); + return 0; + } + + if (strchr(name, ' ')) { ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); + } pbx_builtin_setvar_helper(chan, name, value); - return(0); + + return 0; } int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata) diff --git a/res/res_jabber.c b/res/res_jabber.c index 9548dd800..6b737e70b 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -569,8 +569,16 @@ static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *nam static int gtalk_yuck(iks *node) { 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; } @@ -1577,6 +1585,23 @@ static int aji_act_hook(void *data, int type, iks *node) 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:") + (strlen(node_name) - strlen(aux)), "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) { case IKS_NODE_START: @@ -2405,7 +2430,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *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 { iks *iq, *query; @@ -3038,20 +3063,23 @@ static int aji_get_roster(struct aji_client *client) static int aji_client_connect(void *data, ikspak *pak) { struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); - int res = 0; + int res = IKS_FILTER_PASS; 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); client->state = AJI_CONNECTING; 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); if (!client->component) { /*client*/ aji_get_roster(client); - if (client->distribute_events) { - aji_init_event_distribution(client); - } } + if (client->distribute_events) { + aji_init_event_distribution(client); + } + + iks_filter_remove_hook(client->f, aji_client_connect); + /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ + res = IKS_FILTER_EAT; } } else { ast_log(LOG_ERROR, "Out of memory.\n"); diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index ffd7b2596..72032de60 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -1945,6 +1945,11 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int ast_rtp_instance_get_remote_address(instance1, &remote_address); + if (ast_sockaddr_isnull(&remote_address)) { + ast_debug(1, "Remote address is null, most likely RTP has been stopped\n"); + return 0; + } + /* Send the packet back out */ res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address); if (res < 0) { |