[svn-commits] phsultan: branch phsultan/jingle-support r222808 - in /team/phsultan/jingle-s...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 8 12:17:08 CDT 2009


Author: phsultan
Date: Thu Oct  8 12:17:02 2009
New Revision: 222808

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=222808
Log:
Update to the Jingle signalling and STUN stack.

- compatibility with XEP-0166 (basic Jingle exchanges)
  * handle incoming calls only
  * fix namespaces
- compatibility with XEP-0176 (Jingle ICE-UDP Transport method)
- compatibility with RFC5389 (STUN) that obsoletes RFC3489
- code simplications
- code formatting fixes

Modified:
    team/phsultan/jingle-support/channels/chan_gtalk.c
    team/phsultan/jingle-support/channels/chan_h323.c
    team/phsultan/jingle-support/channels/chan_jingle.c
    team/phsultan/jingle-support/channels/chan_mgcp.c
    team/phsultan/jingle-support/channels/chan_sip.c
    team/phsultan/jingle-support/channels/chan_skinny.c
    team/phsultan/jingle-support/channels/chan_unistim.c
    team/phsultan/jingle-support/include/asterisk/jingle.h
    team/phsultan/jingle-support/include/asterisk/rtp_engine.h
    team/phsultan/jingle-support/include/asterisk/stun.h
    team/phsultan/jingle-support/main/rtp_engine.c
    team/phsultan/jingle-support/main/stun.c
    team/phsultan/jingle-support/res/res_rtp_asterisk.c

Modified: team/phsultan/jingle-support/channels/chan_gtalk.c
URL: http://svnview.digium.com/svn/asterisk/team/phsultan/jingle-support/channels/chan_gtalk.c?view=diff&rev=222808&r1=222807&r2=222808
==============================================================================
--- team/phsultan/jingle-support/channels/chan_gtalk.c (original)
+++ team/phsultan/jingle-support/channels/chan_gtalk.c Thu Oct  8 12:17:02 2009
@@ -1269,15 +1269,15 @@
 	tmp = p->theircandidates;
 	p->laststun = time(NULL);
 	while (tmp) {
-		char username[256];
+		struct stun_credentials credentials;
 
 		/* Find the IP address of the host */
 		hp = ast_gethostbyname(tmp->ip, &ahp);
 		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);
+		ast_copy_string(credentials.local_ufrag, p->ourcandidates->username, sizeof(credentials.local_ufrag));
+		ast_copy_string(credentials.remote_ufrag, tmp->username, sizeof(credentials.remote_ufrag));
 		
 		/* Find out the result of the STUN */
 		ast_rtp_instance_get_remote_address(p->rtp, &aux);
@@ -1287,9 +1287,9 @@
 			remote client */
 		if (aux.sin_addr.s_addr && 
 		    aux.sin_addr.s_addr != sin.sin_addr.s_addr)
-			ast_rtp_instance_stun_request(p->rtp, &aux, username);
+			ast_rtp_instance_stun_request(p->rtp, &aux, &credentials);
 		else 
-			ast_rtp_instance_stun_request(p->rtp, &sin, username);
+			ast_rtp_instance_stun_request(p->rtp, &sin, &credentials);
 		
 		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);
@@ -1390,7 +1390,7 @@
 
 	if (!p->rtp)
 		return &ast_null_frame;
-	f = ast_rtp_instance_read(p->rtp, 0);
+	f = ast_rtp_instance_read(p->rtp, 0, NULL);
 	gtalk_update_stun(p->parent, p);
 	if (p->owner) {
 		/* We already hold the channel lock */

Modified: team/phsultan/jingle-support/channels/chan_h323.c
URL: http://svnview.digium.com/svn/asterisk/team/phsultan/jingle-support/channels/chan_h323.c?view=diff&rev=222808&r1=222807&r2=222808
==============================================================================
--- team/phsultan/jingle-support/channels/chan_h323.c (original)
+++ team/phsultan/jingle-support/channels/chan_h323.c Thu Oct  8 12:17:02 2009
@@ -753,7 +753,7 @@
 		pvt->options.nat = 0;
 	}
 
-	f = ast_rtp_instance_read(pvt->rtp, 0);
+	f = ast_rtp_instance_read(pvt->rtp, 0, NULL);
 	/* Don't send RFC2833 if we're not supposed to */
 	if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
 		return &ast_null_frame;
@@ -810,7 +810,7 @@
 		break;
 	case 1:
 		if (pvt->rtp)
-			fr = ast_rtp_instance_read(pvt->rtp, 1);
+			fr = ast_rtp_instance_read(pvt->rtp, 1, NULL);
 		else
 			fr = &ast_null_frame;
 		break;

Modified: team/phsultan/jingle-support/channels/chan_jingle.c
URL: http://svnview.digium.com/svn/asterisk/team/phsultan/jingle-support/channels/chan_jingle.c?view=diff&rev=222808&r1=222807&r2=222808
==============================================================================
--- team/phsultan/jingle-support/channels/chan_jingle.c (original)
+++ team/phsultan/jingle-support/channels/chan_jingle.c Thu Oct  8 12:17:02 2009
@@ -68,6 +68,7 @@
 #include "asterisk/abstract_jb.h"
 #include "asterisk/jabber.h"
 #include "asterisk/jingle.h"
+#include "asterisk/stun.h"
 
 #define JINGLE_CONFIG "jingle.conf"
 
@@ -97,13 +98,12 @@
 	ast_mutex_t lock;                /*!< Channel private lock */
 	time_t laststun;
 	struct jingle *parent;	         /*!< Parent client */
-	char sid[100];
+	char sid[JINGLE_MAX_ATTRLEN];
 	char them[AJI_MAX_JIDLEN];
 	char ring[10];                   /*!< Message ID of ring */
 	iksrule *ringrule;               /*!< Rule for matching RING request */
 	int initiator;                   /*!< If we're the initiator */
 	int alreadygone;
-	int capability;
 	struct ast_codec_pref prefs;
 	struct jingle_candidate *theircandidates;
 	struct jingle_candidate *ourcandidates;
@@ -111,16 +111,23 @@
 	char cid_name[80];               /*!< Caller ID name */
 	char exten[80];                  /*!< Called extension */
 	struct ast_channel *owner;       /*!< Master Channel */
-	char audio_content_name[100];    /*!< name attribute of content tag */
-	struct ast_rtp_instance *rtp;             /*!< RTP audio session */
-	char video_content_name[100];    /*!< name attribute of content tag */
-	struct ast_rtp_instance *vrtp;            /*!< RTP video session */
-	int jointcapability;             /*!< Supported capability at both ends (codecs ) */
-	int peercapability;
+	char local_password[JINGLE_MAX_ATTRLEN];
+	char remote_password[JINGLE_MAX_ATTRLEN];
+	char local_ufrag[JINGLE_MAX_ATTRLEN];
+	char remote_ufrag[JINGLE_MAX_ATTRLEN];
+	char audio_content_name[JINGLE_MAX_ATTRLEN];    /*!< name attribute of content tag */
+	struct ast_rtp_instance *rtp;             	/*!< RTP audio session */
+	char video_content_name[JINGLE_MAX_ATTRLEN];    /*!< name attribute of content tag */
+	struct ast_rtp_instance *vrtp;            	/*!< RTP video session */
+	int capability;			/*!< Channel codec capability */
+	int peercapability;		/*!< Peer advertized codec capability */
+	int peernoncodeccapability;	/*!< Peer advertized non codec capability (ex. DTMF) */
+	int jointcapability;		/*!< Common codec capability */
 	struct jingle_pvt *next;	/* Next entity */
 };
 
 struct jingle_candidate {
+	char id[JINGLE_MAX_ATTRLEN];
 	unsigned int component;          /*!< ex. : 1 for RTP, 2 for RTCP */
 	unsigned int foundation;         /*!< Function of IP, protocol, type */
 	unsigned int generation;
@@ -129,9 +136,7 @@
 	unsigned int port;
 	unsigned int priority;
 	enum jingle_protocol protocol;
-	char password[100];
 	enum jingle_connect_type type;
-	char ufrag[100];
 	unsigned int preference;
 	struct jingle_candidate *next;
 };
@@ -163,7 +168,7 @@
 static const char desc[] = "Jingle Channel";
 static const char channel_type[] = "Jingle";
 
-static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
+static int global_capability = 0;
 
 AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_pvt's) */
 
@@ -175,7 +180,7 @@
 static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
 static int jingle_hangup(struct ast_channel *ast);
 static int jingle_answer(struct ast_channel *ast);
-static int jingle_newcall(struct jingle *client, ikspak *pak);
+static int jingle_incomingcall(struct jingle *client, ikspak *pak);
 static struct ast_frame *jingle_read(struct ast_channel *ast);
 static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
@@ -292,71 +297,143 @@
 		iks_insert_attrib(payload_g723, "name", "G723");
 		iks_insert_node(dcodecs, payload_g723);
 	}
+	if (!strcasecmp("speex", format)) {
+		iks *payload_speex;
+		payload_speex = iks_new("payload-type");
+		iks_insert_attrib(payload_speex, "id", "110");
+		iks_insert_attrib(payload_speex, "name", "SPEEX");
+		iks_insert_attrib(payload_speex, "clockrate", "16000");
+		iks_insert_node(dcodecs, payload_speex);
+	}
 }
 
 static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
 {
 	struct jingle_pvt *tmp = client->p;
+	struct jingle_candidate *aux = NULL;
 	struct aji_client *c = client->connection;
-	iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
+	iks *iq, *jingle, *content, *dcodecs, *transport;
+	iks *candidates[2];
 	int x;
 	int pref_codec = 0;
 	int alreadysent = 0;
+	int num = 0;
+	char component[16], foundation[16], generation[16], network[16], port[7], priority[16];
 
 	if (p->initiator)
 		return 1;
 
+	/* allocate memory structures */
 	iq = iks_new("iq");
 	jingle = iks_new(JINGLE_NODE);
+	content = iks_new("content");
 	dcodecs = iks_new("description");
-	if (iq && jingle && dcodecs) {
-		iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS);
-
-		for (x = 0; x < 32; x++) {
-			if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
-				break;
-			if (!(client->capability & pref_codec))
-				continue;
-			if (alreadysent & pref_codec)
-				continue;
-			add_codec_to_answer(p, pref_codec, dcodecs);
-			alreadysent |= pref_codec;
-		}
-		payload_red = iks_new("payload-type");
-		iks_insert_attrib(payload_red, "id", "117");
-		iks_insert_attrib(payload_red, "name", "red");
-		payload_audio = iks_new("payload-type");
-		iks_insert_attrib(payload_audio, "id", "106");
-		iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
-		payload_cn = iks_new("payload-type");
-		iks_insert_attrib(payload_cn, "id", "13");
-		iks_insert_attrib(payload_cn, "name", "CN");
-
-
-		iks_insert_attrib(iq, "type", "set");
-		iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
-		iks_insert_attrib(iq, "id", client->connection->mid);
-		ast_aji_increment_mid(client->connection->mid);
-
-		iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
-		iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
-		iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
-		iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
-		iks_insert_node(iq, jingle);
-		iks_insert_node(jingle, dcodecs);
-		iks_insert_node(dcodecs, payload_red);
-		iks_insert_node(dcodecs, payload_audio);
-		iks_insert_node(dcodecs, payload_cn);
-
-		ast_aji_send(c, iq);
-
-		iks_delete(payload_red);
-		iks_delete(payload_audio);
-		iks_delete(payload_cn);
-		iks_delete(dcodecs);
-		iks_delete(jingle);
-		iks_delete(iq);
-	}
+	transport = iks_new("transport");
+	candidates[0] = iks_new("candidate");
+	candidates[1] = iks_new("candidate");
+	if (!iq || !jingle || !content || !transport || !candidates[0] || !candidates[1]) {
+		ast_log(LOG_ERROR, "Memory allocation error\n");
+		goto safeout;
+	}
+
+	iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
+	iks_insert_attrib(transport, "ufrag", p->local_ufrag);
+	iks_insert_attrib(transport, "pwd", p->local_password);
+
+	for (aux = p->ourcandidates; aux; aux = aux->next) {
+		snprintf(component, sizeof(component), "%u", aux->component);
+		snprintf(foundation, sizeof(foundation), "%u", aux->foundation);
+		snprintf(generation, sizeof(generation), "%u", aux->generation);
+		snprintf(network, sizeof(network), "%u", aux->network);
+		snprintf(port, sizeof(port), "%u", aux->port);
+		snprintf(priority, sizeof(priority), "%u", aux->priority);
+
+		iks_insert_attrib(candidates[num], "id", aux->id);
+		iks_insert_attrib(candidates[num], "component", component);
+		iks_insert_attrib(candidates[num], "foundation", foundation);
+		iks_insert_attrib(candidates[num], "generation", generation);
+		iks_insert_attrib(candidates[num], "ip", aux->ip);
+		iks_insert_attrib(candidates[num], "network", network);
+		iks_insert_attrib(candidates[num], "port", port);
+		iks_insert_attrib(candidates[num], "priority", priority);
+		switch (aux->protocol) {
+		case AJI_PROTOCOL_UDP:
+			iks_insert_attrib(candidates[num], "protocol", "udp");
+			break;
+		case AJI_PROTOCOL_SSLTCP:
+			iks_insert_attrib(candidates[num], "protocol", "ssltcp");
+			break;
+		}
+		switch (aux->type) {
+		case AJI_CONNECT_HOST:
+			iks_insert_attrib(candidates[num], "type", "host");
+			break;
+		case AJI_CONNECT_PRFLX:
+			iks_insert_attrib(candidates[num], "type", "prflx");
+			break;
+		case AJI_CONNECT_RELAY:
+			iks_insert_attrib(candidates[num], "type", "relay");
+			break;
+		case AJI_CONNECT_SRFLX:
+			iks_insert_attrib(candidates[num], "type", "srflx");
+			break;
+		}
+		num ++;
+	}
+	p->laststun = 0;
+
+	iks_insert_attrib(dcodecs, "xmlns", JINGLE_RTP_NS);
+	iks_insert_attrib(dcodecs, "media", "audio");
+
+	for (x = 0; x < 32; x++) {
+		if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
+			break;
+		if (!(p->jointcapability & pref_codec))
+			continue;
+		if (alreadysent & pref_codec)
+			continue;
+		add_codec_to_answer(p, pref_codec, dcodecs);
+		alreadysent |= pref_codec;
+	}
+
+	iks_insert_attrib(iq, "type", "set");
+	iks_insert_attrib(iq, "from", client->connection->jid->full);
+	iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
+	iks_insert_attrib(iq, "id", client->connection->mid);
+	ast_aji_increment_mid(client->connection->mid);
+
+	iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
+	iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
+	iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
+	if (!p->initiator) {
+		iks_insert_attrib(jingle, "responder", client->connection->jid->full);
+	}
+	iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
+
+	iks_insert_attrib(content, "creator", "initiator");
+	iks_insert_attrib(content, "name", "A");
+	iks_insert_attrib(content, "senders", "both");
+
+	/* insert nodes */
+	iks_insert_node(iq, jingle);
+	iks_insert_node(jingle, content);
+	iks_insert_node(content, dcodecs);
+	iks_insert_node(content, transport);
+	iks_insert_node(transport, candidates[0]);
+	iks_insert_node(transport, candidates[1]);
+
+	/* send IQ */
+	ast_aji_send(c, iq);
+
+safeout:
+	iks_delete(iq);
+	iks_delete(jingle);
+	iks_delete(content);
+	iks_delete(dcodecs);
+	iks_delete(transport);
+	iks_delete(candidates[0]);
+	iks_delete(candidates[1]);
+
 	return 1;
 }
 
@@ -574,162 +651,36 @@
 	return 1;
 }
 
-static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
-{
-	struct jingle_candidate *tmp;
-	struct aji_client *c = client->connection;
-	struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
-	struct sockaddr_in sin = { 0, };
-	struct sockaddr_in dest;
-	struct in_addr us;
-	struct in_addr externaddr;
-	iks *iq, *jingle, *content, *transport, *candidate;
-	char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16];
-
-
-	iq = iks_new("iq");
-	jingle = iks_new(JINGLE_NODE);
-	content = iks_new("content");
-	transport = iks_new("transport");
-	candidate = iks_new("candidate");
-	if (!iq || !jingle || !content || !transport || !candidate) {
-		ast_log(LOG_ERROR, "Memory allocation error\n");
-		goto safeout;
-	}
-	ours1 = ast_calloc(1, sizeof(*ours1));
-	ours2 = ast_calloc(1, sizeof(*ours2));
-	if (!ours1 || !ours2)
-		goto safeout;
-
-	iks_insert_node(iq, jingle);
-	iks_insert_node(jingle, content);
-	iks_insert_node(content, transport);
-	iks_insert_node(transport, candidate);
-
-	for (; p; p = p->next) {
-		if (!strcasecmp(p->sid, sid))
-			break;
-	}
-
-	if (!p) {
-		ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid);
-		goto safeout;
-	}
-
-	ast_rtp_instance_get_local_address(p->rtp, &sin);
-	ast_find_ourip(&us, bindaddr);
-
-	/* Setup our first jingle candidate */
-	ours1->component = 1;
-	ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP;
-	ours1->generation = 0;
-	ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
-	ours1->network = 0;
-	ours1->port = ntohs(sin.sin_port);
-	ours1->priority = 1678246398;
-	ours1->protocol = AJI_PROTOCOL_UDP;
-	snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
-	ast_copy_string(ours1->password, pass, sizeof(ours1->password));
-	ours1->type = AJI_CONNECT_HOST;
-	snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
-	ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag));
-	p->ourcandidates = ours1;
-
-	if (!ast_strlen_zero(externip)) {
-		/* XXX We should really stun for this one not just go with externip XXX */
-		if (inet_aton(externip, &externaddr))
-			ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip);
-
-		ours2->component = 1;
-		ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP;
-		ours2->generation = 0;
-		ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
-		ours2->network = 0;
-		ours2->port = ntohs(sin.sin_port);
-		ours2->priority = 1678246397;
-		ours2->protocol = AJI_PROTOCOL_UDP;
-		snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
-		ast_copy_string(ours2->password, pass, sizeof(ours2->password));
-		ours2->type = AJI_CONNECT_PRFLX;
-
-		snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
-		ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag));
-		ours1->next = ours2;
-		ours2 = NULL;
-	}
-	ours1 = NULL;
-	dest.sin_addr = __ourip;
-	dest.sin_port = sin.sin_port;
-
-
-	for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
-		snprintf(component, sizeof(component), "%u", tmp->component);
-		snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
-		snprintf(generation, sizeof(generation), "%u", tmp->generation);
-		snprintf(network, sizeof(network), "%u", tmp->network);
-		snprintf(port, sizeof(port), "%u", tmp->port);
-		snprintf(priority, sizeof(priority), "%u", tmp->priority);
-
-		iks_insert_attrib(iq, "from", c->jid->full);
-		iks_insert_attrib(iq, "to", from);
-		iks_insert_attrib(iq, "type", "set");
-		iks_insert_attrib(iq, "id", c->mid);
-		ast_aji_increment_mid(c->mid);
-		iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
-		iks_insert_attrib(jingle, JINGLE_SID, sid);
-		iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
-		iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
-		iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
-		iks_insert_attrib(content, "name", "asterisk-audio-content");
-		iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
-		iks_insert_attrib(candidate, "component", component);
-		iks_insert_attrib(candidate, "foundation", foundation);
-		iks_insert_attrib(candidate, "generation", generation);
-		iks_insert_attrib(candidate, "ip", tmp->ip);
-		iks_insert_attrib(candidate, "network", network);
-		iks_insert_attrib(candidate, "port", port);
-		iks_insert_attrib(candidate, "priority", priority);
-		switch (tmp->protocol) {
-		case AJI_PROTOCOL_UDP:
-			iks_insert_attrib(candidate, "protocol", "udp");
-			break;
-		case AJI_PROTOCOL_SSLTCP:
-			iks_insert_attrib(candidate, "protocol", "ssltcp");
-			break;
-		}
-		iks_insert_attrib(candidate, "pwd", tmp->password);
-		switch (tmp->type) {
-		case AJI_CONNECT_HOST:
-			iks_insert_attrib(candidate, "type", "host");
-			break;
-		case AJI_CONNECT_PRFLX:
-			iks_insert_attrib(candidate, "type", "prflx");
-			break;
-		case AJI_CONNECT_RELAY:
-			iks_insert_attrib(candidate, "type", "relay");
-			break;
-		case AJI_CONNECT_SRFLX:
-			iks_insert_attrib(candidate, "type", "srflx");
-			break;
-		}
-		iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
-
-		ast_aji_send(c, iq);
-	}
-	p->laststun = 0;
-
-safeout:
-	if (ours1)
-		ast_free(ours1);
-	if (ours2)
-		ast_free(ours2);
-	iks_delete(iq);
-	iks_delete(jingle);
-	iks_delete(content);
-	iks_delete(transport);
-	iks_delete(candidate);
-
-	return 1;
+static int jingle_append_candidate(struct jingle_pvt *p, struct jingle_candidate *candidate, struct sockaddr_in sin, int offset)
+{
+	int res = -1;
+
+	if (!p || !candidate) {
+		ast_log(LOG_WARNING, "Could not append candidate\n");
+		return res;
+	}
+
+	snprintf(candidate->id, sizeof(candidate->id), "%08lx", ast_random());
+	candidate->component = 1 + offset;
+	candidate->foundation = 0;
+	candidate->generation = 0;
+	ast_copy_string(candidate->ip, ast_inet_ntoa(sin.sin_addr), sizeof(candidate->ip));
+	candidate->network = 0;
+	candidate->port = ntohs(sin.sin_port) + offset;
+	candidate->priority = 1678246398 - offset;
+	candidate->protocol = AJI_PROTOCOL_UDP;
+	candidate->type = AJI_CONNECT_HOST;
+	candidate->next = NULL;
+
+	if (p->ourcandidates) {
+		p->ourcandidates->next = candidate;
+	} else {
+		p->ourcandidates = candidate;	
+	}
+
+	res = 1;
+
+	return res;;
 }
 
 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid)
@@ -764,7 +715,16 @@
 		return NULL;
 	}
 
+	/* set codec preferences to what has been configured in jingle.conf
+	 * and create an RTP (and RTCP) instance from the asterisk engine */
 	memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
+	tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+	if (!tmp->rtp) {
+		ast_log(LOG_WARNING, "Out of RTP sessions?\n");
+		ast_free(tmp);
+		return NULL;
+	}
+	ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1);
 
 	if (sid) {
 		ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
@@ -774,13 +734,8 @@
 		ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
 		tmp->initiator = 1;
 	}
-	tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+
 	tmp->parent = client;
-	if (!tmp->rtp) {
-		ast_log(LOG_WARNING, "Out of RTP sessions?\n");
-		ast_free(tmp);
-		return NULL;
-	}
 	ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
 	ast_mutex_init(&tmp->lock);
 	ast_mutex_lock(&jinglelock);
@@ -791,79 +746,119 @@
 }
 
 /*! \brief Start new jingle channel */
-static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
+static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *p, int state, const char *title, const char *linkedid)
 {
 	struct ast_channel *tmp;
 	int fmt;
-	int what;
 	const char *str;
-
-	if (title)
+	char pass[JINGLE_MAX_ATTRLEN];
+	char user[JINGLE_MAX_ATTRLEN];
+	struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
+	struct sockaddr_in sin;
+
+	if (title) {
 		str = title;
-	else
-		str = i->them;
-	tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
+	} else {
+		str = p->them;
+	}
+	tmp = ast_channel_alloc(1, state, p->cid_num, p->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
 	if (!tmp) {
 		ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
 		return NULL;
 	}
 	tmp->tech = &jingle_tech;
 
+
+	/* setup ICE ufrag and pwd attributes */
+	snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
+	ast_copy_string(p->local_password, pass, sizeof(p->local_password));
+	snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
+	ast_copy_string(p->local_ufrag, user, sizeof(p->local_ufrag));
+
+	/* Create our ICE candidates */
+	ours1 = ast_calloc(1, sizeof(*ours1));
+	if (!ours1) {
+		return NULL;
+	}
+	ours2 = ast_calloc(1, sizeof(*ours2));
+	if (!ours2) {
+		return NULL;
+	}
+	ast_rtp_instance_get_local_address(p->rtp, &sin);
+	jingle_append_candidate(p, ours1, sin, 0);
+       	jingle_append_candidate(p, ours2, sin, 1);
+
 	/* Select our native format based on codec preference until we receive
 	   something from another device to the contrary. */
-	if (i->jointcapability)
-		what = i->jointcapability;
-	else if (i->capability)
-		what = i->capability;
-	else
-		what = global_capability;
+	if (client->capability) {
+		p->capability = client->capability;
+	} else {
+		p->capability = global_capability;
+	}
+
+	/* Nothing has been received from the remote Jingle peer yet */ 
+	p->peercapability = 0;
+	p->peernoncodeccapability = 0;
+	p->jointcapability = 0;
 
 	/* Set Frame packetization */
-	if (i->rtp)
-		ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
-
-	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
+	if (p->rtp) {
+		ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+	}
+
+	tmp->nativeformats = ast_codec_choose(&p->prefs, p->capability, 1);
 	fmt = ast_best_codec(tmp->nativeformats);
-
-	if (i->rtp) {
-		ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
-		ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
-	}
-	if (i->vrtp) {
-		ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
-		ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
-	}
-	if (state == AST_STATE_RING)
+	ast_log(LOG_NOTICE, "Codec initialized to : %s\n", ast_codec2str(fmt));
+
+	if (p->rtp) {
+		/* set file descriptors (RTP/RTCP) for audio channels */
+		ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(p->rtp, 0));
+		ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(p->rtp, 1));
+	}
+	if (p->vrtp) {
+		/* set file descriptors (RTP/RTCP) for video channels */
+		ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(p->vrtp, 0));
+		ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(p->vrtp, 1));
+	}
+
+	if (state == AST_STATE_RING) {
 		tmp->rings = 1;
+	}
+
 	tmp->adsicpe = AST_ADSI_UNAVAILABLE;
 	tmp->writeformat = fmt;
 	tmp->rawwriteformat = fmt;
 	tmp->readformat = fmt;
 	tmp->rawreadformat = fmt;
-	tmp->tech_pvt = i;
-
+	tmp->tech_pvt = p;
 	tmp->callgroup = client->callgroup;
 	tmp->pickupgroup = client->pickupgroup;
 	tmp->cid.cid_pres = client->callingpres;
-	if (!ast_strlen_zero(client->accountcode))
+	if (!ast_strlen_zero(client->accountcode)) {
 		ast_string_field_set(tmp, accountcode, client->accountcode);
-	if (client->amaflags)
+	}
+	if (client->amaflags) {
 		tmp->amaflags = client->amaflags;
-	if (!ast_strlen_zero(client->language))
+	}
+	if (!ast_strlen_zero(client->language)) {
 		ast_string_field_set(tmp, language, client->language);
-	if (!ast_strlen_zero(client->musicclass))
+	}
+	if (!ast_strlen_zero(client->musicclass)) {
 		ast_string_field_set(tmp, musicclass, client->musicclass);
-	i->owner = tmp;
+	}
+	p->owner = tmp;
 	ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
-	ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
+	ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));
 	/* Don't use ast_set_callerid() here because it will
 	 * generate an unnecessary NewCallerID event  */
-	tmp->cid.cid_ani = ast_strdup(i->cid_num);
-	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
-		tmp->cid.cid_dnid = ast_strdup(i->exten);
+	tmp->cid.cid_ani = ast_strdup(p->cid_num);
+	if (!ast_strlen_zero(p->exten) && strcmp(p->exten, "s")) {
+		tmp->cid.cid_dnid = ast_strdup(p->exten);
+	}
 	tmp->priority = 1;
-	if (i->rtp)
+	if (p->rtp) {
 		ast_jb_configure(tmp, &global_jbconf);
+	}
 	if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
 		ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
 		tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
@@ -874,33 +869,39 @@
 	return tmp;
 }
 
-static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
-{
-	iks *iq, *jingle = NULL;
+static int jingle_terminate(struct jingle *client, struct jingle_pvt *p, const char *causestring)
+{
+	iks *iq, *jingle, *reason, *cause;
 	int res = -1;
 
 	iq = iks_new("iq");
 	jingle = iks_new("jingle");
+	reason = iks_new("reason");
+	cause = iks_new(causestring ? causestring : "gone");
 	
-	if (iq) {
-		iks_insert_attrib(iq, "type", "set");
-		iks_insert_attrib(iq, "from", client->connection->jid->full);
-		iks_insert_attrib(iq, "to", p->them);
-		iks_insert_attrib(iq, "id", client->connection->mid);
-		ast_aji_increment_mid(client->connection->mid);
-		if (jingle) {
-			iks_insert_attrib(jingle, "action", action);
-			iks_insert_attrib(jingle, JINGLE_SID, p->sid);
-			iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
-			iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
-
-			iks_insert_node(iq, jingle);
-
-			ast_aji_send(client->connection, iq);
-			res = 0;
-		}
-	}
-	
+	if (!iq || !jingle || !reason || !cause) {
+		ast_log(LOG_ERROR, "Memory allocation error\n");
+		goto safeout;
+	}
+
+	iks_insert_attrib(iq, "type", "set");
+	iks_insert_attrib(iq, "from", client->connection->jid->full);
+	iks_insert_attrib(iq, "to", p->them);
+	iks_insert_attrib(iq, "id", client->connection->mid);
+	ast_aji_increment_mid(client->connection->mid);
+	iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
+	iks_insert_attrib(jingle, "action", "session-terminate");
+	iks_insert_attrib(jingle, JINGLE_SID, p->sid);
+
+	iks_insert_node(reason, cause);
+	iks_insert_node(jingle, reason);
+	iks_insert_node(iq, jingle);
+
+	res = ast_aji_send(client->connection, iq);
+
+safeout:
+	iks_delete(cause);
+	iks_delete(reason);	
 	iks_delete(jingle);
 	iks_delete(iq);
 	
@@ -921,7 +922,9 @@
 {
 	struct jingle_pvt *cur, *prev = NULL;
 	cur = client->p;
+
 	while (cur) {
+		/* take our jingle_pvt struct out of the list */
 		if (cur == p) {
 			if (prev)
 				prev->next = p->next;
@@ -932,31 +935,43 @@
 		prev = cur;
 		cur = cur->next;
 	}
-	if (p->ringrule)
+
+	if (p->ringrule) {
 		iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
-	if (p->owner)
+	}
+
+	if (p->owner) {
 		ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
-	if (p->rtp)
+	}
+
+	if (p->rtp) {
 		ast_rtp_instance_destroy(p->rtp);
-	if (p->vrtp)
+	}
+
+	if (p->vrtp) {
 		ast_rtp_instance_destroy(p->vrtp);
+	}
+
+	jingle_free_candidates(p->ourcandidates);
 	jingle_free_candidates(p->theircandidates);
 	ast_free(p);
 }
 
 
-static int jingle_newcall(struct jingle *client, ikspak *pak)
+static int jingle_incomingcall(struct jingle *client, ikspak *pak)
 {
 	struct jingle_pvt *p, *tmp = client->p;
 	struct ast_channel *chan;
 	int res;
 	iks *codec, *content, *description;
 	char *from = NULL;
+	struct ast_rtp_codecs *rtpcodecs = NULL;
 
 	/* Make sure our new call doesn't exist yet */
 	from = iks_find_attrib(pak->x,"to");
-	if(!from)
+	if(!from) {
 		from = client->connection->jid->full;
+	}
 
 	while (tmp) {
 		if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
@@ -973,6 +988,7 @@
  		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);
+			jingle_response(client, pak, "service-unavailable", NULL);
  			return -1;
  		}
  	}
@@ -980,32 +996,55 @@
 	p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
 	if (!p) {
 		ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
+		jingle_response(client, pak, "resource-constraint", NULL);
 		return -1;
 	}
+
 	chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
 	if (!chan) {
 		jingle_free_pvt(client, p);
+		jingle_response(client, pak, "resource-constraint", NULL);
 		return -1;
 	}
+
 	ast_mutex_lock(&p->lock);
 	ast_copy_string(p->them, pak->from->full, sizeof(p->them));
 	if (iks_find_attrib(pak->query, JINGLE_SID)) {
-		ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
-				sizeof(p->sid));
+		ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID), sizeof(p->sid));
 	}
 	
 	/* content points to the first <content/> tag */	
 	content = iks_child(iks_child(pak->x));
+	if (!content) {
+		ast_log(LOG_WARNING, "No content tag found, aborting\n");
+		ast_hangup(chan);
+		jingle_free_pvt(client, p);
+		jingle_response(client, pak, "bad-request", NULL);
+		return -1;
+	}
+
+	rtpcodecs = ast_rtp_instance_get_codecs(p->rtp);
+	if (!rtpcodecs) {
+		ast_log(LOG_WARNING, "RTP instance has no codecs\n");
+		ast_hangup(chan);
+		jingle_free_pvt(client, p);
+		jingle_response(client, pak, "resource-constraint", NULL);
+		return -1;
+	}
+
 	while (content) {
-		description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
+		/* We record the audio and video contents advertized by the
+		 * remote Jingle client here. We'll compare that with our
+		 * local capabilities later */
+		description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS);
 		if (description) {
-			/* audio content found */
+			/* process audio content */
 			codec = iks_child(iks_child(content));
 		        ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
 
 			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);
+				ast_rtp_codecs_payloads_set_m_type(rtpcodecs, p->rtp, atoi(iks_find_attrib(codec, "id")));
+				ast_rtp_codecs_payloads_set_rtpmap_type(rtpcodecs, p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
 				codec = iks_next(codec);
 			}
 		}
@@ -1013,20 +1052,34 @@
 		description = NULL;
 		codec = NULL;
 
-		description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
+		description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS);
 		if (description) {
-			/* video content found */
+			/* process video content */
 			codec = iks_child(iks_child(content));
 		        ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
 
 			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);
+				ast_rtp_codecs_payloads_set_m_type(rtpcodecs, p->rtp, atoi(iks_find_attrib(codec, "id")));
+				ast_rtp_codecs_payloads_set_rtpmap_type(rtpcodecs, p->rtp, atoi(iks_find_attrib(codec, "id")), "video", iks_find_attrib(codec, "name"), 0);
 				codec = iks_next(codec);
 			}
 		}
 		
 		content = iks_next(content);
+	}
+
+	/* now we can acknowledge the session-initiate message, and possibly
+	 * terminate the session immediatly in case of an error */
+	jingle_response(client, pak, NULL, NULL);
+
+	ast_rtp_codecs_payload_formats(rtpcodecs, &p->peercapability, &p->peernoncodeccapability);
+	p->jointcapability = p->capability & p->peercapability;
+	if (!p->jointcapability) {
+		ast_debug(1, "No matching codec found.\n");
+		jingle_terminate(client, p, "failed-application");
+		p->alreadygone = 1;
+		ast_hangup(chan);
+		return -1;
 	}
 
 	ast_mutex_unlock(&p->lock);
@@ -1036,18 +1089,18 @@
 	switch (res) {
 	case AST_PBX_FAILED:
 		ast_log(LOG_WARNING, "Failed to start PBX :(\n");
-		jingle_response(client, pak, "service-unavailable", NULL);
+		jingle_terminate(client, p, "failed-application");
+		p->alreadygone = 1;
+		ast_hangup(chan);
 		break;
 	case AST_PBX_CALL_LIMIT:
 		ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
-		jingle_response(client, pak, "service-unavailable", NULL);
+		jingle_terminate(client, p, "failed-application");
+		p->alreadygone = 1;
+		ast_hangup(chan);
 		break;
 	case AST_PBX_SUCCESS:
-		jingle_response(client, pak, NULL, NULL);
-		jingle_create_candidates(client, p,
-					 iks_find_attrib(pak->query, JINGLE_SID),
-					 iks_find_attrib(pak->x, "from"));
-		/* nothing to do */
+		/* nothing to do here */
 		break;
 	}
 
@@ -1067,14 +1120,17 @@
 	tmp = p->theircandidates;
 	p->laststun = time(NULL);
 	while (tmp) {
-		char username[256];
+		struct stun_credentials credentials;
 		hp = ast_gethostbyname(tmp->ip, &ahp);
 		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->ufrag, p->ourcandidates->ufrag);
-
-		ast_rtp_instance_stun_request(p->rtp, &sin, username);
+		ast_copy_string(credentials.local_ufrag, p->local_ufrag, sizeof(credentials.local_ufrag));
+		ast_copy_string(credentials.remote_ufrag, p->remote_ufrag, sizeof(credentials.remote_ufrag));
+		ast_copy_string(credentials.local_password, p->local_password, sizeof(credentials.local_password));
+		ast_copy_string(credentials.remote_password, p->remote_password, sizeof(credentials.remote_password));
+
+		ast_rtp_instance_stun_request(p->rtp, &sin, &credentials);
 		tmp = tmp->next;
 	}
 	return 1;
@@ -1108,17 +1164,20 @@
 			continue;
 		}
 		if(!strcasecmp(iks_name(traversenodes), "transport")) {
+			ast_copy_string(p->remote_ufrag, iks_find_attrib(traversenodes, "ufrag"), sizeof(p->remote_ufrag));
+			ast_copy_string(p->remote_password, iks_find_attrib(traversenodes, "pwd"), sizeof(p->remote_password));
 			traversenodes = iks_child(traversenodes);
 			continue;
 		}
 
 		if(!strcasecmp(iks_name(traversenodes), "candidate")) {
+			ast_log(LOG_NOTICE, "Processing candidate\n");
 			newcandidate = ast_calloc(1, sizeof(*newcandidate));
 			if (!newcandidate)
 				return 0;
+			ast_copy_string(newcandidate->id, iks_find_attrib(traversenodes, "id"), sizeof(newcandidate->id));
 			ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
 			newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
-			ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
 			if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
 				newcandidate->protocol = AJI_PROTOCOL_UDP;
 			else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
@@ -1135,7 +1194,6 @@
 
 			newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
 			newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
-			newcandidate->next = NULL;
 		
 			newcandidate->next = p->theircandidates;
 			p->theircandidates = newcandidate;
@@ -1145,6 +1203,7 @@
 		}
 		traversenodes = iks_next(traversenodes);
 	}
+	ast_log(LOG_NOTICE, "Candidates parsed\n");
 	
 	receipt = iks_new("iq");
 	iks_insert_attrib(receipt, "type", "result");
@@ -1161,10 +1220,29 @@
 static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
 {
 	struct ast_frame *f;
+	struct stun_credentials credentials;
 
 	if (!p->rtp)
 		return &ast_null_frame;
-	f = ast_rtp_instance_read(p->rtp, 0);
+
+	ast_copy_string(credentials.local_ufrag, p->local_ufrag, sizeof(credentials.local_ufrag));
+	ast_copy_string(credentials.remote_ufrag, p->remote_ufrag, sizeof(credentials.remote_ufrag));
+	ast_copy_string(credentials.local_password, p->local_password, sizeof(credentials.local_password));
+	ast_copy_string(credentials.remote_password, p->remote_password, sizeof(credentials.remote_password));
+
+	switch (ast->fdno) {
+		case 0:
+			/* RTP auudio */
+			f = ast_rtp_instance_read(p->rtp, 0, &credentials);
+			break;
+		case 1:
+			/* RTCP audio control channel */
+			f = ast_rtp_instance_read(p->rtp, 1, &credentials);
+			break;
+		default:
+			f = &ast_null_frame;
+	}
+
 	jingle_update_stun(p->parent, p);
 	if (p->owner) {
 		/* We already hold the channel lock */
@@ -1357,6 +1435,7 @@
 
 	return -1;
 }
+
 static int jingle_transmit_invite(struct jingle_pvt *p)
 {
 	struct jingle *aux = NULL;
@@ -1390,7 +1469,8 @@

[... 1106 lines stripped ...]



More information about the svn-commits mailing list