aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b>2010-10-07 16:51:23 +0000
committerlmadsen <lmadsen@f38db490-d61c-443f-a65b-d21fe96a405b>2010-10-07 16:51:23 +0000
commit533e04bb23ff2d532ed9df6eeaf8bc4b6cc86209 (patch)
treeb752d1dab2c00d256ae804c744d645b81d4e9d11
parent06acc1b52254c01a885cb73f9e0b4af96e3f7543 (diff)
parent66afa1aec386d92340077b44a43f0e627ba8651a (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.c3
-rw-r--r--apps/app_directed_pickup.c28
-rw-r--r--channels/chan_gtalk.c290
-rw-r--r--channels/chan_iax2.c332
-rw-r--r--include/asterisk/jabber.h1
-rw-r--r--include/asterisk/jingle.h3
-rw-r--r--main/file.c8
-rw-r--r--main/pbx.c11
-rw-r--r--res/res_jabber.c40
-rw-r--r--res/res_rtp_asterisk.c5
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(&gtalk_list, name, user,,, strcasecmp);
- if (!gtalk) {
+ if (!gtalk) {
/* guest call */
ASTOBJ_CONTAINER_TRAVERSE(&gtalk_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, &regseconds, 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(&regexbuf, peer->name, 0, NULL, 0))
+ }
+ if (havepattern && regexec(&regexbuf, 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(&registrations);
AST_LIST_TRAVERSE(&registrations, 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(&reg->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(&registrations);
AST_LIST_TRAVERSE(&registrations, 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(&reg->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, &reg->us, sizeof(oldus));
oldmsgs = reg->messages;
- if (inaddrcmp(&reg->addr, sin)) {
+ ast_sockaddr_to_sin(&reg->addr, &reg_addr);
+ if (inaddrcmp(&reg_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(&reg_addr_tmp, &reg->addr);
- if (ast_dnsmgr_lookup(hostname, &reg_addr_tmp, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
+ if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
ast_free(reg);
return -1;
}
- ast_sockaddr_to_sin(&reg_addr_tmp, &reg->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(&reg->addr, porta ? atoi(porta) : IAX_DEFAULT_PORTNO);
AST_LIST_LOCK(&registrations);
AST_LIST_INSERT_HEAD(&registrations, 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(&reg->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(&reg->addr, &reg_addr);
+
+ if (inaddrcmp(&reg_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(&reg->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(&reg->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, &reg->addr, NEW_FORCE, defaultsockfd, 0);
+
+ ast_sockaddr_to_sin(&reg->addr, &reg_addr);
+
+ reg->callno = find_callno_locked(0, 0, &reg_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) {