[svn-commits] mjordan: trunk r354544 - in /trunk: ./ channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 9 10:37:09 CST 2012


Author: mjordan
Date: Thu Feb  9 10:37:01 2012
New Revision: 354544

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=354544
Log:
Fix SIP INFO DTMF handling for non-numeric codes

In ASTERISK-18924, SIP INFO DTMF handlingw as changed to account for both
lowercase alphatbetic DTMF events, as well as uppercase alphabetic DTMF
events.  When this occurred, the comparison of the character buffer containing
the event code was changed such that the buffer was first compared again '0'
and '9' to determine if it was numeric.  Unfortunately, since the first
character in the buffer will typically be '1' in the case of non-numeric
event codes (10-16), this caused those codes to be converted to a DTMF event
of '1'.  This patch fixes that, and cleans up handling of both
application/dtmf-relay and application/dtmf content types.

Review: https://reviewboard.asterisk.org/r/1722/

(closes issue ASTERISK-19290)
Reported by: Ira Emus
Tested by: mjordan
........

Merged revisions 354542 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 354543 from http://svn.asterisk.org/svn/asterisk/branches/10

Modified:
    trunk/   (props changed)
    trunk/channels/chan_sip.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-10-merged' - no diff available.

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=354544&r1=354543&r2=354544
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Feb  9 10:37:01 2012
@@ -19434,7 +19434,8 @@
 
 	/* Need to check the media/type */
 	if (!strcasecmp(c, "application/dtmf-relay") ||
-	    !strcasecmp(c, "application/vnd.nortelnetworks.digits")) {
+	    !strcasecmp(c, "application/vnd.nortelnetworks.digits") ||
+	    !strcasecmp(c, "application/dtmf")) {
 		unsigned int duration = 0;
 
 		if (!p->owner) {	/* not a PBX call */
@@ -19443,44 +19444,52 @@
 			return;
 		}
 
-		/* Try getting the "signal=" part */
-		if (ast_strlen_zero(c = get_body(req, "Signal", '=')) && ast_strlen_zero(c = get_body(req, "d", '='))) {
-			ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid);
-			transmit_response(p, "200 OK", req); /* Should return error */
-			return;
+		/* If dtmf-relay or vnd.nortelnetworks.digits, parse the signal and duration; otherwise use the body as the signal */
+		if (strcasecmp(c, "application/dtmf")) {
+			const char *msg_body;
+
+			if (ast_strlen_zero(msg_body = get_body(req, "Signal", '=')) && ast_strlen_zero(msg_body = get_body(req, "d", '='))) {
+				ast_log(LOG_WARNING, "Unable to retrieve DTMF signal for INFO message on call %s\n", p->callid);
+				transmit_response(p, "200 OK", req);
+				return;
+			} else {
+				ast_copy_string(buf, msg_body, sizeof(buf));
+			}
+
+			if (!ast_strlen_zero((msg_body = get_body(req, "Duration", '=')))) {
+				sscanf(msg_body, "%30u", &duration);
+			}
 		} else {
-			ast_copy_string(buf, c, sizeof(buf));
-		}
-
-		if (!ast_strlen_zero((c = get_body(req, "Duration", '=')))) {
-			duration = atoi(c);
-		}
-		if (!duration) {
-			duration = 100; /* 100 ms */
-		}
-
-
+			/* Type is application/dtmf, simply use what's in the message body */
+			get_msg_text(buf, sizeof(buf), req);
+		}
+
+		/* An empty message body requires us to send a 200 OK */
 		if (ast_strlen_zero(buf)) {
 			transmit_response(p, "200 OK", req);
 			return;
 		}
 
-		if ('0' <= buf[0] && buf[0] <= '9') {
-			event = buf[0] - '0';
-		} else if (buf[0] == '*') {
+		if (!duration) {
+			duration = 100; /* 100 ms */
+		}
+
+		if (buf[0] == '*') {
 			event = 10;
 		} else if (buf[0] == '#') {
 			event = 11;
+		} else if (buf[0] == '!') {
+			event = 16;
 		} else if ('A' <= buf[0] && buf[0] <= 'D') {
 			event = 12 + buf[0] - 'A';
 		} else if ('a' <= buf[0] && buf[0] <= 'd') {
 			event = 12 + buf[0] - 'a';
-		} else if (buf[0] == '!') {
-			event = 16;
-		} else {
-			/* Unknown digit */
-			event = 0;
-		}
+		} else if ((sscanf(buf, "%30u", &event) != 1) || event > 16) {
+			ast_log(AST_LOG_WARNING, "Unable to convert DTMF event signal code to a valid value for INFO message on call %s\n", p->callid);
+			transmit_response(p, "200 OK", req);
+			return;
+		}
+
 		if (event == 16) {
 			/* send a FLASH event */
 			struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH, } };
@@ -19508,55 +19517,6 @@
 		}
 		transmit_response(p, "200 OK", req);
 		return;
-	} else if (!strcasecmp(c, "application/dtmf")) {
-		/*! \todo Note: Doesn't read the duration of the DTMF. Should be fixed. */
-		unsigned int duration = 0;
-
-		if (!p->owner) {	/* not a PBX call */
-			transmit_response(p, "481 Call leg/transaction does not exist", req);
-			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-			return;
-		}
-
-		get_msg_text(buf, sizeof(buf), req);
-		duration = 100; /* 100 ms */
-
-		if (ast_strlen_zero(buf)) {
-			transmit_response(p, "200 OK", req);
-			return;
-		}
-		event = atoi(buf);
-		if (event == 16) {
-			/* send a FLASH event */
-			struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH }, };
-			ast_queue_frame(p->owner, &f);
-			if (sipdebug) {
-				ast_verbose("* DTMF-relay event received: FLASH\n");
-			}
-		} else {
-			/* send a DTMF event */
-			struct ast_frame f = { AST_FRAME_DTMF, };
-			if (event < 10) {
-				f.subclass.integer = '0' + event;
-			} else if (event == 10) {
-				f.subclass.integer = '*';
-			} else if (event == 11) {
-				f.subclass.integer = '#';
-			} else if (event < 16) {
-				f.subclass.integer = 'A' + (event - 12);
-			} else {
-				/* Unknown digit. */
-				f.subclass.integer = '0';
-			}
-			f.len = duration;
-			ast_queue_frame(p->owner, &f);
-			if (sipdebug) {
-				ast_verbose("* DTMF-relay event received: %c\n", (int) f.subclass.integer);
-			}
-		}
-		transmit_response(p, "200 OK", req);
-		return;
-
 	} else if (!strcasecmp(c, "application/media_control+xml")) {
 		/* Eh, we'll just assume it's a fast picture update for now */
 		if (p->owner) {




More information about the svn-commits mailing list