[svn-commits] mmichelson: branch group/CCSS r225312 - in /team/group/CCSS: ./ channels/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Oct 21 17:16:58 CDT 2009


Author: mmichelson
Date: Wed Oct 21 17:16:55 2009
New Revision: 225312

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=225312
Log:
sync with trunk

Modified:
    team/group/CCSS/   (props changed)
    team/group/CCSS/channels/chan_iax2.c

Propchange: team/group/CCSS/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/CCSS/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Oct 21 17:16:55 2009
@@ -1,1 +1,1 @@
-/trunk:1-225252
+/trunk:1-225311

Modified: team/group/CCSS/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/chan_iax2.c?view=diff&rev=225312&r1=225311&r2=225312
==============================================================================
--- team/group/CCSS/channels/chan_iax2.c (original)
+++ team/group/CCSS/channels/chan_iax2.c Wed Oct 21 17:16:55 2009
@@ -820,6 +820,15 @@
 	int frames_received;
 	/*! num bytes used for calltoken ie, even an empty ie should contain 2 */
 	unsigned char calltoken_ie_len;
+	/*! hold all signaling frames from the pbx thread until we have a destination callno */
+	char hold_signaling;
+	/*! frame queue for signaling frames from pbx thread waiting for destination callno */
+	AST_LIST_HEAD_NOLOCK(signaling_queue, signaling_queue_entry) signaling_queue;
+};
+
+struct signaling_queue_entry {
+	struct ast_frame f;
+	AST_LIST_ENTRY(signaling_queue_entry) next;
 };
 
 /*! table of available call numbers */
@@ -1703,10 +1712,56 @@
 	return 0;
 }
 
+static void free_signaling_queue_entry(struct signaling_queue_entry *s)
+{
+	ast_free(s->f.data.ptr);
+	ast_free(s);
+}
+
+/*! \brief This function must be called once we are sure the other side has
+ *  given us a call number.  All signaling is held here until that point. */
+static void send_signaling(struct chan_iax2_pvt *pvt)
+{
+	struct signaling_queue_entry *s = NULL;
+
+	while ((s = AST_LIST_REMOVE_HEAD(&pvt->signaling_queue, next))) {
+		iax2_send(pvt, &s->f, 0, -1, 0, 0, 0);
+		free_signaling_queue_entry(s);
+	}
+	pvt->hold_signaling = 0;
+}
+
+/*! \brief All frames other than that of type AST_FRAME_IAX must be held until
+ *  we have received a destination call number. */
+static int queue_signalling(struct chan_iax2_pvt *pvt, struct ast_frame *f)
+{
+	struct signaling_queue_entry *new;
+
+	if (f->frametype == AST_FRAME_IAX || !pvt->hold_signaling) {
+		return 1; /* do not queue this frame */
+	} else if (!(new = ast_calloc(1, sizeof(struct signaling_queue_entry)))) {
+		return -1;  /* out of memory */
+	}
+
+	memcpy(&new->f, f, sizeof(new->f)); /* copy ast_frame into our queue entry */
+
+	if (new->f.datalen) { /* if there is data in this frame copy it over as well */
+		if (!(new->f.data.ptr = ast_calloc(1, new->f.datalen))) {
+			free_signaling_queue_entry(new);
+			return -1;
+		}
+		memcpy(new->f.data.ptr, f->data.ptr, sizeof(*new->f.data.ptr));
+	}
+	AST_LIST_INSERT_TAIL(&pvt->signaling_queue, new, next);
+
+	return 0;
+}
+
 static void pvt_destructor(void *obj)
 {
 	struct chan_iax2_pvt *pvt = obj;
 	struct iax_frame *cur = NULL;
+	struct signaling_queue_entry *s = NULL;
 
 	ast_mutex_lock(&iaxsl[pvt->callno]);
 
@@ -1724,6 +1779,10 @@
 	}
 
 	ast_mutex_unlock(&iaxsl[pvt->callno]);
+
+	while ((s = AST_LIST_REMOVE_HEAD(&pvt->signaling_queue, next))) {
+		free_signaling_queue_entry(s);
+	}
 
 	if (pvt->reg) {
 		pvt->reg->callno = 0;
@@ -1780,6 +1839,9 @@
 	jb_setconf(tmp->jb,&jbconf);
 
 	AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries);
+
+	tmp->hold_signaling = 1;
+	AST_LIST_HEAD_INIT_NOLOCK(&tmp->signaling_queue);
 
 	return tmp;
 }
@@ -7148,12 +7210,17 @@
 		int now, int transfer, int final)
 {
 	struct ast_frame f = { 0, };
+	int res = 0;
 
 	f.frametype = type;
 	f.subclass = command;
 	f.datalen = datalen;
 	f.src = __FUNCTION__;
 	f.data.ptr = (void *) data;
+
+	if ((res = queue_signalling(i, &f)) <= 0) {
+		return res;
+	}
 
 	return iax2_send(i, &f, ts, seqno, now, transfer, final);
 }
@@ -9634,19 +9701,15 @@
 		int check_dcallno = 0;
 
 		/*
-		 * We enforce accurate destination call numbers for all full frames except
-		 * LAGRQ and PING commands.  This is because older versions of Asterisk
-		 * schedule these commands to get sent very quickly, and they will sometimes
-		 * be sent before they receive the first frame from the other side.  When
-		 * that happens, it doesn't contain the destination call number.  However,
-		 * not checking it for these frames is safe.
-		 * 
+		 * We enforce accurate destination call numbers for ACKs.  This forces the other
+		 * end to know the destination call number before call setup can complete.
+		 *
 		 * Discussed in the following thread:
 		 *    http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 
 		 */
 
-		if (ntohs(mh->callno) & IAX_FLAG_FULL) {
-			check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1;
+		if ((ntohs(mh->callno) & IAX_FLAG_FULL) && ((f.frametype == AST_FRAME_IAX) && (f.subclass == IAX_COMMAND_ACK))) {
+			check_dcallno = 1;
 		}
 
 		if (!(fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno))) {
@@ -9920,6 +9983,12 @@
 			if (ies.vars) {
 				ast_debug(1, "I have IAX variables, but they were not processed\n");
 			}
+		}
+
+		/* once we receive our first IAX Full Frame that is not CallToken related, send all
+		 * queued signaling frames that were being held. */
+		if ((f.frametype == AST_FRAME_IAX) && (f.subclass != IAX_COMMAND_CALLTOKEN) && iaxs[fr->callno]->hold_signaling) {
+			send_signaling(iaxs[fr->callno]);
 		}
 
 		if (f.frametype == AST_FRAME_VOICE) {




More information about the svn-commits mailing list