[Asterisk-code-review] channel/chan_pjsip: add dialplan function for music on hold (...asterisk[13])

Torrey Searle asteriskteam at digium.com
Thu Sep 19 03:58:37 CDT 2019


Torrey Searle has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/12893


Change subject: channel/chan_pjsip: add dialplan function for music on hold
......................................................................

channel/chan_pjsip: add dialplan function for music on hold

Add a new dialplan function PJSIP_MOH_PASSTHROUGH that allows
the on-hold behavior to be controlled on a per-call basis

ASTERISK-28542 #close

Change-Id: Iebe905b2ad6dbaa87ab330267147180b05a3c3a8
---
M channels/chan_pjsip.c
M channels/pjsip/dialplan_functions.c
M channels/pjsip/include/dialplan_functions.h
M include/asterisk/res_pjsip_session.h
M res/res_pjsip_session.c
5 files changed, 112 insertions(+), 3 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/93/12893/1

diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 2a243b6..57ff53a 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -1526,7 +1526,7 @@
 		device_buf = alloca(device_buf_size);
 		ast_channel_get_device_name(ast, device_buf, device_buf_size);
 		ast_devstate_changed_literal(AST_DEVICE_ONHOLD, 1, device_buf);
-		if (!channel->session->endpoint->moh_passthrough) {
+		if (!channel->session->moh_passthrough) {
 			ast_moh_start(ast, data, NULL);
 		} else {
 			if (ast_sip_push_task(channel->session->serializer, remote_send_hold, ao2_bump(channel->session))) {
@@ -1542,7 +1542,7 @@
 		device_buf = alloca(device_buf_size);
 		ast_channel_get_device_name(ast, device_buf, device_buf_size);
 		ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, 1, device_buf);
-		if (!channel->session->endpoint->moh_passthrough) {
+		if (!channel->session->moh_passthrough) {
 			ast_moh_stop(ast);
 		} else {
 			if (ast_sip_push_task(channel->session->serializer, remote_send_unhold, ao2_bump(channel->session))) {
@@ -2859,6 +2859,12 @@
 	.write = pjsip_acf_dtmf_mode_write
 };
 
+static struct ast_custom_function moh_passthrough_function = {
+	.name = "PJSIP_MOH_PASSTHROUGH",
+	.read = pjsip_acf_moh_passthrough_read,
+	.write = pjsip_acf_moh_passthrough_write
+};
+
 static struct ast_custom_function session_refresh_function = {
 	.name = "PJSIP_SEND_SESSION_REFRESH",
 	.write = pjsip_acf_session_refresh_write,
@@ -2913,6 +2919,11 @@
 		goto end;
 	}
 
+	if (ast_custom_function_register(&moh_passthrough_function)) {
+		ast_log(LOG_WARNING, "Unable to register PJSIP_MOH_PASSTHROUGH 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;
@@ -2973,6 +2984,7 @@
 	ast_sip_session_unregister_supplement(&chan_pjsip_supplement);
 	ast_sip_session_unregister_supplement(&call_pickup_supplement);
 	ast_custom_function_unregister(&dtmf_mode_function);
+	ast_custom_function_unregister(&moh_passthrough_function);
 	ast_custom_function_unregister(&media_offer_function);
 	ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
 	ast_custom_function_unregister(&chan_pjsip_parse_uri_function);
@@ -2998,6 +3010,7 @@
 	ast_sip_session_unregister_supplement(&call_pickup_supplement);
 
 	ast_custom_function_unregister(&dtmf_mode_function);
+	ast_custom_function_unregister(&moh_passthrough_function);
 	ast_custom_function_unregister(&media_offer_function);
 	ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
 	ast_custom_function_unregister(&chan_pjsip_parse_uri_function);
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index 6cdc721..445588a 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -80,6 +80,19 @@
 		<para>This function uses the same DTMF mode naming as the dtmf_mode configuration option</para>
 	</description>
 </function>
+<function name="PJSIP_MOH_PASSTHROUGH" language="en_US">
+	<synopsis>
+		Get or change the on hold behavior for a SIP call.
+	</synopsis>
+	<syntax>
+	</syntax>
+	<description>
+		<para>When read, returns the current moh passthrough mode</para>
+		<para>When written, sets the current moh passthrough mode</para>
+		<para>If Yes On-Hold Re-Invites are sent If No, music on hold is generated.</para>
+		<para>This function can be used to overried the moh_passthrough 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
@@ -1303,6 +1316,37 @@
 	return 0;
 }
 
+int pjsip_acf_moh_passthrough_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 (len < 3) {
+		ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
+		ast_channel_unlock(chan);
+		return -1;
+	}
+
+	channel = ast_channel_tech_pvt(chan);
+	strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
+
+	ast_channel_unlock(chan);
+	return 0;
+}
+
 struct refresh_data {
 	struct ast_sip_session *session;
 	enum ast_sip_session_refresh_method method;
@@ -1445,6 +1489,30 @@
 	return ast_sip_push_task_wait_serializer(channel->session->serializer, dtmf_mode_refresh_cb, &rdata);
 }
 
+int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+	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);
+	channel->session->moh_passthrough = ast_true(value);
+
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
 static int refresh_write_cb(void *obj)
 {
 	struct refresh_data *data = obj;
diff --git a/channels/pjsip/include/dialplan_functions.h b/channels/pjsip/include/dialplan_functions.h
index a9332a2..370f6e3 100644
--- a/channels/pjsip/include/dialplan_functions.h
+++ b/channels/pjsip/include/dialplan_functions.h
@@ -73,6 +73,31 @@
 int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
 
 /*!
+ * \brief PJSIP_MOH_PASSTHROUGH 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_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
+
+/*!
+ * \brief PJSIP_MOH_PASSTHROUGH 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_moh_passthrough_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
  * \param cmd The name of the function
@@ -123,4 +148,4 @@
  */
 int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
 
-#endif /* _PJSIP_DIALPLAN_FUNCTIONS */
\ No newline at end of file
+#endif /* _PJSIP_DIALPLAN_FUNCTIONS */
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 51d75c6..9ae1883 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -161,6 +161,8 @@
 	unsigned int defer_end:1;
 	/*! Session end (remote hangup) requested while termination deferred */
 	unsigned int ended_while_deferred:1;
+	/*! Whether to pass through hold and unhold using re-invites with recvonly and sendrecv */
+	unsigned int moh_passthrough:1;
 	/*! DTMF mode to use with this session, from endpoint but can change */
 	enum ast_sip_dtmf_mode dtmf;
 	/*! Initial incoming INVITE Request-URI.  NULL otherwise. */
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 0cc514a..81f36a7 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1484,6 +1484,7 @@
 	session->inv_session = inv_session;
 
 	session->dtmf = endpoint->dtmf;
+	session->moh_passthrough = endpoint->moh_passthrough;
 
 	if (ast_sip_session_add_supplements(session)) {
 		/* Release the ref held by session->inv_session */

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/12893
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Change-Id: Iebe905b2ad6dbaa87ab330267147180b05a3c3a8
Gerrit-Change-Number: 12893
Gerrit-PatchSet: 1
Gerrit-Owner: Torrey Searle <tsearle at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20190919/ecb5b491/attachment-0001.html>


More information about the asterisk-code-review mailing list