[asterisk-commits] oej: branch oej/pinefrog-1.4 r237655 - in /team/oej/pinefrog-1.4: ./ main/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 5 05:21:37 CST 2010


Author: oej
Date: Tue Jan  5 05:21:33 2010
New Revision: 237655

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=237655
Log:
Preparing for RTCP labs this afternoon...

Added:
    team/oej/pinefrog-1.4/README.pinefrog-rtcp   (with props)
Modified:
    team/oej/pinefrog-1.4/   (props changed)
    team/oej/pinefrog-1.4/main/channel.c
    team/oej/pinefrog-1.4/main/rtp.c
    team/oej/pinefrog-1.4/res/res_features.c

Propchange: team/oej/pinefrog-1.4/
------------------------------------------------------------------------------
--- automerge (original)
+++ automerge Tue Jan  5 05:21:33 2010
@@ -1,1 +1,1 @@
-Note to myself: Try to understand chan_sip
+http://www.codename-pineapple.org/

Added: team/oej/pinefrog-1.4/README.pinefrog-rtcp
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/README.pinefrog-rtcp?view=auto&rev=237655
==============================================================================
--- team/oej/pinefrog-1.4/README.pinefrog-rtcp (added)
+++ team/oej/pinefrog-1.4/README.pinefrog-rtcp Tue Jan  5 05:21:33 2010
@@ -1,0 +1,65 @@
+Olle E. Johansson
+oej at edvina.net
+
+
+
+
+
+
+
+
+Pinefrog - RTCP cleanup and additions
+-------------------------------------
+
+RTCP, as defined in RFC 3550, is a protocol that co-exists with RTP, the protocol used
+for realtime multimedia in VoIP. RTCP gives the endpoints a tool to exchange data about
+the media streams exchanged. As a result, both ends can get informaiton about the
+latency for data sent in both directions, packet loss and jitter for each media stream.
+
+A VoIP call is at least two media streams and they can have different properties in
+regards of quality. A router or switch in the middle could have a lot of outbound traffic,
+causing delays and possible packet loss. This might not affect inbound traffic.
+
+In Asterisk, the RTCP handler is part of the RTP module. The RTP module produces RTCP
+report that can be added to channel variables, cdr logs or sent through AMI.
+
+In 1.4, the data used is mostly based on the latest report, it's not aggregated. This
+is fixed in trunk.
+
+In both implementations (and the 1.6 releases in between) the RTCP support is not
+very complete.
+
+- It doesn't handle RTCP SDES packets
+- It doesn't send RTCP END packets at end of session
+- It doesn't handle receiving END packets
+- It doesn't handle re-invites in a good way.
+- It seems to mix sender and receiver reports, thus mixing data from two streams 
+    - when does this happen, if at all?
+
+Todo
+----
+- Add support of outbound and inbound SDES. The SDES includes a stream identifier, CNAME. 
+  When this changes, we have a different stream and need to restart the stats.
+  Should we add ability to produce multiple RTCP reports for one "call" and aggregate them?
+  The different parts might have different properties.
+- Check RTCP support for the p2p RTP bridge - today it doesn't work properly.
+
+Ideas and thoughts for the future
+---------------------------------
+- Asterisk propagates jitter and packet loss over a bridge (especially the p2p RTP bridge).
+  If the call is transfered on the OTHER side of the bridge, we have a new call with new
+  properties. Maybe events like this should generate a new SDES and reset RTCP?
+  Part A of the call can have very different properties than part B. If I have a call with
+  someone internally, that then transfers me to a call with someone on the Internet, the
+  call quality (jitter etc) will change dramatically. This will require some sort of CONTROL
+  packet over the bridge, informing about changes on the other side of the bridge (masq).
+- Can we have some sort of ring buffer for the latest RTCP reports for a device (peer) 
+  and use that to determine the status of the connection to the peer?
+- Can we use the APP packet for relaying events in joined bridges, like meetme?
+
+
+Scenarios to test
+------------------
+- normal bridged call
+- RTP p2p bridged call
+- 

Propchange: team/oej/pinefrog-1.4/README.pinefrog-rtcp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/pinefrog-1.4/README.pinefrog-rtcp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/oej/pinefrog-1.4/README.pinefrog-rtcp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/oej/pinefrog-1.4/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/main/channel.c?view=diff&rev=237655&r1=237654&r2=237655
==============================================================================
--- team/oej/pinefrog-1.4/main/channel.c (original)
+++ team/oej/pinefrog-1.4/main/channel.c Tue Jan  5 05:21:33 2010
@@ -999,12 +999,28 @@
 	return __ast_queue_frame(chan, fin, 1, NULL);
 }
 
+static void set_hangupchannelvars(struct ast_channel *chan, const char *name)
+{
+	if (!chan || ast_strlen_zero(name)) {
+		return;
+	}
+
+	/* Set a channel variable */
+	pbx_builtin_setvar_helper(chan, "HANGUPCHANNEL", name);
+
+	/* Also set a cdr variable, that can be reached regardless of the cdr before h option */
+	if (chan->cdr) {
+		ast_cdr_setvar(chan->cdr, "hangupchannel", name, 0);
+	}
+}
+
 /*! \brief Queue a hangup frame for channel */
 int ast_queue_hangup(struct ast_channel *chan)
 {
 	struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
 	/* Yeah, let's not change a lock-critical value without locking */
 	if (!ast_channel_trylock(chan)) {
+		set_hangupchannelvars(chan, chan->name);
 		chan->_softhangup |= AST_SOFTHANGUP_DEV;
 		ast_channel_unlock(chan);
 	}
@@ -1460,6 +1476,8 @@
 {
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
+
+	set_hangupchannelvars(chan, "system");
 	/* Inform channel driver that we need to be hung up, if it cares */
 	chan->_softhangup |= cause;
 	ast_queue_frame(chan, &ast_null_frame);

Modified: team/oej/pinefrog-1.4/main/rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/main/rtp.c?view=diff&rev=237655&r1=237654&r2=237655
==============================================================================
--- team/oej/pinefrog-1.4/main/rtp.c (original)
+++ team/oej/pinefrog-1.4/main/rtp.c Tue Jan  5 05:21:33 2010
@@ -64,12 +64,30 @@
 #define RTCP_MIN_INTERVALMS       500	/*!< Min milli-seconds between RTCP reports we send */
 #define RTCP_MAX_INTERVALMS       60000	/*!< Max milli-seconds between RTCP reports we send */
 
-#define RTCP_PT_FUR     192
-#define RTCP_PT_SR      200
-#define RTCP_PT_RR      201
-#define RTCP_PT_SDES    202
-#define RTCP_PT_BYE     203
-#define RTCP_PT_APP     204
+#define RTCP_PT_FUR     192		/*!< FIR  - Full Intra-frame request */
+#define RTCP_PT_NACK    193		/*!< NACK - Negative acknowledgement */
+#define RTCP_PT_IJ      195		/*!< IJ   - RFC 5450 Extended Inter-arrival jitter report */
+#define RTCP_PT_SR      200		/*!< SR   - RFC 3550 Sender report */
+#define RTCP_PT_RR      201		/*!< RR   - RFC 3550 Receiver report */
+#define RTCP_PT_SDES    202		/*!< SDES - Source Description */
+#define RTCP_PT_BYE     203		/*!< BYE  - Goodbye */
+#define RTCP_PT_APP     204		/*!< APP  - Application defined */
+#define RTCP_PT_RTPFB   205		/*!< RTPFB - Generic RTP feedback RFC 4585 */
+#define RTCP_PT_PSFB    206		/*!< PSFB - Payload specific data  RFC 4585 */
+#define RTCP_PT_XR      207		/*!< XR   - Extended report - RFC3611 */
+
+/*! \brief RFC 3550 RTCP SDES Item types */
+enum rtcp_sdes {
+	SDES_END	= 0,		/*!< End of SDES list */
+	SDES_CNAME	= 1,		/*!< Canonical name */
+	SDES_NAME	= 2,		/*!< User name */
+	SDES_EMAIL	= 3,		/*!< User's e-mail address */
+	SDES_PHONE	= 4,		/*!< User's phone number */
+	SDES_LOC	= 5,		/*!< Geographic user location */
+	SDES_TOOL	= 6,		/*!< Name of application or tool */
+	SDES_NOTE	= 7,		/*!< Notice about the source */
+	SDES_PRIV	= 8,		/*!< SDES Private extensions */
+};
 
 #define RTP_MTU		1200
 
@@ -872,6 +890,8 @@
 	int position, i, packetwords;
 	int res;
 	struct sockaddr_in sin;
+	char sdestext[255];
+	unsigned int sdesheader, sdeslength, sdestype;
 	unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
 	unsigned int *rtcpheader;
 	int pt;
@@ -893,7 +913,8 @@
 	len = sizeof(sin);
 	
 	res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
-					0, (struct sockaddr *)&sin, &len);
+			0, (struct sockaddr *)&sin, &len);
+
 	rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
 	
 	if (res < 0) {
@@ -905,7 +926,7 @@
 		return &ast_null_frame;
 	}
 
-	packetwords = res / 4;
+	packetwords = res / 4;	/* Each RTCP segment is 32 bits */
 
 	if (rtp->nat) {
 		/* Send to whoever sent to us */
@@ -914,41 +935,48 @@
 		    ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) ||
 		    (rtp->rtcp->altthem.sin_port != sin.sin_port))) {
 			memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
-			if (option_debug || rtpdebug)
+			if (option_debug || rtpdebug) {
 				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 (option_debug)
-		ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
+			}
+		}
+	}
+
+	if (option_debug) {
+		ast_log(LOG_DEBUG, "Got RTCP report of %d bytes - %d messages\n", res, packetwords);
+	}
 
 	/* Process a compound packet */
 	position = 0;
 	while (position < packetwords) {
 		i = position;
+		ast_log(LOG_DEBUG, "***** Debug - position = %d\n", position);
+
 		length = ntohl(rtcpheader[i]);
+
+		/* Packet type */
 		pt = (length & 0xff0000) >> 16;
 		rc = (length & 0x1f000000) >> 24;
 		length &= 0xffff;
     
 		if ((i + length) > packetwords) {
-			ast_log(LOG_WARNING, "RTCP Read too short\n");
+			ast_log(LOG_WARNING, "RTCP Read too short - position %d\n", i);
 			return &ast_null_frame;
 		}
 		
 		if (rtcp_debug_test_addr(&sin)) {
-		  	ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-		  	ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
-		  	ast_verbose("Reception reports: %d\n", rc);
-		  	ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
+		  	ast_verbose("\n-- Got RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+		  	ast_verbose("   PT: %d(%s)", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Other");
+		  	ast_verbose("   Reception reports: %d\n", rc);
+		  	ast_verbose("   SSRC of packet sender: %u", rtcpheader[i + 1]);
+		  	ast_verbose("   (Position %d of %d)\n", i, packetwords);
 		}
     
 		i += 2; /* Advance past header and ssrc */
-		
-		switch (pt) {
+
+		switch (pt) {	/* Find the RTCP Packet type */
 		case RTCP_PT_SR:
-			gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
-			rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
+			gettimeofday(&rtp->rtcp->rxlsr, NULL); /* To be able to populate the dlsr */
+			rtp->rtcp->spc = ntohl(rtcpheader[i + 3]);
 			rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
 			rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
     
@@ -956,8 +984,9 @@
 				ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
 				ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
 				ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
+				ast_verbose("RC (number of reports) %d\n", rc);
 			}
-			i += 5;
+			i += 5;	/* Sender's report is five bytes */
 			if (rc < 1)
 				break;
 			/* Intentional fall through */
@@ -975,10 +1004,10 @@
 				/* Convert end to end delay to usec (keeping the calculation in 64bit space)
 				   sess->ee_delay = (eedelay * 1000) / 65536; */
 				if (rtt < 4294) {
-				    rtt = (rtt * 1000000) >> 16;
+					rtt = (rtt * 1000000) >> 16;
 				} else {
-				    rtt = (rtt * 1000) >> 16;
-				    rtt *= 1000;
+					rtt = (rtt * 1000) >> 16;
+					rtt *= 1000;
 				}
 				rtt = rtt / 1000.;
 				rttsec = rtt / 1000.;
@@ -1008,15 +1037,16 @@
 				ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
 				ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
 				ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
-				ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
-				ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
+				ast_verbose("  Last SR (our NTP): %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
+				ast_verbose("  DLSR: %4.4f (sec)\n", ntohl(rtcpheader[i + 5])/65536.0);
 				if (rtt)
 					ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
 			}
 			break;
 		case RTCP_PT_FUR:
-			if (rtcp_debug_test_addr(&sin))
+			if (rtcp_debug_test_addr(&sin)) {
 				ast_verbose("Received an RTCP Fast Update Request\n");
+			}
 			rtp->f.frametype = AST_FRAME_CONTROL;
 			rtp->f.subclass = AST_CONTROL_VIDUPDATE;
 			rtp->f.datalen = 0;
@@ -1026,12 +1056,46 @@
 			f = &rtp->f;
 			break;
 		case RTCP_PT_SDES:
+			sdesheader = ntohl(rtcpheader[i]);
+			sdeslength = (sdesheader & 0xff0000) >> 16;
+			sdestype = (sdesheader & 0x800000) >> 16;
+			if (rtcp_debug_test_addr(&sin)) {
+				ast_verbose("Received an SDES from %s:%d (Type %u, Length %u)\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), sdestype, sdeslength);
+			}
+
+//	/*! \brief RFC 3550 RTCP SDES Item types */
+//	enum rtcp_sdes {
+	//	SDES_END	= 0,		/*!< End of SDES list */
+	//	SDES_CNAME	= 1,		/*!< Canonical name */
+	//	SDES_NAME	= 2,		/*!< User name */
+	//	SDES_EMAIL	= 3,		/*!< User's e-mail address */
+	//	SDES_PHONE	= 4,		/*!< User's phone number */
+	//	SDES_LOC	= 5,		/*!< Geographic user location */
+	//	SDES_TOOL	= 6,		/*!< Name of application or tool */
+	//	SDES_NOTE	= 7,		/*!< Notice about the source */
+	//	SDES_PRIV	= 8,		/*!< SDES Private extensions */
+//	};
+
+			break;
+		case RTCP_PT_NACK:
 			if (rtcp_debug_test_addr(&sin))
-				ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+				ast_verbose("Received a RTCP NACK from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
 			break;
 		case RTCP_PT_BYE:
 			if (rtcp_debug_test_addr(&sin))
-				ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+				ast_verbose("Received a RTCP BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			break;
+		case RTCP_PT_XR:
+			if (rtcp_debug_test_addr(&sin))
+				ast_verbose("Received a RTCP Extended Report (XR) packet from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			break;
+		case RTCP_PT_APP:
+			if (rtcp_debug_test_addr(&sin))
+				ast_verbose("Received a RTCP APP packet from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			break;
+		case RTCP_PT_IJ:
+			if (rtcp_debug_test_addr(&sin))
+				ast_verbose("Received a RTCP IJ from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
 			break;
 		default:
 			if (option_debug)
@@ -1039,10 +1103,12 @@
 			break;
 		}
 		position += (length + 1);
-	}
+	} /* While */
+
+	return f;
+}
+
 			
-	return f;
-}
 
 static void sanitize_tv(struct timeval *tv)
 {

Modified: team/oej/pinefrog-1.4/res/res_features.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/res/res_features.c?view=diff&rev=237655&r1=237654&r2=237655
==============================================================================
--- team/oej/pinefrog-1.4/res/res_features.c (original)
+++ team/oej/pinefrog-1.4/res/res_features.c Tue Jan  5 05:21:33 2010
@@ -2001,6 +2001,7 @@
 	if (config->end_bridge_callback) {
 		config->end_bridge_callback(config->end_bridge_callback_data);
 	}
+
 
 	if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 
 	    ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {




More information about the asterisk-commits mailing list