[asterisk-commits] kharwell: trunk r397484 - in /trunk/res: res_pjsip.c res_pjsip_dtmf_info.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Aug 22 17:09:22 CDT 2013


Author: kharwell
Date: Thu Aug 22 17:09:16 2013
New Revision: 397484

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397484
Log:
res_sip_dtmf_info: Support sending of 'raw' DTMF

Added the ability to handle 'raw' DTMF within the body of an INFO message.
Also made it so values 10-16 are mapped to valid DTMF values.

(closes issue ASTERISK-22144)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2776/

Modified:
    trunk/res/res_pjsip.c
    trunk/res/res_pjsip_dtmf_info.c

Modified: trunk/res/res_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip.c?view=diff&rev=397484&r1=397483&r2=397484
==============================================================================
--- trunk/res/res_pjsip.c (original)
+++ trunk/res/res_pjsip.c Thu Aug 22 17:09:16 2013
@@ -685,7 +685,7 @@
 					Signifies that a domain is an alias. If the domain on a session is
 					not found to match an AoR then this object is used to see if we have
 					an alias for the AoR to which the endpoint is binding. This objects
-					name as defined in configuration should be the domain alias and a 
+					name as defined in configuration should be the domain alias and a
 					config option is provided to specify the domain to be aliased.
 				</para></description>
 				<configOption name="type">
@@ -851,7 +851,7 @@
 					This must be used in conjuction with the <literal>PJSIP_DIAL_CONTACTS</literal>.
 					</para><para>
 					Registrations: For Asterisk to match an inbound registration to an endpoint,
-					the AoR object name must match the user portion of the SIP URI in the "To:" 
+					the AoR object name must match the user portion of the SIP URI in the "To:"
 					header of the inbound SIP registration. That will usually be equivalent
 					to the "user name" set in your hard or soft phones configuration.
 				</para></description>
@@ -935,7 +935,7 @@
 				<description><para>
 					The settings in this section are global. In addition to being global, the values will
 					not be re-evaluated when a reload is performed. This is because the values must be set
-					before the SIP stack is initialized. The only way to reset these values is to either 
+					before the SIP stack is initialized. The only way to reset these values is to either
 					restart Asterisk, or unload res_pjsip.so and then load it again.
 				</para></description>
 				<configOption name="timert1" default="500">
@@ -1724,7 +1724,7 @@
 
 	pjsip_media_type_init2(&compare, type, subtype);
 
-	return pjsip_media_type_cmp(content_type, &compare, 0) ? -1 : 0;
+	return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
 }
 
 pj_caching_pool caching_pool;

Modified: trunk/res/res_pjsip_dtmf_info.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip_dtmf_info.c?view=diff&rev=397484&r1=397483&r2=397484
==============================================================================
--- trunk/res/res_pjsip_dtmf_info.c (original)
+++ trunk/res/res_pjsip_dtmf_info.c Thu Aug 22 17:09:16 2013
@@ -32,77 +32,114 @@
 #include "asterisk/res_pjsip_session.h"
 #include "asterisk/module.h"
 
+static int is_media_type(pjsip_rx_data *rdata, char *subtype)
+{
+	return !pj_strcmp2(&rdata->msg_info.ctype->media.type, "application") &&
+		!pj_strcmp2(&rdata->msg_info.ctype->media.subtype, subtype);
+}
+
+static void send_response(struct ast_sip_session *session,
+			  struct pjsip_rx_data *rdata, int code)
+{
+	pjsip_tx_data *tdata;
+	pjsip_dialog *dlg = session->inv_session->dlg;
+
+	if (pjsip_dlg_create_response(dlg, rdata, code,
+				      NULL, &tdata) == PJ_SUCCESS) {
+		struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+		pjsip_dlg_send_response(dlg, tsx, tdata);
+	}
+}
+
+static char get_event(const char *c)
+{
+	unsigned int event;
+
+	if (*c == '!' || *c == '*' || *c == '#' ||
+	    ('A' <= *c && *c <= 'D') ||
+	    ('a' <= *c && *c <= 'd')) {
+		return *c;
+	}
+
+	if ((sscanf(c, "%30u", &event) != 1) || event > 16) {
+		return '\0';
+	}
+
+	if (event < 10) {
+		return *c;
+	}
+
+	switch (event) {
+	case 10: return '*';
+	case 11: return '#';
+	case 16: return '!';
+	}
+
+	return 'A' + (event - 12);
+}
+
 static int dtmf_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 {
-	int res = 0;
 	pjsip_msg_body *body = rdata->msg_info.msg->body;
-
-	pjsip_tx_data *tdata;
-
 	char buf[body ? body->len : 0];
 	char *cur = buf;
 	char *line;
 
 	char event = '\0';
-	unsigned int duration = 0;
+	unsigned int duration = 100;
 
-	if (!body || !ast_sip_is_content_type(&body->content_type, "application", "dtmf-relay")) {
+	char is_dtmf = is_media_type(rdata, "dtmf");
+
+	if (!is_dtmf && !is_media_type(rdata, "dtmf-relay")) {
+		return 0;
+	}
+
+	if (!body || !body->len) {
+		/* need to return 200 OK on empty body */
+		send_response(session, rdata, 200);
 		return 0;
 	}
 
 	body->print_body(body, buf, body->len);
 
-	while ((line = strsep(&cur, "\r\n"))) {
-		char *c;
+	if (is_dtmf) {
+		/* directly use what is in the message body */
+		event = get_event(cur);
+	} else { /* content type = application/dtmf-relay */
+		while ((line = strsep(&cur, "\r\n"))) {
+			char *c;
 
-		if (!(c = strchr(line, '='))) {
-			continue;
+			if (!(c = strchr(line, '='))) {
+				continue;
+			}
+
+			*c++ = '\0';
+			c = ast_skip_blanks(c);
+
+			if (!strcasecmp(line, "signal")) {
+				if (!(event = get_event(c))) {
+					break;
+				}
+			} else if (!strcasecmp(line, "duration")) {
+				sscanf(c, "%30u", &duration);
+			}
 		}
-		*c++ = '\0';
-
-		c = ast_skip_blanks(c);
-
-		if (!strcasecmp(line, "signal")) {
-			if (c[0] == '!' || c[0] == '*' || c[0] == '#' ||
-			    ('0' <= c[0] && c[0] <= '9') ||
-			    ('A' <= c[0] && c[0] <= 'D') ||
-			    ('a' <= c[0] && c[0] <= 'd')) {
-				event = c[0];
-			} else {
-				ast_log(LOG_ERROR, "Invalid DTMF event signal in INFO message.\n");
-				res = -1;
-				break;
-			}
-		} else if (!strcasecmp(line, "duration")) {
-			sscanf(c, "%30u", &duration);
-		}
-	}
-
-	if (!duration) {
-		duration = 100;
 	}
 
 	if (event == '!') {
 		struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH, } };
-
 		ast_queue_frame(session->channel, &f);
 	} else if (event != '\0') {
 		struct ast_frame f = { AST_FRAME_DTMF, };
 		f.len = duration;
 		f.subclass.integer = event;
-
 		ast_queue_frame(session->channel, &f);
 	} else {
-		res = -1;
+		ast_log(LOG_ERROR, "Invalid DTMF event signal in INFO message.\n");
 	}
 
-	if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, !res ? 200 : 500, NULL, &tdata) == PJ_SUCCESS) {
-		struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
-
-		pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
-	}
-
-	return res;
+	send_response(session, rdata, event ? 200 : 500);
+	return event ? 0 : -1;
 }
 
 static struct ast_sip_session_supplement dtmf_info_supplement = {




More information about the asterisk-commits mailing list