<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19455">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><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, 122 insertions(+), 67 deletions(-)<br><br></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..3d88c18 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,47 @@</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%);">+enum notify_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ NOTIFY_ENDPOINT,</span><br><span style="color: hsl(120, 100%, 40%);">+      NOTIFY_URI,</span><br><span style="color: hsl(120, 100%, 40%);">+   NOTIFY_CHANNEL,</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%);">+static void manager_send_response(struct mansession *s, const struct message *m, enum notify_type type, enum notify_result res, struct ast_variable *vars, const char *endpoint_name)</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%);">+         if (type == NOTIFY_CHANNEL) {</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, "Channel not found");</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</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%);">+                }</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%);">+                if (type == NOTIFY_ENDPOINT) {</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_va(s, m, "Unable to retrieve endpoint %s", endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</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%);">+                }</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 +1124,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 (!ast_strlen_zero(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 +1146,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, NOTIFY_ENDPOINT, res, vars, endpoint_name);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1119,29 +1162,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 (!ast_strlen_zero(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, NOTIFY_URI, res, vars, NULL);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1151,29 +1192,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, NOTIFY_CHANNEL, res, vars, NULL);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1185,6 +1210,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,7 +1224,11 @@</span><br><span>              ++count;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (1 < count) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((!ast_strlen_zero(option) && !ast_strlen_zero(variables)) || (ast_strlen_zero(option) && ast_strlen_zero(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%);">+  } else 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>                         "You must use only one of them.");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19455">change 19455</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/+/19455"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: Ie4496b322b63b61eaf9672183a959ab99a04b6b5 </div>
<div style="display:none"> Gerrit-Change-Number: 19455 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: N A <asterisk@phreaknet.org> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>