]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
chan_pjsip: add a new function PJSIP_DTMF_MODE
authorTorrey Searle <torrey@voxbone.com>
Mon, 26 Jun 2017 12:52:52 +0000 (14:52 +0200)
committerGeorge Joseph <gjoseph@digium.com>
Tue, 1 Aug 2017 21:45:25 +0000 (15:45 -0600)
This function is a replica of SIPDtmfMode, allowing the DTMF mode of a
PJSIP call to be modified on a per-call basis

ASTERISK-27085 #close

Change-Id: I20eef5da3e5d1d3e58b304416bc79683f87e7612

CHANGES
channels/chan_pjsip.c
channels/pjsip/dialplan_functions.c
channels/pjsip/include/dialplan_functions.h
include/asterisk/res_pjsip.h
include/asterisk/res_pjsip_session.h
res/res_pjsip.c
res/res_pjsip/pjsip_configuration.c
res/res_pjsip_sdp_rtp.c
res/res_pjsip_session.c

diff --git a/CHANGES b/CHANGES
index 18248c080f9700b2b33fc60c9518a1992958a429..03fa9beebd727fb8d3ff3ea11f6b29aa416f29a7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,9 @@ res_musiconhold
    which sends signals to the application and its descendants directly, or
    "process" which sends signals only to the application itself.
 
+ * New dialplan function PJSIP_DTMF_MODE added to get or change the DTMF mode
+   of a channel on a per-call basis.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.5.0 to Asterisk 14.6.0 ------------
 ------------------------------------------------------------------------------
index ad798f4a39bd89abfbae358e4aeb32b798525bfa..94aca702ed56f392b8f03b9cab3a681745565580 100644 (file)
@@ -1750,7 +1750,7 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit)
        struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
        int res = 0;
 
-       switch (channel->session->endpoint->dtmf) {
+       switch (channel->session->dtmf) {
        case AST_SIP_DTMF_RFC_4733:
                if (!media || !media->rtp) {
                        return -1;
@@ -1870,7 +1870,7 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
        struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
        int res = 0;
 
-       switch (channel->session->endpoint->dtmf) {
+       switch (channel->session->dtmf) {
        case AST_SIP_DTMF_AUTO_INFO:
        {
                if (!media || !media->rtp) {
@@ -2682,6 +2682,12 @@ static struct ast_custom_function media_offer_function = {
        .write = pjsip_acf_media_offer_write
 };
 
+static struct ast_custom_function dtmf_mode_function = {
+       .name = "PJSIP_DTMF_MODE",
+       .read = pjsip_acf_dtmf_mode_read,
+       .write = pjsip_acf_dtmf_mode_write
+};
+
 static struct ast_custom_function session_refresh_function = {
        .name = "PJSIP_SEND_SESSION_REFRESH",
        .write = pjsip_acf_session_refresh_write,
@@ -2726,6 +2732,11 @@ static int load_module(void)
                goto end;
        }
 
+       if (ast_custom_function_register(&dtmf_mode_function)) {
+               ast_log(LOG_WARNING, "Unable to register PJSIP_DTMF_MODE dialplan function\n");
+               goto end;
+       }
+
        if (ast_custom_function_register(&session_refresh_function)) {
                ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
                goto end;
@@ -2785,6 +2796,7 @@ static int load_module(void)
 end:
        ao2_cleanup(pjsip_uids_onhold);
        pjsip_uids_onhold = NULL;
+       ast_custom_function_unregister(&dtmf_mode_function);
        ast_custom_function_unregister(&media_offer_function);
        ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
        ast_custom_function_unregister(&session_refresh_function);
@@ -2807,6 +2819,7 @@ static int unload_module(void)
        ast_sip_session_unregister_supplement(&chan_pjsip_ack_supplement);
        ast_sip_session_unregister_supplement(&call_pickup_supplement);
 
+       ast_custom_function_unregister(&dtmf_mode_function);
        ast_custom_function_unregister(&media_offer_function);
        ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
        ast_custom_function_unregister(&session_refresh_function);
index 01081e935e9229014815a0e98f329c1aa7cb7b9c..13d9fab3ad15b3d4b10740e67382c859503b2e77 100644 (file)
                <ref type="function">PJSIP_SEND_SESSION_REFRESH</ref>
        </see-also>
 </function>
+<function name="PJSIP_DTMF_MODE" language="en_US">
+       <synopsis>
+               Get or change the DTMF mode for a SIP call.
+       </synopsis>
+       <syntax>
+       </syntax>
+       <description>
+               <para>When read, returns the current DTMF mode</para>
+               <para>When written, sets the current DTMF mode</para>
+               <para>This function uses the same DTMF mode naming as the dtmf_mode configuration option</para>
+       </description>
+</function>
 <function name="PJSIP_SEND_SESSION_REFRESH" language="en_US">
        <synopsis>
                W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session
@@ -440,6 +452,7 @@ ASTERISK_REGISTER_FILE()
 #include "asterisk/app.h"
 #include "asterisk/channel.h"
 #include "asterisk/format.h"
+#include "asterisk/dsp.h"
 #include "asterisk/pbx.h"
 #include "asterisk/res_pjsip.h"
 #include "asterisk/res_pjsip_session.h"
@@ -1039,6 +1052,34 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char
        return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
 }
 
+int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+       struct ast_sip_channel_pvt *channel;
+
+       if (!chan) {
+               ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
+               return -1;
+       }
+
+       ast_channel_lock(chan);
+       if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
+               ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
+               ast_channel_unlock(chan);
+               return -1;
+       }
+
+       channel = ast_channel_tech_pvt(chan);
+
+       if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {
+               ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));
+               ast_channel_unlock(chan);
+               return -1;
+       }
+
+       ast_channel_unlock(chan);
+       return 0;
+}
+
 struct refresh_data {
        struct ast_sip_session *session;
        enum ast_sip_session_refresh_method method;
@@ -1067,6 +1108,117 @@ static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_dat
        return 0;
 }
 
+static int dtmf_mode_refresh_cb(void *obj)
+{
+       struct refresh_data *data = obj;
+
+       if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
+               ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
+
+               ast_sip_session_refresh(data->session, NULL, NULL,
+                       sip_session_response_cb, data->method, 1);
+       }
+
+       return 0;
+}
+
+int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+       struct ast_sip_channel_pvt *channel;
+       struct chan_pjsip_pvt *pjsip_pvt;
+       int dsp_features = 0;
+       int dtmf = -1;
+       struct refresh_data rdata = {
+                       .method = AST_SIP_SESSION_REFRESH_METHOD_INVITE,
+               };
+
+       if (!chan) {
+               ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
+               return -1;
+       }
+
+       ast_channel_lock(chan);
+       if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
+               ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
+               ast_channel_unlock(chan);
+               return -1;
+       }
+
+       channel = ast_channel_tech_pvt(chan);
+       rdata.session = channel->session;
+
+       dtmf = ast_sip_str_to_dtmf(value);
+
+       if (dtmf == -1) {
+               ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
+                       ast_channel_name(chan));
+               ast_channel_unlock(chan);
+               return -1;
+       }
+
+       if (channel->session->dtmf == dtmf) {
+               /* DTMF mode unchanged, nothing to do! */
+               ast_channel_unlock(chan);
+               return 0;
+       }
+
+       channel->session->dtmf = dtmf;
+
+       pjsip_pvt = channel->pvt;
+       if (pjsip_pvt->media[SIP_MEDIA_AUDIO]  && (pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) {
+               if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {
+                       ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 1);
+                       ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_RFC2833);
+               } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {
+                       ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);
+                       ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);
+               } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {
+                       ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);
+                       ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_INBAND);
+               } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {
+                       ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);
+                       ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);
+               } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {
+                       if (ast_rtp_instance_dtmf_mode_get((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) != AST_RTP_DTMF_MODE_RFC2833) {
+                               /* no RFC4733 negotiated, enable inband */
+                               ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_INBAND);
+                       }
+               } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
+                       ast_rtp_instance_set_prop((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_PROPERTY_DTMF, 0);
+                       if (ast_rtp_instance_dtmf_mode_get((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp) == AST_RTP_DTMF_MODE_INBAND) {
+                               /* if inband, switch to INFO */
+                               ast_rtp_instance_dtmf_mode_set((pjsip_pvt->media[SIP_MEDIA_AUDIO])->rtp, AST_RTP_DTMF_MODE_NONE);
+                       }
+               }
+       }
+
+       if (channel->session->dsp) {
+               dsp_features = ast_dsp_get_features(channel->session->dsp);
+       }
+       if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||
+               channel->session->dtmf == AST_SIP_DTMF_AUTO) {
+               dsp_features |= DSP_FEATURE_DIGIT_DETECT;
+       } else {
+               dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
+       }
+       if (dsp_features) {
+               if (!channel->session->dsp) {
+                       if (!(channel->session->dsp = ast_dsp_new())) {
+                               ast_channel_unlock(chan);
+                               return 0;
+                       }
+               }
+               ast_dsp_set_features(channel->session->dsp, dsp_features);
+       } else if (channel->session->dsp) {
+               ast_dsp_free(channel->session->dsp);
+               channel->session->dsp = NULL;
+       }
+
+       ast_channel_unlock(chan);
+
+       return ast_sip_push_task_synchronous(channel->session->serializer, dtmf_mode_refresh_cb, &rdata);
+}
+
 static int refresh_write_cb(void *obj)
 {
        struct refresh_data *data = obj;
index 8b80bfa7474919f9d23a2b573539351179d03ffc..731e91d139eb781a2d1898c3551feeba0618755f 100644 (file)
@@ -47,6 +47,31 @@ int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data
  */
 int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
 
+/*!
+ * \brief PJSIP_DTMF_MODE function read callback
+ * \param chan The channel the function is called on
+ * \param cmd The name of the function
+ * \param data Arguments passed to the function
+ * \param buf Out buffer that should be populated with the data
+ * \param len Size of the buffer
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
+
+/*!
+ * \brief PJSIP_DTMF_MODE function write callback
+ * \param chan The channel the function is called on
+ * \param cmd The name of the function
+ * \param data Arguments passed to the function
+ * \param value Value to be set by the function
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
+
 /*!
  * \brief PJSIP_MEDIA_OFFER function read callback
  * \param chan The channel the function is called on
index 9b42527ac2fdb94d0cd04c9e83aa22eb53edbcd7..a6743139457fd9b06513f8a10ede31bb52dc8763 100644 (file)
@@ -2859,4 +2859,31 @@ int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoin
 int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,
        pjsip_tpselector *selector);
 
+/*!
+ * \brief Convert the DTMF mode enum value into a string
+ * \since 13.18.0
+ *
+ * \param dtmf the dtmf mode
+ * \param buf Buffer to receive dtmf mode string
+ * \param buf_len Buffer length
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ *
+ */
+int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf,
+       char *buf, size_t buf_len);
+
+/*!
+ * \brief Convert the DTMF mode name into an enum
+ * \since 13.18.0
+ *
+ * \param dtmf_mode dtmf mode as a string
+ *
+ * \retval  >= 0 The enum value
+ * \retval -1 Failure
+ *
+ */
+int ast_sip_str_to_dtmf(const char *dtmf_mode);
+
 #endif /* _RES_PJSIP_H */
index e2a90662ed02be5e1b503cfb1aa9319fbaa82bc2..ca331cbcc422a60d8b2a5fdbabf7d6bc341e155a 100644 (file)
@@ -159,6 +159,8 @@ struct ast_sip_session {
        unsigned int defer_end:1;
        /*! Session end (remote hangup) requested while termination deferred */
        unsigned int ended_while_deferred:1;
+       /*! DTMF mode to use with this session, from endpoint but can change */
+       enum ast_sip_dtmf_mode dtmf;
 };
 
 typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
index 4fa28a13c7d7aa122543407ef42e459338fc76de..e2d2c0ab745b836b276593022d439aee5d5dbf7a 100644 (file)
@@ -4431,6 +4431,56 @@ const char *ast_sip_get_host_ip_string(int af)
        return NULL;
 }
 
+int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf,
+                       char *buf, size_t buf_len)
+{
+       switch (dtmf) {
+       case AST_SIP_DTMF_NONE:
+               ast_copy_string(buf, "none", buf_len);
+               break;
+       case AST_SIP_DTMF_RFC_4733:
+               ast_copy_string(buf, "rfc4733", buf_len);
+               break;
+       case AST_SIP_DTMF_INBAND:
+               ast_copy_string(buf, "inband", buf_len);
+               break;
+       case AST_SIP_DTMF_INFO:
+               ast_copy_string(buf, "info", buf_len);
+               break;
+       case AST_SIP_DTMF_AUTO:
+               ast_copy_string(buf, "auto", buf_len);
+               break;
+       case AST_SIP_DTMF_AUTO_INFO:
+               ast_copy_string(buf, "auto_info", buf_len);
+               break;
+       default:
+               buf[0] = '\0';
+               return -1;
+       }
+       return 0;
+}
+
+int ast_sip_str_to_dtmf(const char * dtmf_mode)
+{
+       int result = -1;
+
+       if (!strcasecmp(dtmf_mode, "info")) {
+               result = AST_SIP_DTMF_INFO;
+       } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
+               result = AST_SIP_DTMF_RFC_4733;
+       } else if (!strcasecmp(dtmf_mode, "inband")) {
+               result = AST_SIP_DTMF_INBAND;
+       } else if (!strcasecmp(dtmf_mode, "none")) {
+               result = AST_SIP_DTMF_NONE;
+       } else if (!strcasecmp(dtmf_mode, "auto")) {
+               result = AST_SIP_DTMF_AUTO;
+       } else if (!strcasecmp(dtmf_mode, "auto_info")) {
+               result = AST_SIP_DTMF_AUTO_INFO;
+       }
+
+       return result;
+}
+
 /*!
  * \brief Set name and number information on an identity header.
  *
index 4e501e69d7e461970741436eceae8187d4513938..fb15db06dae0a37a2c95c0ac5acd5ae198f2d56b 100644 (file)
@@ -365,47 +365,29 @@ static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
 static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
 {
        struct ast_sip_endpoint *endpoint = obj;
+       enum ast_sip_dtmf_mode dtmf = ast_sip_str_to_dtmf(var->value);
 
-       if (!strcasecmp(var->value, "rfc4733")) {
-               endpoint->dtmf = AST_SIP_DTMF_RFC_4733;
-       } else if (!strcasecmp(var->value, "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")) {
-               endpoint->dtmf = AST_SIP_DTMF_INFO;
-       } else if (!strcasecmp(var->value, "auto")) {
-               endpoint->dtmf = AST_SIP_DTMF_AUTO;
-       } else if (!strcasecmp(var->value, "none")) {
-               endpoint->dtmf = AST_SIP_DTMF_NONE;
-       } else {
+       if (dtmf == -1) {
                return -1;
        }
 
+       endpoint->dtmf = dtmf;
        return 0;
 }
 
 static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
 {
        const struct ast_sip_endpoint *endpoint = obj;
+       char dtmf_str[20];
+       int result = -1;
 
-       switch (endpoint->dtmf) {
-       case AST_SIP_DTMF_RFC_4733 :
-               *buf = "rfc4733"; break;
-       case AST_SIP_DTMF_INBAND :
-               *buf = "inband"; break;
-       case AST_SIP_DTMF_INFO :
-               *buf = "info"; break;
-       case AST_SIP_DTMF_AUTO :
-               *buf = "auto"; break;
-       case AST_SIP_DTMF_AUTO_INFO :
-               *buf = "auto_info";
-               break;
-       default:
-               *buf = "none";
-       }
+       result = ast_sip_dtmf_to_str(endpoint->dtmf, dtmf_str, sizeof(dtmf_str));
 
-       *buf = ast_strdup(*buf);
+       if (result == 0) {
+               *buf = ast_strdup(dtmf_str);
+       } else {
+               *buf = ast_strdup("none");
+       }
        return 0;
 }
 
index 6b29e798be729dd78802c4839007bf45fdf27cd5..5fff7677712641b8c5cb8675983b1e3a0bd5707e 100644 (file)
@@ -247,10 +247,10 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
                ice->stop(session_media->rtp);
        }
 
-       if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {
+       if (session->dtmf == AST_SIP_DTMF_RFC_4733 || session->dtmf == AST_SIP_DTMF_AUTO || session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
                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);
-       } else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
+       } else if (session->dtmf == AST_SIP_DTMF_INBAND) {
                ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
        }
 
@@ -333,11 +333,11 @@ 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->dtmf == AST_SIP_DTMF_AUTO)) {
                ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
        }
 
-       if (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) {
+       if (session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
                if  (tel_event) {
                        ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833);
                } else {
@@ -450,7 +450,7 @@ static int set_caps(struct ast_sip_session *session,
                        ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
                }
 
-               if ( ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) || (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) )
+               if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->dtmf == AST_SIP_DTMF_AUTO_INFO) )
                    && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833)
                    && (session->dsp)) {
                        dsp_features = ast_dsp_get_features(session->dsp);
@@ -1178,7 +1178,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
        pj_str_t stmp;
        pjmedia_sdp_attr *attr;
        int index = 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 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;
        int min_packet_size = 0, max_packet_size = 0;
        int rtp_code;
        RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
index aedf3f680ec3c0be23f6cc839d0063449eb8dbcb..aed047b895ed7a6b2e19fe4181861afdbf05ae89 100644 (file)
@@ -1481,6 +1481,8 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
        session->contact = ao2_bump(contact);
        session->inv_session = inv_session;
 
+       session->dtmf = endpoint->dtmf;
+
        if (add_supplements(session)) {
                /* Release the ref held by session->inv_session */
                ao2_ref(session, -1);