mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-04 20:25:29 +00:00
res_pjsip: Add DTMF INFO Failback mode
The existing auto dtmf mode reverts to inband if 4733 fails to be negotiated. This patch adds a new mode auto_info which will switch to INFO instead of inband if 4733 is not available. ASTERISK-27066 #close Change-Id: Id185b11e84afd9191a2f269e8443019047765e91
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -25,6 +25,10 @@ res_pjsip
|
|||||||
whether to notify dialog-info state 'early' or 'confirmed' on Ringing
|
whether to notify dialog-info state 'early' or 'confirmed' on Ringing
|
||||||
when already INUSE.
|
when already INUSE.
|
||||||
|
|
||||||
|
* The endpoint option 'dtmf_mode' has a new option 'auto_dtmf' added. This
|
||||||
|
mode works similar to 'auto' except uses DTMF INFO as fallback instead of
|
||||||
|
INBAND.
|
||||||
|
|
||||||
res_agi
|
res_agi
|
||||||
------------------
|
------------------
|
||||||
* The EAGI() application will now look for a dialplan variable named
|
* The EAGI() application will now look for a dialplan variable named
|
||||||
|
@@ -1708,14 +1708,20 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast_rtp_instance_dtmf_begin(media->rtp, digit);
|
ast_rtp_instance_dtmf_begin(media->rtp, digit);
|
||||||
break;
|
break;
|
||||||
case AST_SIP_DTMF_AUTO:
|
case AST_SIP_DTMF_AUTO:
|
||||||
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
|
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_rtp_instance_dtmf_begin(media->rtp, digit);
|
ast_rtp_instance_dtmf_begin(media->rtp, digit);
|
||||||
break;
|
break;
|
||||||
|
case AST_SIP_DTMF_AUTO_INFO:
|
||||||
|
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_NONE)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ast_rtp_instance_dtmf_begin(media->rtp, digit);
|
||||||
|
break;
|
||||||
case AST_SIP_DTMF_NONE:
|
case AST_SIP_DTMF_NONE:
|
||||||
break;
|
break;
|
||||||
case AST_SIP_DTMF_INBAND:
|
case AST_SIP_DTMF_INBAND:
|
||||||
@@ -1816,6 +1822,20 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
switch (channel->session->endpoint->dtmf) {
|
switch (channel->session->endpoint->dtmf) {
|
||||||
|
case AST_SIP_DTMF_AUTO_INFO:
|
||||||
|
{
|
||||||
|
if (!media || !media->rtp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ast_rtp_instance_dtmf_mode_get(media->rtp) != AST_RTP_DTMF_MODE_NONE) {
|
||||||
|
ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast));
|
||||||
|
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* If RFC_4733 was not negotiated, fail through to the DTMF_INFO processing */
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
case AST_SIP_DTMF_INFO:
|
case AST_SIP_DTMF_INFO:
|
||||||
{
|
{
|
||||||
struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
|
struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
|
||||||
@@ -1848,14 +1868,15 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
|
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
|
||||||
break;
|
break;
|
||||||
case AST_SIP_DTMF_AUTO:
|
case AST_SIP_DTMF_AUTO:
|
||||||
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
|
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
|
||||||
|
break;
|
||||||
|
|
||||||
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AST_SIP_DTMF_NONE:
|
case AST_SIP_DTMF_NONE:
|
||||||
break;
|
break;
|
||||||
|
@@ -0,0 +1,57 @@
|
|||||||
|
"""Add auto_info to endpoint dtmf_mode
|
||||||
|
|
||||||
|
Revision ID: 164abbd708c
|
||||||
|
Revises: 86bb1efa278d
|
||||||
|
Create Date: 2017-06-19 13:55:15.354706
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '164abbd708c'
|
||||||
|
down_revision = '86bb1efa278d'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
OLD_ENUM = ['rfc4733', 'inband', 'info', 'auto']
|
||||||
|
NEW_ENUM = ['rfc4733', 'inband', 'info', 'auto', 'auto_info']
|
||||||
|
|
||||||
|
old_type = sa.Enum(*OLD_ENUM, name='pjsip_dtmf_mode_values_v2')
|
||||||
|
new_type = sa.Enum(*NEW_ENUM, name='pjsip_dtmf_mode_values_v3')
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
context = op.get_context()
|
||||||
|
|
||||||
|
# Upgrading to this revision WILL clear your directmedia values.
|
||||||
|
if context.bind.dialect.name != 'postgresql':
|
||||||
|
op.alter_column('ps_endpoints', 'dtmf_mode',
|
||||||
|
type_=new_type,
|
||||||
|
existing_type=old_type)
|
||||||
|
else:
|
||||||
|
enum = ENUM('rfc4733', 'inband', 'info', 'auto', 'auto_info',
|
||||||
|
name='pjsip_dtmf_mode_values_v3')
|
||||||
|
enum.create(op.get_bind(), checkfirst=False)
|
||||||
|
|
||||||
|
op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE'
|
||||||
|
' pjsip_dtmf_mode_values_v3 USING'
|
||||||
|
' dtmf_mode::text::pjsip_dtmf_mode_values_v3')
|
||||||
|
|
||||||
|
ENUM(name="pjsip_dtmf_mode_values_v2").drop(op.get_bind(), checkfirst=False)
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
context = op.get_context()
|
||||||
|
|
||||||
|
if context.bind.dialect.name != 'postgresql':
|
||||||
|
op.alter_column('ps_endpoints', 'dtmf_mode',
|
||||||
|
type_=old_type,
|
||||||
|
existing_type=new_type)
|
||||||
|
else:
|
||||||
|
enum = ENUM('rfc4733', 'inband', 'info', 'auto',
|
||||||
|
name='pjsip_dtmf_mode_values_v2')
|
||||||
|
enum.create(op.get_bind(), checkfirst=False)
|
||||||
|
|
||||||
|
op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE'
|
||||||
|
' pjsip_dtmf_mode_values USING'
|
||||||
|
' dtmf_mode::text::pjsip_dtmf_mode_values_v2')
|
||||||
|
|
||||||
|
ENUM(name="pjsip_dtmf_mode_values_v3").drop(op.get_bind(), checkfirst=False)
|
@@ -363,6 +363,8 @@ enum ast_sip_dtmf_mode {
|
|||||||
AST_SIP_DTMF_INFO,
|
AST_SIP_DTMF_INFO,
|
||||||
/*! Use SIP 4733 if supported by the other side or INBAND if not */
|
/*! Use SIP 4733 if supported by the other side or INBAND if not */
|
||||||
AST_SIP_DTMF_AUTO,
|
AST_SIP_DTMF_AUTO,
|
||||||
|
/*! Use SIP 4733 if supported by the other side or INFO DTMF (blech) if not */
|
||||||
|
AST_SIP_DTMF_AUTO_INFO,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@@ -229,6 +229,9 @@
|
|||||||
<enum name="auto">
|
<enum name="auto">
|
||||||
<para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para>
|
<para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para>
|
||||||
</enum>
|
</enum>
|
||||||
|
<enum name="auto_info">
|
||||||
|
<para>DTMF is sent as RFC 4733 if the other side supports it or as SIP INFO if not.</para>
|
||||||
|
</enum>
|
||||||
</enumlist>
|
</enumlist>
|
||||||
</description>
|
</description>
|
||||||
</configOption>
|
</configOption>
|
||||||
|
@@ -373,6 +373,8 @@ static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var,
|
|||||||
endpoint->dtmf = AST_SIP_DTMF_RFC_4733;
|
endpoint->dtmf = AST_SIP_DTMF_RFC_4733;
|
||||||
} else if (!strcasecmp(var->value, "inband")) {
|
} else if (!strcasecmp(var->value, "inband")) {
|
||||||
endpoint->dtmf = AST_SIP_DTMF_INBAND;
|
endpoint->dtmf = AST_SIP_DTMF_INBAND;
|
||||||
|
} else if (!strcasecmp(var->value, "auto_info")) {
|
||||||
|
endpoint->dtmf = AST_SIP_DTMF_AUTO_INFO;
|
||||||
} else if (!strcasecmp(var->value, "info")) {
|
} else if (!strcasecmp(var->value, "info")) {
|
||||||
endpoint->dtmf = AST_SIP_DTMF_INFO;
|
endpoint->dtmf = AST_SIP_DTMF_INFO;
|
||||||
} else if (!strcasecmp(var->value, "auto")) {
|
} else if (!strcasecmp(var->value, "auto")) {
|
||||||
@@ -397,8 +399,11 @@ static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
|
|||||||
*buf = "inband"; break;
|
*buf = "inband"; break;
|
||||||
case AST_SIP_DTMF_INFO :
|
case AST_SIP_DTMF_INFO :
|
||||||
*buf = "info"; break;
|
*buf = "info"; break;
|
||||||
case AST_SIP_DTMF_AUTO :
|
case AST_SIP_DTMF_AUTO :
|
||||||
*buf = "auto"; break;
|
*buf = "auto"; break;
|
||||||
|
case AST_SIP_DTMF_AUTO_INFO :
|
||||||
|
*buf = "auto_info";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*buf = "none";
|
*buf = "none";
|
||||||
}
|
}
|
||||||
|
@@ -246,7 +246,7 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
|
|||||||
ice->stop(session_media->rtp);
|
ice->stop(session_media->rtp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) {
|
if (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_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);
|
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);
|
||||||
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_DTMF, 1);
|
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_DTMF, 1);
|
||||||
} else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
|
} else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
|
||||||
@@ -269,7 +269,7 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs,
|
static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs,
|
||||||
struct ast_sip_session_media *session_media)
|
struct ast_sip_session_media *session_media)
|
||||||
{
|
{
|
||||||
pjmedia_sdp_attr *attr;
|
pjmedia_sdp_attr *attr;
|
||||||
pjmedia_sdp_rtpmap *rtpmap;
|
pjmedia_sdp_rtpmap *rtpmap;
|
||||||
@@ -335,6 +335,16 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
|
|||||||
if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) {
|
if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) {
|
||||||
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
|
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {
|
||||||
|
if (tel_event) {
|
||||||
|
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);
|
||||||
|
} else {
|
||||||
|
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get the packetization, if it exists */
|
/* Get the packetization, if it exists */
|
||||||
if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
|
if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
|
||||||
unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
|
unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
|
||||||
@@ -429,7 +439,8 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi
|
|||||||
ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
|
ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
|
||||||
ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
|
ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
|
||||||
}
|
}
|
||||||
if ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO)
|
|
||||||
|
if ( ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) || (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) )
|
||||||
&& (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833)
|
&& (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833)
|
||||||
&& (session->dsp)) {
|
&& (session->dsp)) {
|
||||||
dsp_features = ast_dsp_get_features(session->dsp);
|
dsp_features = ast_dsp_get_features(session->dsp);
|
||||||
@@ -1149,7 +1160,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
|
|||||||
pj_str_t stmp;
|
pj_str_t stmp;
|
||||||
pjmedia_sdp_attr *attr;
|
pjmedia_sdp_attr *attr;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) ? AST_RTP_DTMF : 0;
|
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;
|
||||||
int min_packet_size = 0, max_packet_size = 0;
|
int min_packet_size = 0, max_packet_size = 0;
|
||||||
int rtp_code;
|
int rtp_code;
|
||||||
RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
|
RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
|
||||||
|
Reference in New Issue
Block a user