<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/5842">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Joshua Colp: Looks good to me, but someone else must approve
Matthew Fredrickson: Looks good to me, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: Add DTMF INFO Failback mode<br><br>The existing auto dtmf mode reverts to inband if 4733 fails to be<br>negotiated. This patch adds a new mode auto_info which will<br>switch to INFO instead of inband if 4733 is not available.<br><br>ASTERISK-27066 #close<br><br>Change-Id: Id185b11e84afd9191a2f269e8443019047765e91<br>---<br>M CHANGES<br>M channels/chan_pjsip.c<br>A contrib/ast-db-manage/config/versions/164abbd708c_add_auto_info_to_endpoint_dtmf_mode.py<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip.c<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_sdp_rtp.c<br>7 files changed, 121 insertions(+), 18 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index 1b87dbf..c2a9c8f 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -25,6 +25,10 @@<br> whether to notify dialog-info state 'early' or 'confirmed' on Ringing<br> when already INUSE.<br> <br>+ * The endpoint option 'dtmf_mode' has a new option 'auto_dtmf' added. This<br>+ mode works similar to 'auto' except uses DTMF INFO as fallback instead of<br>+ INBAND.<br>+<br> res_agi<br> ------------------<br> * The EAGI() application will now look for a dialplan variable named<br>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c<br>index 486a237..d1691b8 100644<br>--- a/channels/chan_pjsip.c<br>+++ b/channels/chan_pjsip.c<br>@@ -1708,14 +1708,20 @@<br> }<br> <br> ast_rtp_instance_dtmf_begin(media->rtp, digit);<br>- break;<br>+ break;<br> case AST_SIP_DTMF_AUTO:<br>- if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {<br>- return -1;<br>- }<br>+ if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {<br>+ return -1;<br>+ }<br> <br>- ast_rtp_instance_dtmf_begin(media->rtp, digit);<br>- break;<br>+ ast_rtp_instance_dtmf_begin(media->rtp, digit);<br>+ break;<br>+ case AST_SIP_DTMF_AUTO_INFO:<br>+ if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_NONE)) {<br>+ return -1;<br>+ }<br>+ ast_rtp_instance_dtmf_begin(media->rtp, digit);<br>+ break;<br> case AST_SIP_DTMF_NONE:<br> break;<br> case AST_SIP_DTMF_INBAND:<br>@@ -1816,6 +1822,20 @@<br> int res = 0;<br> <br> switch (channel->session->endpoint->dtmf) {<br>+ case AST_SIP_DTMF_AUTO_INFO:<br>+ {<br>+ if (!media || !media->rtp) {<br>+ return -1;<br>+ }<br>+ if (ast_rtp_instance_dtmf_mode_get(media->rtp) != AST_RTP_DTMF_MODE_NONE) {<br>+ ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast));<br>+ ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);<br>+ break;<br>+ }<br>+ /* If RFC_4733 was not negotiated, fail through to the DTMF_INFO processing */<br>+ ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 NOT negotiated using INFO instead.\n", ast_channel_name(ast));<br>+ }<br>+<br> case AST_SIP_DTMF_INFO:<br> {<br> struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);<br>@@ -1848,14 +1868,15 @@<br> }<br> <br> ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);<br>- break;<br>- case AST_SIP_DTMF_AUTO:<br>- if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {<br>- return -1;<br>- }<br>+ break;<br>+ case AST_SIP_DTMF_AUTO:<br>+ if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {<br>+ return -1;<br>+ }<br> <br>- ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);<br>- break;<br>+ ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);<br>+ break;<br>+<br> <br> case AST_SIP_DTMF_NONE:<br> break;<br>diff --git a/contrib/ast-db-manage/config/versions/164abbd708c_add_auto_info_to_endpoint_dtmf_mode.py b/contrib/ast-db-manage/config/versions/164abbd708c_add_auto_info_to_endpoint_dtmf_mode.py<br>new file mode 100644<br>index 0000000..dbc8ce9<br>--- /dev/null<br>+++ b/contrib/ast-db-manage/config/versions/164abbd708c_add_auto_info_to_endpoint_dtmf_mode.py<br>@@ -0,0 +1,57 @@<br>+"""Add auto_info to endpoint dtmf_mode<br>+<br>+Revision ID: 164abbd708c<br>+Revises: 86bb1efa278d<br>+Create Date: 2017-06-19 13:55:15.354706<br>+<br>+"""<br>+<br>+# revision identifiers, used by Alembic.<br>+revision = '164abbd708c'<br>+down_revision = '86bb1efa278d'<br>+<br>+from alembic import op<br>+import sqlalchemy as sa<br>+<br>+OLD_ENUM = ['rfc4733', 'inband', 'info', 'auto']<br>+NEW_ENUM = ['rfc4733', 'inband', 'info', 'auto', 'auto_info']<br>+<br>+old_type = sa.Enum(*OLD_ENUM, name='pjsip_dtmf_mode_values_v2')<br>+new_type = sa.Enum(*NEW_ENUM, name='pjsip_dtmf_mode_values_v3')<br>+<br>+def upgrade():<br>+ context = op.get_context()<br>+<br>+ # Upgrading to this revision WILL clear your directmedia values.<br>+ if context.bind.dialect.name != 'postgresql':<br>+ op.alter_column('ps_endpoints', 'dtmf_mode',<br>+ type_=new_type,<br>+ existing_type=old_type)<br>+ else:<br>+ enum = ENUM('rfc4733', 'inband', 'info', 'auto', 'auto_info',<br>+ name='pjsip_dtmf_mode_values_v3')<br>+ enum.create(op.get_bind(), checkfirst=False)<br>+<br>+ op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE'<br>+ ' pjsip_dtmf_mode_values_v3 USING'<br>+ ' dtmf_mode::text::pjsip_dtmf_mode_values_v3')<br>+<br>+ ENUM(name="pjsip_dtmf_mode_values_v2").drop(op.get_bind(), checkfirst=False)<br>+<br>+def downgrade():<br>+ context = op.get_context()<br>+<br>+ if context.bind.dialect.name != 'postgresql':<br>+ op.alter_column('ps_endpoints', 'dtmf_mode',<br>+ type_=old_type,<br>+ existing_type=new_type)<br>+ else:<br>+ enum = ENUM('rfc4733', 'inband', 'info', 'auto',<br>+ name='pjsip_dtmf_mode_values_v2')<br>+ enum.create(op.get_bind(), checkfirst=False)<br>+<br>+ op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE'<br>+ ' pjsip_dtmf_mode_values USING'<br>+ ' dtmf_mode::text::pjsip_dtmf_mode_values_v2')<br>+<br>+ ENUM(name="pjsip_dtmf_mode_values_v3").drop(op.get_bind(), checkfirst=False)<br>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h<br>index 04e0c65..b5a0288 100644<br>--- a/include/asterisk/res_pjsip.h<br>+++ b/include/asterisk/res_pjsip.h<br>@@ -363,6 +363,8 @@<br> AST_SIP_DTMF_INFO,<br> /*! Use SIP 4733 if supported by the other side or INBAND if not */<br> AST_SIP_DTMF_AUTO,<br>+ /*! Use SIP 4733 if supported by the other side or INFO DTMF (blech) if not */<br>+ AST_SIP_DTMF_AUTO_INFO,<br> };<br> <br> /*!<br>diff --git a/res/res_pjsip.c b/res/res_pjsip.c<br>index f79ebfd..057ae33 100644<br>--- a/res/res_pjsip.c<br>+++ b/res/res_pjsip.c<br>@@ -229,6 +229,9 @@<br> <enum name="auto"><br> <para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para><br> </enum><br>+ <enum name="auto_info"><br>+ <para>DTMF is sent as RFC 4733 if the other side supports it or as SIP INFO if not.</para><br>+ </enum><br> </enumlist><br> </description><br> </configOption><br>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c<br>index d2d1a0c..9604ff2 100644<br>--- a/res/res_pjsip/pjsip_configuration.c<br>+++ b/res/res_pjsip/pjsip_configuration.c<br>@@ -373,6 +373,8 @@<br> endpoint->dtmf = AST_SIP_DTMF_RFC_4733;<br> } else if (!strcasecmp(var->value, "inband")) {<br> endpoint->dtmf = AST_SIP_DTMF_INBAND;<br>+ } else if (!strcasecmp(var->value, "auto_info")) {<br>+ endpoint->dtmf = AST_SIP_DTMF_AUTO_INFO;<br> } else if (!strcasecmp(var->value, "info")) {<br> endpoint->dtmf = AST_SIP_DTMF_INFO;<br> } else if (!strcasecmp(var->value, "auto")) {<br>@@ -397,8 +399,11 @@<br> *buf = "inband"; break;<br> case AST_SIP_DTMF_INFO :<br> *buf = "info"; break;<br>- case AST_SIP_DTMF_AUTO :<br>+ case AST_SIP_DTMF_AUTO :<br> *buf = "auto"; break;<br>+ case AST_SIP_DTMF_AUTO_INFO :<br>+ *buf = "auto_info";<br>+ break;<br> default:<br> *buf = "none";<br> }<br>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c<br>index d39842f..a6bd2d7 100644<br>--- a/res/res_pjsip_sdp_rtp.c<br>+++ b/res/res_pjsip_sdp_rtp.c<br>@@ -246,7 +246,7 @@<br> ice->stop(session_media->rtp);<br> }<br> <br>- if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) {<br>+ if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {<br> ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);<br> ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_DTMF, 1);<br> } else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {<br>@@ -269,7 +269,7 @@<br> }<br> <br> static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs,<br>- struct ast_sip_session_media *session_media)<br>+ struct ast_sip_session_media *session_media)<br> {<br> pjmedia_sdp_attr *attr;<br> pjmedia_sdp_rtpmap *rtpmap;<br>@@ -335,6 +335,16 @@<br> if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) {<br> ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);<br> }<br>+<br>+ if (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {<br>+ if (tel_event) {<br>+ ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);<br>+ } else {<br>+ ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_NONE);<br>+ }<br>+ }<br>+<br>+<br> /* Get the packetization, if it exists */<br> if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {<br> unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));<br>@@ -429,7 +439,8 @@<br> ast_set_read_format(session->channel, ast_channel_readformat(session->channel));<br> ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));<br> }<br>- if ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO)<br>+<br>+ if ( ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) || (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) )<br> && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833)<br> && (session->dsp)) {<br> dsp_features = ast_dsp_get_features(session->dsp);<br>@@ -1149,7 +1160,7 @@<br> pj_str_t stmp;<br> pjmedia_sdp_attr *attr;<br> int index = 0;<br>- int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) ? AST_RTP_DTMF : 0;<br>+ int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) ? AST_RTP_DTMF : 0;<br> int min_packet_size = 0, max_packet_size = 0;<br> int rtp_code;<br> RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/5842">change 5842</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/5842"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Id185b11e84afd9191a2f269e8443019047765e91 </div>
<div style="display:none"> Gerrit-Change-Number: 5842 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Torrey Searle <tsearle@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Alexei Gradinari <alex2grad@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Matthew Fredrickson <creslin@digium.com> </div>