[asterisk-commits] file: branch group/vldtmf r41374 - in /team/group/vldtmf: ./ channels/ codecs...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Aug 30 09:42:25 MST 2006


Author: file
Date: Wed Aug 30 11:42:24 2006
New Revision: 41374

URL: http://svn.digium.com/view/asterisk?rev=41374&view=rev
Log:
Merged revisions 41302-41303,41316-41318,41335,41338,41357,41373 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

........
r41302 | file | 2006-08-29 21:22:46 -0400 (Tue, 29 Aug 2006) | 2 lines

This is the last round of RTP bridge optimizations. Basically it introduces a way that under a straight bridge (ie: no transcoding and no DTMF detection) the core is not touched at all and no frames pass through (not even null frames). This is accomplished by stealing the file descriptors from the channel and using the provided IO context with a custom callback. When a channel is placed on hold this bridge is broken so audio can flow from the core to the other side. When a channel is off hold this bridge is re-established.

........
r41303 | file | 2006-08-29 21:29:59 -0400 (Tue, 29 Aug 2006) | 2 lines

If the RTP stack is already being operated in callback mode, then suspend it upon switching to P2P callback bridging. Once P2P callback bridging has ended, then restore callback mode.

........
r41316 | file | 2006-08-29 23:16:03 -0400 (Tue, 29 Aug 2006) | 2 lines

Use an API call (ast_rtp_get_bridged) to return the RTP stream we are bridged to, and also use it in chan_sip so we know to ignore the no RTP activity checking

........
r41317 | file | 2006-08-29 23:18:04 -0400 (Tue, 29 Aug 2006) | 2 lines

Only switch the second alert fd (which is RTCP) to callback mode if it is in use

........
r41318 | markster | 2006-08-29 23:20:54 -0400 (Tue, 29 Aug 2006) | 2 lines

Fix transcoding performance issue

........
r41335 | oej | 2006-08-30 10:36:46 -0400 (Wed, 30 Aug 2006) | 2 lines

Issue #7822 - don't issue SRV lookups if it's disabled. (barthek)

........
r41338 | file | 2006-08-30 10:57:06 -0400 (Wed, 30 Aug 2006) | 2 lines

Only feed a DTMF frame into the core if we need to

........
r41357 | file | 2006-08-30 11:15:06 -0400 (Wed, 30 Aug 2006) | 2 lines

Print what read-only variable is being set so that the user doesn't have to guess and figure it out or look at the list in cdr.c and match it up (issue #7831 reported by sedwards)

........
r41373 | file | 2006-08-30 12:04:24 -0400 (Wed, 30 Aug 2006) | 2 lines

Clarify what show translations is displaying a bit more (issue #7772 reported by Mithraen)

........

Modified:
    team/group/vldtmf/   (props changed)
    team/group/vldtmf/channels/chan_sip.c
    team/group/vldtmf/codecs/codec_zap.c
    team/group/vldtmf/include/asterisk/rtp.h
    team/group/vldtmf/main/cdr.c
    team/group/vldtmf/main/rtp.c
    team/group/vldtmf/main/translate.c

Propchange: team/group/vldtmf/
------------------------------------------------------------------------------
    automerge = muffins

Propchange: team/group/vldtmf/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/group/vldtmf/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Aug 30 11:42:24 2006
@@ -1,1 +1,1 @@
-/trunk:1-41287
+/trunk:1-41373

Modified: team/group/vldtmf/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/channels/chan_sip.c?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/channels/chan_sip.c (original)
+++ team/group/vldtmf/channels/chan_sip.c Wed Aug 30 11:42:24 2006
@@ -14396,12 +14396,15 @@
 								ast_mutex_lock(&sip->lock);
 							}
 							if (sip->owner) {
-								ast_log(LOG_NOTICE,
-									"Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
-									sip->owner->name,
-									(long) (t - sip->lastrtprx));
-								/* Issue a softhangup */
-								ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
+								if (!(ast_rtp_get_bridged(sip->rtp))) {
+									ast_log(LOG_NOTICE,
+										"Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
+										sip->owner->name,
+										(long) (t - sip->lastrtprx));
+									/* Issue a softhangup */
+									ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
+								} else
+									ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", sip->owner->name, (long) (t - sip->lastrtprx));
 								ast_channel_unlock(sip->owner);
 								/* forget the timeouts for this call, since a hangup
 								   has already been requested and we don't want to
@@ -15327,7 +15330,7 @@
 				peer->expire = -1;
 				ast_clear_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC);
 				if (!obproxyfound || !strcasecmp(v->name, "outboundproxy")) {
-					if (ast_get_ip_or_srv(&peer->addr, v->value, "_sip._udp")) {
+					if (ast_get_ip_or_srv(&peer->addr, v->value, srvlookup ? "_sip._udp" : NULL)) {
 						ASTOBJ_UNREF(peer, sip_destroy_peer);
 						return NULL;
 					}
@@ -15684,7 +15687,7 @@
 		} else if (!strcasecmp(v->name, "fromdomain")) {
 			ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain));
 		} else if (!strcasecmp(v->name, "outboundproxy")) {
-			if (ast_get_ip_or_srv(&outboundproxyip, v->value, "_sip._udp") < 0)
+			if (ast_get_ip_or_srv(&outboundproxyip, v->value, srvlookup ? "_sip._udp" : NULL) < 0)
 				ast_log(LOG_WARNING, "Unable to locate host '%s'\n", v->value);
 		} else if (!strcasecmp(v->name, "outboundproxyport")) {
 			/* Port needs to be after IP */

Modified: team/group/vldtmf/codecs/codec_zap.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/codecs/codec_zap.c?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/codecs/codec_zap.c (original)
+++ team/group/vldtmf/codecs/codec_zap.c Wed Aug 30 11:42:24 2006
@@ -75,6 +75,10 @@
 struct pvt {
 	int fd;
 	int fake;
+#ifdef DEBUG_TRANSCODE
+	int totalms;
+	int lasttotalms;
+#endif
 	struct zt_transcode_header *hdr;
 	struct ast_frame f;
 };
@@ -106,7 +110,7 @@
 		hdr->srcoffset = 0;
 	}
 
-	memcpy(hdr->srcdata + hdr->srcoffset, f->data, f->datalen);
+	memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, f->data, f->datalen);
 	hdr->srclen += f->datalen;
 	pvt->samples += f->samples;
 
@@ -131,24 +135,34 @@
 		pvt->samples = 0;
 	} else if (ztp->fake == 1) {
 		return NULL;
-	} else if (!hdr->srclen) {
-		return NULL;
 	} else {
-		hdr->dstoffset = 0;
-		hdr->dstlen = 0;
-		x = ZT_TCOP_TRANSCODE;
-		if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
-			ast_log(LOG_WARNING, "Failed to transcode: %s\n", strerror(errno));
-		if (!hdr->dstlen)
+		if (hdr->dstlen) {
+#ifdef DEBUG_TRANSCODE
+			ztp->totalms += hdr->dstsamples;
+			if ((ztp->totalms - ztp->lasttotalms) > 8000) {
+				printf("Whee %p, %d (%d to %d)\n", ztp, hdr->dstlen, ztp->lasttotalms, ztp->totalms);
+				ztp->lasttotalms = ztp->totalms;
+			}
+#endif
+			ztp->f.frametype = AST_FRAME_VOICE;
+			ztp->f.subclass = hdr->dstfmt;
+			ztp->f.samples = hdr->dstsamples;
+			ztp->f.data = hdr->dstdata + hdr->dstoffset;
+			ztp->f.offset = hdr->dstoffset;
+			ztp->f.datalen = hdr->dstlen;
+			ztp->f.mallocd = 0;
+			pvt->samples -= ztp->f.samples;
+			hdr->dstlen = 0;
+			
+		} else {
+			if (hdr->srclen) {
+				hdr->dstoffset = AST_FRIENDLY_OFFSET;
+				x = ZT_TCOP_TRANSCODE;
+				if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
+					ast_log(LOG_WARNING, "Failed to transcode: %s\n", strerror(errno));
+			}
 			return NULL;
-		ztp->f.frametype = AST_FRAME_VOICE;
-		ztp->f.subclass = hdr->dstfmt;
-		ztp->f.samples = hdr->dstsamples;
-		ztp->f.data = hdr->dstdata + hdr->dstoffset;
-		ztp->f.offset = hdr->dstoffset;
-		ztp->f.datalen = hdr->dstlen;
-		ztp->f.mallocd = 0;
-		pvt->samples -= ztp->f.samples;
+		}
 	}
 
 	return &ztp->f;
@@ -169,9 +183,16 @@
 	unsigned int x = ZT_TCOP_RESET;
 	struct pvt *ztp = pvt->pvt;
 	struct zt_transcode_header *hdr;
+	int flags;
 	
 	if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
 		return -1;
+	flags = fcntl(fd, F_GETFL);
+	if (flags > - 1) {
+		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
+			ast_log(LOG_WARNING, "Could not set non-block mode!\n");
+	}
+	
 
 	if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
 		ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));

Modified: team/group/vldtmf/include/asterisk/rtp.h
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/include/asterisk/rtp.h?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/include/asterisk/rtp.h (original)
+++ team/group/vldtmf/include/asterisk/rtp.h Wed Aug 30 11:42:24 2006
@@ -120,6 +120,8 @@
 
 void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us);
 
+struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp);
+
 void ast_rtp_destroy(struct ast_rtp *rtp);
 
 void ast_rtp_reset(struct ast_rtp *rtp);

Modified: team/group/vldtmf/main/cdr.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/main/cdr.c?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/main/cdr.c (original)
+++ team/group/vldtmf/main/cdr.c Wed Aug 30 11:42:24 2006
@@ -290,7 +290,7 @@
 	
 	for(x = 0; cdr_readonly_vars[x]; x++) {
 		if (!strcasecmp(name, cdr_readonly_vars[x])) {
-			ast_log(LOG_ERROR, "Attempt to set a read-only variable!.\n");
+			ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
 			return -1;
 		}
 	}

Modified: team/group/vldtmf/main/rtp.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/main/rtp.c?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/main/rtp.c (original)
+++ team/group/vldtmf/main/rtp.c Wed Aug 30 11:42:24 2006
@@ -170,6 +170,7 @@
 static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
 static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
 int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
+static int bridge_p2p_rtcp_write(struct ast_rtp *rtp, unsigned int *rtcpheader, int len);
 
 #define FLAG_3389_WARNING		(1 << 0)
 #define FLAG_NAT_ACTIVE			(3 << 1)
@@ -178,7 +179,8 @@
 #define FLAG_HAS_DTMF			(1 << 3)
 #define FLAG_P2P_SENT_MARK              (1 << 4)
 #define FLAG_P2P_NEED_DTMF              (1 << 5)
-#define FLAG_DTMF_COMPENSATE            (1 << 6)
+#define FLAG_CALLBACK_MODE              (1 << 6)
+#define FLAG_DTMF_COMPENSATE            (1 << 7)
 
 /*!
  * \brief Structure defining an RTCP session.
@@ -788,6 +790,11 @@
 				ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
 		}
 	}
+
+	/* If we are P2P bridged to another RTP stream, send it directly over */
+	if (ast_rtp_get_bridged(rtp) && !bridge_p2p_rtcp_write(rtp, rtcpheader, res))
+		return &ast_null_frame;
+
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
 
@@ -940,10 +947,33 @@
 		rtp->rtcp->minrxjitter = rtp->rxjitter;
 }
 
-/*! \brief Perform a Packet2Packet write */
-static int bridge_p2p_write(struct ast_rtp *rtp, unsigned int *rtpheader, int len, int hdrlen)
-{
-	struct ast_rtp *bridged = rtp->bridged;
+/*! \brief Perform a Packet2Packet RTCP write */
+static int bridge_p2p_rtcp_write(struct ast_rtp *rtp, unsigned int *rtcpheader, int len)
+{
+	struct ast_rtp *bridged = ast_rtp_get_bridged(rtp);
+	int res = 0;
+
+	/* If RTCP is not present on the bridged RTP session, then ignore this */
+	if (!bridged->rtcp)
+		return 0;
+
+	/* Send the data out */
+	res = sendto(bridged->rtcp->s, (void *)rtcpheader, len, 0, (struct sockaddr *)&bridged->rtcp->them, sizeof(bridged->rtcp->them));
+	if (res < 0) {
+		if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE)))
+			ast_log(LOG_DEBUG, "RTCP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->rtcp->them.sin_addr), ntohs(bridged->rtcp->them.sin_port), strerror(errno));
+		else if ((((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug)) && (option_debug || rtpdebug))
+			ast_log(LOG_DEBUG, "RTCP NAT: Can't write RTCP to private address %s:%d, waiting for other end to send first...\n", ast_inet_ntoa(bridged->rtcp->them.sin_addr), ntohs(bridged->rtcp->them.sin_port));
+	} else if (rtp_debug_test_addr(&bridged->rtcp->them))
+		ast_verbose("Sent RTCP P2P packet to %s:%d (len %-6.6u)\n", ast_inet_ntoa(bridged->rtcp->them.sin_addr), ntohs(bridged->rtcp->them.sin_port), len);
+
+	return 0;
+}
+
+/*! \brief Perform a Packet2Packet RTP write */
+static int bridge_p2p_rtp_write(struct ast_rtp *rtp, unsigned int *rtpheader, int len, int hdrlen)
+{
+	struct ast_rtp *bridged = ast_rtp_get_bridged(rtp);
 	int res = 0, payload = 0, bridged_payload = 0, version, padding, mark, ext;
 	struct rtpPayloadType rtpPT;
 	unsigned int seqno;
@@ -961,7 +991,7 @@
 	rtpPT = ast_rtp_lookup_pt(rtp, payload);
 
 	/* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
-	if (!rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
+	if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
 		return -1;
 
 	/* Otherwise adjust bridged payload to match */
@@ -976,23 +1006,19 @@
 	/* Reconstruct part of the packet */
 	rtpheader[0] = htonl((version << 30) | (mark << 23) | (bridged_payload << 16) | (seqno));
 
-	if (bridged->them.sin_port && bridged->them.sin_addr.s_addr) {
-		res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
-		if (res < 0) {
-			if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-				ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
-			} else if ((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) {
-				if (option_debug || rtpdebug)
-					ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
-				ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
-			}
-			return -1;
-		} else {
-			if (rtp_debug_test_addr(&bridged->them))
-				ast_verbose("Sent RTP P2P packet to %s:%d (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
-			return 0;
-		}
-	}
+	/* Send the packet back out */
+	res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
+	if (res < 0) {
+		if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
+			ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
+		} else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
+			if (option_debug || rtpdebug)
+				ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
+			ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
+		}
+		return -1;
+	} else if (rtp_debug_test_addr(&bridged->them))
+			ast_verbose("Sent RTP P2P packet to %s:%d (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
 
 	return -1;
 }
@@ -1039,11 +1065,6 @@
 		return &ast_null_frame;
 	}
 
-	/* If we are P2P bridged to another channel, and the write is a success - then return a null frame and not the actual data */
-	if (rtp->bridged && !bridge_p2p_write(rtp, rtpheader, res, hdrlen)) {
-		return &ast_null_frame;
-	}
-
 	/* Get fields */
 	seqno = ntohl(rtpheader[0]);
 
@@ -1078,7 +1099,7 @@
 	}
 
 	/* If we are bridged to another RTP stream, send direct */
-	if (rtp->bridged && !bridge_p2p_write(rtp, rtpheader, res, hdrlen))
+	if (ast_rtp_get_bridged(rtp) && !bridge_p2p_rtp_write(rtp, rtpheader, res, hdrlen))
 		return &ast_null_frame;
 
 	if (version != 2)
@@ -1767,11 +1788,11 @@
 			return NULL;
 		}
 	}
-	if (io && sched && callbackmode) {
-		/* Operate this one in a callback mode */
-		rtp->sched = sched;
-		rtp->io = io;
+	rtp->sched = sched;
+	rtp->io = io;
+	if (callbackmode) {
 		rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
+		ast_set_flag(rtp, FLAG_CALLBACK_MODE);
 	}
 	ast_rtp_pt_default(rtp);
 	return rtp;
@@ -1821,6 +1842,11 @@
 void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
 {
 	*us = rtp->us;
+}
+
+struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp)
+{
+	return rtp->bridged;
 }
 
 void ast_rtp_stop(struct ast_rtp *rtp)
@@ -2420,7 +2446,7 @@
 		if (res <0) {
 			if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
 				ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
-			} else if ((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) {
+			} else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
 				/* Only give this error message once if we are not RTP debugging */
 				if (option_debug || rtpdebug)
 					ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
@@ -2769,11 +2795,115 @@
 	return AST_BRIDGE_FAILED;
 }
 
+/*! \brief P2P RTP/RTCP Callback */
+static int p2p_rtp_callback(int *id, int fd, short events, void *cbdata)
+{
+	int res = 0, hdrlen = 12;
+	struct sockaddr_in sin;
+	socklen_t len;
+	unsigned int *header;
+	struct ast_rtp *rtp = cbdata;
+	int is_rtp = 0, is_rtcp = 0;
+
+	if (!rtp)
+		return 1;
+
+	len = sizeof(sin);
+	if ((res = recvfrom(fd, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0)
+		return 1;
+
+	header = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
+
+	/* Determine what this file descriptor is for */
+	if (rtp->s == fd)
+		is_rtp = 1;
+	else if (rtp->rtcp && rtp->rtcp->s == fd)
+		is_rtcp = 1;
+
+	/* If NAT support is turned on, then see if we need to change their address */
+	if (rtp->nat) {
+		/* If this is for RTP, check that - if it's for RTCP, check that */
+		if (is_rtp) {
+			if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
+			    (rtp->them.sin_port != sin.sin_port)) {
+				rtp->them = sin;
+				rtp->rxseqno = 0;
+				ast_set_flag(rtp, FLAG_NAT_ACTIVE);
+				if (option_debug || rtpdebug)
+					ast_log(LOG_DEBUG, "P2P RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
+			}
+		} else if (is_rtcp) {
+			if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
+			    (rtp->rtcp->them.sin_port != sin.sin_port)) {
+				rtp->rtcp->them = sin;
+				if (option_debug || rtpdebug)
+					ast_log(LOG_DEBUG, "P2P RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			}
+		}
+	}
+
+	/* If this came from the RTP stream, write out via RTP - if it's RTCP, write out via RTCP */
+	if (is_rtp)
+		bridge_p2p_rtp_write(rtp, header, res, hdrlen);
+	else if (is_rtcp)
+		bridge_p2p_rtcp_write(rtp, header, res);
+
+	return 1;
+}
+
+/*! \brief Helper function to switch a channel and RTP stream into callback mode */
+static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
+{
+	/* If we need DTMF or we have no IO structure, then we can't do direct callback */
+	if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) || !rtp->io)
+		return 0;
+
+	/* If the RTP structure is already in callback mode, remove it temporarily */
+	if (rtp->ioid) {
+		ast_io_remove(rtp->io, rtp->ioid);
+		rtp->ioid = NULL;
+	}
+
+	/* Steal the file descriptors from the channel and stash them away */
+	fds[0] = chan->fds[0];
+	fds[1] = chan->fds[1];
+	chan->fds[0] = -1;
+	chan->fds[1] = -1;
+
+	/* Now, fire up callback mode */
+	iod[0] = ast_io_add(rtp->io, fds[0], p2p_rtp_callback, AST_IO_IN, rtp);
+	if (fds[1] >= 0)
+		iod[1] = ast_io_add(rtp->io, fds[1], p2p_rtp_callback, AST_IO_IN, rtp);
+
+	return 1;
+}
+
+/*! \brief Helper function to switch a channel and RTP stream out of callback mode */
+static int p2p_callback_disable(struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
+{
+	ast_channel_lock(chan);
+	/* Remove the callback from the IO context */
+	ast_io_remove(rtp->io, iod[0]);
+	ast_io_remove(rtp->io, iod[1]);
+	/* Restore file descriptors */
+	chan->fds[0] = fds[0];
+	chan->fds[1] = fds[1];
+	ast_channel_unlock(chan);
+	/* Restore callback mode if previously used */
+	if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
+	    rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
+	return 0;
+}
+
 /*! \brief Bridge loop for partial native bridge (packet2packet) */
 static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
 {
 	struct ast_frame *fr = NULL;
 	struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
+	int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
+	int *p0_iod[2] = {NULL, }, *p1_iod[2] = {NULL, };
+	int p0_callback = 0, p1_callback = 0;
+	enum ast_bridge_result res = AST_BRIDGE_FAILED;
 
 	/* Okay, setup each RTP structure to do P2P forwarding */
 	ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
@@ -2787,6 +2917,10 @@
 		vp1->bridged = vp0;
 	}
 
+	/* Activate callback modes if possible */
+	p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
+	p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
+
 	/* Now let go of the channel locks and be on our way */
 	ast_channel_unlock(c0);
 	ast_channel_unlock(c1);
@@ -2801,12 +2935,15 @@
 		    (c1->tech_pvt != pvt1) ||
 		    (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
 			ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
-			return AST_BRIDGE_RETRY;
+			res = AST_BRIDGE_RETRY;
+			break;
 		}
 		/* Wait on a channel to feed us a frame */
 		if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
-			if (!timeoutms)
-				return AST_BRIDGE_RETRY;
+			if (!timeoutms) {
+				res = AST_BRIDGE_RETRY;
+				break;
+			}
 			if (option_debug)
 				ast_log(LOG_NOTICE, "Ooh, empty read...\n");
 			if (ast_check_hangup(c0) || ast_check_hangup(c1))
@@ -2832,18 +2969,31 @@
 				vp0->bridged = NULL;
 				vp1->bridged = NULL;
 			}
-			return AST_BRIDGE_COMPLETE;
+			res = AST_BRIDGE_COMPLETE;
+			break;
 		} else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
 			if ((fr->subclass == AST_CONTROL_HOLD) ||
 			    (fr->subclass == AST_CONTROL_UNHOLD) ||
 			    (fr->subclass == AST_CONTROL_VIDUPDATE)) {
+				/* If we are going on hold, then break callback mode */
+				if (fr->subclass == AST_CONTROL_HOLD) {
+					if (p0_callback)
+						p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
+					if (p1_callback)
+						p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
+				} else if (fr->subclass == AST_CONTROL_UNHOLD) {
+					/* If we are off hold, then go back to callback mode */
+					p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
+					p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
+				}
 				ast_indicate(other, fr->subclass);
 				ast_frfree(fr);
 			} else {
 				*fo = fr;
 				*rc = who;
 				ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
-				return AST_BRIDGE_COMPLETE;
+				res = AST_BRIDGE_COMPLETE;
+				break;
 			}
 		} else {
 			/* If this is a DTMF, voice, or video frame write it to the other channel */
@@ -2860,7 +3010,13 @@
 		cs[1] = cs[2];
 	}
 
-	return AST_BRIDGE_FAILED;
+	/* If we are totally avoiding the core, then restore our link to it */
+	if (p0_callback)
+		p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
+	if (p1_callback)
+		p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
+
+	return res;
 }
 
 /*! \brief Bridge calls. If possible and allowed, initiate

Modified: team/group/vldtmf/main/translate.c
URL: http://svn.digium.com/view/asterisk/team/group/vldtmf/main/translate.c?rev=41374&r1=41373&r2=41374&view=diff
==============================================================================
--- team/group/vldtmf/main/translate.c (original)
+++ team/group/vldtmf/main/translate.c Wed Aug 30 11:42:24 2006
@@ -502,7 +502,7 @@
 		rebuild_matrix(z);
 	}
 
-	ast_cli(fd, "         Translation times between formats (in milliseconds)\n");
+	ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
 	ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
 	/* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
 	for (x = 0; x < SHOW_TRANS; x++) {



More information about the asterisk-commits mailing list