[asterisk-commits] oej: branch oej/pinefrog-1.4 r238580 - in /team/oej/pinefrog-1.4: channels/ i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jan 8 10:02:36 CST 2010


Author: oej
Date: Fri Jan  8 10:02:32 2010
New Revision: 238580

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=238580
Log:
A lot of unstructured updates to various stuff, a lot of it not tested.
But I'm really making progress here.

Thanks to Eduardo for finding the bug in chan_sip.c. Keep them bug reports coming :-)

Modified:
    team/oej/pinefrog-1.4/channels/chan_sip.c
    team/oej/pinefrog-1.4/include/asterisk/rtp.h
    team/oej/pinefrog-1.4/main/rtp.c
    team/oej/pinefrog-1.4/utils/Makefile

Modified: team/oej/pinefrog-1.4/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/channels/chan_sip.c?view=diff&rev=238580&r1=238579&r2=238580
==============================================================================
--- team/oej/pinefrog-1.4/channels/chan_sip.c (original)
+++ team/oej/pinefrog-1.4/channels/chan_sip.c Fri Jan  8 10:02:32 2010
@@ -18672,7 +18672,7 @@
 				default_qualify = 0;
 			}
 		} else if (!strcasecmp(v->name, "rtcpevents")) {
-			global_callevents = ast_true(v->value);
+			global_rtcpevents = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "callevents")) {
 			global_callevents = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "maxcallbitrate")) {

Modified: team/oej/pinefrog-1.4/include/asterisk/rtp.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/include/asterisk/rtp.h?view=diff&rev=238580&r1=238579&r2=238580
==============================================================================
--- team/oej/pinefrog-1.4/include/asterisk/rtp.h (original)
+++ team/oej/pinefrog-1.4/include/asterisk/rtp.h Fri Jan  8 10:02:32 2010
@@ -78,17 +78,21 @@
 };
 
 struct ast_rtp_quality {
-	unsigned int local_ssrc;          /* Our SSRC */
-	unsigned int local_lostpackets;   /* Our lost packets */
-	double       local_jitter;        /* Our calculated jitter */
-	unsigned int local_count;         /* Number of received packets */
-	unsigned int remote_ssrc;         /* Their SSRC */
-	unsigned int remote_lostpackets;  /* Their lost packets */
-	double       remote_jitter;       /* Their reported jitter */
-	unsigned int remote_count;        /* Number of transmitted packets */
-	double       rtt;                 /* Round trip time */
-	int lasttxformat;
-	int lastrxformat;
+	unsigned int local_ssrc;          /*!< Our SSRC */
+	unsigned int local_lostpackets;   /*!< Our lost packets */
+	double       local_jitter;        /*!< Our calculated jitter */
+	double       local_jitter_max;    /*!< Our calculated jitter */
+	double       local_jitter_min;    /*!< Our calculated jitter */
+	unsigned int local_count;         /*!< Number of received packets */
+	unsigned int remote_ssrc;         /*!< Their SSRC */
+	unsigned int remote_lostpackets;  /*!< Their lost packets */
+	double       remote_jitter;       /*!< Their reported jitter */
+	unsigned int remote_count;        /*!< Number of transmitted packets */
+	double       rtt;                 /*!< Round trip time */
+	double       rttmax;              /*!< Max observed round trip time */
+	double       rttmin;              /*!< Max observed round trip time */
+	int lasttxformat;		  /*!< Last used codec on transmitted stream */
+	int lastrxformat;		  /*!< Last used codec on received stream */
 };
 
 

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=238580&r1=238579&r2=238580
==============================================================================
--- team/oej/pinefrog-1.4/main/rtp.c (original)
+++ team/oej/pinefrog-1.4/main/rtp.c Fri Jan  8 10:02:32 2010
@@ -178,10 +178,12 @@
 	struct timeval dtmfmute;
 	struct ast_smoother *smoother;
 	int *ioid;
+	int *ioidrtcp;
 	unsigned short seqno;		/*!< Sequence number, RFC 3550, page 13. */
 	unsigned short rxseqno;
 	struct sched_context *sched;
-	struct io_context *io;
+	struct io_context *io;		/*!< for RTP callback */
+	struct io_context *iortcp;	/*!< for RTCP callback */
 	void *data;
 	ast_rtp_callback callback;
 	ast_mutex_t bridge_lock;
@@ -200,11 +202,14 @@
 /* Forward declarations */
 static int ast_rtcp_write(const void *data);
 static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
-static int ast_rtcp_write_sr(const void *data);
-static int ast_rtcp_write_rr(const void *data);
+static int ast_rtcp_write_sr(const void *data, int goodbye);
+static int ast_rtcp_write_rr(const void *data, int goodbye);
 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 struct ast_frame *ast_rtcp_read_fd(int fd, struct ast_rtp *rtp);
+static int ast_rtcp_write_empty(struct ast_rtp *rtp, int fd);
+static int p2p_rtcp_callback(int *id, int fd, short events, void *cbdata);
 
 #define FLAG_3389_WARNING		(1 << 0)
 #define FLAG_NAT_ACTIVE			(3 << 1)
@@ -230,7 +235,9 @@
 struct ast_rtcp {
 	int s;				/*!< Socket */
 	char ourcname[255];		/*!< Our SDES RTP session name (CNAME) */
+	size_t ourcnamelength;		/*!< Length of CNAME (utf8) */
 	char theircname[255];		/*!< Their SDES RTP session name (CNAME) */
+	size_t theircnamelength;	/*!< Length of CNAME (utf8) */
 	struct sockaddr_in us;		/*!< Socket representation of the local endpoint. */
 	struct sockaddr_in them;	/*!< Socket representation of the remote endpoint. */
 	struct sockaddr_in altthem;	/*!< Alternate source for RTCP */
@@ -248,12 +255,23 @@
 	double accumulated_transit;	/*!< accumulated a-dlsr-lsr */
 	double rtt;			/*!< Last reported rtt */
 	unsigned int reported_jitter;	/*!< The contents of their last jitter entry in the RR */
+	double reported_maxjitter;	/*!< The contents of their last jitter entry in the RR */
+	double reported_minjitter;	/*!< The contents of their last jitter entry in the RR */
+	unsigned int reported_jitter_count;
 	unsigned int reported_lost;	/*!< Reported lost packets in their RR */
+	double reported_maxlost;
+	double reported_minlost;
+	double rxlost;
+	double maxrxlost;
+	double minrxlost;
+	unsigned int rxlost_count;
 	char quality[AST_MAX_USER_FIELD];
 	double maxrxjitter;
 	double minrxjitter;
+	unsigned int rxjitter_count;
 	double maxrtt;
 	double minrtt;
+	unsigned int rtt_count;
 	int sendfur;
 };
 
@@ -552,6 +570,22 @@
 	return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
 }
 
+/*! \brief Schedule RTCP transmissions for RTP channel */
+static void ast_rtcp_schedule(struct ast_rtp *rtp)
+{
+	/* Do not schedule RR if RTCP isn't run */
+	if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+		/* Schedule transmission of Receiver Report */
+		ast_rtcp_write_empty(rtp, rtp->rtcp->s);
+		rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+				ast_log(LOG_DEBUG, "-------- SCHEDULING RTCP reports!!!\n");
+	} else {
+		//ast_log(LOG_DEBUG, "----- NOT SCHEDULING RTCP - RTCP %s RTCP address %s schedid %d\n", 
+			//rtp->rtcp ? "yes" : "no",
+			//rtp->rtcp->them.sin_addr.s_addr ? "yes" : "no", rtp->rtcp->schedid);
+	}
+}
+
 unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
 {
 	unsigned int interval;
@@ -888,7 +922,20 @@
 	return 1;
 }
 
+static int p2p_rtcp_callback(int *id, int fd, short events, void *cbdata)
+{
+	struct ast_rtp *rtp = cbdata;
+	ast_rtcp_read_fd(fd, rtp);
+	/* For now, skip any frames that is output. Which is bad for FUR's, but well. DEBUG */
+	return 1;
+}
+
 struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
+{
+	return ast_rtcp_read_fd(rtp->rtcp->s, rtp);
+}
+
+static struct ast_frame *ast_rtcp_read_fd(int fd, struct ast_rtp *rtp)
 {
 	socklen_t len;
 	int position, i, j, packetwords;
@@ -916,7 +963,7 @@
 
 	len = sizeof(sin);
 	
-	res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
+	res = recvfrom(fd, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
 			0, (struct sockaddr *)&sin, &len);
 
 	rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
@@ -961,49 +1008,62 @@
 
 		length = ntohl(rtcpheader[i]);
 
-		/* Packet type */
-		pt = (length & 0xff0000) >> 16;
-		rc = (length & 0x1f000000) >> 24;
+		pt = (length & 0xff0000) >> 16;		/* Packet type */
+		rc = (length & 0x1f000000) >> 24;	/* Number of chunks, i.e. streams reported */
 		length &= 0xffff;
     
 		if ((i + length) > packetwords) {
-			ast_log(LOG_WARNING, "RTCP Read too short - position %d\n", i);
-			return &ast_null_frame;
+			ast_log(LOG_WARNING, "RTCP Read too short - packet type %d position %d\n", pt, i);
+			return f;
 		}
 		
 		if (rtcp_debug_test_addr(&sin)) {
 		  	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("   Length : %d\n", length);
-		  	ast_verbose("   Reception reports: %d\n", rc);
-		  	ast_verbose("   SSRC of packet sender: %u", rtcpheader[i + 1]);
+		  	ast_verbose("   Length : %d Chunks: %d\n", length, rc);
+		  	ast_verbose("   SSRC of packet sender: %u (%x)", rtcpheader[i + 1], rtcpheader[i + 1]);
 		  	ast_verbose("   (Position %d of %d)\n", i, packetwords);
+			if (rc == 0) {
+		  		ast_verbose("   Empty - no reports! \n");
+			}
 		}
     
 		i += 2; /* Advance past header and ssrc */
+		if (rc == 0) {	/* We're receiving a report with no reports, which is ok */
+			position += (length + 1);
+			continue;
+		}
 
 		switch (pt) {	/* Find the RTCP Packet type */
-		case RTCP_PT_SR:
+		case RTCP_PT_SR:	/* Sender's report - about what they have sent us */
+			if (rtcp_debug_test_addr(&sin)) {
+				ast_verbose("    - RTCP SR (sender report) from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			}
+			/* Don't handle multiple reception reports (rc > 1) yet */
 			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->spc = ntohl(rtcpheader[i + 3]);	/* Sender packet count */
+			rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);	/* Sender octet count */
+
 			rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
     
 			if (rtcp_debug_test_addr(&sin)) {
-				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);
+				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;	/* Sender's report is five bytes */
+			i += 5;	/* Sender's info report is five bytes */
 			if (rc < 1)
 				break;
-			/* Intentional fall through */
-		case RTCP_PT_RR:
+			/* Intentional fall through - the report blocks are the same for RR and SR */
+		case RTCP_PT_RR:	/* Receiver report - data about what we have sent to them */
+			if (rtcp_debug_test_addr(&sin)) {
+				ast_verbose("Received a RTCP RR (receiver report) from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+			}
 			/* Don't handle multiple reception reports (rc > 1) yet */
 			/* Calculate RTT per RFC */
 			gettimeofday(&now, NULL);
 			timeval2ntp(now, &msw, &lsw);
+			/* Get timing */
 			if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
 				comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
 				lsr = ntohl(rtcpheader[i + 4]);
@@ -1024,10 +1084,11 @@
 				if (comp - dlsr >= lsr) {
 					rtp->rtcp->accumulated_transit += rttsec;
 					rtp->rtcp->rtt = rttsec;
-					if (rtp->rtcp->maxrtt<rttsec)
+					if (rtp->rtcp->maxrtt < rttsec)
 						rtp->rtcp->maxrtt = rttsec;
-					if (rtp->rtcp->minrtt>rttsec)
+					if (rtp->rtcp->minrtt > rttsec || rtp->rtcp->minrtt == 0) {
 						rtp->rtcp->minrtt = rttsec;
+					}
 				} else if (rtcp_debug_test_addr(&sin)) {
 					ast_verbose("Internal RTCP NTP clock skew detected: "
 							   "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
@@ -1039,17 +1100,25 @@
 			}
 
 			rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
+			if (rtp->rtcp->reported_jitter > rtp->rtcp->reported_maxjitter) {
+				rtp->rtcp->reported_maxjitter = rtp->rtcp->reported_jitter;
+			} else if (rtp->rtcp->reported_jitter < rtp->rtcp->reported_minjitter || rtp->rtcp->reported_minjitter == 0) {
+				rtp->rtcp->reported_minjitter = rtp->rtcp->reported_jitter;
+			}
 			rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
 			if (rtcp_debug_test_addr(&sin)) {
 				ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
 				ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
 				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("  Interarrival jitter: %u Max %u Min %u\n", rtp->rtcp->reported_jitter,
+					rtp->rtcp->reported_maxjitter, rtp->rtcp->reported_minjitter);
 				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);
+					ast_verbose("  RTT: %lu(sec) Max %lu Min %lu\n", (unsigned long) rtt, 
+						(unsigned long) rtp->rtcp->maxrtt,
+						(unsigned long) rtp->rtcp->minrtt );
 			}
 			break;
 		case RTCP_PT_FUR:
@@ -1074,7 +1143,6 @@
 			   In the SDES message, there can be several items, ending with SDES_END
 			   The length of the all items is length - header 
 			   Chunk starts on a 32-bit boundary and needs padding by 0's
-
 		
 			   the "rc" variable contains the number of chunks 
 			   When we start, we're beyond the SSRC and starts with SDES items in the
@@ -1098,39 +1166,55 @@
 				}
 				switch (sdestype) {
 				case SDES_CNAME:
+					if (!ast_strlen_zero(rtp->rtcp->theircname)) {
+						if (strncmp(rtp->rtcp->theircname, sdes, sdeslength)) {
+							ast_log(LOG_WARNING, "New RTP stream received (new RTCP CNAME for session. Old name: %s\n", rtp->rtcp->theircname);
+						}
+					}
 					strncpy(rtp->rtcp->theircname, sdes, sdeslength);
 					rtp->rtcp->theircname[sdeslength] = '\0';
+					rtp->rtcp->theircnamelength = sdeslength;
 					if (rtcp_debug_test_addr(&sin)) {
 						ast_verbose(" --- SDES CNAME (utf8) %s\n", rtp->rtcp->theircname);
 					}
 					break;
 				case SDES_EMAIL:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES EMAIL \n");
+					}
 					break;
 				case SDES_PHONE:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES PHONE \n");
+					}
 					break;
 				case SDES_LOC:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES LOC \n");
+					}
 					break;
 				case SDES_NOTE:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES NOTE \n");
+					}
 					break;
 				case SDES_PRIV:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES PRIV \n");
+					}
+					break;
+				case SDES_END:
+					if (rtcp_debug_test_addr(&sin)) {
+						ast_verbose(" --- SDES END \n");
+					}
 					break;
 				}
-				j += sdeslength;	/* Header (1 byte) + length */
+				j += 2 + sdeslength;	/* Header (1 byte) + length */
 				sdes += sdeslength;
+				if (sdestype == SDES_END) {
+					break;	/* The while loop */
+				}
 			}
-
-//	/*! \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:
@@ -1201,6 +1285,7 @@
 	}
 
 	gettimeofday(&now,NULL);
+
 	/* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
 	tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate;
 	tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125;
@@ -1214,10 +1299,18 @@
 	if (d<0)
 		d=-d;
 	rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
-	if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
+	if (!rtp->rtcp) {
+		return;
+	}
+
+	if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
 		rtp->rtcp->maxrxjitter = rtp->rxjitter;
-	if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
+	if (rtp->rtcp->rxjitter_count == 1) {
 		rtp->rtcp->minrxjitter = rtp->rxjitter;
+	}
+	if (rtp->rxjitter < rtp->rtcp->minrxjitter)
+		rtp->rtcp->minrxjitter = rtp->rxjitter;
+	rtp->rtcp->rxjitter_count++;
 }
 
 /*! \brief Perform a Packet2Packet RTP write */
@@ -1271,6 +1364,8 @@
 		return 0;
 	} else if (rtp_debug_test_addr(&bridged->them))
 			ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
+	rtp->txcount++;
+	//SKREP rtp->lasttxformat = rtpPT;
 
 	return 0;
 }
@@ -1408,11 +1503,9 @@
 		rtp->seedrxseqno = seqno;
 	}
 
-	/* Do not schedule RR if RTCP isn't run */
-	if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
-		/* Schedule transmission of Receiver Report */
-		rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-	}
+	/* Schedule RTCP report transmissions if possible */
+	ast_rtcp_schedule(rtp);
+
 	if ( (int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
 		rtp->cycles += RTP_SEQ_MOD;
 
@@ -2160,6 +2253,7 @@
 	if (callbackmode) {
 		rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
 		ast_set_flag(rtp, FLAG_CALLBACK_MODE);
+		rtp->ioidrtcp = ast_io_add(rtp->iortcp, rtp->rtcp->s, p2p_rtcp_callback, AST_IO_IN, rtp);
 	}
 	ast_rtp_pt_default(rtp);
 	return rtp;
@@ -2180,6 +2274,7 @@
 		return;
 	}
 	ast_copy_string(rtp->rtcp->ourcname, cname, length > 255 ? 255 : length);
+	rtp->rtcp->ourcnamelength = length;
 	ast_log(LOG_DEBUG, "--- Copied CNAME %s to RTCP structure (length %d)\n", cname, (int) length);
 }
 
@@ -2271,6 +2366,9 @@
 	memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
 	memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
 	if (rtp->rtcp) {
+		/* Send RTCP goodbye packet */
+		ast_log(LOG_DEBUG, "----- REQUESTING GOODBYE RTCP \n");
+		ast_rtcp_write_sr((const void *) rtp, 1);
 		memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
 		memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
 	}
@@ -2348,27 +2446,40 @@
 {
 	if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
 		/*Print some info on the call here */
-		ast_verbose("  RTP-stats\n");
+		ast_verbose(" RTP-stats\n");
 		ast_verbose("* Our Receiver:\n");
-		ast_verbose("  SSRC:		 %u\n", rtp->themssrc);
-		ast_verbose("  Received packets: %u\n", rtp->rxcount);
-		ast_verbose("  Lost packets:	 %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
-		ast_verbose("  Jitter:		 %.4f\n", rtp->rxjitter);
-		ast_verbose("  Transit:		 %.4f\n", rtp->rxtransit);
-		ast_verbose("  RR-count:	 %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
+		ast_verbose("   SSRC:		  %u\n", rtp->themssrc);
+		ast_verbose("   CNAME:		  %s\n", rtp->rtcp ? rtp->rtcp->theircname : "");
+		ast_verbose("   Received packets: %u\n", rtp->rxcount);
+		ast_verbose("   Lost packets:	  %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
+		ast_verbose("   Jitter:		  %.4f\n", rtp->rxjitter);
+		ast_verbose("   Transit:	  %.4f\n", rtp->rxtransit);
+		ast_verbose("   RR-count:	  %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
+
 		ast_verbose("* Our Sender:\n");
-		ast_verbose("  SSRC:		 %u\n", rtp->ssrc);
-		ast_verbose("  Sent packets:	 %u\n", rtp->txcount);
-		ast_verbose("  Lost packets:	 %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
-		ast_verbose("  Jitter:		 %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
-		ast_verbose("  SR-count:	 %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
-		ast_verbose("  RTT:		 %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
+		ast_verbose("   SSRC:		  %u\n", rtp->ssrc);
+		ast_verbose("   CNAME:		  %s\n", rtp->rtcp ? rtp->rtcp->ourcname : "");
+		ast_verbose("   Sent packets:	  %u\n", rtp->txcount);
+		ast_verbose("   Lost packets:	  %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
+		ast_verbose("   Jitter:		  %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
+		ast_verbose("   SR-count:	  %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
+		ast_verbose("   RTT:		  %lu\n", rtp->rtcp ? (unsigned long) rtp->rtcp->rtt : 0);
+		ast_verbose("   RTT Max:	  %lu\n", rtp->rtcp ? (unsigned long) rtp->rtcp->maxrtt : 0);
+		ast_verbose("   RTT Min:	  %lu\n", rtp->rtcp ? (unsigned long) rtp->rtcp->minrtt : 0);
+
+		ast_verbose("* Media\n");
+		ast_verbose("   Last format sent: %s\n", ast_getformatname(rtp->lasttxformat));
+		ast_verbose("   Last format recv: %s\n", ast_getformatname(rtp->lastrxformat));
+
+		ast_verbose("\n");
 	}
 
 	if (rtp->smoother)
 		ast_smoother_free(rtp->smoother);
 	if (rtp->ioid)
 		ast_io_remove(rtp->io, rtp->ioid);
+	if (rtp->ioidrtcp)
+		ast_io_remove(rtp->iortcp, rtp->ioidrtcp);
 	if (rtp->s > -1)
 		close(rtp->s);
 	if (rtp->rtcp) {
@@ -2572,45 +2683,116 @@
 	return res;
 }
 
-static int add_sdes_bodypart(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len)
-{
-	unsigned int *start = rtcp_packet;
-	char *sdes;
-	int cnamelen;
-
-	rtcp_packet++;	/* Move 32 bits ahead */
+/*! \brief Basically add SSRC */
+static int add_sdes_header(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len)
+{
+	/* 2 is version, 1 is number of chunks, then RTCP packet type (SDES) and length */
+	*rtcp_packet = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((len/4)-1));
+
+	rtcp_packet++;	/* Move 32 bits ahead for the header */
 	*rtcp_packet = htonl(rtp->ssrc);               /* Our SSRC */
 	rtcp_packet ++;
 
-	len += 8;	/* Header + SSRC */
-
-	ast_log(LOG_DEBUG, "----About to copy CNAME to SDES packet --- (len %d)\n", len);
+	/* Header + SSRC */
+	return len + 8;
+}
+
+static int add_sdes_bodypart(struct ast_rtp *rtp, unsigned int *rtcp_packet, int len, int type)
+{
+	int cnamelen;
+	int sdeslen = 0;
+	char *sdes;
 
 	sdes = (char *) rtcp_packet;
-	cnamelen = (int) strlen(rtp->rtcp->ourcname);
-
-	*sdes = SDES_CNAME;
-	sdes++;
-	*sdes = (char) cnamelen;
-	sdes++;
-	strncpy(sdes, rtp->rtcp->ourcname, cnamelen);	/* NO terminating 0 */
-	sdes+=cnamelen;
-	*sdes = SDES_END;	/* Terminating SDES packet */
-
-	/* THere must be a multiple of four bytes in the packet */
-	len += 2 + cnamelen + ((cnamelen +2) % 4 == 0 ? 0 : 4 - ((cnamelen + 2) % 4)) ;
-	ast_log(LOG_DEBUG, "----our CNAME %s--- (cnamelen %d len %d)\n", rtp->rtcp->ourcname, cnamelen, len);
-
-	/* 2 is version, 1 is number of chunks, then RTCP packet type (SDES) and length */
-	*start = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((len/4)-1));
+	switch (type) {
+	case SDES_CNAME:
+		ast_log(LOG_DEBUG, "----About to copy CNAME to SDES packet --- (len %d)\n", len);
+
+		cnamelen = (int) strlen(rtp->rtcp->ourcname);
+
+		*sdes = SDES_CNAME;
+		sdes++;
+		*sdes = (char) cnamelen;
+		sdes++;
+		strncpy(sdes, rtp->rtcp->ourcname, cnamelen);	/* NO terminating 0 */
+
+		/* THere must be a multiple of four bytes in the packet */
+		sdeslen = cnamelen;
+		ast_log(LOG_DEBUG, "----our CNAME %s--- (cnamelen %d len %d)\n", rtp->rtcp->ourcname, cnamelen, len);
+		break;
+	case SDES_END:
+		*sdes = SDES_END;
+		sdes++;
+		*sdes = (char) 0;
+		sdes++;
+		sdeslen = 2;
+	}
+	len += sdeslen + (sdeslen % 4 == 0 ? 0 : 4 - (sdeslen % 4)) ;
 
 	ast_log(LOG_DEBUG, "----Copied our CNAME to SDES packet --- (len %d)\n", len);
 
 	return len;
 }
 
+/*! \brief Send emtpy RTCP receiver's report and SDES message 
+ 	Mainly used to open NAT sessions  */
+static int ast_rtcp_write_empty(struct ast_rtp *rtp, int fd)
+{
+	char bdata[512];
+	unsigned int *rtcpheader, *start;
+	int len, res;
+
+	if (!rtp || !rtp->rtcp) {
+		ast_log(LOG_DEBUG, "---- NOT sending empty RTCP packet\n");
+		return 0;
+	} 
+	if (fd == -1) {
+		ast_log(LOG_DEBUG, "--- No file descriptor to use \n");
+	}
+	
+	if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
+		ast_verbose("RTCP SR transmission error, rtcp halted\n");
+		AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+		return 0;
+	}
+	ast_log(LOG_DEBUG,  "---- About to send empty RTCP packet\n");
+	rtcpheader = (unsigned int *)bdata;
+	/* Add a RR header with no reports (chunks = 0) - The RFC says that it's always needed 
+		first in a compound packet.
+	 */
+	rtcpheader[0] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_RR << 16) | 1);
+	rtcpheader[1] = htonl(rtp->ssrc);
+	len = 8;
+	start = &rtcpheader[len/4];
+	len +=8; /* SKip header for now */
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+	/* Now, add header when we know the actual length */
+	add_sdes_header(rtp, start, len);
+
+	res = sendto(fd, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+
+	if (res < 0) {
+		ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
+		/* Remove the scheduler */
+		AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+		return 0;
+	}
+
+	rtp->rtcp->rr_count++;
+
+	if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+		ast_verbose("\n* Sending Empty RTCP RR to %s:%d  Our SSRC: %u\n",
+			ast_inet_ntoa(rtp->rtcp->them.sin_addr),
+			ntohs(rtp->rtcp->them.sin_port),
+			rtp->ssrc);
+	}
+
+	return res;
+}
+
 /*! \brief Send RTCP sender's report */
-static int ast_rtcp_write_sr(const void *data)
+static int ast_rtcp_write_sr(const void *data, int goodbye)
 {
 	struct ast_rtp *rtp = (struct ast_rtp *)data;
 	int res;
@@ -2618,7 +2800,7 @@
 	struct timeval now;
 	unsigned int now_lsw;
 	unsigned int now_msw;
-	unsigned int *rtcpheader;
+	unsigned int *rtcpheader, *start;
 	unsigned int lost;
 	unsigned int extended;
 	unsigned int expected;
@@ -2629,8 +2811,7 @@
 	struct timeval dlsr;
 	char bdata[512];
 
-	/* Commented condition is always not NULL if rtp->rtcp is not NULL */
-	if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
+	if (!rtp || !rtp->rtcp)
 		return 0;
 	
 	if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
@@ -2673,6 +2854,7 @@
 	rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
 	len += 24;
 	
+	/* Set the header for sender's report */
 	rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
 
 	if (rtp->rtcp->sendfur) {
@@ -2682,9 +2864,24 @@
 		rtp->rtcp->sendfur = 0;
 	}
 
-	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len);
-	
-	
+	start = &rtcpheader[len/4];
+	len +=8; /* SKip header for now */
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+	/* Now, add header when we know the actual length */
+	ast_log(LOG_DEBUG, "----- AFTER SENDING CNAME RTCP Len: %d \n", len);
+	add_sdes_header(rtp, start, len);
+
+	if (goodbye) {
+		ast_log(LOG_DEBUG, "----- SENDING GOODBYE RTCP Len: %d \n", len);
+		/* An additional RTCP block */
+		len+=4;
+		rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_BYE << 16) | 1);
+		len += 4;
+		rtcpheader[len/4] = htonl(rtp->ssrc);               /* Our SSRC */
+		len += 4;
+		ast_log(LOG_DEBUG, "----- SENT GOODBYE RTCP Len: %d \n", len);
+	}
 	
 	res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
 	if (res < 0) {
@@ -2703,6 +2900,7 @@
 		ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
 		ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
 		ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
+		ast_verbose("  Send NTP variant: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[2]),((unsigned long) ntohl(rtcpheader[3])) * 4096);
 		ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
 		ast_verbose("  Sent packets: %u\n", rtp->txcount);
 		ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
@@ -2717,7 +2915,7 @@
 }
 
 /*! \brief Send RTCP recepient's report */
-static int ast_rtcp_write_rr(const void *data)
+static int ast_rtcp_write_rr(const void *data, int goodbye)
 {
 	struct ast_rtp *rtp = (struct ast_rtp *)data;
 	int res;
@@ -2729,7 +2927,7 @@
 	unsigned int received_interval;
 	int lost_interval;
 	struct timeval now;
-	unsigned int *rtcpheader;
+	unsigned int *rtcpheader, *start;
 	char bdata[1024];
 	struct timeval dlsr;
 	int fraction;
@@ -2751,6 +2949,8 @@
 	received_interval = rtp->rxcount - rtp->rtcp->received_prior;
 	rtp->rtcp->received_prior = rtp->rxcount;
 	lost_interval = expected_interval - received_interval;
+
+	rtp->rtcp->rxlost_count++;
 	if (expected_interval == 0 || lost_interval <= 0)
 		fraction = 0;
 	else
@@ -2774,13 +2974,13 @@
 		rtp->rtcp->sendfur = 0;
 	}
 
-	/*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 
-	it can change mid call, and SDES can't) */
-	rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-	rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
-	rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
-	len += 12;
-	
+	start = &rtcpheader[len/4];
+	len +=8; /* SKip header for now */
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_CNAME);
+	len = add_sdes_bodypart(rtp, &rtcpheader[len/4], len, SDES_END);
+	/* Now, add header when we know the actual length */
+	add_sdes_header(rtp, start, len);
+
 	res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
 
 	if (res < 0) {
@@ -2821,9 +3021,9 @@
 		return 0;
 
 	if (rtp->txcount > rtp->rtcp->lastsrtxcount)
-		res = ast_rtcp_write_sr(data);
+		res = ast_rtcp_write_sr(data, 0);
 	else
-		res = ast_rtcp_write_rr(data);
+		res = ast_rtcp_write_rr(data, 0);
 	
 	return res;
 }
@@ -2955,10 +3155,8 @@
 			rtp->txcount++;
 			rtp->txoctetcount +=(res - hdrlen);
 			
-			/* Do not schedule RR if RTCP isn't run */
-			if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
-			    rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-			}
+			/* Schedule RTCP report transmissions if possible */
+			ast_rtcp_schedule(rtp);
 		}
 				
 		if (rtp_debug_test_addr(&rtp->them))
@@ -3337,6 +3535,7 @@
 
 /*! \brief P2P RTP Callback */
 #ifdef P2P_INTENSE
+
 static int p2p_rtp_callback(int *id, int fd, short events, void *cbdata)
 {
 	int res = 0, hdrlen = 12;
@@ -3351,6 +3550,11 @@
 	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;
+
+	rtp->rxcount++;
+
+	/* Schedule RTCP report transmissions if possible */
+	ast_rtcp_schedule(rtp);
 
 	header = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
 
@@ -3386,11 +3590,18 @@
 	}
 
 	/* Steal the file descriptors from the channel and stash them away */
-	fds[0] = chan->fds[0];
+	fds[0] = chan->fds[0];	/* RTP */
+	fds[1] = chan->fds[1];	/* RTCP */
 	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);
+	iod[1] = ast_io_add(rtp->ioc, fds[1], p2p_rtcp_callback, AST_IO_IN, rtp);
+
+	/* Kick the RTCP stream going by sending one empty stupid little packet */
+	ast_rtcp_write_empty(rtp, rtp->rtcp->s);
+	ast_log(LOG_DEBUG, "--- Enabled p2p callback for RTCP reads \n");
 
 	return 1;
 }
@@ -3408,14 +3619,18 @@
 
 	/* Remove the callback from the IO context */
 	ast_io_remove(rtp->io, iod[0]);
+	ast_io_remove(rtp->iortcp, 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))
+	if (ast_test_flag(rtp, FLAG_CALLBACK_MODE)) {
 		rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
+		rtp->ioidrtcp = ast_io_add(rtp->iortcp, fds[1], p2p_rtcp_callback, AST_IO_IN, rtp);
+	}
 
 	return 0;
 }
@@ -3453,6 +3668,10 @@
 	/* Now let go of the channel locks and be on our way */
 	ast_channel_unlock(c0);
 	ast_channel_unlock(c1);
+
+	/* Kick the RTCP stream going by sending one empty stupid little packet */
+	ast_rtcp_write_empty(p0, p0->rtcp->s);
+	ast_rtcp_write_empty(p1, p1->rtcp->s);
 
 	/* Go into a loop forwarding frames until we don't need to anymore */
 	cs[0] = c0;

Modified: team/oej/pinefrog-1.4/utils/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinefrog-1.4/utils/Makefile?view=diff&rev=238580&r1=238579&r2=238580
==============================================================================
--- team/oej/pinefrog-1.4/utils/Makefile (original)
+++ team/oej/pinefrog-1.4/utils/Makefile Fri Jan  8 10:02:32 2010
@@ -30,6 +30,11 @@
 UTILS:=$(ALL_UTILS)
 
 include $(ASTTOPDIR)/Makefile.rules
+
+ifneq ($(findstring darwin,$(OSARCH)),)
+  _ASTCFLAGS+=-D__Darwin__
+  AUDIO_LIBS=-framework CoreAudio
+endif
 
 ifeq ($(OSARCH),SunOS)
   LIBS+=-lsocket -lnsl




More information about the asterisk-commits mailing list