[asterisk-commits] branch mogorman/asterisk-xmpp r19702 - in /team/mogorman/asterisk-xmpp: chann...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Apr 12 22:54:09 MST 2006


Author: markster
Date: Thu Apr 13 00:54:08 2006
New Revision: 19702

URL: http://svn.digium.com/view/asterisk?rev=19702&view=rev
Log:
Start making the channel driver look more like a real channel driver.

Modified:
    team/mogorman/asterisk-xmpp/channels/chan_jingle.c
    team/mogorman/asterisk-xmpp/include/asterisk/jingle.h
    team/mogorman/asterisk-xmpp/res/res_jabber.c

Modified: team/mogorman/asterisk-xmpp/channels/chan_jingle.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/channels/chan_jingle.c?rev=19702&r1=19701&r2=19702&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/channels/chan_jingle.c (original)
+++ team/mogorman/asterisk-xmpp/channels/chan_jingle.c Thu Apr 13 00:54:08 2006
@@ -63,6 +63,7 @@
 #include "asterisk/manager.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/utils.h"
+#include "asterisk/causes.h"
 #include "asterisk/jabber.h"
 #include "asterisk/jingle.h"
 
@@ -89,13 +90,13 @@
 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_answer2(struct jingle *client, ikspak *pak);
+static int jingle_newcall(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);
 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
-static struct jingle_pvt *jingle_alloc(char *data, int format);
+static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
 
 /* PBX interface structure for channel registration */
 static const struct ast_channel_tech jingle_tech = {
@@ -125,7 +126,7 @@
 static struct io_context *io;		/*!< The IO context */
 static struct in_addr __ourip;
 /*----- RTP interface functions */
-static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, int codecs, int nat_active);
+static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
 static struct ast_rtp *jingle_get_rtp_peer(struct ast_channel *chan);
 static int jingle_get_codec(struct ast_channel *chan);
 
@@ -237,7 +238,7 @@
 	return p->peercapability;
 }
 
-static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, int codecs, int nat_active)
+static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
 {
 	struct jingle_pvt *p;
 
@@ -279,10 +280,10 @@
 		p = p->next;
 	}
 	
-	hp = ast_gethostbyname(p->candidates->ip, &ahp);
+	hp = ast_gethostbyname(p->theircandidates->ip, &ahp);
         sin.sin_family = AF_INET;
 	memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
-	sin.sin_port = htons(p->candidates->port);
+	sin.sin_port = htons(p->theircandidates->port);
 	if (p->rtp && sin.sin_port) {
 		ast_rtp_set_peer(p->rtp, &sin);
 		ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(iabuf,sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
@@ -355,10 +356,9 @@
 	return 1;
 }
 
-static int jingle_create_candidates(struct jingle *client,ikspak *pak)
+static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, ikspak *pak)
 {
 	struct jingle_candidate *tmp;
-	struct jingle_pvt *p = client->p;
 	struct aji_client *c = client->connection;
 	struct sockaddr_in sin;
 	struct sockaddr_in dest;
@@ -366,14 +366,21 @@
 
 	iks *iq, *jingle, *candidate;
 	char user[17], pass[17], preference[5], port[7];
-	tmp = p->candidates;
+
+
+	tmp = client->ourcandidates;
+
 	iq = iks_new("iq");
 	jingle = iks_new(GOOGLE_NODE);
 	candidate = iks_new("candidate");
+	if (!iq || !jingle || !candidate) {
+		ast_log(LOG_WARNING, "out of memory!\n");
+		goto safeout;
+	}
+
 	iks_insert_node(iq,jingle);
 	iks_insert_node(jingle,candidate);
-	
-	
+		
 	while(p) {
 		if(!strcasecmp(p->sid,iks_find_attrib(pak->query,GOOGLE_SID))) {
 			break;
@@ -424,7 +431,7 @@
 		iks_send(c->p,iq);
 		tmp=tmp->next;
 	}
-	if(!p->candidates) { /*send default stun, and local, and relay */
+	if(!p->theircandidates) { /*send default stun, and local, and relay */
 		snprintf(user, sizeof(user),"%08x%08x",thread_safe_rand(),thread_safe_rand());
 		snprintf(pass, sizeof(pass),"%08x%08x",thread_safe_rand(),thread_safe_rand());
 		iks_insert_attrib(iq,"from", c->jid->full);
@@ -473,9 +480,13 @@
 		iks_insert_attrib(candidate, "type", "relay");
 		iks_send(c->p,iq);
 	}
-	iks_delete(candidate);
-	iks_delete(jingle);
-	iks_delete(iq);
+safeout:
+	if (iq)
+		iks_delete(iq);
+	if (jingle)
+		iks_delete(jingle);
+	if (candidate)
+		iks_delete(candidate);
 	return 1;
 }
 
@@ -612,7 +623,7 @@
 	return 1;
 }
 
-static struct jingle_pvt *jingle_alloc2(struct jingle *client, ikspak *pak)
+static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid)
 {
 	struct jingle_pvt *tmp = client->p;
 
@@ -620,7 +631,16 @@
 		return NULL;
 	}
 	tmp->rtp =  ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-
+	if (!tmp->rtp) {
+		ast_log(LOG_WARNING, "Out of RTP sessions?\n");
+		free(tmp);
+		return NULL;
+	}
+	ast_copy_string(tmp->from, from, sizeof(tmp->from));
+	if (sid)
+		ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
+	else
+		snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
 	ast_mutex_init(&tmp->lock);
 	ast_mutex_lock(&jinglelock);
 	tmp->next = client->p;
@@ -629,49 +649,232 @@
 	return tmp;
 }
 
-static int jingle_answer2(struct jingle *client,ikspak *pak)
+/*! \brief Start new jingle channel */
+static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title)
+{
+	struct ast_channel *tmp;
+	int fmt;
+	int what;
+
+	tmp = ast_channel_alloc(1);
+	if (!tmp) {
+		ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
+		return NULL;
+	}
+	tmp->tech = &jingle_tech;
+
+	/* 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;
+	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
+	fmt = ast_best_codec(tmp->nativeformats);
+
+	if (title)
+		ast_string_field_build(tmp, name, "Jingle/%s-%04lx", title, ast_random() & 0xffff);
+	else
+		ast_string_field_build(tmp, name, "Jingle/%s-%04lx", i->from, ast_random() & 0xffff);
+
+	if (i->rtp) {
+		tmp->fds[0] = ast_rtp_fd(i->rtp);
+		tmp->fds[1] = ast_rtcp_fd(i->rtp);
+	}
+	if (i->vrtp) {
+		tmp->fds[2] = ast_rtp_fd(i->vrtp);
+		tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+	}
+	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->callgroup = client->callgroup;
+	tmp->pickupgroup = client->pickupgroup;
+	tmp->cid.cid_pres = client->callingpres;
+	if (!ast_strlen_zero(client->accountcode))
+		ast_string_field_set(tmp, accountcode, client->accountcode);
+	if (client->amaflags)
+		tmp->amaflags = client->amaflags;
+	if (!ast_strlen_zero(client->language))
+		ast_string_field_set(tmp, language, client->language);
+	if (!ast_strlen_zero(client->musicclass))
+		ast_string_field_set(tmp, musicclass, client->musicclass);
+	i->owner = tmp;
+	ast_mutex_lock(&usecnt_lock);
+	usecnt++;
+	ast_mutex_unlock(&usecnt_lock);
+	ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
+	ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
+	if (!ast_strlen_zero(i->cid_num)) 
+		tmp->cid.cid_num = ast_strdup(i->cid_num);
+	if (!ast_strlen_zero(i->cid_name))
+		tmp->cid.cid_name = ast_strdup(i->cid_name);
+	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
+		tmp->cid.cid_dnid = ast_strdup(i->exten);
+	tmp->priority = 1;
+	ast_setstate(tmp, state);
+	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;
+		ast_hangup(tmp);
+		tmp = NULL;
+	}
+	return tmp;
+}
+
+static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr)
+{
+	iks *response, *error=NULL, *reason=NULL;
+	int res = -1;
+		
+	response = iks_new("iq");
+	if (response) {
+		iks_insert_attrib(response,"type","result");
+		iks_insert_attrib(response,"from", client->connection->jid->full);
+		iks_insert_attrib(response,"to",iks_find_attrib(pak->x,"from"));
+		iks_insert_attrib(response,"id",iks_find_attrib(pak->x,"id"));
+		if (reasonstr) {
+			error = iks_new("error");
+			if (error) {
+				iks_insert_attrib(error, "type", "cancel");
+				reason = iks_new(reasonstr);
+				if (reason)
+					iks_insert_node(error, reason);
+				iks_insert_node(response, error);
+			}
+		}
+		iks_send(client->connection->p, response);
+		if (reason)
+			iks_delete(reason);
+		if (error)
+			iks_delete(error);
+		iks_delete(response);
+		res = 0;
+	}
+	return res;
+}
+
+static void jingle_free_candidates(struct jingle_candidate *candidate)
+{
+	struct jingle_candidate *last;
+	while (candidate) {
+		last = candidate;
+		candidate = candidate->next;
+		free(last);
+	}
+}
+
+static struct jingle_candidate *jingle_dup_candidates(struct jingle_candidate *candidate)
+{
+	struct jingle_candidate *newcan=NULL, *prev=NULL, *tmp;
+	while (candidate) {
+		tmp = malloc(sizeof(struct jingle_candidate));
+		if (tmp) {
+			memcpy(tmp, candidate, sizeof(struct jingle_candidate));
+			tmp->next = NULL;
+			if (prev) 
+				prev->next = tmp;
+			else
+				newcan = tmp;
+			prev = tmp;
+		}
+		candidate = candidate->next;
+	}
+	return newcan;
+}
+
+static void jingle_free(struct jingle *client, struct jingle_pvt *p)
+{
+	struct jingle_pvt *cur, *prev = NULL;
+	cur = client->p;
+	while (cur) {
+		if (cur == p) {
+			if (prev)
+				prev->next = p->next;
+			else
+				client->p = p->next;
+			break;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+	if (p->owner)
+		ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
+	if (p->rtp)
+		ast_rtp_destroy(p->rtp);
+	if (p->vrtp)
+		ast_rtp_destroy(p->vrtp);
+	jingle_free_candidates(p->theircandidates);
+	free(p);
+}
+
+
+static int jingle_newcall(struct jingle *client, ikspak *pak)
 {
 	struct jingle_pvt *p ,*tmp = client->p;
-	struct aji_client *c = client->connection;
 	struct ast_channel *chan;
-	iks *accept, *codec;
-
-
-	codec = iks_child(iks_child(iks_child(pak->x)));
-	chan = ast_channel_alloc(1);
-	chan->tech = &jingle_tech;
+	int res;
+	iks *codec;
+
+	/* Make sure our new call doesn't exist yet */
 	while(tmp) {
-		if(iks_find_with_attrib(pak->x,GOOGLE_NODE,GOOGLE_SID,tmp->sid))
-		{
+		if (iks_find_with_attrib(pak->x, GOOGLE_NODE,GOOGLE_SID, tmp->sid)) {
+			ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
+			jingle_response(client, pak, "out-of-order");
 			return -1;
 		}
 		tmp=tmp->next;
 	}
-	p = jingle_alloc2(client, pak);
-	ast_mutex_lock(&p->lock);
-	if(iks_find_attrib(pak->x,"from"))
-		ast_copy_string(p->from,iks_find_attrib(pak->x,"from"),sizeof(p->from));
-	if(iks_find_attrib(pak->query,GOOGLE_SID)) {
-		ast_copy_string(p->sid,iks_find_attrib(pak->query,GOOGLE_SID),sizeof(p->sid));
-	}
-
-	while(codec) {
-		ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec,"id")));
-		ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec,"id")), "audio", iks_find_attrib(codec,"name"));
-		ast_verbose("yatta!!\n");
-		codec= iks_next(codec);
-	}
-	ast_pbx_start(chan);
-	p->owner = chan;
-	ast_mutex_unlock(&p->lock);
-	accept = iks_new("iq");
-	iks_insert_attrib(accept,"type","result");
-	iks_insert_attrib(accept,"from",c->jid->full);
-	iks_insert_attrib(accept,"to",iks_find_attrib(pak->x,"from"));
-	iks_insert_attrib(accept,"id",iks_find_attrib(pak->x,"id"));
-	iks_send(c->p,accept);
-	iks_delete(accept);
-	jingle_create_candidates(client,pak);
+	
+	p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query,GOOGLE_SID));
+	if (!p) {
+		ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
+		return -1;
+	}
+	chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user);
+	if (chan) {
+		ast_mutex_lock(&p->lock);
+		ast_copy_string(p->from, pak->from->full, sizeof(p->from));
+		if(iks_find_attrib(pak->query,GOOGLE_SID)) {
+			ast_copy_string(p->sid,iks_find_attrib(pak->query,GOOGLE_SID),sizeof(p->sid));
+		}
+	
+		codec = iks_child(iks_child(iks_child(pak->x)));
+		while(codec) {
+			ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec,"id")));
+			ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec,"id")), "audio", iks_find_attrib(codec,"name"));
+			ast_verbose("yatta!!\n");
+			codec= iks_next(codec);
+		}
+		ast_mutex_unlock(&p->lock);
+		res = ast_pbx_start(chan);
+		jingle_create_candidates(client, p, pak);
+
+		switch (res) {
+		case AST_PBX_FAILED:
+			ast_log(LOG_WARNING, "Failed to start PBX :(\n");
+			jingle_response(client, pak, "service-unavailable");
+			break;
+		case AST_PBX_CALL_LIMIT:
+			ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
+			jingle_response(client, pak, "service-unavailable");
+			break;
+		case AST_PBX_SUCCESS:
+			jingle_response(client, pak, NULL);
+			/* nothing to do */
+			break;
+		}
+	} else {
+		jingle_free(client, p);
+	}
 	return 1;
 }
 
@@ -732,8 +935,8 @@
 			ast_rtp_set_peer(p->rtp, &sin);
 			ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(iabuf,sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
 		}
-		newcandidate->next = p->candidates;
-		p->candidates = newcandidate;
+		newcandidate->next = p->theircandidates;
+		p->theircandidates = newcandidate;
 		ast_verbose("sending\n");	
 		receipt = iks_new("iq");
 		iks_insert_attrib(receipt,"type","result");
@@ -789,24 +992,44 @@
 	return fr;
 }
 
-static int jingle_write(struct ast_channel *ast, struct ast_frame *f)
+/*! \brief Send frame to media channel (rtp) */
+static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
 {
 	struct jingle_pvt *p = ast->tech_pvt;
-	int res = -1;
-	int isoutbound;
-
-	/* Just queue for delivery to the other side */
-	ast_mutex_lock(&p->lock);
-//	isoutbound = IS_OUTBOUND(ast, p);
-	if (f && (f->frametype == AST_FRAME_VOICE)) 
-		check_bridge(p, isoutbound);
-//	if (!p->alreadymasqed)
-//		res = jingle_queue_frame(p, isoutbound, f, ast);
-//	else {
-//		ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
-//		res = 0;
-//	}
-	ast_mutex_unlock(&p->lock);
+	int res = 0;
+
+	switch (frame->frametype) {
+	case AST_FRAME_VOICE:
+		if (!(frame->subclass & ast->nativeformats)) {
+			ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
+				frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
+			return 0;
+		}
+		if (p) {
+			ast_mutex_lock(&p->lock);
+			if (p->rtp) {
+				res =  ast_rtp_write(p->rtp, frame);
+			}
+			ast_mutex_unlock(&p->lock);
+		}
+		break;
+	case AST_FRAME_VIDEO:
+		if (p) {
+			ast_mutex_lock(&p->lock);
+			if (p->vrtp) {
+				res =  ast_rtp_write(p->vrtp, frame);
+			}
+			ast_mutex_unlock(&p->lock);
+		}
+		break;
+	case AST_FRAME_IMAGE:
+		return 0;
+		break;
+	default: 
+		ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n", frame->frametype);
+		return 0;
+	}
+
 	return res;
 }
 
@@ -941,10 +1164,9 @@
 /*! \brief Hangup a call through the jingle proxy channel */
 static int jingle_hangup(struct ast_channel *ast)
 {
-#if 0 
 	struct jingle_pvt *p = ast->tech_pvt;
 	struct jingle *peer = NULL;
-	struct aji_client *client = NULL;
+	struct jingle *client = NULL;
 	client = ast_aji_get_client("asterisk");
 	int isoutbound;
 	struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
@@ -954,67 +1176,19 @@
 	const char *status;
 
 	ast_mutex_lock(&p->lock);
-	if (isoutbound) {
-//		status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
-		if(status)
-			pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
-//		p->chan = NULL;
-//		p->launchedpbx = 0;
-	} else
-		p->owner = NULL;
+	p->owner = NULL;
 	ast->tech_pvt = NULL;
-	
+	if (!p->alreadygone) {
+		
+	}
+	ast_mutex_unlock(&p->lock);
 	ast_mutex_lock(&usecnt_lock);
 	usecnt--;
 	ast_mutex_unlock(&usecnt_lock);
-	
-	if (!p->owner ) {
-		/* Okay, done with the private part now, too. */
-//		glaredetect = p->glaredetect;
-		/* If we have a queue holding, don't actually destroy p yet, but
-		   let jingle_queue do it. */
-//		if (p->glaredetect)
-//			p->cancelqueue = 1;
-		ast_mutex_unlock(&p->lock);
-		/* Remove from list */
-		ast_mutex_lock(&jinglelock);
-
-		if((peer = find_jingle(client,pak)))
-			cur = peer->p;
-		while(cur) {
-			if (cur == p) {
-				if (prev)
-					prev->next = cur->next;
-				else
-					peer->p = cur->next;
-				break;
-			}
-			prev = cur;
-			cur = cur->next;
-		}
-		ast_mutex_unlock(&jinglelock);
-		/* Grab / release lock just in case */
-		ast_mutex_lock(&p->lock);
-		ast_mutex_unlock(&p->lock);
-		/* And destroy */
-/*		if (!glaredetect) {
-			ast_mutex_destroy(&p->lock);
-			free(p);
-		}*/
-		return 0;
-	}
-//	if (p->chan )
-//		/* Need to actually hangup since there is no PBX */
-//		ochan = p->chan;
-//	else
-//		jingle_queue_frame(p, isoutbound, &f, NULL);
-	ast_mutex_unlock(&p->lock);
-	if (ochan)
-		ast_hangup(ochan);
-#endif
 	return 0;
 }
 
+#if 0
 /*! \brief Create a call structure */
 static struct jingle_pvt *jingle_alloc(char *data, int format)
 {
@@ -1025,31 +1199,22 @@
 	}
 	return tmp;
 }
-
-/*! \brief Start new jingle channel */
-static struct ast_channel *jingle_new(struct jingle_pvt *p, int state)
-{
-	struct ast_channel *tmp;
-
-	tmp = ast_channel_alloc(1);
-	ast_mutex_lock(&usecnt_lock);
-	usecnt++;
-	ast_mutex_unlock(&usecnt_lock);
-	ast_update_use_count();
-	return tmp;
-}
-
+#endif
 
 /*! \brief Part of PBX interface */
 static struct ast_channel *jingle_request(const char *type, int format, void *data, int *cause)
 {
+#if 0
 	struct jingle_pvt *p;
 	struct ast_channel *chan = NULL;
-
+	
 	p = jingle_alloc(data, format);
 	if (p)
 		chan = jingle_new(p, AST_STATE_DOWN);
 	return chan;
+#endif	
+
+	return NULL;
 }
 
 #if 0 
@@ -1059,7 +1224,7 @@
 	struct jingle_pvt *p=NULL;
 	struct jingle *peer=NULL;
 	struct jingle_candidate *tmp;
-	struct aji_client *client = NULL;
+	struct jingle *client = NULL;
 	client = ast_aji_get_client("asterisk");
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
@@ -1097,9 +1262,10 @@
 	struct jingle *client= ASTOBJ_REF((struct jingle *) udata);;
 	
 	ast_verbose("WOOHOO!!!\n");
-	if(iks_find_with_attrib(pak->x,GOOGLE_NODE,"type",JINGLE_INITIATE)) 
-		jingle_answer2(client, pak);
-	else if(iks_find_with_attrib(pak->x,GOOGLE_NODE,"type",GOOGLE_NEGOTIATE)) {
+	if(iks_find_with_attrib(pak->x,GOOGLE_NODE,"type",JINGLE_INITIATE)) {
+		/* New call */
+		jingle_newcall(client, pak);
+	} else if(iks_find_with_attrib(pak->x,GOOGLE_NODE,"type",GOOGLE_NEGOTIATE)) {
 		jingle_add_candidate(client,pak);
 		if(flipflop == 2) {
 			flipflop = 0;
@@ -1123,9 +1289,9 @@
 static struct jingle_candidate *jingle_create_candidate(char *args)
 {
 	char *name, *type, *preference, *protocol;
-	struct axi_candidate *res;
-	res= malloc(sizeof(struct axi_candidate));
-	memset(res,0,sizeof(struct axi_candidate));
+	struct jingle_candidate *res;
+	res= malloc(sizeof(struct jingle_candidate));
+	memset(res,0,sizeof(struct jingle_candidate));
 	if(args)
 		name = args;
 	if((args = strchr(args,','))) {
@@ -1150,17 +1316,17 @@
 	}
 	if(protocol) {
 		if(!strcasecmp("udp",protocol))
-			res->protocol=AXI_PROTOCOL_UDP;
+			res->protocol=AJI_PROTOCOL_UDP;
 		if(!strcasecmp("ssltcp",protocol))
-			res->protocol=AXI_PROTOCOL_SSLTCP;
+			res->protocol=AJI_PROTOCOL_SSLTCP;
 	}
 	if(type) {
 		if(!strcasecmp("stun",type))
-			res->type = AXI_CONNECT_STUN;
+			res->type = AJI_CONNECT_STUN;
 		if(!strcasecmp("local",type))
-			res->type = AXI_CONNECT_LOCAL;
+			res->type = AJI_CONNECT_LOCAL;
 		if(!strcasecmp("relay",type))
-			res->type = AXI_CONNECT_RELAY;
+			res->type = AJI_CONNECT_RELAY;
 	}
 
 	return res;
@@ -1168,7 +1334,7 @@
 
 static int jingle_create_member(char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct jingle *member)
 {
-	struct aji_client *client=NULL;
+	struct aji_client *client;
 	if(!member)	
 		ast_log(LOG_WARNING, "Out of memory.\n");
 	ast_copy_string(member->name, label, sizeof(member->name));
@@ -1189,8 +1355,8 @@
 		else if (!strcasecmp(var->name, "candidate")) {
 			candidate = jingle_create_candidate(var->value);
 			if(candidate) {
-				candidate->next = client->ourcandidates;
-				client->ourcandidates = canidate;
+				candidate->next = member->ourcandidates;
+				member->ourcandidates = candidate;
 			}
 		}
 		else if (!strcasecmp(var->name, "connection")) {
@@ -1223,6 +1389,7 @@
 	struct jingle *member;
 	struct ast_codec_pref prefs;
 	struct aji_client_container *clients;
+	struct jingle_candidate *global_candidates = NULL;
 
 	cfg = ast_config_load(JINGLE_CONFIG);
 	if(!cfg) {
@@ -1246,8 +1413,8 @@
 		else if (!strcasecmp(var->name, "candidate")) {
 			candidate = jingle_create_candidate(var->value);
 			if(candidate) {
-				candidate->next = client->ourcandidates;
-				client->ourcandidates = canidate;
+				candidate->next = global_candidates;
+				global_candidates = candidate;
 			}
 		}
 
@@ -1265,6 +1432,7 @@
 				ast_copy_string(member->user, "guest", sizeof(member->user));
 				ast_copy_string(member->context, context, sizeof(member->context));
 				member->allowguest=allowguest;
+				member->ourcandidates = jingle_dup_candidates(global_candidates);
 				member->prefs=prefs;
 				while(var) {
 					if(!strcasecmp(var->name,"disallow"))
@@ -1276,8 +1444,8 @@
 					else if (!strcasecmp(var->name, "candidate")) {
 						candidate = jingle_create_candidate(var->value);
 						if(candidate) {
-							candidate->next = client->ourcandidates;
-							client->ourcandidates = canidate;
+							candidate->next = member->ourcandidates;
+							member->ourcandidates = candidate;
 						}
 					}
 
@@ -1313,6 +1481,7 @@
 		}
 		cat = ast_category_browse(cfg,cat);
 	}
+	jingle_free_candidates(global_candidates);
 	return 1;
 }
 

Modified: team/mogorman/asterisk-xmpp/include/asterisk/jingle.h
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/include/asterisk/jingle.h?rev=19702&r1=19701&r2=19702&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/include/asterisk/jingle.h (original)
+++ team/mogorman/asterisk-xmpp/include/asterisk/jingle.h Thu Apr 13 00:54:08 2006
@@ -53,24 +53,37 @@
 	ast_mutex_t lock;			/* Channel private lock */
 	char sid[100];
 	char from[100];
-	struct jingle_candidate *candidates;
+	int capability;
+	struct ast_codec_pref prefs;
+	struct jingle_candidate *theircandidates;
+	char cid_num[80];		/*!< Caller ID num */
+	char cid_name[80];		/*!< Caller ID name */
+	char exten[80];			/* Called extension */
 	struct ast_channel *owner;		/* Master Channel */
 	struct ast_rtp *rtp;          /*!< RTP Session */
+	struct ast_rtp *vrtp;
 	int jointcapability;			/*!< Supported capability at both ends (codecs ) */
 	int peercapability;
-
 	struct jingle_pvt *next;		/* Next entity */
 };
 
 struct jingle {
 	ASTOBJ_COMPONENTS(struct jingle);
-	void *connection;
+	struct jingle_candidate *ourcandidates;
+	struct aji_client *connection;
 	struct jingle_pvt *p;
 	struct ast_codec_pref prefs;
+	int amaflags;				/*!< AMA Flags */
 	char user[100];
 	char context[100];
+	char accountcode[AST_MAX_ACCOUNT_CODE];	/* Account code */
 	int capability;
+	ast_group_t callgroup;			/*!< Call group */
+	ast_group_t pickupgroup;		/*!< Pickup group */
+	int callingpres;			/*!< Calling presentation */
 	int allowguest;
+	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
+	char musicclass[MAX_MUSICCLASS];/*!<  Music on Hold class */
 };
 
 struct jingle_container {

Modified: team/mogorman/asterisk-xmpp/res/res_jabber.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/res_jabber.c?rev=19702&r1=19701&r2=19702&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/res/res_jabber.c (original)
+++ team/mogorman/asterisk-xmpp/res/res_jabber.c Thu Apr 13 00:54:08 2006
@@ -286,15 +286,16 @@
 	ikspak *pak;
 	pak=iks_packet(node);
 	 
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
 	client = ASTOBJ_REF((struct aji_client *) udata);
 	
 	if(client->component == AJI_CLIENT) {
 		switch(type) {
 			case IKS_NODE_START:
 				if(client->usetls &&!iks_is_secure(client->p)) {
-					iks_start_tls(client->p);
+					if (iks_has_tls())
+						iks_start_tls(client->p);
+					else
+						ast_log(LOG_ERROR, "gnuTLS not installed.\n");
 					break;
 				}
 				if(!client->usesasl) {
@@ -395,11 +396,13 @@
 						sprintf(buffer2,"%s%s",pak->id,client->password);
 						ast_sha1_hash(buffer3,buffer2);
 						ast_verbose("Oh Really... %s\n",buffer2);
-						handshake = (char *)malloc((strlen("<handshake></handshake>")+strlen(buffer3)+1)*sizeof(char));
-						sprintf(handshake,"<handshake>%s</handshake>",buffer3);
-						iks_send_raw(client->p,handshake);
-						free(handshake);
-						handshake=NULL;
+						handshake = NULL;
+						asprintf(&handshake, "<handshake>%s</handshake>",buffer3);
+						if (handshake) {
+							iks_send_raw(client->p,handshake);
+							free(handshake);
+							handshake=NULL;
+						}
 						client->state=AJI_CONNECTED;
 						iks_filter_add_rule (client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
 						iks_filter_add_rule (client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
@@ -471,12 +474,10 @@
 
 static int aji_register_approve_handler(void *udata,ikspak *pak)
 {
-	int res=0;
 	struct aji_client *client;
 	iks *iq, *query;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
-	client =ASTOBJ_REF((struct aji_client *) udata);
+
+	client = ASTOBJ_REF((struct aji_client *) udata);
 	
 	iq = iks_new("iq");
 	query = iks_new("query");
@@ -501,8 +502,7 @@
 	int res=0;
 	struct aji_client *client;
 	char *node = NULL;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
+
 	client =ASTOBJ_REF((struct aji_client *) udata);
 	
 	if(!(node = iks_find_attrib(pak->query,"node"))) {
@@ -534,8 +534,7 @@
 	int res=0;
 	struct aji_client *client;
 	char *node = NULL;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
+
 	client =ASTOBJ_REF((struct aji_client *) udata);
 	if(!(node = iks_find_attrib(pak->query,"node"))) {
 		iks *iq, *query, *item;
@@ -614,8 +613,7 @@
 	int res=0;
 	struct aji_client *client;
 	char *node= NULL;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
+
 	client =ASTOBJ_REF((struct aji_client *) udata);
 	if(!(node = iks_find_attrib(pak->query,"node"))) {
 		iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
@@ -871,7 +869,7 @@
 	int res=0;
 	struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
 	while (res == IKS_OK) {
-		res =iks_recv(client->p,1);
+		res = iks_recv(client->p,1);
 		if(res==IKS_HOOK) {
 			ast_verbose("JABBER: Got hook event.\n");
 			break;
@@ -927,9 +925,7 @@
 	struct aji_client *client; 
 	struct aji_buddy *buddy=NULL;
 	iks *send;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
-	client =ASTOBJ_REF((struct aji_client *) udata);
+	client = ASTOBJ_REF((struct aji_client *) udata);
 	ASTOBJ_CONTAINER_TRAVERSE(&client->buddies,1, {
 		ASTOBJ_RDLOCK(iterator);
 		if(iterator->btype==AJI_TRANS ) {
@@ -967,9 +963,7 @@
 	struct aji_client *client; 
 	struct aji_buddy *buddy=NULL;
 	iks *regquery, *reguser, *regpass, *regiq;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
-	client =ASTOBJ_REF((struct aji_client *) udata);
+	client = ASTOBJ_REF((struct aji_client *) udata);
 	ASTOBJ_CONTAINER_TRAVERSE(&client->buddies,1, {
 		ASTOBJ_RDLOCK(iterator);
 		if(iterator->btype==AJI_TRANS)
@@ -1076,9 +1070,8 @@
 	iks *x;
 	struct aji_client *client;
 	struct aji_buddy *buddy;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
-	client =ASTOBJ_REF((struct aji_client *) udata);
+
+	client = ASTOBJ_REF((struct aji_client *) udata);
 	
 	ASTOBJ_CONTAINER_TRAVERSE(&client->buddies,1, {
 		ASTOBJ_RDLOCK(iterator);
@@ -1167,9 +1160,7 @@
 	int res=0;
 	struct aji_client *client;
 	iks *roster;
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
-	client =ASTOBJ_REF((struct aji_client *) udata);
+	client = ASTOBJ_REF((struct aji_client *) udata);
 	
 	if(client->state==AJI_DISCONNECTED) {
 		client->state=AJI_CONNECTING;
@@ -1204,8 +1195,6 @@
 	char buffer[41],*handshake;
 	iksha *sha;
 
-	client = (struct aji_client *)malloc(sizeof(struct aji_client));
-	memset(client,0,sizeof(struct aji_client));
 	client = ASTOBJ_REF((struct aji_client *) udata);
 
 	ast_verbose(" so long, state %d\n", client->state);
@@ -1218,11 +1207,14 @@
 					iks_sha_hash (sha,client->sid,strlen(client->sid),0);
 					iks_sha_hash (sha, (const unsigned char*)client->password, strlen (client->password), 1);
 					iks_sha_print (sha, buffer);
-					handshake = (char *)malloc((strlen("<handshake></handshake>")+strlen(buffer)+1)*sizeof(char));
-					sprintf(handshake,"<handshake>%s</handshake>",buffer);
 					iks_sha_delete (sha);		
-					res = iks_send_raw(client->p,handshake);
-					free(handshake);
+
+					handshake = NULL;
+					asprintf(&handshake, "<handshake>%s</handshake>",buffer);
+					if (handshake) {
+						res = iks_send_raw(client->p,handshake);
+						free(handshake);
+					}
 					handshake=NULL;
 					client->state=AJI_ALMOST;
 					break;
@@ -1252,22 +1244,38 @@
 	char *resource;
 	int connected = 0;
 	client->p = iks_stream_new(IKS_NS_CLIENT, client,aji_act_hook);
+	if (!client->p) {
+		ast_log(LOG_WARNING, "Failed to create stream for client '%s'!\n", client->name);
+		goto failed;
+	}
 	client->stack = iks_stack_new(8192,8192);
-
-	if(!client->f)
-		client->f= iks_filter_new();
-	else
+	if (!client->stack) {
+		ast_log(LOG_WARNING, "Failed to allocate stack for client '%s'\n", client->name);
+		goto failedstack;
+	}
+
+	if (client->f)
 		iks_filter_delete(client->f);
+
+	client->f = iks_filter_new();
+
+	if (!client->f) {
+		ast_log(LOG_WARNING, "Failed to create filter for client '%s'\n", client->name);
+		goto failedfilter;
+	}
 	
 	iks_set_log_hook(client->p,aji_log_hook);
 	if(!strchr(client->user,'/')) {
-		resource = (char *)malloc(strlen(client->user) + 9); /*+ 9 for asterisk / */
-		sprintf(resource,"%s/asterisk", client->user);
-		client->jid = iks_id_new(client->stack,resource);
-		free(resource);
+		resource = NULL;
+		asprintf(&resource,"%s/asterisk", client->user);
+		if (resource) {
+			client->jid = iks_id_new(client->stack,resource);
+			free(resource);
+		}
 	} else {
 		client->jid = iks_id_new(client->stack,client->user);
 	}
+
 	connected = iks_connect_via(client->p, client->serverhost, client->port, client->server);
 
 	if(connected== IKS_NET_NOCONN)
@@ -1275,6 +1283,17 @@
 	if(connected == IKS_NET_NODNS)
 		ast_verbose("JABBER ERROR: No DNS");
 	return 1;
+
+failedfilter:
+	iks_stack_delete(client->stack);
+	client->stack = NULL;
+	
+failedstack:
+	iks_parser_delete(client->p);
+	client->p = NULL;
+
+failed:	
+	return -1;
 }
 
 /*!
@@ -1594,7 +1613,7 @@
 		if(strcasecmp(cat, "general")) {
 			utype = ast_variable_retrieve(cfg, cat, "type");
 			if(utype) {
-				var =ast_variable_browse(cfg, cat);
+				var = ast_variable_browse(cfg, cat);
 				client = (struct aji_client *) malloc(sizeof(struct aji_client));
 				memset(client,0,sizeof(struct aji_client));
 				ASTOBJ_INIT(client);



More information about the asterisk-commits mailing list