<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19415">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip_notify: Add option support for AMI.<br><br>The PJSIP notify CLI commands allow for using<br>"options" configured in pjsip_notify.conf.<br><br>This allows these same options to be used in<br>AMI actions as well.<br><br>Additionally, as part of this improvement,<br>some repetitive common code is refactored.<br><br>ASTERISK-30263 #close<br><br>Change-Id: Ie4496b322b63b61eaf9672183a959ab99a04b6b5<br>---<br>A doc/CHANGES-staging/res_pjsip_notify_options.txt<br>M res/res_pjsip_notify.c<br>2 files changed, 107 insertions(+), 66 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/15/19415/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/res_pjsip_notify_options.txt b/doc/CHANGES-staging/res_pjsip_notify_options.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..0a500f6</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_pjsip_notify_options.txt</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_pjsip_notify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Allows using the config options in pjsip_notify.conf</span><br><span style="color: hsl(120, 100%, 40%);">+from AMI actions as with the existing CLI commands.</span><br><span>diff --git a/res/res_pjsip_notify.c b/res/res_pjsip_notify.c</span><br><span>index 3ae9f62..e9a3e16 100644</span><br><span>--- a/res/res_pjsip_notify.c</span><br><span>+++ b/res/res_pjsip_notify.c</span><br><span>@@ -52,11 +52,16 @@</span><br><span> <parameter name="channel" required="false"></span><br><span> <para>Channel name to send the NOTIFY. Must be a PJSIP channel.</para></span><br><span> </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Variable" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="Option" required="false"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The config section name from <literal>pjsip_notify.conf</literal> to use.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>One of Option or Variable must be specified.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="Variable" required="false"></span><br><span> <para>Appends variables as headers/content to the NOTIFY. If the variable is</span><br><span> named <literal>Content</literal>, then the value will compose the body</span><br><span> of the message if another variable sets <literal>Content-Type</literal>.</span><br><span> <replaceable>name</replaceable>=<replaceable>value</replaceable></para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>One of Option or Variable must be specified.</para></span><br><span> </parameter></span><br><span> </syntax></span><br><span> <description></span><br><span>@@ -1071,6 +1076,31 @@</span><br><span> AST_CLI_DEFINE(cli_notify, "Send a NOTIFY request to a SIP endpoint")</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void manager_send_response(struct mansession *s, const struct message *m, enum notify_result res, struct ast_variable *vars)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case INVALID_CHANNEL:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Shouldn't be possible. */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case INVALID_ENDPOINT:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Shouldn't be possible. */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case ALLOC_ERROR:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "Unable to allocate NOTIFY task data");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TASK_PUSH_ERROR:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Don't need to destroy vars since it is handled by cleanup in push_notify, push_notify_uri, etc. */</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "Unable to push Notify task");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case SUCCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_ack(s, m, "NOTIFY sent");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span> * \internal</span><br><span> * \brief Completes SIPNotify AMI command in Endpoint mode.</span><br><span>@@ -1078,7 +1108,19 @@</span><br><span> static void manager_notify_endpoint(struct mansession *s,</span><br><span> const struct message *m, const char *endpoint_name)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct notify_cfg *, cfg, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct notify_option *, option, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *vars = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum notify_result res;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *option_name = astman_get_header(m, "Option");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (option_name && (cfg = ao2_global_obj_ref(globals)) && !(option = notify_option_find(cfg->notify_options, option_name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error_va(s, m, "Unable to find notify type '%s'\n", option_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!option) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (!strncasecmp(endpoint_name, "sip/", 4)) {</span><br><span> endpoint_name += 4;</span><br><span>@@ -1088,28 +1130,13 @@</span><br><span> endpoint_name += 6;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (push_notify(endpoint_name, vars, notify_ami_data_create)) {</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_CHANNEL:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Shouldn't be possible. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_ENDPOINT:</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(vars);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error_va(s, m, "Unable to retrieve endpoint %s",</span><br><span style="color: hsl(0, 100%, 40%);">- endpoint_name);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case ALLOC_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(vars);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to allocate NOTIFY task data");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case TASK_PUSH_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Don't need to destroy vars since it is handled by cleanup in push_notify */</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to push NOTIFY task");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SUCCESS:</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "NOTIFY sent");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (option) {</span><br><span style="color: hsl(120, 100%, 40%);">+ res = push_notify(endpoint_name, option, notify_cli_data_create); /* The CLI version happens to be suitable for options. */</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ res = push_notify(endpoint_name, vars, notify_ami_data_create);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ manager_send_response(s, m, res, vars);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1119,29 +1146,27 @@</span><br><span> static void manager_notify_uri(struct mansession *s,</span><br><span> const struct message *m, const char *uri)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct notify_cfg *, cfg, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct notify_option *, option, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum notify_result res;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *option_name = astman_get_header(m, "Option");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *vars = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (push_notify_uri(uri, vars, notify_ami_uri_data_create)) {</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_CHANNEL:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Shouldn't be possible. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_ENDPOINT:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Shouldn't be possible. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case ALLOC_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(vars);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to allocate NOTIFY task data");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case TASK_PUSH_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Don't need to destroy vars since it is handled by cleanup in push_notify_uri */</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to push Notify task");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SUCCESS:</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "NOTIFY sent");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (option_name && (cfg = ao2_global_obj_ref(globals)) && !(option = notify_option_find(cfg->notify_options, option_name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error_va(s, m, "Unable to find notify type '%s'\n", option_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!option) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (option) {</span><br><span style="color: hsl(120, 100%, 40%);">+ res = push_notify_uri(uri, option, notify_cli_uri_data_create);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ res = push_notify_uri(uri, vars, notify_ami_uri_data_create);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ manager_send_response(s, m, res, vars);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1151,29 +1176,13 @@</span><br><span> static void manager_notify_channel(struct mansession *s,</span><br><span> const struct message *m, const char *channel)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum notify_result res;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *vars = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (push_notify_channel(channel, vars, notify_ami_channel_data_create)) {</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_CHANNEL:</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(vars);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Channel not found");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case INVALID_ENDPOINT:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Shouldn't be possible. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case ALLOC_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(vars);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to allocate NOTIFY task data");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case TASK_PUSH_ERROR:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Don't need to destroy vars since it is handled by cleanup in push_notify_channel */</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Unable to push Notify task");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SUCCESS:</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "NOTIFY sent");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ vars = astman_get_variables_order(m, ORDER_NATURAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ res = push_notify_channel(channel, vars, notify_ami_channel_data_create);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ manager_send_response(s, m, res, vars);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1185,6 +1194,8 @@</span><br><span> const char *endpoint_name = astman_get_header(m, "Endpoint");</span><br><span> const char *uri = astman_get_header(m, "URI");</span><br><span> const char *channel = astman_get_header(m, "Channel");</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *variables = astman_get_header(m, "Variable");</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *option = astman_get_header(m, "Option");</span><br><span> int count = 0;</span><br><span> </span><br><span> if (!ast_strlen_zero(endpoint_name)) {</span><br><span>@@ -1197,6 +1208,12 @@</span><br><span> ++count;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if ((option && variables) || (!option && !variables)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m,</span><br><span style="color: hsl(120, 100%, 40%);">+ "PJSIPNotify requires either an Option or Variable(s)."</span><br><span style="color: hsl(120, 100%, 40%);">+ "You must use only one of them.");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (1 < count) {</span><br><span> astman_send_error(s, m,</span><br><span> "PJSIPNotify requires either an endpoint name, a SIP URI, or a channel. "</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19415">change 19415</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19415"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ie4496b322b63b61eaf9672183a959ab99a04b6b5 </div>
<div style="display:none"> Gerrit-Change-Number: 19415 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>