[Asterisk-code-review] channels/chan pjsip: Add PJSIP SEND SESSION REFRESH (asterisk[14])

Matt Jordan asteriskteam at digium.com
Wed Aug 10 11:22:12 CDT 2016


Matt Jordan has uploaded a new change for review.

  https://gerrit.asterisk.org/3451

Change subject: channels/chan_pjsip: Add PJSIP_SEND_SESSION_REFRESH
......................................................................

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
---
M CHANGES
M channels/chan_pjsip.c
M channels/pjsip/dialplan_functions.c
M channels/pjsip/include/dialplan_functions.h
4 files changed, 148 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/51/3451/1

diff --git a/CHANGES b/CHANGES
index d46765c..937b643 100644
--- a/CHANGES
+++ b/CHANGES
@@ -381,11 +381,20 @@
 ------------------
  * Added "mwi_tps_queue_high" and "mwi_tps_queue_low" global configuration
    options to tune taskprocessor alert levels.
+
  * Added "mwi_disable_initial_unsolicited" global configuration option
    to disable sending unsolicited MWI to all endpoints on startup.
    Additional information can be found in the sample configuration file at
    config/samples/pjsip.conf.sample.
 
+chan_pjsip
+------------------
+ * A new dialplan function, PJSIP_SEND_SESSION_REFRESH, has been added. When
+   invoked, a re-INVITE or UPDATE request will be sent immediately to the
+   endpoint underlying the channel. When used in combination with the existing
+   dialplan function PJSIP_MEDIA_OFFER, this allows the formats on a PJSIP
+   channel to be re-negotiated and updated after session set up.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
 ------------------------------------------------------------------------------
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 2e87393..02da0db 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -2433,6 +2433,11 @@
 	.write = pjsip_acf_media_offer_write
 };
 
+static struct ast_custom_function session_refresh_function = {
+	.name = "PJSIP_SEND_SESSION_REFRESH",
+	.write = pjsip_acf_session_refresh_write,
+};
+
 /*!
  * \brief Load the module
  *
@@ -2469,6 +2474,11 @@
 
 	if (ast_custom_function_register(&media_offer_function)) {
 		ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER 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;
 	}
 
@@ -2528,6 +2538,7 @@
 	pjsip_uids_onhold = NULL;
 	ast_custom_function_unregister(&media_offer_function);
 	ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
+	ast_custom_function_unregister(&session_refresh_function);
 	ast_channel_unregister(&chan_pjsip_tech);
 	ast_rtp_glue_unregister(&chan_pjsip_rtp_glue);
 
@@ -2549,6 +2560,7 @@
 
 	ast_custom_function_unregister(&media_offer_function);
 	ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
+	ast_custom_function_unregister(&session_refresh_function);
 
 	ast_channel_unregister(&chan_pjsip_tech);
 	ao2_ref(chan_pjsip_tech.capabilities, -1);
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index 1c08997..c1a3873 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -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 @@
 
 	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);
+}
diff --git a/channels/pjsip/include/dialplan_functions.h b/channels/pjsip/include/dialplan_functions.h
index cbc06f0..8b80bfa 100644
--- a/channels/pjsip/include/dialplan_functions.h
+++ b/channels/pjsip/include/dialplan_functions.h
@@ -61,6 +61,18 @@
 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
  * \param cmd The name of the function

-- 
To view, visit https://gerrit.asterisk.org/3451
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib98fe09ba889aafe26d58d32f0fd1323f8fd9b1b
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-Owner: Matt Jordan <mjordan at digium.com>



More information about the asterisk-code-review mailing list