[svn-commits] branch kpfleming/vldtmf r9030 - /team/kpfleming/vldtmf/rtp.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Tue Jan 31 20:27:03 MST 2006


Author: kpfleming
Date: Tue Jan 31 21:27:03 2006
New Revision: 9030

URL: http://svn.digium.com/view/asterisk?rev=9030&view=rev
Log:
more code simplification and restructuring

Modified:
    team/kpfleming/vldtmf/rtp.c

Modified: team/kpfleming/vldtmf/rtp.c
URL: http://svn.digium.com/view/asterisk/team/kpfleming/vldtmf/rtp.c?rev=9030&r1=9029&r2=9030&view=diff
==============================================================================
--- team/kpfleming/vldtmf/rtp.c (original)
+++ team/kpfleming/vldtmf/rtp.c Tue Jan 31 21:27:03 2006
@@ -4,6 +4,7 @@
  * Copyright (C) 1999 - 2006, Digium, Inc.
  *
  * Mark Spencer <markster at digium.com>
+ * Kevin P. Fleming <kpfleming at digium.com>
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -22,6 +23,7 @@
  * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
  *
  * \author Mark Spencer <markster at digium.com>
+ * \author Kevin P. Fleming <kpfleming at digium.com>
  * 
  * \note RTP is defined in RFC 3550.
  */
@@ -174,7 +176,6 @@
 };
 
 struct rfc2833_event {
-	struct rtp_header header;
 	/* Always keep in network byte order */
 #if __BYTE_ORDER == __BIG_ENDIAN
 	uint32_t event:8;
@@ -196,7 +197,6 @@
 };
 
 struct rfc3389_event {
-	struct rtp_header header;
 	char level;
 };
 
@@ -225,6 +225,42 @@
 void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
 {
 	rtp->nat = nat;
+}
+
+static char digit_to_code(char digit)
+{
+	if ((digit <= '9') && (digit >= '0'))
+		return digit - '0';
+	else if (digit == '*')
+		return 10;
+	else if (digit == '#')
+		return 11;
+	else if ((digit >= 'A') && (digit <= 'D')) 
+		return digit - 'A' + 12;
+	else if ((digit >= 'a') && (digit <= 'd')) 
+		return digit - 'a' + 12;
+	else {
+		ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+		return -1;
+	}
+}
+
+static char code_to_digit(char code)
+{
+	if (code < 10) {
+		return '0' + code;
+	} else if (code < 11) {
+		return '*';
+	} else if (code < 12) {
+		return '#';
+	} else if (code < 16) {
+		return 'A' + (code - 12);
+	} else if (code == 16) {
+		return 'X';
+	} else {
+		ast_log(LOG_WARNING, "Don't know how to represent '%d'\n", code);
+		return -1;
+	}
 }
 
 static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
@@ -280,20 +316,12 @@
 	event &= 0x001F;
 	if (option_debug > 2 || rtpdebug)
 		ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
-	if (event < 10) {
-		resp = '0' + event;
-	} else if (event < 11) {
-		resp = '*';
-	} else if (event < 12) {
-		resp = '#';
-	} else if (event < 16) {
-		resp = 'A' + (event - 12);
-	} else if (event < 17) {
-		resp = 'X';
-	}
-	if (rtp->resp && (rtp->resp != resp)) {
+
+	resp = code_to_digit(event);
+
+	if (rtp->resp && (rtp->resp != resp))
 		f = send_dtmf(rtp);
-	}
+
 	rtp->resp = resp;
 	rtp->dtmfcount = dtmftimeout;
 	return f;
@@ -305,58 +333,42 @@
  * RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
  * 
  * \param rtp
- * \param data
- * \param len
- * \param seqno
+ * \param header
+ * \param event
  * \returns
  */
-static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno)
-{
-	unsigned int event;
-	unsigned int event_end;
-	unsigned int duration;
+static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, struct rtp_header *header, struct rfc2833_event *event)
+{
 	char resp = 0;
 	struct ast_frame *f = NULL;
 
-	event = ntohl(*((unsigned int *)(data)));
-	event >>= 24;
-	event_end = ntohl(*((unsigned int *)(data)));
-	event_end <<= 8;
-	event_end >>= 24;
-	duration = ntohl(*((unsigned int *)(data)));
-	duration &= 0xFFFF;
 	if (rtpdebug || option_debug > 2)
-		ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
-	if (event < 10) {
-		resp = '0' + event;
-	} else if (event < 11) {
-		resp = '*';
-	} else if (event < 12) {
-		resp = '#';
-	} else if (event < 16) {
-		resp = 'A' + (event - 12);
-	} else if (event < 17) {	/* Event 16: Hook flash */
-		resp = 'X';	
-	}
+		ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x\n", event->event);
+
+	resp = code_to_digit(event->event);
+
 	if (rtp->resp && (rtp->resp != resp)) {
 		f = send_dtmf(rtp);
-	} else if(event_end & 0x80) {
+	} else if (event->end) {
 		if (rtp->resp) {
-			if(rtp->lasteventendseqn != seqno) {
+			if (rtp->lasteventendseqn != header->sequence) {
 				f = send_dtmf(rtp);
-				rtp->lasteventendseqn = seqno;
+				rtp->lasteventendseqn = header->sequence;
 			}
 			rtp->resp = 0;
 		}
 		resp = 0;
-		duration = 0;
-	} else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) {
+		event->duration = 0;
+	} else if (rtp->resp && rtp->dtmfduration && (event->duration < rtp->dtmfduration)) {
 		f = send_dtmf(rtp);
 	}
-	if (!(event_end & 0x80))
+
+	if (!event->end)
 		rtp->resp = resp;
+
 	rtp->dtmfcount = dtmftimeout;
-	rtp->dtmfduration = duration;
+	rtp->dtmfduration = event->duration;
+
 	return f;
 }
 
@@ -366,7 +378,8 @@
  * This is incomplete at the moment.
  * 
 */
-static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
+static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, struct rtp_header *header, struct rfc3389_event *event,
+					 int len)
 {
 	struct ast_frame *f = NULL;
 
@@ -384,16 +397,12 @@
 			ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
 		ast_set_flag(rtp, FLAG_3389_WARNING);
 	}
-
-	/* Must have at least one byte */
-	if (!len)
-		return NULL;
 
 	if (len < 24) {
 		rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
 		rtp->f.datalen = len - 1;
 		rtp->f.offset = AST_FRIENDLY_OFFSET;
-		memcpy(rtp->f.data, data + 1, len - 1);
+		memcpy(rtp->f.data, ((unsigned char *) event) + 1, len - 1);
 	} else {
 		rtp->f.data = NULL;
 		rtp->f.offset = 0;
@@ -401,8 +410,7 @@
 	}
 
 	rtp->f.frametype = AST_FRAME_CNG;
-	rtp->f.subclass = data[0] & 0x7f;
-	rtp->f.datalen = len - 1;
+	rtp->f.subclass = event->level;
 	rtp->f.samples = 0;
 	rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
 	f = &rtp->f;
@@ -482,8 +490,6 @@
 	int res;
 	struct sockaddr_in sin;
 	socklen_t len;
-	unsigned int seqno;
-	unsigned int timestamp;
 	char iabuf[INET_ADDRSTRLEN];
 	struct rtp_header *header;
 	static struct ast_frame *f;
@@ -534,13 +540,19 @@
 		return &ast_null_frame;
 	
 	/* Get fields */
-	seqno = ntohs(header->sequence);
-	timestamp = ntohl(header->timestamp);
+	header->sequence = ntohs(header->sequence);
+	header->timestamp = ntohl(header->timestamp);
 
 	/* Remove padding bytes, if any*/
 	if (header->padding)
 		res -= *(buffer + res - 1);
 	
+	/* Are CSRC IDs present? */
+	if (header->csrc_count) {
+		buffer += header->csrc_count << 2;
+		res -= header->csrc_count << 2;
+	}
+
 	/* Is an RTP Extension present? */
 	if (header->extension) {
 		int ext_len = 4;
@@ -559,42 +571,52 @@
 	if (rtp_debug_test_addr(&sin))
 		ast_verbose("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len %d)\n",
 			    ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr),
-			    ntohs(sin.sin_port), header->payload, seqno,
-			    timestamp, res);
+			    ntohs(sin.sin_port), header->payload, header->sequence,
+			    header->timestamp, res);
 
    	rtpPT = ast_rtp_lookup_pt(rtp, header->payload);
 	if (!rtpPT.isAstFormat) {
+		/* This is special in-band data that's not one of our codecs */
 		f = &ast_null_frame;
 		switch (rtpPT.code) {
 		case AST_RTP_DTMF:
-			/* This is special in-band data that's not one of our codecs */
+			if (res < sizeof(struct rfc2833_event)) {
+				ast_log(LOG_WARNING, "RFC2833 event too short\n");
+				return &ast_null_frame;
+			}
+
 			/* It's special -- rfc2833 process it */
 			if (rtp_debug_test_addr(&sin)) {
-				struct rfc2833_event *event = (struct rfc2833_event *) header;
+				struct rfc2833_event *event = (struct rfc2833_event *) buffer;
 
 				ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n",
 					    ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr),
-					    ntohs(sin.sin_port), header->payload, seqno,
-					    timestamp, res, header->marker,
-					    event->event, event->end, event->duration);
+					    ntohs(sin.sin_port), header->payload, header->sequence,
+					    header->timestamp, res, header->marker,
+					    event->event, event->end, ntohs(event->duration));
 			}
-			if (rtp->lasteventseqn <= seqno || rtp->resp == 0 ||
-			    (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
-				f = process_rfc2833(rtp, buffer, res, seqno);
-				rtp->lasteventseqn = seqno;
+			if (rtp->lasteventseqn <= header->sequence || rtp->resp == 0 ||
+			    (rtp->lasteventseqn >= 65530 && header->sequence <= 6)) {
+				f = process_rfc2833(rtp, header, (struct rfc2833_event *) buffer);
+				rtp->lasteventseqn = header->sequence;
 			}
 			break;
 		case AST_RTP_CISCO_DTMF:
 			/* It's really special -- process it the Cisco way */
-			if (rtp->lasteventseqn <= seqno || rtp->resp == 0 ||
-			    (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
+			if (rtp->lasteventseqn <= header->sequence || rtp->resp == 0 ||
+			    (rtp->lasteventseqn >= 65530 && header->sequence <= 6)) {
 				f = process_cisco_dtmf(rtp, buffer, res);
-				rtp->lasteventseqn = seqno;
+				rtp->lasteventseqn = header->sequence;
 			}
 			break;
 		case AST_RTP_CN:
+			if (res < sizeof(struct rfc3389_event)) {
+				ast_log(LOG_WARNING, "RFC3389 event too short\n");
+				return &ast_null_frame;
+			}
+
 			/* Comfort Noise */
-			f = process_rfc3389(rtp, buffer, res);
+			f = process_rfc3389(rtp, header, (struct rfc3389_event *) buffer, res);
 			break;
 		default:
 			ast_log(LOG_NOTICE, "Unknown RTP payload %d received\n", header->payload);
@@ -610,15 +632,15 @@
 		rtp->f.frametype = AST_FRAME_VIDEO;
 
 	if (!rtp->lastrxts)
-		rtp->lastrxts = timestamp;
+		rtp->lastrxts = header->timestamp;
 
 	if (rtp->dtmfcount) {
-		rtp->dtmfcount -= (timestamp - rtp->lastrxts);
+		rtp->dtmfcount -= (header->timestamp - rtp->lastrxts);
 		if (rtp->dtmfcount < 0)
 			rtp->dtmfcount = 0;
 	}
 
-	rtp->lastrxts = timestamp;
+	rtp->lastrxts = header->timestamp;
 
 	/* Send any pending DTMF */
 	if (rtp->resp && !rtp->dtmfcount) {
@@ -636,13 +658,13 @@
 		rtp->f.samples = ast_codec_get_samples(&rtp->f);
 		if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
 			ast_frame_byteswap_be(&rtp->f);
-		calc_rxstamp(&rtp->f.delivery, rtp, timestamp, header->marker);
+		calc_rxstamp(&rtp->f.delivery, rtp, header->timestamp, header->marker);
 	} else {
 		/* Video -- samples is # of samples vs. 90000 */
 		if (!rtp->lastividtimestamp)
-			rtp->lastividtimestamp = timestamp;
-		rtp->f.samples = timestamp - rtp->lastividtimestamp;
-		rtp->lastividtimestamp = timestamp;
+			rtp->lastividtimestamp = header->timestamp;
+		rtp->f.samples = header->timestamp - rtp->lastividtimestamp;
+		rtp->lastividtimestamp = header->timestamp;
 		rtp->f.delivery.tv_sec = 0;
 		rtp->f.delivery.tv_usec = 0;
 		if (header->marker)
@@ -1212,24 +1234,6 @@
 	return (unsigned int) ms;
 }
 
-static char prep_digit(char digit)
-{
-	if ((digit <= '9') && (digit >= '0'))
-		return digit - '0';
-	else if (digit == '*')
-		return 10;
-	else if (digit == '#')
-		return 11;
-	else if ((digit >= 'A') && (digit <= 'D')) 
-		return digit - 'A' + 12;
-	else if ((digit >= 'a') && (digit <= 'd')) 
-		return digit - 'a' + 12;
-	else {
-		ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-		return -1;
-	}
-}
-
 void static prep_header(struct rtp_header *header, struct ast_rtp *rtp, int payload)
 {
 	header->payload = ast_rtp_lookup_code(rtp, 0, payload);
@@ -1245,13 +1249,15 @@
 	if (!rtp->them.sin_addr.s_addr)
 		return 0;
 
-	if ((digit = prep_digit(digit)) == -1)
+	if ((digit = digit_to_code(digit)) == -1)
 		return -1;
 }
 
 int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
 {
-	struct rfc2833_event event;
+	unsigned char packet[sizeof(struct rtp_header) + sizeof(struct rfc2833_event)];
+	struct rtp_header *header = (struct rtp_header *) &packet[0];
+	struct rfc2833_event *event = (struct rfc2833_event *) &packet[sizeof(struct rtp_header)];
 	int res;
 	int x;
 	char iabuf[INET_ADDRSTRLEN];
@@ -1260,22 +1266,22 @@
 	if (!rtp->them.sin_addr.s_addr)
 		return 0;
 
-	if ((digit = prep_digit(digit)) == -1)
+	if ((digit = digit_to_code(digit)) == -1)
 		return -1;
 
-	memset(&event, 0, sizeof(event));
-
-	prep_header(&event.header, rtp, AST_RTP_DTMF);
-	event.header.marker = 1;
+	memset(packet, 0, sizeof(packet));
+
+	prep_header(header, rtp, AST_RTP_DTMF);
+	header->marker = 1;
 
 	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 	
-	event.event = digit;
-	event.volume = 0xa;
+	event->event = digit;
+	event->volume = 0xa;
 
 	for (x = 0; x < 6; x++) {
 		if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-			res = sendto(rtp->s, &event, sizeof(event), 0,
+			res = sendto(rtp->s, packet, sizeof(packet), 0,
 				     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
 			if (res < 0) 
 				ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
@@ -1284,19 +1290,19 @@
 			if (rtp_debug_test_addr(&rtp->them))
 				ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %lu)\n",
 					    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
-					    ntohs(rtp->them.sin_port), event.header.payload,
-					    rtp->seqno, rtp->lastdigitts, sizeof(event));
+					    ntohs(rtp->them.sin_port), header->payload,
+					    rtp->seqno, rtp->lastdigitts, sizeof(*event));
 		}
 		/* Sequence number of last two end packets does not get incremented */
 		if (x < 3)
 			rtp->seqno++;
 		/* Clear marker bit and set seqno */
-		event.header.marker = 0;
-		event.header.sequence = htons(rtp->seqno);
+		header->marker = 0;
+		header->sequence = htons(rtp->seqno);
 		/* For the last three packets, set the duration and the end bit */
 		if (x == 2) {
-			event.duration = htons(800);
-			event.end = 1;
+			event->duration = htons(800);
+			event->end = 1;
 		}
 	}
 	/* Increment the digit timestamp by 120ms, to ensure that digits
@@ -1315,7 +1321,9 @@
 
 int ast_rtp_sendcng(struct ast_rtp *rtp, int level)
 {
-	struct rfc3389_event event;
+	unsigned char packet[sizeof(struct rtp_header) + sizeof(struct rfc3389_event)];
+	struct rtp_header *header = (struct rtp_header *) &packet[0];
+	struct rfc3389_event *event = (struct rfc3389_event *) &packet[sizeof(struct rtp_header)];
 	int res;
 	char iabuf[INET_ADDRSTRLEN];
 
@@ -1325,16 +1333,16 @@
 
 	level = 127 - (level & 0x7f);
 
-	memset(&event, 0, sizeof(event));
-
-	prep_header(&event.header, rtp, AST_RTP_CN);
+	memset(packet, 0, sizeof(packet));
+
+	prep_header(header, rtp, AST_RTP_CN);
 
 	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 
-	event.level = level;
+	event->level = level;
 
 	if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-		res = sendto(rtp->s, &event, sizeof(event), 0,
+		res = sendto(rtp->s, packet, sizeof(packet), 0,
 			     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
 		if (res <0) 
 			ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n",
@@ -1343,8 +1351,8 @@
 		if (rtp_debug_test_addr(&rtp->them))
 			ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %lu)\n",
 				    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
-				    ntohs(rtp->them.sin_port), event.header.payload,
-				    rtp->seqno, rtp->lastts, sizeof(event));
+				    ntohs(rtp->them.sin_port), header->payload,
+				    rtp->seqno, rtp->lastts, sizeof(*event));
 	}
 
 	rtp->seqno++;
@@ -1402,13 +1410,13 @@
 	if (rtp->lastts > rtp->lastdigitts)
 		rtp->lastdigitts = rtp->lastts;
 
-	header = (struct rtp_header *)(f->data - sizeof(*header));
+	header = (struct rtp_header *) (f->data - sizeof(*header));
 	prep_header(header, rtp, codec);
 	header->marker = mark;
 
 	if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
 		res = sendto(rtp->s, header, f->datalen + sizeof(*header), 0,
-			     (struct sockaddr *)&rtp->them, sizeof(rtp->them));
+			     (struct sockaddr *) &rtp->them, sizeof(rtp->them));
 		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",
@@ -1884,23 +1892,26 @@
 
 static int rtp_do_debug(int fd, int argc, char *argv[])
 {
-	if(argc != 2) {
-		if(argc != 4)
+	if (argc != 2) {
+		if (argc != 4)
 			return RESULT_SHOWUSAGE;
 		return rtp_do_debug_ip(fd, argc, argv);
 	}
+
 	rtpdebug = 1;
 	memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
 	ast_cli(fd, "RTP Debugging Enabled\n");
+
 	return RESULT_SUCCESS;
 }
    
 static int rtp_no_debug(int fd, int argc, char *argv[])
 {
-	if(argc !=3)
+	if (argc != 3)
 		return RESULT_SHOWUSAGE;
 	rtpdebug = 0;
 	ast_cli(fd,"RTP Debugging Disabled\n");
+
 	return RESULT_SUCCESS;
 }
 
@@ -1929,8 +1940,8 @@
 	rtpstart = 5000;
 	rtpend = 31000;
 	dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-	cfg = ast_config_load("rtp.conf");
-	if (cfg) {
+
+	if ((cfg = ast_config_load("rtp.conf"))) {
 		if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
 			rtpstart = atoi(s);
 			if (rtpstart < 1024)



More information about the svn-commits mailing list