<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/5909">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Sean Bright: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, but someone else must approve; Verified
George Joseph: Looks good to me, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_pjsip: add a new function PJSIP_DTMF_MODE<br><br>This function is a replica of SIPDtmfMode, allowing the DTMF mode of a<br>PJSIP call to be modified on a per-call basis<br><br>ASTERISK-27085 #close<br><br>Change-Id: I20eef5da3e5d1d3e58b304416bc79683f87e7612<br>---<br>M CHANGES<br>M channels/chan_pjsip.c<br>M channels/pjsip/dialplan_functions.c<br>M channels/pjsip/include/dialplan_functions.h<br>M include/asterisk/res_pjsip.h<br>M include/asterisk/res_pjsip_session.h<br>M res/res_pjsip.c<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_sdp_rtp.c<br>M res/res_pjsip_session.c<br>10 files changed, 293 insertions(+), 37 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index c7d801d..d9ea437 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -28,6 +28,9 @@<br> which sends signals to the application and its descendants directly, or<br> "process" which sends signals only to the application itself.<br> <br>+ * New dialplan function PJSIP_DTMF_MODE added to get or change the DTMF mode<br>+ of a channel on a per-call basis.<br>+<br> ------------------------------------------------------------------------------<br> --- Functionality changes from Asterisk 13.16.0 to Asterisk 13.17.0 ----------<br> ------------------------------------------------------------------------------<br>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c<br>index e2fd13c..83aca39 100644<br>--- a/channels/chan_pjsip.c<br>+++ b/channels/chan_pjsip.c<br>@@ -1700,7 +1700,7 @@<br> struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];<br> int res = 0;<br> <br>- switch (channel->session->endpoint->dtmf) {<br>+ switch (channel->session->dtmf) {<br> case AST_SIP_DTMF_RFC_4733:<br> if (!media || !media->rtp) {<br> return -1;<br>@@ -1820,7 +1820,7 @@<br> struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];<br> int res = 0;<br> <br>- switch (channel->session->endpoint->dtmf) {<br>+ switch (channel->session->dtmf) {<br> case AST_SIP_DTMF_AUTO_INFO:<br> {<br> if (!media || !media->rtp) {<br>@@ -2632,6 +2632,12 @@<br> .write = pjsip_acf_media_offer_write<br> };<br> <br>+static struct ast_custom_function dtmf_mode_function = {<br>+ .name = "PJSIP_DTMF_MODE",<br>+ .read = pjsip_acf_dtmf_mode_read,<br>+ .write = pjsip_acf_dtmf_mode_write<br>+};<br>+<br> static struct ast_custom_function session_refresh_function = {<br> .name = "PJSIP_SEND_SESSION_REFRESH",<br> .write = pjsip_acf_session_refresh_write,<br>@@ -2673,6 +2679,11 @@<br> <br> if (ast_custom_function_register(&media_offer_function)) {<br> ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");<br>+ goto end;<br>+ }<br>+<br>+ if (ast_custom_function_register(&dtmf_mode_function)) {<br>+ ast_log(LOG_WARNING, "Unable to register PJSIP_DTMF_MODE dialplan function\n");<br> goto end;<br> }<br> <br>@@ -2735,6 +2746,7 @@<br> end:<br> ao2_cleanup(pjsip_uids_onhold);<br> pjsip_uids_onhold = NULL;<br>+ ast_custom_function_unregister(&dtmf_mode_function);<br> ast_custom_function_unregister(&media_offer_function);<br> ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);<br> ast_custom_function_unregister(&session_refresh_function);<br>@@ -2757,6 +2769,7 @@<br> ast_sip_session_unregister_supplement(&chan_pjsip_ack_supplement);<br> ast_sip_session_unregister_supplement(&call_pickup_supplement);<br> <br>+ ast_custom_function_unregister(&dtmf_mode_function);<br> ast_custom_function_unregister(&media_offer_function);<br> ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);<br> ast_custom_function_unregister(&session_refresh_function);<br>diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c<br>index 22d7738..a382c4e 100644<br>--- a/channels/pjsip/dialplan_functions.c<br>+++ b/channels/pjsip/dialplan_functions.c<br>@@ -68,6 +68,18 @@<br> <ref type="function">PJSIP_SEND_SESSION_REFRESH</ref><br> </see-also><br> </function><br>+<function name="PJSIP_DTMF_MODE" language="en_US"><br>+ <synopsis><br>+ Get or change the DTMF mode for a SIP call.<br>+ </synopsis><br>+ <syntax><br>+ </syntax><br>+ <description><br>+ <para>When read, returns the current DTMF mode</para><br>+ <para>When written, sets the current DTMF mode</para><br>+ <para>This function uses the same DTMF mode naming as the dtmf_mode configuration option</para><br>+ </description><br>+</function><br> <function name="PJSIP_SEND_SESSION_REFRESH" language="en_US"><br> <synopsis><br> W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session<br>@@ -440,6 +452,7 @@<br> #include "asterisk/app.h"<br> #include "asterisk/channel.h"<br> #include "asterisk/format.h"<br>+#include "asterisk/dsp.h"<br> #include "asterisk/pbx.h"<br> #include "asterisk/res_pjsip.h"<br> #include "asterisk/res_pjsip_session.h"<br>@@ -1039,6 +1052,34 @@<br> return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);<br> }<br> <br>+int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)<br>+{<br>+ struct ast_sip_channel_pvt *channel;<br>+<br>+ if (!chan) {<br>+ ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);<br>+ return -1;<br>+ }<br>+<br>+ ast_channel_lock(chan);<br>+ if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {<br>+ ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ channel = ast_channel_tech_pvt(chan);<br>+<br>+ if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {<br>+ ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+}<br>+<br> struct refresh_data {<br> struct ast_sip_session *session;<br> enum ast_sip_session_refresh_method method;<br>@@ -1067,6 +1108,117 @@<br> return 0;<br> }<br> <br>+static int dtmf_mode_refresh_cb(void *obj)<br>+{<br>+ struct refresh_data *data = obj;<br>+<br>+ if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {<br>+ ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSER completion. Sending session refresh\n", ast_channel_name(data->session->channel));<br>+<br>+ ast_sip_session_refresh(data->session, NULL, NULL,<br>+ sip_session_response_cb, data->method, 1);<br>+ }<br>+<br>+ return 0;<br>+}<br>+<br>+int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)<br>+{<br>+ struct ast_sip_channel_pvt *channel;<br>+ struct chan_pjsip_pvt *pjsip_pvt;<br>+ int dsp_features = 0;<br>+ int dtmf = -1;<br>+ struct refresh_data rdata = {<br>+ .method = AST_SIP_SESSION_REFRESH_METHOD_INVITE,<br>+ };<br>+<br>+ if (!chan) {<br>+ ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);<br>+ return -1;<br>+ }<br>+<br>+ ast_channel_lock(chan);<br>+ if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {<br>+ ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ channel = ast_channel_tech_pvt(chan);<br>+ rdata.session = channel->session;<br>+<br>+ dtmf = ast_sip_str_to_dtmf(value);<br>+<br>+ if (dtmf == -1) {<br>+ ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,<br>+ ast_channel_name(chan));<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ if (channel->session->dtmf == dtmf) {<br>+ /* DTMF mode unchanged, nothing to do! */<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+ }<br>+<br>+ channel->session->dtmf = dtmf;<br>+<br>+ pjsip_pvt = channel->pvt;<br>+ if (pjsip_pvt->media[SIP_MEDIA_AUDIO] && (pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) {<br>+ if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {<br>+ ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 1);<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_RFC2833);<br>+ } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {<br>+ ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);<br>+ } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {<br>+ ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_INBAND);<br>+ } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {<br>+ ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);<br>+ } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {<br>+ if (ast_rtp_instance_dtmf_mode_get((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) != AST_RTP_DTMF_MODE_RFC2833) {<br>+ /* no RFC4733 negotiated, enable inband */<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_INBAND);<br>+ }<br>+ } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {<br>+ ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);<br>+ if (ast_rtp_instance_dtmf_mode_get((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) == AST_RTP_DTMF_MODE_INBAND) {<br>+ /* if inband, switch to INFO */<br>+ ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);<br>+ }<br>+ }<br>+ }<br>+<br>+ if (channel->session->dsp) {<br>+ dsp_features = ast_dsp_get_features(channel->session->dsp);<br>+ }<br>+ if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||<br>+ channel->session->dtmf == AST_SIP_DTMF_AUTO) {<br>+ dsp_features |= DSP_FEATURE_DIGIT_DETECT;<br>+ } else {<br>+ dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;<br>+ }<br>+ if (dsp_features) {<br>+ if (!channel->session->dsp) {<br>+ if (!(channel->session->dsp = ast_dsp_new())) {<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+ }<br>+ }<br>+ ast_dsp_set_features(channel->session->dsp, dsp_features);<br>+ } else if (channel->session->dsp) {<br>+ ast_dsp_free(channel->session->dsp);<br>+ channel->session->dsp = NULL;<br>+ }<br>+<br>+ ast_channel_unlock(chan);<br>+<br>+ return ast_sip_push_task_synchronous(channel->session->serializer, dtmf_mode_refresh_cb, &rdata);<br>+}<br>+<br> static int refresh_write_cb(void *obj)<br> {<br> struct refresh_data *data = obj;<br>diff --git a/channels/pjsip/include/dialplan_functions.h b/channels/pjsip/include/dialplan_functions.h<br>index 8b80bfa..731e91d 100644<br>--- a/channels/pjsip/include/dialplan_functions.h<br>+++ b/channels/pjsip/include/dialplan_functions.h<br>@@ -48,6 +48,31 @@<br> int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);<br> <br> /*!<br>+ * \brief PJSIP_DTMF_MODE function read callback<br>+ * \param chan The channel the function is called on<br>+ * \param cmd The name of the function<br>+ * \param data Arguments passed to the function<br>+ * \param buf Out buffer that should be populated with the data<br>+ * \param len Size of the buffer<br>+ *<br>+ * \retval 0 on success<br>+ * \retval -1 on failure<br>+ */<br>+int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);<br>+<br>+/*!<br>+ * \brief PJSIP_DTMF_MODE function write callback<br>+ * \param chan The channel the function is called on<br>+ * \param cmd The name of the function<br>+ * \param data Arguments passed to the function<br>+ * \param value Value to be set by the function<br>+ *<br>+ * \retval 0 on success<br>+ * \retval -1 on failure<br>+ */<br>+int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);<br>+<br>+/*!<br> * \brief PJSIP_MEDIA_OFFER function read callback<br> * \param chan The channel the function is called on<br> * \param cmd The name of the function<br>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h<br>index b5a0288..e239827 100644<br>--- a/include/asterisk/res_pjsip.h<br>+++ b/include/asterisk/res_pjsip.h<br>@@ -2906,4 +2906,31 @@<br> int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,<br> pjsip_tpselector *selector);<br> <br>+/*!<br>+ * \brief Convert the DTMF mode enum value into a string<br>+ * \since 13.18.0<br>+ *<br>+ * \param dtmf the dtmf mode<br>+ * \param buf Buffer to receive dtmf mode string<br>+ * \param buf_len Buffer length<br>+ *<br>+ * \retval 0 Success<br>+ * \retval -1 Failure<br>+ *<br>+ */<br>+int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf,<br>+ char *buf, size_t buf_len);<br>+<br>+/*!<br>+ * \brief Convert the DTMF mode name into an enum<br>+ * \since 13.18.0<br>+ *<br>+ * \param dtmf_mode dtmf mode as a string<br>+ *<br>+ * \retval >= 0 The enum value<br>+ * \retval -1 Failure<br>+ *<br>+ */<br>+int ast_sip_str_to_dtmf(const char *dtmf_mode);<br>+<br> #endif /* _RES_PJSIP_H */<br>diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h<br>index 457edd8..ca919da 100644<br>--- a/include/asterisk/res_pjsip_session.h<br>+++ b/include/asterisk/res_pjsip_session.h<br>@@ -157,6 +157,8 @@<br> unsigned int defer_end:1;<br> /*! Session end (remote hangup) requested while termination deferred */<br> unsigned int ended_while_deferred:1;<br>+ /*! DTMF mode to use with this session, from endpoint but can change */<br>+ enum ast_sip_dtmf_mode dtmf;<br> };<br> <br> typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);<br>diff --git a/res/res_pjsip.c b/res/res_pjsip.c<br>index 258713d..428ec47 100644<br>--- a/res/res_pjsip.c<br>+++ b/res/res_pjsip.c<br>@@ -4397,6 +4397,56 @@<br> return NULL;<br> }<br> <br>+int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf,<br>+ char *buf, size_t buf_len)<br>+{<br>+ switch (dtmf) {<br>+ case AST_SIP_DTMF_NONE:<br>+ ast_copy_string(buf, "none", buf_len);<br>+ break;<br>+ case AST_SIP_DTMF_RFC_4733:<br>+ ast_copy_string(buf, "rfc4733", buf_len);<br>+ break;<br>+ case AST_SIP_DTMF_INBAND:<br>+ ast_copy_string(buf, "inband", buf_len);<br>+ break;<br>+ case AST_SIP_DTMF_INFO:<br>+ ast_copy_string(buf, "info", buf_len);<br>+ break;<br>+ case AST_SIP_DTMF_AUTO:<br>+ ast_copy_string(buf, "auto", buf_len);<br>+ break;<br>+ case AST_SIP_DTMF_AUTO_INFO:<br>+ ast_copy_string(buf, "auto_info", buf_len);<br>+ break;<br>+ default:<br>+ buf[0] = '\0';<br>+ return -1;<br>+ }<br>+ return 0;<br>+}<br>+<br>+int ast_sip_str_to_dtmf(const char * dtmf_mode)<br>+{<br>+ int result = -1;<br>+<br>+ if (!strcasecmp(dtmf_mode, "info")) {<br>+ result = AST_SIP_DTMF_INFO;<br>+ } else if (!strcasecmp(dtmf_mode, "rfc4733")) {<br>+ result = AST_SIP_DTMF_RFC_4733;<br>+ } else if (!strcasecmp(dtmf_mode, "inband")) {<br>+ result = AST_SIP_DTMF_INBAND;<br>+ } else if (!strcasecmp(dtmf_mode, "none")) {<br>+ result = AST_SIP_DTMF_NONE;<br>+ } else if (!strcasecmp(dtmf_mode, "auto")) {<br>+ result = AST_SIP_DTMF_AUTO;<br>+ } else if (!strcasecmp(dtmf_mode, "auto_info")) {<br>+ result = AST_SIP_DTMF_AUTO_INFO;<br>+ }<br>+<br>+ return result;<br>+}<br>+<br> /*!<br> * \brief Set name and number information on an identity header.<br> *<br>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c<br>index 893c81e..39e10c5 100644<br>--- a/res/res_pjsip/pjsip_configuration.c<br>+++ b/res/res_pjsip/pjsip_configuration.c<br>@@ -368,47 +368,29 @@<br> static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)<br> {<br> struct ast_sip_endpoint *endpoint = obj;<br>+ enum ast_sip_dtmf_mode dtmf = ast_sip_str_to_dtmf(var->value);<br> <br>- if (!strcasecmp(var->value, "rfc4733")) {<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>- endpoint->dtmf = AST_SIP_DTMF_AUTO;<br>- } else if (!strcasecmp(var->value, "none")) {<br>- endpoint->dtmf = AST_SIP_DTMF_NONE;<br>- } else {<br>+ if (dtmf == -1) {<br> return -1;<br> }<br> <br>+ endpoint->dtmf = dtmf;<br> return 0;<br> }<br> <br> static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)<br> {<br> const struct ast_sip_endpoint *endpoint = obj;<br>+ char dtmf_str[20];<br>+ int result = -1;<br> <br>- switch (endpoint->dtmf) {<br>- case AST_SIP_DTMF_RFC_4733 :<br>- *buf = "rfc4733"; break;<br>- case AST_SIP_DTMF_INBAND :<br>- *buf = "inband"; break;<br>- case AST_SIP_DTMF_INFO :<br>- *buf = "info"; break;<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>+ result = ast_sip_dtmf_to_str(endpoint->dtmf, dtmf_str, sizeof(dtmf_str));<br>+<br>+ if (result == 0) {<br>+ *buf = ast_strdup(dtmf_str);<br>+ } else {<br>+ *buf = ast_strdup("none");<br> }<br>-<br>- *buf = ast_strdup(*buf);<br> return 0;<br> }<br> <br>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c<br>index a6bd2d7..a7c1b7c 100644<br>--- a/res/res_pjsip_sdp_rtp.c<br>+++ b/res/res_pjsip_sdp_rtp.c<br>@@ -246,10 +246,10 @@<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 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {<br>+ if (session->dtmf == AST_SIP_DTMF_RFC_4733 || session->dtmf == AST_SIP_DTMF_AUTO || session->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>+ } else if (session->dtmf == AST_SIP_DTMF_INBAND) {<br> ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);<br> }<br> <br>@@ -332,11 +332,11 @@<br> }<br> }<br> }<br>- if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) {<br>+ if (!tel_event && (session->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 (session->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>@@ -440,7 +440,7 @@<br> ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));<br> }<br> <br>- if ( ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) || (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) )<br>+ if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->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>@@ -1160,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 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) ? AST_RTP_DTMF : 0;<br>+ int noncodec = (session->dtmf == AST_SIP_DTMF_RFC_4733 || session->dtmf == AST_SIP_DTMF_AUTO || session->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>diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c<br>index d6c5fbc..c1684ed 100644<br>--- a/res/res_pjsip_session.c<br>+++ b/res/res_pjsip_session.c<br>@@ -1481,6 +1481,8 @@<br> session->contact = ao2_bump(contact);<br> session->inv_session = inv_session;<br> <br>+ session->dtmf = endpoint->dtmf;<br>+<br> if (add_supplements(session)) {<br> /* Release the ref held by session->inv_session */<br> ao2_ref(session, -1);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/5909">change 5909</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/5909"/><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: I20eef5da3e5d1d3e58b304416bc79683f87e7612 </div>
<div style="display:none"> Gerrit-Change-Number: 5909 </div>
<div style="display:none"> Gerrit-PatchSet: 14 </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: George Joseph <gjoseph@digium.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: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>