[Asterisk-code-review] pjsip: New function PJSIP PARSE URI to parse URI and return ... (asterisk[16])

Alexei Gradinari asteriskteam at digium.com
Tue Nov 13 09:33:47 CST 2018


Alexei Gradinari has uploaded this change for review. ( https://gerrit.asterisk.org/10633


Change subject: pjsip: New function PJSIP_PARSE_URI to parse URI and return part of URI
......................................................................

pjsip: New function PJSIP_PARSE_URI to parse URI and return part of URI

New dialplan function PJSIP_PARSE_URI added to parse an URI and return
a specified part of the URI.

This is useful when need to get part of the URI instead of cutting it
using a CUT function.

For example to get 'user' part of Remote URI
${PJSIP_PARSE_URI(${CHANNEL(pjsip,remote_uri)},user)}

ASTERISK-28144 #close

Change-Id: I5d828fb87f6803b6c1152bb7b44835f027bb9d5a
---
M CHANGES
M channels/chan_pjsip.c
M channels/pjsip/dialplan_functions.c
M channels/pjsip/include/dialplan_functions.h
4 files changed, 206 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/33/10633/1

diff --git a/CHANGES b/CHANGES
index e00c16f..48334fc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,12 @@
 --- Functionality changes from Asterisk 16.0.0 to Asterisk 16.1.0 ------------
 ------------------------------------------------------------------------------
 
+chan_pjsip
+------------------
+ * New dialplan function PJSIP_PARSE_URI added to parse an URI and return
+   a specified part of the URI.
+
+
 res_pjsip
 ------------------
  * New options 'trust_connected_line' and 'send_connected_line' have been
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 8e4e40c..792b3fc 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -3052,6 +3052,11 @@
 	.read = pjsip_acf_dial_contacts_read,
 };
 
+static struct ast_custom_function chan_pjsip_parse_uri_function = {
+	.name = "PJSIP_PARSE_URI",
+	.read = pjsip_acf_parse_uri_read,
+};
+
 static struct ast_custom_function media_offer_function = {
 	.name = "PJSIP_MEDIA_OFFER",
 	.read = pjsip_acf_media_offer_read,
@@ -3101,6 +3106,11 @@
 		goto end;
 	}
 
+	if (ast_custom_function_register(&chan_pjsip_parse_uri_function)) {
+		ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI dialplan function\n");
+		goto end;
+	}
+
 	if (ast_custom_function_register(&media_offer_function)) {
 		ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");
 		goto end;
@@ -3155,6 +3165,7 @@
 	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(&chan_pjsip_parse_uri_function);
 	ast_custom_function_unregister(&session_refresh_function);
 	ast_channel_unregister(&chan_pjsip_tech);
 	ast_rtp_glue_unregister(&chan_pjsip_rtp_glue);
@@ -3179,6 +3190,7 @@
 	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(&chan_pjsip_parse_uri_function);
 	ast_custom_function_unregister(&session_refresh_function);
 
 	ast_channel_unregister(&chan_pjsip_tech);
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index d21a80c..70507bb 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -121,6 +121,60 @@
 		<ref type="function">PJSIP_MEDIA_OFFER</ref>
 	</see-also>
 </function>
+<function name="PJSIP_PARSE_URI" language="en_US">
+	<synopsis>
+		Parse an uri and return a type part of the URI.
+	</synopsis>
+	<syntax>
+		<parameter name="uri" required="true">
+			<para>URI to parse</para>
+		</parameter>
+		<parameter name="type" required="true">
+			<para>The <literal>type</literal> parameter specifies which URI part to read</para>
+			<enumlist>
+				<enum name="display">
+					<para>Display name.</para>
+				</enum>
+				<enum name="scheme">
+					<para>URI scheme.</para>
+				</enum>
+				<enum name="user">
+					<para>User part.</para>
+				</enum>
+				<enum name="passwd">
+					<para>Password part.</para>
+				</enum>
+				<enum name="host">
+					<para>Host part.</para>
+				</enum>
+				<enum name="port">
+					<para>Port number, or zero.</para>
+				</enum>
+				<enum name="user_param">
+					<para>User parameter.</para>
+				</enum>
+				<enum name="method_param">
+					<para>Method parameter.</para>
+				</enum>
+				<enum name="transport_param">
+					<para>Transport parameter.</para>
+				</enum>
+				<enum name="ttl_param">
+					<para>TTL param, or -1.</para>
+				</enum>
+				<enum name="lr_param">
+					<para>Loose routing param, or zero.</para>
+				</enum>
+				<enum name="maddr_param">
+					<para>Maddr param.</para>
+				</enum>
+			</enumlist>
+		</parameter>
+	</syntax>
+	<description>
+		<para>Parse an URI and return a specified part of the URI.</para>
+	</description>
+</function>
 <info name="CHANNEL" language="en_US" tech="PJSIP">
 	<enumlist>
 		<enum name="rtp">
@@ -1041,6 +1095,127 @@
 	return state;
 }
 
+/*! \brief Struct used to push PJSIP_PARSE_URI function arguments to task processor */
+struct parse_uri_args {
+	const char *uri;
+	const char *type;
+	char *buf;
+	size_t buflen;
+	int ret;
+};
+
+/*! \internal \brief Taskprocessor callback that handles the PJSIP_PARSE_URI on a PJSIP thread */
+static int parse_uri_cb(void *data)
+{
+	struct parse_uri_args *args = data;
+	pj_pool_t *pool;
+	pjsip_name_addr *uri;
+	pjsip_sip_uri *sip_uri;
+	pj_str_t tmp;
+
+	args->ret = 0;
+
+	pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "ParseUri", 128, 128);
+	if (!pool) {
+		ast_log(LOG_ERROR, "Failed to allocate ParseUri endpoint pool.\n");
+		args->ret = -1;
+		return 0;
+	}
+
+	pj_strdup2_with_null(pool, &tmp, args->uri);
+	uri = (pjsip_name_addr *)pjsip_parse_uri(pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
+	if (!uri) {
+		ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", args->uri);
+		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+		args->ret = -1;
+		return 0;
+	}
+
+	if (!strcmp(args->type, "scheme")) {
+		ast_copy_pj_str(args->buf, pjsip_uri_get_scheme(uri), args->buflen);
+		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+		return 0;
+	} else if (!strcmp(args->type, "display")) {
+		ast_copy_pj_str(args->buf, &uri->display, args->buflen);
+		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+		return 0;
+	}
+
+	sip_uri = pjsip_uri_get_uri(uri);
+	if (!sip_uri) {
+		ast_log(LOG_ERROR, "Failed to get an URI object for '%s'\n", args->uri);
+		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+		args->ret = -1;
+		return 0;
+	}
+
+	if (!strcmp(args->type, "user")) {
+		ast_copy_pj_str(args->buf, &sip_uri->user, args->buflen);
+	} else if (!strcmp(args->type, "passwd")) {
+		ast_copy_pj_str(args->buf, &sip_uri->passwd, args->buflen);
+	} else if (!strcmp(args->type, "host")) {
+		ast_copy_pj_str(args->buf, &sip_uri->host, args->buflen);
+	} else if (!strcmp(args->type, "port")) {
+		snprintf(args->buf, args->buflen, "%d", sip_uri->port);
+	} else if (!strcmp(args->type, "user_param")) {
+		ast_copy_pj_str(args->buf, &sip_uri->user_param, args->buflen);
+	} else if (!strcmp(args->type, "method_param")) {
+		ast_copy_pj_str(args->buf, &sip_uri->method_param, args->buflen);
+	} else if (!strcmp(args->type, "transport_param")) {
+		ast_copy_pj_str(args->buf, &sip_uri->transport_param, args->buflen);
+	} else if (!strcmp(args->type, "ttl_param")) {
+		snprintf(args->buf, args->buflen, "%d", sip_uri->ttl_param);
+	} else if (!strcmp(args->type, "lr_param")) {
+		snprintf(args->buf, args->buflen, "%d", sip_uri->lr_param);
+	} else if (!strcmp(args->type, "maddr_param")) {
+		ast_copy_pj_str(args->buf, &sip_uri->maddr_param, args->buflen);
+	} else {
+		ast_log(AST_LOG_WARNING, "Unknown type part '%s' specified\n", args->type);
+		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+		args->ret = -1;
+		return 0;
+	}
+
+	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+
+	return 0;
+}
+
+int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
+{
+	struct parse_uri_args func_args = { 0, };
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(uri_str);
+		AST_APP_ARG(type);
+	);
+
+	AST_STANDARD_APP_ARGS(args, data);
+
+	if (ast_strlen_zero(args.uri_str)) {
+		ast_log(LOG_WARNING, "An URI must be specified when using the '%s' dialplan function\n", cmd);
+		return -1;
+	}
+
+	if (ast_strlen_zero(args.type)) {
+		ast_log(LOG_WARNING, "A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
+		return -1;
+	}
+
+	memset(buf, 0, buflen);
+
+	func_args.uri = args.uri_str;
+	func_args.type = args.type;
+	func_args.buf = buf;
+	func_args.buflen = buflen;
+	if (ast_sip_push_task_wait_serializer(NULL, parse_uri_cb, &func_args)) {
+		ast_log(LOG_WARNING, "Unable to parse URI: failed to push task\n");
+		return -1;
+	}
+
+	return func_args.ret;
+}
+
 static int media_offer_read_av(struct ast_sip_session *session, char *buf,
 			       size_t len, enum ast_media_type media_type)
 {
diff --git a/channels/pjsip/include/dialplan_functions.h b/channels/pjsip/include/dialplan_functions.h
index 731e91d..a9332a2 100644
--- a/channels/pjsip/include/dialplan_functions.h
+++ b/channels/pjsip/include/dialplan_functions.h
@@ -110,4 +110,17 @@
  */
 int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
 
+/*!
+ * \brief PJSIP_PARSE_URI 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_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

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

Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5d828fb87f6803b6c1152bb7b44835f027bb9d5a
Gerrit-Change-Number: 10633
Gerrit-PatchSet: 1
Gerrit-Owner: Alexei Gradinari <alex2grad at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181113/8d5d56b9/attachment-0001.html>


More information about the asterisk-code-review mailing list