[Asterisk-cvs] asterisk/channels chan_iax2.c,1.185,1.186

markster at lists.digium.com markster at lists.digium.com
Fri Sep 17 08:40:57 CDT 2004


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv5694/channels

Modified Files:
	chan_iax2.c 
Log Message:
Merge steven davie's IAX2 jitterbuffer fixes


Index: chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.185
retrieving revision 1.186
diff -u -d -r1.185 -r1.186
--- chan_iax2.c	16 Sep 2004 16:18:53 -0000	1.185
+++ chan_iax2.c	17 Sep 2004 12:45:03 -0000	1.186
@@ -171,7 +171,7 @@
 
 static int iax2_dropcount = DEFAULT_DROP;
 
-static int use_jitterbuffer = 0;
+static int globalusejitterbuf = 0;
 
 static int iaxdebug = 0;
 
@@ -212,6 +212,7 @@
 	struct iax2_context *contexts;
 	struct iax2_user *next;
 	int notransfer;
+	int usejitterbuf;
 };
 
 struct iax2_peer {
@@ -255,6 +256,7 @@
 	struct ast_ha *ha;
 	struct iax2_peer *next;
 	int notransfer;
+	int usejitterbuf;
 };
 
 #define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
@@ -329,6 +331,9 @@
 
 #define MAX_TIMESTAMP_SKEW	640
 
+/* If consecutive voice frame timestamps jump by more than this many milliseconds, then jitter buffer will resync */
+#define TS_GAP_FOR_JB_RESYNC	5000
+
 /* If we have more than this much excess real jitter buffer, shrink it. */
 static int max_jitter_buffer = MAX_JITTER_BUFFER;
 /* If we have less than this much excess real jitter buffer, enlarge it. */
@@ -472,6 +477,7 @@
 	int trunk;
 	struct iax2_dpcache *dpentries;
 	int notransfer;		/* do we want native bridging */
+	int usejitterbuf;	/* use jitter buffer on this channel? */
 };
 
 static struct ast_iax2_queue {
@@ -872,6 +878,7 @@
 			iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
 			iaxs[x]->amaflags = amaflags;
 			iaxs[x]->notransfer = globalnotransfer;
+			iaxs[x]->usejitterbuf = globalusejitterbuf;
 			strncpy(iaxs[x]->accountcode, accountcode, sizeof(iaxs[x]->accountcode)-1);
 		} else {
 			ast_log(LOG_WARNING, "Out of resources\n");
@@ -1650,7 +1657,7 @@
 { { "iax2", "show", "cache", NULL }, iax2_show_cache, "Display IAX cached dialplan", show_cache_usage };
 
 
-static unsigned int calc_rxstamp(struct chan_iax2_pvt *p);
+static unsigned int calc_rxstamp(struct chan_iax2_pvt *p, unsigned int offset);
 
 #ifdef BRIDGE_OPTIMIZATION
 static unsigned int calc_fakestamp(struct chan_iax2_pvt *from, struct chan_iax2_pvt *to, unsigned int ts);
@@ -1659,6 +1666,8 @@
 {
 	struct chan_iax2_pvt *p1, *p2;
 	char iabuf[INET_ADDRSTRLEN];
+	int res, orig_ts;
+
 	p1 = iaxs[fr->callno];
 	p2 = iaxs[p1->bridgecallno];
 	if (!p1)
@@ -1675,79 +1684,133 @@
 				ntohs(p2->addr.sin_port));
 
 	/* Undo wraparound - which can happen when full VOICE frame wasn't sent by our peer.
-	   This is necessary for when our peer is chan_iax2.c v1.175 or earlier which didn't
+	   This is necessary for when our peer is chan_iax2.c v1.1nn or earlier which didn't
 	   send full frame on timestamp wrap when doing optimized bridging
+	   (actually current code STILL doesn't)
 	*/
-	if (fr->ts + 32767 <= p1->last) {
+	if (fr->ts + 50000 <= p1->last) {
 		fr->ts = ( (p1->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
-		p1->last = fr->ts; /* necessary? */
 		if (option_debug)
 			ast_log(LOG_DEBUG, "forward_delivery: pushed forward timestamp to %u\n", fr->ts);
 	}
 
-	/* Fix relative timestamp */
+	/* Send with timestamp adjusted to the origin of the outbound leg */
+	/* But don't destroy inbound timestamp still needed later to set "last" */
+	orig_ts = fr->ts;
 	fr->ts = calc_fakestamp(p1, p2, fr->ts);
-	/* Now just send it send on the 2nd one 
-	   with adjusted timestamp */
-	return iax2_send(p2, &fr->af, fr->ts, -1, 0, 0, 0);
+	res = iax2_send(p2, &fr->af, fr->ts, -1, 0, 0, 0);
+	fr->ts = orig_ts;
+	return res;
 }
 #endif
 
+static void unwrap_timestamp(struct iax_frame *fr)
+{
+	int x;
+
+	if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
+		x = fr->ts - iaxs[fr->callno]->last;
+		if (x < -50000) {
+			/* Sudden big jump backwards in timestamp:
+			   What likely happened here is that miniframe timestamp has circled but we haven't
+			   gotten the update from the main packet.  We'll just pretend that we did, and
+			   update the timestamp appropriately. */
+			fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
+			if (option_debug)
+				ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
+		}
+		if (x > 50000) {
+			/* Sudden apparent big jump forwards in timestamp:
+			   What's likely happened is this is an old miniframe belonging to the previous
+			   top-16-bit timestamp that has turned up out of order.
+			   Adjust the timestamp appropriately. */
+			fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
+			if (option_debug)
+				ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
+		}
+	}
+}
+
 static int schedule_delivery(struct iax_frame *fr, int reallydeliver, int updatehistory)
 {
 	int ms,x;
+	int delay;
+	unsigned int orig_ts;
 	int drops[MEMORY_SIZE];
 	int min, max=0, prevjitterbuffer, maxone=0,y,z, match;
 
 	/* Remember current jitterbuffer so we can log any change */
 	prevjitterbuffer = iaxs[fr->callno]->jitterbuffer;
+	/* Similarly for the frame timestamp */
+	orig_ts = fr->ts;
 
-	/* ms is a measure of the "lateness" of the packet relative to the first
-	   packet we received.  Understand that "ms" can easily be -ve if lag improves
-	   since call start.
-	   Called by IAX thread, with iaxsl lock held. */
-	ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
+#if 0
+	if (option_debug)
+		ast_log(LOG_DEBUG, "schedule_delivery: ts=%d, last=%d, really=%d, update=%d\n",
+				fr->ts, iaxs[fr->callno]->last, reallydeliver, updatehistory);
+#endif
 
-	if (ms > 32767) {
-		/* What likely happened here is that our counter has circled but we haven't
-		   gotten the update from the main packet.  We'll just pretend that we did, and
-		   update the timestamp appropriately. */
-		/*ms -= 65536; 	fr->ts += 65536;*/
-		fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
-		iaxs[fr->callno]->last = fr->ts;
-		ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
-		if (option_debug)
-			ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
-	}
+	/* Attempt to recover wrapped timestamps */
+	unwrap_timestamp(fr);
 
-	if (ms < -32768) {
-		/* We got this packet out of order.  Lets add 65536 to it to bring it into our new
-		   time frame */
-		/*ms += 65536;  fr->ts -= 65536;*/
-		fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
-		iaxs[fr->callno]->last = fr->ts;
-		ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
-		if (option_debug)
-			ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
-	}
+	if (updatehistory) {
 
-	/* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
-	fr->af.delivery.tv_sec = iaxs[fr->callno]->rxcore.tv_sec;
-	fr->af.delivery.tv_usec = iaxs[fr->callno]->rxcore.tv_usec;
-	fr->af.delivery.tv_sec += fr->ts / 1000;
-	fr->af.delivery.tv_usec += (fr->ts % 1000) * 1000;
-	if (fr->af.delivery.tv_usec >= 1000000) {
-		fr->af.delivery.tv_usec -= 1000000;
-		fr->af.delivery.tv_sec += 1;
-	}
+		/* Attempt to spot a change of timebase on timestamps coming from the other side
+		   We detect by noticing a jump in consecutive timestamps that can't reasonably be explained
+		   by network jitter or reordering.  Sometimes, also, the peer stops sending us frames
+		   for a while - in this case this code might also resync us.  But that's not a bad thing.
+		   Be careful of non-voice frames which are timestamped differently (especially ACKS!)
+		   [that's why we only do this when updatehistory is true]
+		*/
+		x = fr->ts - iaxs[fr->callno]->last;
+		if (x > TS_GAP_FOR_JB_RESYNC || x < -TS_GAP_FOR_JB_RESYNC) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "schedule_delivery: call=%d: TS jumped.  resyncing rxcore (ts=%d, last=%d)\n",
+							fr->callno, fr->ts, iaxs[fr->callno]->last);
+			/* zap rxcore - calc_rxstamp will make a new one based on this frame */
+			iaxs[fr->callno]->rxcore.tv_sec = 0;
+			iaxs[fr->callno]->rxcore.tv_usec = 0;
+			/* wipe "last" if stamps have jumped backwards */
+			if (x<0)
+				iaxs[fr->callno]->last = 0;
+			/* should we also empty history? */
+		}
 
-	/* Rotate our history queue of "lateness".  Don't worry about those initial
-	   zeros because the first entry will always be zero */
-	if (updatehistory) {
+		/* ms is a measure of the "lateness" of the frame relative to the "reference"
+		   frame we received.  (initially the very first, but also see code just above here).
+		   Understand that "ms" can easily be -ve if lag improves since the reference frame.
+		   Called by IAX thread, with iaxsl lock held. */
+		ms = calc_rxstamp(iaxs[fr->callno], fr->ts) - fr->ts;
+	
+		/* Rotate our history queue of "lateness".  Don't worry about those initial
+		   zeros because the first entry will always be zero */
 		for (x=0;x<MEMORY_SIZE - 1;x++) 
 			iaxs[fr->callno]->history[x] = iaxs[fr->callno]->history[x+1];
 		/* Add a history entry for this one */
 		iaxs[fr->callno]->history[x] = ms;
+
+	}
+	else
+		ms = 0;
+
+	/* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
+	if (iaxs[fr->callno]->rxcore.tv_sec || iaxs[fr->callno]->rxcore.tv_usec) {
+		fr->af.delivery.tv_sec = iaxs[fr->callno]->rxcore.tv_sec;
+		fr->af.delivery.tv_usec = iaxs[fr->callno]->rxcore.tv_usec;
+		fr->af.delivery.tv_sec += fr->ts / 1000;
+		fr->af.delivery.tv_usec += (fr->ts % 1000) * 1000;
+		if (fr->af.delivery.tv_usec >= 1000000) {
+			fr->af.delivery.tv_usec -= 1000000;
+			fr->af.delivery.tv_sec += 1;
+		}
+	}
+	else {
+#if 0
+		if (reallydeliver)
+			ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet.\n");
+#endif
+		fr->af.delivery.tv_sec = 0;
+		fr->af.delivery.tv_usec = 0;
 	}
 
 	/* Initialize the minimum to reasonable values.  It's too much
@@ -1782,7 +1845,8 @@
 	}
 	/* Just for reference, keep the "jitter" value, the difference between the
 	   earliest and the latest. */
-	iaxs[fr->callno]->jitter = max - min;	
+	if (max >= min)
+		iaxs[fr->callno]->jitter = max - min;	
 	
 	/* IIR filter for keeping track of historic jitter, but always increase
 	   historic jitter immediately for increase */
@@ -1805,16 +1869,6 @@
 	if (max > iaxs[fr->callno]->jitterbuffer - min_jitter_buffer)
 		iaxs[fr->callno]->jitterbuffer += jittershrinkrate;
 
-
-#if 1
-	/* Constrain our maximum jitter buffer appropriately */
-	if (max > min + maxjitterbuffer) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Constraining buffer from %d to %d + %d\n", max, min , maxjitterbuffer);
-		max = min + maxjitterbuffer;
-	}
-#endif
-
 	/* If our jitter buffer is smaller than our maximum delay, grow the jitter
 	   buffer immediately to accomodate it (and a little more).  */
 	if (max > iaxs[fr->callno]->jitterbuffer)
@@ -1825,38 +1879,45 @@
 	if (!reallydeliver)
 		return 0;
 
-	if (option_debug)
+	/* Subtract the lateness from our jitter buffer to know how long to wait
+	   before sending our packet.  */
+	delay = iaxs[fr->callno]->jitterbuffer - ms;
+
+	/* Whatever happens, no frame waits longer than maxjitterbuffer */
+	if (delay > maxjitterbuffer)
+		delay = maxjitterbuffer;
+	
+	/* If jitter buffer is disabled then just pretend the frame is "right on time" */
+	if (!iaxs[fr->callno]->usejitterbuf)
+		delay = 0;
+
+	if (option_debug) {
 		/* Log jitter stats for possible offline analysis */
-		ast_log(LOG_DEBUG, "Jitter: call=%d ts=%d %s: min=%d max=%d jb=%d %+d; lateness=%d; jitter=%d historic=%d\n",
-					fr->callno, fr->ts,
+		ast_log(LOG_DEBUG, "Jitter: call=%d ts=%d orig=%d last=%d %s: min=%d max=%d jb=%d %+d lateness=%d jbdelay=%d jitter=%d historic=%d\n",
+					fr->callno, fr->ts, orig_ts, iaxs[fr->callno]->last,
 					(fr->af.frametype == AST_FRAME_VOICE) ? "VOICE" : "CONTROL",
 					min, max, iaxs[fr->callno]->jitterbuffer,
 					iaxs[fr->callno]->jitterbuffer - prevjitterbuffer,
-					ms, iaxs[fr->callno]->jitter, iaxs[fr->callno]->historicjitter);
-	
-	/* Subtract the lateness from our jitter buffer to know how long to wait
-	   before sending our packet.  */
-	ms = iaxs[fr->callno]->jitterbuffer - ms;
-	
-	if (!use_jitterbuffer)
-		ms = 0;
+					ms, delay,
+					iaxs[fr->callno]->jitter, iaxs[fr->callno]->historicjitter);
+	}
 
-	if (ms < 1) {
+	if (delay < 1) {
 		/* Don't deliver it more than 4 ms late */
-		if ((ms > -4) || (fr->af.frametype != AST_FRAME_VOICE)) {
+		if ((delay > -4) || (fr->af.frametype != AST_FRAME_VOICE)) {
 			if (option_debug)
-				ast_log(LOG_DEBUG, "schedule_delivery: Delivering immediately (Calculated ms is %d)\n", ms);
+				ast_log(LOG_DEBUG, "schedule_delivery: Delivering immediately (Calculated delay is %d)\n", delay);
 			__do_deliver(fr);
 		} else {
 			if (option_debug)
-				ast_log(LOG_DEBUG, "schedule_delivery: Dropping voice packet since %d ms is too old\n", ms);
+				ast_log(LOG_DEBUG, "schedule_delivery: Dropping voice packet since %dms delay is too old\n", delay);
 			/* Free our iax frame */
 			iax2_frame_free(fr);
 		}
 	} else {
 		if (option_debug)
-			ast_log(LOG_DEBUG, "schedule_delivery: Scheduling delivery in %d ms\n", ms);
-		fr->retrans = ast_sched_add(sched, ms, do_deliver, fr);
+			ast_log(LOG_DEBUG, "schedule_delivery: Scheduling delivery in %d ms\n", delay);
+		fr->retrans = ast_sched_add(sched, delay, do_deliver, fr);
 	}
 	return 0;
 }
@@ -2072,7 +2133,7 @@
 }
 #endif /* MYSQL_FRIENDS */
 
-static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, int *maxtime, char *peer, char *context, int *trunk, int *notransfer, char *username, int usernlen, char *secret, int seclen, int *ofound, char *peercontext)
+static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, int *maxtime, char *peer, char *context, int *trunk, int *notransfer, int *usejitterbuf, char *username, int usernlen, char *secret, int seclen, int *ofound, char *peercontext)
 {
 	struct ast_hostent ahp; struct hostent *hp;
 	struct iax2_peer *p;
@@ -2126,6 +2187,8 @@
 			}
 			if (notransfer)
 				*notransfer=p->notransfer;
+			if (usejitterbuf)
+				*usejitterbuf=p->usejitterbuf;
 		} else {
 			if (p->temponly)
 				free(p);
@@ -2242,7 +2305,7 @@
 		strsep(&stringp, ":");
 		portno = strsep(&stringp, ":");
 	}
-	if (create_addr(&sin, NULL, NULL, NULL, hname, context, NULL, NULL, storedusern, sizeof(storedusern) - 1, storedsecret, sizeof(storedsecret) - 1, NULL, peercontext)) {
+	if (create_addr(&sin, NULL, NULL, NULL, hname, context, NULL, NULL, NULL, storedusern, sizeof(storedusern) - 1, storedsecret, sizeof(storedsecret) - 1, NULL, peercontext)) {
 		ast_log(LOG_WARNING, "No address associated with '%s'\n", hname);
 		return -1;
 	}
@@ -2296,6 +2359,8 @@
 	ast_mutex_lock(&iaxsl[callno]);
 	if (!ast_strlen_zero(c->context))
 		strncpy(iaxs[callno]->context, c->context, sizeof(iaxs[callno]->context) - 1);
+	if (username)
+		strncpy(iaxs[callno]->username, username, sizeof(iaxs[callno]->username)-1);
 	if (secret) {
 		if (secret[0] == '[') {
 			/* This is an RSA key, not a normal secret */
@@ -2777,6 +2842,8 @@
 	if (delivery && (delivery->tv_sec || delivery->tv_usec)) {
 		ms = (delivery->tv_sec - p->offset.tv_sec) * 1000 +
 			(1000000 + delivery->tv_usec - p->offset.tv_usec) / 1000 - 1000;
+		if (option_debug)
+			ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
 	} else {
 		gettimeofday(&tv, NULL);
 		ms = (tv.tv_sec - p->offset.tv_sec) * 1000 +
@@ -2846,14 +2913,30 @@
 }
 #endif
 
-static unsigned int calc_rxstamp(struct chan_iax2_pvt *p)
+static unsigned int calc_rxstamp(struct chan_iax2_pvt *p, unsigned int offset)
 {
-	/* Returns where in "receive time" we are */
+	/* Returns where in "receive time" we are.  That is, how many ms
+	   since we received (or would have received) the frame with timestamp 0 */
 	struct timeval tv;
 	int ms;
 	/* Setup rxcore if necessary */
-	if (!p->rxcore.tv_sec && !p->rxcore.tv_usec)
+	if (!p->rxcore.tv_sec && !p->rxcore.tv_usec) {
 		gettimeofday(&p->rxcore, NULL);
+		if (option_debug)
+			ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
+					p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
+		p->rxcore.tv_sec -= offset / 1000;
+		p->rxcore.tv_usec -= (offset % 1000) * 1000;
+		if (p->rxcore.tv_usec < 0) {
+			p->rxcore.tv_usec += 1000000;
+			p->rxcore.tv_sec -= 1;
+		}
+#if 1
+		if (option_debug)
+			ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
+					p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
+#endif
+	}
 
 	gettimeofday(&tv, NULL);
 	ms = (tv.tv_sec - p->rxcore.tv_sec) * 1000 +
@@ -3272,29 +3355,46 @@
 		if (pvt->history[i] < min)
 			min = pvt->history[i];
 	}
-	return pvt->jitterbuffer - min;
+	if (pvt->jitterbuffer - min > maxjitterbuffer)
+		return maxjitterbuffer;
+	else
+		return pvt->jitterbuffer - min;
 }
 
 static int iax2_show_channels(int fd, int argc, char *argv[])
 {
-#define FORMAT2 "%-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
-#define FORMAT  "%-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  %-5.5dms  %-4.4dms  %-4.4dms  %-6.6s\n"
+#define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
+#define FORMAT  "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  %-5.5dms  %-4.4dms  %-4.4dms  %-6.6s\n"
+#define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
 	int x;
 	int numchans = 0;
 	char iabuf[INET_ADDRSTRLEN];
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
-	ast_cli(fd, FORMAT2, "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
+	ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
 	for (x=0;x<IAX_MAX_CALLS;x++) {
 		ast_mutex_lock(&iaxsl[x]);
 		if (iaxs[x]) {
-			ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[x]->addr.sin_addr), 
+#ifdef BRIDGE_OPTIMIZATION
+			if (iaxs[x]->bridgecallno)
+				ast_cli(fd, FORMATB,
+						iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
+						ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[x]->addr.sin_addr), 
+						!ast_strlen_zero(iaxs[x]->username) ? iaxs[x]->username : "(None)", 
+						iaxs[x]->callno, iaxs[x]->peercallno, 
+						iaxs[x]->oseqno, iaxs[x]->iseqno, 
+						iaxs[x]->bridgecallno );
+			else
+#endif
+				ast_cli(fd, FORMAT,
+						iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
+						ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[x]->addr.sin_addr), 
 						!ast_strlen_zero(iaxs[x]->username) ? iaxs[x]->username : "(None)", 
 						iaxs[x]->callno, iaxs[x]->peercallno, 
 						iaxs[x]->oseqno, iaxs[x]->iseqno, 
 						iaxs[x]->lag,
 						iaxs[x]->jitter,
-						use_jitterbuffer ? jitterbufsize(iaxs[x]) : 0,
+						iaxs[x]->usejitterbuf ? jitterbufsize(iaxs[x]) : 0,
 						ast_getformatname(iaxs[x]->voiceformat) );
 			numchans++;
 		}
@@ -3626,6 +3726,7 @@
 		if (!ast_strlen_zero(user->language))
 			strncpy(iaxs[callno]->language, user->language, sizeof(iaxs[callno]->language)-1);
 		iaxs[callno]->notransfer = user->notransfer;
+		iaxs[callno]->usejitterbuf = user->usejitterbuf;
 		res = 0;
 	}
 	iaxs[callno]->trunk = iax2_getpeertrunk(*sin);
@@ -4890,6 +4991,7 @@
 	unsigned int ts;
 	char empty[32]="";		/* Safety measure */
 	dblbuf[0] = 0;	/* Keep GCC from whining */
+	struct iax_frame *duped_fr;
 
 	fr.callno = 0;
 	
@@ -5052,6 +5154,14 @@
 		fr.oseqno = fh->oseqno;
 		fr.iseqno = fh->iseqno;
 		fr.ts = ntohl(fh->ts);
+#if 0
+		if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) ||
+		     ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX &&
+								(f.subclass == IAX_COMMAND_NEW ||
+								 f.subclass == IAX_COMMAND_AUTHREQ ||
+								 f.subclass == IAX_COMMAND_ACCEPT ||
+								 f.subclass == IAX_COMMAND_REJECT))      ) )
+#endif
 		if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE))
 			updatehistory = 0;
 		if ((iaxs[fr.callno]->iseqno != fr.oseqno) &&
@@ -5849,6 +5959,7 @@
 		else
 			f.data = NULL;
 		fr.ts = (iaxs[fr.callno]->last & 0xFFFF0000L) | ntohs(mh->ts);
+		/* FIXME? Surely right here would be the right place to undo timestamp wraparound? */
 	}
 	/* Don't pass any packets until we're started */
 	if (!(iaxs[fr.callno]->state & IAX_STATE_STARTED)) {
@@ -5867,7 +5978,7 @@
 
 	/* If this is our most recent packet, use it as our basis for timestamping */
 	if (iaxs[fr.callno]->last < fr.ts) {
-		iaxs[fr.callno]->last = fr.ts;
+		/*iaxs[fr.callno]->last = fr.ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/
 		fr.outoforder = 0;
 	} else {
 		if (option_debug)
@@ -5878,11 +5989,24 @@
 	if (iaxs[fr.callno]->bridgecallno) {
 		forward_delivery(&fr);
 	} else {
-		schedule_delivery(iaxfrdup2(&fr), 1, updatehistory);
+		duped_fr = iaxfrdup2(&fr);
+		schedule_delivery(duped_fr, 1, updatehistory);
+		fr.ts = duped_fr->ts;
 	}
 #else
-	schedule_delivery(iaxfrdup2(&fr), 1, updatehistory);
+	duped_fr = iaxfrdup2(&fr);
+	schedule_delivery(duped_fr, 1, updatehistory);
+	fr.ts = duped_fr->ts;
 #endif
+
+	if (iaxs[fr.callno]->last < fr.ts) {
+		iaxs[fr.callno]->last = fr.ts;
+#if 1
+		if (option_debug)
+			ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr.callno, fr.ts);
+#endif
+	}
+
 	/* Always run again */
 	ast_mutex_unlock(&iaxsl[fr.callno]);
 	return 1;
@@ -5943,7 +6067,7 @@
 	if (end)
 		memcpy(&sin, end, sizeof(sin));
 	else {
-		if (create_addr(&sin, NULL, NULL, NULL, dest, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL))
+		if (create_addr(&sin, NULL, NULL, NULL, dest, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL))
 			return -1;
 	}
 	/* Build the rest of the message */
@@ -6076,6 +6200,7 @@
 	int capability = iax2_capability;
 	int trunk;
 	int notransfer = globalnotransfer;
+	int usejitterbuf = globalusejitterbuf;
 	strncpy(s, (char *)data, sizeof(s)-1);
 	/* FIXME The next two lines seem useless */
 	stringp=s;
@@ -6097,7 +6222,7 @@
 	}							
 
 	/* Populate our address from the given */
-	if (create_addr(&sin, &capability, &sendani, &maxtime, hostname, NULL, &trunk, &notransfer, NULL, 0, NULL, 0, &found, NULL)) {
+	if (create_addr(&sin, &capability, &sendani, &maxtime, hostname, NULL, &trunk, &notransfer, &usejitterbuf, NULL, 0, NULL, 0, &found, NULL)) {
 		return NULL;
 	}
 	if (portno) {
@@ -6117,6 +6242,7 @@
 	iaxs[callno]->sendani = sendani;
 	iaxs[callno]->maxtime = maxtime;
 	iaxs[callno]->notransfer = notransfer;
+	iaxs[callno]->usejitterbuf = usejitterbuf;
 	if (found)
 		strncpy(iaxs[callno]->host, hostname, sizeof(iaxs[callno]->host) - 1);
 	c = ast_iax2_new(callno, AST_STATE_DOWN, capability);
@@ -6261,8 +6387,9 @@
 		peer->expire = -1;
 		peer->pokeexpire = -1;
 	}
-	peer->messagedetail = globalmessagedetail;
 	if (peer) {
+		peer->messagedetail = globalmessagedetail;
+		peer->usejitterbuf = globalusejitterbuf;
 		if (!found) {
 			strncpy(peer->name, name, sizeof(peer->name)-1);
 			peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
@@ -6286,6 +6413,8 @@
 				peer->authmethods = get_auth_methods(v->value);
 			} else if (!strcasecmp(v->name, "notransfer")) {
 				peer->notransfer = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "jitterbuffer")) {
+				peer->usejitterbuf = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "host")) {
 				if (!strcasecmp(v->value, "dynamic")) {
 					/* They'll register with us */
@@ -6429,6 +6558,7 @@
 		user->capability = iax2_capability;
 		strncpy(user->name, name, sizeof(user->name)-1);
 		strncpy(user->language, language, sizeof(user->language) - 1);
+		user->usejitterbuf = globalusejitterbuf;
 		while(v) {
 			if (!strcasecmp(v->name, "context")) {
 				con = build_context(v->value);
@@ -6464,6 +6594,8 @@
 				user->authmethods = get_auth_methods(v->value);
 			} else if (!strcasecmp(v->name, "notransfer")) {
 				user->notransfer = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "jitterbuffer")) {
+				user->usejitterbuf = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "secret")) {
 				strncpy(user->secret, v->value, sizeof(user->secret)-1);
 			} else if (!strcasecmp(v->name, "callerid")) {
@@ -6669,12 +6801,12 @@
 			iax2_dropcount = atoi(v->value);
 		else if (!strcasecmp(v->name, "bindaddr"))
 			inet_aton(v->value, &sin->sin_addr);
-		else if (!strcasecmp(v->name, "jitterbuffer"))
-			use_jitterbuffer = ast_true(v->value);
 		else if (!strcasecmp(v->name, "authdebug"))
 			authdebug = ast_true(v->value);
 		else if (!strcasecmp(v->name, "notransfer"))
 			globalnotransfer = ast_true(v->value);
+		else if (!strcasecmp(v->name, "jitterbuffer"))
+			globalusejitterbuf = ast_true(v->value);
 		else if (!strcasecmp(v->name, "delayreject"))
 			delayreject = ast_true(v->value);
 		else if (!strcasecmp(v->name, "mailboxdetail"))
@@ -6815,6 +6947,7 @@
 	amaflags = 0;
 	delayreject = 0;
 	globalnotransfer = 0;
+	globalusejitterbuf = 0;
 	srand(time(NULL));
 	delete_users();
 	set_config(config,&dead_sin);
@@ -6885,7 +7018,7 @@
 		host = st;
 	}
 	/* Populate our address from the given */
-	if (create_addr(&sin, NULL, NULL, NULL, host, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL)) {
+	if (create_addr(&sin, NULL, NULL, NULL, host, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL)) {
 		return -1;
 	}
 	ast_log(LOG_DEBUG, "host: %s, user: %s, password: %s, context: %s\n", host, username, password, context);




More information about the svn-commits mailing list