[svn-commits] oej: trunk r89278 - in /trunk: channels/chan_sip.c configs/sip.conf.sample

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Nov 15 04:21:42 CST 2007


Author: oej
Date: Thu Nov 15 04:21:41 2007
New Revision: 89278

URL: http://svn.digium.com/view/asterisk?view=rev&rev=89278
Log:
Add support for application/dtmf SIP INFO dtmf handling. Yep, another
way of handling DTMF in SIP. Totally undocumented, but implemented
in enough devices so we have to support it. 

Code by sergee, small changes by oej.

Closes issue #11049

Modified:
    trunk/channels/chan_sip.c
    trunk/configs/sip.conf.sample

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=89278&r1=89277&r2=89278
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Nov 15 04:21:41 2007
@@ -796,6 +796,7 @@
 #define SIP_DTMF_INBAND		(1 << 16)	/*!< DP: DTMF Support: Inband audio, only for ULAW/ALAW - "inband" */
 #define SIP_DTMF_INFO		(2 << 16)	/*!< DP: DTMF Support: SIP Info messages - "info" */
 #define SIP_DTMF_AUTO		(3 << 16)	/*!< DP: DTMF Support: AUTO switch between rfc2833 and in-band DTMF */
+#define SIP_DTMF_SHORTINFO      (4 << 16)       /*!< DP: DTMF Support: SIP Info messages - "info" - short variant */
 
 /* NAT settings - see nat2str() */
 #define SIP_NAT			(3 << 18)	/*!< DP: four settings, uses two bits */
@@ -1742,7 +1743,7 @@
 static int add_header_contentLength(struct sip_request *req, int len);
 static int add_line(struct sip_request *req, const char *line);
 static int add_text(struct sip_request *req, const char *text);
-static int add_digit(struct sip_request *req, char digit, unsigned int duration);
+static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode);
 static int add_vidupdate(struct sip_request *req);
 static void add_route(struct sip_request *req, struct sip_route *route);
 static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -4385,6 +4386,7 @@
 	sip_pvt_lock(p);
 	switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
 	case SIP_DTMF_INFO:
+	case SIP_DTMF_SHORTINFO:
 		transmit_info_with_digit(p, digit, duration);
 		break;
 	case SIP_DTMF_RFC2833:
@@ -4550,7 +4552,7 @@
 	}
 	sip_pvt_lock(i);
 
-	tmp->tech = ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INFO ?  &sip_tech_info : &sip_tech;
+	tmp->tech = ( ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INFO || ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO) ?  &sip_tech_info : &sip_tech;
 
 	/* Select our native format based on codec preference until we receive
 	   something from another device to the contrary. */
@@ -6763,16 +6765,35 @@
 	return 0;
 }
 
-/*! \brief Add DTMF INFO tone to sip message */
-/* Always adds default duration 250 ms, regardless of what came in over the line */
-static int add_digit(struct sip_request *req, char digit, unsigned int duration)
+/*! \brief Add DTMF INFO tone to sip message 
+	Mode = 	0 for application/dtmf-relay (Cisco)
+		1 for application/dtmf
+*/
+static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode)
 {
 	char tmp[256];
-
-	snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
-	add_header(req, "Content-Type", "application/dtmf-relay");
-	add_header_contentLength(req, strlen(tmp));
-	add_line(req, tmp);
+	int event;
+	if (mode) {
+		/* Application/dtmf short version used by some implementations */
+		if (digit == '*')
+			event = 10;
+		else if (digit == '#')
+			event = 11;
+		else if ((digit >= 'A') && (digit <= 'D'))
+			event = 12 + digit - 'A';
+		else
+			event = atoi(&digit);
+		snprintf(tmp, sizeof(tmp), "%d\r\n", event);
+		add_header(req, "Content-Type", "application/dtmf");
+		add_header_contentLength(req, strlen(tmp));
+		add_line(req, tmp);
+	} else {
+		/* Application/dtmf-relay as documented by Cisco */
+		snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
+		add_header(req, "Content-Type", "application/dtmf-relay");
+		add_header_contentLength(req, strlen(tmp));
+		add_line(req, tmp);
+	}
 	return 0;
 }
 
@@ -8479,7 +8500,7 @@
 	struct sip_request req;
 
 	reqprep(&req, p, SIP_INFO, 0, 1);
-	add_digit(&req, digit, duration);
+	add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO));
 	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
 }
 
@@ -10944,6 +10965,7 @@
 static struct _map_x_s dtmfstr[] = {
 	{ SIP_DTMF_RFC2833,     "rfc2833" },
 	{ SIP_DTMF_INFO,        "info" },
+	{ SIP_DTMF_SHORTINFO,   "shortinfo" },
 	{ SIP_DTMF_INBAND,      "inband" },
 	{ SIP_DTMF_AUTO,        "auto" },
 	{ -1,                   NULL }, /* terminator */
@@ -12333,6 +12355,49 @@
 		}
 		transmit_response(p, "200 OK", req);
 		return;
+	} else if (!strcasecmp(c, "application/dtmf")) {
+		unsigned int duration = 0;
+
+		get_msg_text(buf, sizeof(buf), req);
+		duration = 100; /* 100 ms */
+
+		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;
+		}
+
+		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 = '0' + event;
+			} else if (event < 11) {
+				f.subclass = '*';
+			} else if (event < 12) {
+				f.subclass = '#';
+			} else if (event < 16) {
+				f.subclass = 'A' + (event - 12);
+			}
+			f.len = duration;
+			ast_queue_frame(p->owner, &f);
+			if (sipdebug)
+				ast_verbose("* DTMF-relay event received: %c\n", f.subclass);
+		}
+		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)
@@ -17086,6 +17151,8 @@
 			ast_set_flag(&flags[0], SIP_DTMF_RFC2833);
 		else if (!strcasecmp(v->value, "info"))
 			ast_set_flag(&flags[0], SIP_DTMF_INFO);
+		else if (!strcasecmp(v->value, "shortinfo"))
+			ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO);
 		else if (!strcasecmp(v->value, "auto"))
 			ast_set_flag(&flags[0], SIP_DTMF_AUTO);
 		else {
@@ -18774,6 +18841,10 @@
 		ast_clear_flag(&p->flags[0], SIP_DTMF);
 		ast_set_flag(&p->flags[0], SIP_DTMF_INFO);
 		p->jointnoncodeccapability &= ~AST_RTP_DTMF;
+	} else if (!strcasecmp(mode,"shortinfo")) {
+		ast_clear_flag(&p->flags[0], SIP_DTMF);
+		ast_set_flag(&p->flags[0], SIP_DTMF_SHORTINFO);
+		p->jointnoncodeccapability &= ~AST_RTP_DTMF;
 	} else if (!strcasecmp(mode,"rfc2833")) {
 		ast_clear_flag(&p->flags[0], SIP_DTMF);
 		ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);

Modified: trunk/configs/sip.conf.sample
URL: http://svn.digium.com/view/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=89278&r1=89277&r2=89278
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Thu Nov 15 04:21:41 2007
@@ -126,7 +126,8 @@
 				; a valid phone number
 ;dtmfmode = rfc2833		; Set default dtmfmode for sending DTMF. Default: rfc2833
 				; Other options: 
-				; info : SIP INFO messages
+				; info : SIP INFO messages (application/dtmf-relay)
+				; shortinfo : SIP INFO messages (application/dtmf)
 				; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
 				; auto : Use rfc2833 if offered, inband otherwise
 




More information about the svn-commits mailing list