mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-07 13:49:18 +00:00
chan_pjsip: add a new function PJSIP_DTMF_MODE
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
This commit is contained in:
committed by
George Joseph
parent
c16000f201
commit
423d01cf16
3
CHANGES
3
CHANGES
@@ -33,6 +33,9 @@ res_musiconhold
|
|||||||
which sends signals to the application and its descendants directly, or
|
which sends signals to the application and its descendants directly, or
|
||||||
"process" which sends signals only to the application itself.
|
"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 13.16.0 to Asterisk 13.17.0 ----------
|
--- Functionality changes from Asterisk 13.16.0 to Asterisk 13.17.0 ----------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@@ -1701,7 +1701,7 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit)
|
|||||||
struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
|
struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
switch (channel->session->endpoint->dtmf) {
|
switch (channel->session->dtmf) {
|
||||||
case AST_SIP_DTMF_RFC_4733:
|
case AST_SIP_DTMF_RFC_4733:
|
||||||
if (!media || !media->rtp) {
|
if (!media || !media->rtp) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1821,7 +1821,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];
|
struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
switch (channel->session->endpoint->dtmf) {
|
switch (channel->session->dtmf) {
|
||||||
case AST_SIP_DTMF_AUTO_INFO:
|
case AST_SIP_DTMF_AUTO_INFO:
|
||||||
{
|
{
|
||||||
if (!media || !media->rtp) {
|
if (!media || !media->rtp) {
|
||||||
@@ -2633,6 +2633,12 @@ static struct ast_custom_function media_offer_function = {
|
|||||||
.write = pjsip_acf_media_offer_write
|
.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 = {
|
static struct ast_custom_function session_refresh_function = {
|
||||||
.name = "PJSIP_SEND_SESSION_REFRESH",
|
.name = "PJSIP_SEND_SESSION_REFRESH",
|
||||||
.write = pjsip_acf_session_refresh_write,
|
.write = pjsip_acf_session_refresh_write,
|
||||||
@@ -2677,6 +2683,11 @@ static int load_module(void)
|
|||||||
goto end;
|
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)) {
|
if (ast_custom_function_register(&session_refresh_function)) {
|
||||||
ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
|
ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
|
||||||
goto end;
|
goto end;
|
||||||
@@ -2736,6 +2747,7 @@ static int load_module(void)
|
|||||||
end:
|
end:
|
||||||
ao2_cleanup(pjsip_uids_onhold);
|
ao2_cleanup(pjsip_uids_onhold);
|
||||||
pjsip_uids_onhold = NULL;
|
pjsip_uids_onhold = NULL;
|
||||||
|
ast_custom_function_unregister(&dtmf_mode_function);
|
||||||
ast_custom_function_unregister(&media_offer_function);
|
ast_custom_function_unregister(&media_offer_function);
|
||||||
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
|
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
|
||||||
ast_custom_function_unregister(&session_refresh_function);
|
ast_custom_function_unregister(&session_refresh_function);
|
||||||
@@ -2758,6 +2770,7 @@ static int unload_module(void)
|
|||||||
ast_sip_session_unregister_supplement(&chan_pjsip_ack_supplement);
|
ast_sip_session_unregister_supplement(&chan_pjsip_ack_supplement);
|
||||||
ast_sip_session_unregister_supplement(&call_pickup_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(&media_offer_function);
|
||||||
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
|
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
|
||||||
ast_custom_function_unregister(&session_refresh_function);
|
ast_custom_function_unregister(&session_refresh_function);
|
||||||
|
@@ -68,6 +68,18 @@
|
|||||||
<ref type="function">PJSIP_SEND_SESSION_REFRESH</ref>
|
<ref type="function">PJSIP_SEND_SESSION_REFRESH</ref>
|
||||||
</see-also>
|
</see-also>
|
||||||
</function>
|
</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">
|
<function name="PJSIP_SEND_SESSION_REFRESH" language="en_US">
|
||||||
<synopsis>
|
<synopsis>
|
||||||
W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session
|
W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session
|
||||||
@@ -440,6 +452,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#include "asterisk/app.h"
|
#include "asterisk/app.h"
|
||||||
#include "asterisk/channel.h"
|
#include "asterisk/channel.h"
|
||||||
#include "asterisk/format.h"
|
#include "asterisk/format.h"
|
||||||
|
#include "asterisk/dsp.h"
|
||||||
#include "asterisk/pbx.h"
|
#include "asterisk/pbx.h"
|
||||||
#include "asterisk/res_pjsip.h"
|
#include "asterisk/res_pjsip.h"
|
||||||
#include "asterisk/res_pjsip_session.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);
|
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 refresh_data {
|
||||||
struct ast_sip_session *session;
|
struct ast_sip_session *session;
|
||||||
enum ast_sip_session_refresh_method method;
|
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;
|
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)
|
static int refresh_write_cb(void *obj)
|
||||||
{
|
{
|
||||||
struct refresh_data *data = obj;
|
struct refresh_data *data = obj;
|
||||||
|
@@ -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);
|
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
|
* \brief PJSIP_MEDIA_OFFER function read callback
|
||||||
* \param chan The channel the function is called on
|
* \param chan The channel the function is called on
|
||||||
|
@@ -2906,4 +2906,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,
|
int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,
|
||||||
pjsip_tpselector *selector);
|
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 */
|
#endif /* _RES_PJSIP_H */
|
||||||
|
@@ -157,6 +157,8 @@ struct ast_sip_session {
|
|||||||
unsigned int defer_end:1;
|
unsigned int defer_end:1;
|
||||||
/*! Session end (remote hangup) requested while termination deferred */
|
/*! Session end (remote hangup) requested while termination deferred */
|
||||||
unsigned int ended_while_deferred:1;
|
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);
|
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
|
||||||
|
@@ -4397,6 +4397,56 @@ const char *ast_sip_get_host_ip_string(int af)
|
|||||||
return NULL;
|
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.
|
* \brief Set name and number information on an identity header.
|
||||||
*
|
*
|
||||||
|
@@ -368,47 +368,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)
|
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||||
{
|
{
|
||||||
struct ast_sip_endpoint *endpoint = 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")) {
|
if (dtmf == -1) {
|
||||||
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 {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endpoint->dtmf = dtmf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
|
static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf)
|
||||||
{
|
{
|
||||||
const struct ast_sip_endpoint *endpoint = obj;
|
const struct ast_sip_endpoint *endpoint = obj;
|
||||||
|
char dtmf_str[20];
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
switch (endpoint->dtmf) {
|
result = ast_sip_dtmf_to_str(endpoint->dtmf, dtmf_str, sizeof(dtmf_str));
|
||||||
case AST_SIP_DTMF_RFC_4733 :
|
|
||||||
*buf = "rfc4733"; break;
|
if (result == 0) {
|
||||||
case AST_SIP_DTMF_INBAND :
|
*buf = ast_strdup(dtmf_str);
|
||||||
*buf = "inband"; break;
|
} else {
|
||||||
case AST_SIP_DTMF_INFO :
|
*buf = ast_strdup("none");
|
||||||
*buf = "info"; break;
|
|
||||||
case AST_SIP_DTMF_AUTO :
|
|
||||||
*buf = "auto"; break;
|
|
||||||
case AST_SIP_DTMF_AUTO_INFO :
|
|
||||||
*buf = "auto_info";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*buf = "none";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*buf = ast_strdup(*buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -246,10 +246,10 @@ 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 || 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_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->dtmf == AST_SIP_DTMF_INBAND) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,11 +332,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);
|
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) {
|
if (tel_event) {
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
@@ -440,7 +440,7 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi
|
|||||||
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) || (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)
|
&& (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);
|
||||||
@@ -1160,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 || 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 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);
|
||||||
|
@@ -1481,6 +1481,8 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
|
|||||||
session->contact = ao2_bump(contact);
|
session->contact = ao2_bump(contact);
|
||||||
session->inv_session = inv_session;
|
session->inv_session = inv_session;
|
||||||
|
|
||||||
|
session->dtmf = endpoint->dtmf;
|
||||||
|
|
||||||
if (add_supplements(session)) {
|
if (add_supplements(session)) {
|
||||||
/* Release the ref held by session->inv_session */
|
/* Release the ref held by session->inv_session */
|
||||||
ao2_ref(session, -1);
|
ao2_ref(session, -1);
|
||||||
|
Reference in New Issue
Block a user