[asterisk-commits] branch kpfleming/vldtmf r9030 -
/team/kpfleming/vldtmf/rtp.c
asterisk-commits at lists.digium.com
asterisk-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 asterisk-commits
mailing list