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



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@354542 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Jordan
2012-02-09 16:30:56 +00:00
parent 9c33d62bcb
commit ead2b47907

View File

@@ -18714,7 +18714,8 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
/* Need to check the media/type */ /* Need to check the media/type */
if (!strcasecmp(c, "application/dtmf-relay") || 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; unsigned int duration = 0;
if (!p->owner) { /* not a PBX call */ if (!p->owner) { /* not a PBX call */
@@ -18723,48 +18724,59 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
return; return;
} }
/* Try getting the "signal=" part */ /* If dtmf-relay or vnd.nortelnetworks.digits, parse the signal and duration; otherwise use the body as the signal */
if (ast_strlen_zero(c = get_body(req, "Signal", '=')) && ast_strlen_zero(c = get_body(req, "d", '='))) { if (strcasecmp(c, "application/dtmf")) {
ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); const char *msg_body;
transmit_response(p, "200 OK", req); /* Should return error */
return; 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 { } else {
ast_copy_string(buf, c, sizeof(buf)); /* Type is application/dtmf, simply use what's in the message body */
get_msg_text(buf, sizeof(buf), req);
} }
if (!ast_strlen_zero((c = get_body(req, "Duration", '=')))) /* An empty message body requires us to send a 200 OK */
duration = atoi(c);
if (!duration)
duration = 100; /* 100 ms */
if (ast_strlen_zero(buf)) { if (ast_strlen_zero(buf)) {
transmit_response(p, "200 OK", req); transmit_response(p, "200 OK", req);
return; return;
} }
if ('0' <= buf[0] && buf[0] <= '9') { if (!duration) {
event = buf[0] - '0'; duration = 100; /* 100 ms */
} else if (buf[0] == '*') { }
if (buf[0] == '*') {
event = 10; event = 10;
} else if (buf[0] == '#') { } else if (buf[0] == '#') {
event = 11; event = 11;
} else if (buf[0] == '!') {
event = 16;
} else if ('A' <= buf[0] && buf[0] <= 'D') { } else if ('A' <= buf[0] && buf[0] <= 'D') {
event = 12 + buf[0] - 'A'; event = 12 + buf[0] - 'A';
} else if ('a' <= buf[0] && buf[0] <= 'd') { } else if ('a' <= buf[0] && buf[0] <= 'd') {
event = 12 + buf[0] - 'a'; event = 12 + buf[0] - 'a';
} else if (buf[0] == '!') { } else if ((sscanf(buf, "%30u", &event) != 1) || event > 16) {
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);
} else { transmit_response(p, "200 OK", req);
/* Unknown digit */ return;
event = 0;
} }
if (event == 16) { if (event == 16) {
/* send a FLASH event */ /* 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); ast_queue_frame(p->owner, &f);
if (sipdebug) if (sipdebug) {
ast_verbose("* DTMF-relay event received: FLASH\n"); ast_verbose("* DTMF-relay event received: FLASH\n");
}
} else { } else {
/* send a DTMF event */ /* send a DTMF event */
struct ast_frame f = { AST_FRAME_DTMF, }; struct ast_frame f = { AST_FRAME_DTMF, };
@@ -18779,58 +18791,12 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
} }
f.len = duration; f.len = duration;
ast_queue_frame(p->owner, &f); ast_queue_frame(p->owner, &f);
if (sipdebug) if (sipdebug) {
ast_verbose("* DTMF-relay event received: %c\n", (int) f.subclass.integer); 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)) {
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); transmit_response(p, "200 OK", req);
return; return;
} else if (!strcasecmp(c, "application/media_control+xml")) { } else if (!strcasecmp(c, "application/media_control+xml")) {
/* Eh, we'll just assume it's a fast picture update for now */ /* Eh, we'll just assume it's a fast picture update for now */
if (p->owner) if (p->owner)