summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2012-02-09 16:37:01 +0000
committerMatthew Jordan <mjordan@digium.com>2012-02-09 16:37:01 +0000
commitba08e9f4d681fa30caba6addaff51cbb3b59fc84 (patch)
treeb15a5d7848e2e11d84e32b2bc6af79f63472b34f
parent16fbc7e9028a3cbc3e2756178920a175637e589d (diff)
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@354544 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c102
1 files changed, 31 insertions, 71 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index d6ffa8a69..df14b2273 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -19434,7 +19434,8 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
/* 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,92 +19444,55 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
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;
- } else {
- ast_copy_string(buf, c, sizeof(buf));
- }
+ /* 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((c = get_body(req, "Duration", '=')))) {
- duration = atoi(c);
- }
- if (!duration) {
- duration = 100; /* 100 ms */
- }
+ 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 {
+ /* 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;
- }
- 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);
- }
- 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/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)) {
+ } 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;
}
- event = atoi(buf);
+
if (event == 16) {
/* send a FLASH event */
- struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH }, };
+ 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");
@@ -19544,9 +19508,6 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
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);
@@ -19556,7 +19517,6 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
}
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) {