summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
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 /channels/chan_sip.c
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
Diffstat (limited to 'channels/chan_sip.c')
-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) {