mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
channels/chan_pjsip: Add PJSIP_SEND_SESSION_REFRESH
This patch adds a new PJSIP specific dialplan function,
PJSIP_SEND_SESSION_REFRESH. When invoked on a PJSIP channel, the media
session will be refreshed via either an UPDATE or re-INVITE request.
When used in conjunction with the PJSIP_MEDIA_OFFER dialplan function,
the formats in use on a PJSIP channel can be re-negotiated and changed
dynamically after call setup.
ASTERISK-26277 #close
Change-Id: Ib98fe09ba889aafe26d58d32f0fd1323f8fd9b1b
(cherry picked from commit eec60dd773
)
This commit is contained in:
@@ -59,8 +59,55 @@
|
||||
</parameter>
|
||||
</syntax>
|
||||
<description>
|
||||
<para>Returns the codecs offered based upon the media choice</para>
|
||||
<para>When read, returns the codecs offered based upon the media choice.</para>
|
||||
<para>When written, sets the codecs to offer when an outbound dial attempt is made,
|
||||
or when a session refresh is sent using <replaceable>PJSIP_SEND_SESSION_REFRESH</replaceable>.
|
||||
</para>
|
||||
</description>
|
||||
<see-also>
|
||||
<ref type="function">PJSIP_SEND_SESSION_REFRESH</ref>
|
||||
</see-also>
|
||||
</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
|
||||
</synopsis>
|
||||
<syntax>
|
||||
<parameter name="update_type" required="false">
|
||||
<para>The type of update to send. Default is <literal>invite</literal>.</para>
|
||||
<enumlist>
|
||||
<enum name="invite">
|
||||
<para>Send the session refresh as a re-INVITE.</para>
|
||||
</enum>
|
||||
<enum name="update">
|
||||
<para>Send the session refresh as an UPDATE.</para>
|
||||
</enum>
|
||||
</enumlist>
|
||||
</parameter>
|
||||
</syntax>
|
||||
<description>
|
||||
<para>This function will cause the PJSIP stack to immediately refresh
|
||||
the media session for the channel. This will be done using either a
|
||||
re-INVITE (default) or an UPDATE request.
|
||||
</para>
|
||||
<para>This is most useful when combined with the <replaceable>PJSIP_MEDIA_OFFER</replaceable>
|
||||
dialplan function, as it allows the formats in use on a channel to be
|
||||
re-negotiated after call setup.</para>
|
||||
<warning>
|
||||
<para>The formats the endpoint supports are <emphasis>not</emphasis>
|
||||
checked or enforced by this function. Using this function to offer
|
||||
formats not supported by the endpoint <emphasis>may</emphasis> result
|
||||
in a loss of media.</para>
|
||||
</warning>
|
||||
<example title="Re-negotiate format to g722">
|
||||
; Within some existing extension on an answered channel
|
||||
same => n,Set(PJSIP_MEDIA_OFFER(audio)=!all,g722)
|
||||
same => n,Set(PJSIP_SEND_SESSION_REFRESH()=invite)
|
||||
</example>
|
||||
</description>
|
||||
<see-also>
|
||||
<ref type="function">PJSIP_MEDIA_OFFER</ref>
|
||||
</see-also>
|
||||
</function>
|
||||
<info name="PJSIPCHANNEL" language="en_US" tech="PJSIP">
|
||||
<enumlist>
|
||||
@@ -961,3 +1008,70 @@ 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);
|
||||
}
|
||||
|
||||
struct refresh_data {
|
||||
struct ast_sip_session *session;
|
||||
enum ast_sip_session_refresh_method method;
|
||||
};
|
||||
|
||||
static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
|
||||
{
|
||||
struct ast_format *fmt;
|
||||
|
||||
if (!session->channel) {
|
||||
/* Egads! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
fmt = ast_format_cap_get_best_by_type(ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_AUDIO);
|
||||
if (!fmt) {
|
||||
/* No format? That's weird. */
|
||||
return 0;
|
||||
}
|
||||
ast_channel_set_writeformat(session->channel, fmt);
|
||||
ast_channel_set_rawwriteformat(session->channel, fmt);
|
||||
ast_channel_set_readformat(session->channel, fmt);
|
||||
ast_channel_set_rawreadformat(session->channel, fmt);
|
||||
ao2_ref(fmt, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int refresh_write_cb(void *obj)
|
||||
{
|
||||
struct refresh_data *data = obj;
|
||||
|
||||
ast_sip_session_refresh(data->session, NULL, NULL,
|
||||
sip_session_response_cb, data->method, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pjsip_acf_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
|
||||
{
|
||||
struct ast_sip_channel_pvt *channel;
|
||||
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;
|
||||
}
|
||||
|
||||
if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
|
||||
ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
channel = ast_channel_tech_pvt(chan);
|
||||
rdata.session = channel->session;
|
||||
|
||||
if (!strcmp(value, "invite")) {
|
||||
rdata.method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
|
||||
} else if (!strcmp(value, "update")) {
|
||||
rdata.method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
|
||||
}
|
||||
|
||||
return ast_sip_push_task_synchronous(channel->session->serializer, refresh_write_cb, &rdata);
|
||||
}
|
||||
|
@@ -60,6 +60,18 @@ int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char
|
||||
*/
|
||||
int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
|
||||
|
||||
/*!
|
||||
* \brief PJSIP_SEND_SESSION_REFRESH 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_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
|
||||
|
||||
/*!
|
||||
* \brief PJSIP_DIAL_CONTACTS function read callback
|
||||
* \param chan The channel the function is called on
|
||||
|
Reference in New Issue
Block a user