From 2f67f665779c1cbc714c9757143769e79845fd5c Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Tue, 6 Sep 2005 21:04:40 +0000
Subject: [PATCH] Allow "auto" dtmf mode to select between RFC2833 and inband
 based on peer's offer or answer.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6518 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channels/chan_sip.c     | 23 +++++++++++++++++++----
 configs/sip.conf.sample |  1 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 9ea866c342..eb00e3c01f 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -489,6 +489,7 @@ struct sip_auth {
 #define SIP_DTMF_RFC2833	(0 << 16)	/* RTP DTMF */
 #define SIP_DTMF_INBAND		(1 << 16)	/* Inband audio, only for ULAW/ALAW */
 #define SIP_DTMF_INFO		(2 << 16)	/* SIP Info messages */
+#define SIP_DTMF_AUTO		(3 << 16)	/* AUTO switch between rfc2833 and in-band DTMF */
 /* NAT settings */
 #define SIP_NAT			(3 << 18)	/* four settings, uses two bits */
 #define SIP_NAT_NEVER		(0 << 18)	/* No nat support */
@@ -1814,7 +1815,7 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
 	/* Set timer T1 to RTT for this peer (if known by qualify=) */
 	if (peer->maxms && peer->lastms)
 		r->timer_t1 = peer->lastms;
-	if (ast_test_flag(r, SIP_DTMF) == SIP_DTMF_RFC2833)
+	if ((ast_test_flag(r, SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(r, SIP_DTMF) == SIP_DTMF_AUTO))
 		r->noncodeccapability |= AST_RTP_DTMF;
 	else
 		r->noncodeccapability &= ~AST_RTP_DTMF;
@@ -2976,7 +2977,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
 	/* Assign default music on hold class */
 	strcpy(p->musicclass, global_musicclass);
 	p->capability = global_capability;
-	if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
+	if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_AUTO))
 		p->noncodeccapability |= AST_RTP_DTMF;
 	strcpy(p->context, default_context);
 
@@ -3418,6 +3419,16 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
 	p->peercapability = (peercapability | vpeercapability);
 	p->noncodeccapability = noncodeccapability & peernoncodeccapability;
 	
+	if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_AUTO) {
+		ast_clear_flag(p, SIP_DTMF);
+		if (p->noncodeccapability & AST_RTP_DTMF) {
+			/* XXX Would it be reasonable to drop the DSP at this point? XXX */
+			ast_set_flag(p, SIP_DTMF_RFC2833);
+		} else {
+			ast_set_flag(p, SIP_DTMF_INBAND);
+		}
+	}
+	
 	if (debug) {
 		/* shame on whoever coded this.... */
 		const unsigned slen=512;
@@ -6589,7 +6600,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
 			p->jointcapability = user->capability;
 			if (p->peercapability)
 				p->jointcapability &= p->peercapability;
-			if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
+			if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_AUTO))
 				p->noncodeccapability |= AST_RTP_DTMF;
 			else
 				p->noncodeccapability &= ~AST_RTP_DTMF;
@@ -6691,7 +6702,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
 				p->jointcapability = peer->capability;
 				if (p->peercapability)
 					p->jointcapability &= p->peercapability;
-				if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
+				if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_AUTO))
 					p->noncodeccapability |= AST_RTP_DTMF;
 				else
 					p->noncodeccapability &= ~AST_RTP_DTMF;
@@ -7134,6 +7145,8 @@ static const char *dtmfmode2str(int mode)
 		return "info";
 	case SIP_DTMF_INBAND:
 		return "inband";
+	case SIP_DTMF_AUTO:
+		return "auto";
 	}
 	return "<error>";
 }
@@ -10834,6 +10847,8 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
 			ast_set_flag(flags, SIP_DTMF_RFC2833);
 		else if (!strcasecmp(v->value, "info"))
 			ast_set_flag(flags, SIP_DTMF_INFO);
+		else if (!strcasecmp(v->value, "auto"))
+			ast_set_flag(flags, SIP_DTMF_AUTO);
 		else {
 			ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno);
 			ast_set_flag(flags, SIP_DTMF_RFC2833);
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 23cc922f2e..3fb215017c 100755
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -83,6 +83,7 @@ srvlookup=yes			; Enable DNS SRV lookups on outbound calls
 				; Other options: 
 				; info : SIP INFO messages
 				; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
+				; auto : Use rfc2833 if offered, inband otherwise
 
 ;compactheaders = yes		; send compact sip headers.
 ;sipdebug = yes			; Turn on SIP debugging by default, from
-- 
GitLab