<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18856">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_header_funcs: Add custom parameter support.<br><br>Adds support for custom URI and header parameters<br>in the From header in PJSIP. Parameters can be<br>both set and read using this function.<br><br>ASTERISK-30150 #close<br><br>Change-Id: Ifb1bc3c512ad5f6faeaebd7817f004a2ecbd6428<br>---<br>A doc/CHANGES-staging/res_pjsip_parameters.txt<br>M res/res_pjsip_header_funcs.c<br>2 files changed, 287 insertions(+), 1 deletion(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/res_pjsip_parameters.txt b/doc/CHANGES-staging/res_pjsip_parameters.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..c95b43d</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_pjsip_parameters.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_pjsip_header_funcs</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The new PJSIP_HEADER_PARAM function now fully supports both</span><br><span style="color: hsl(120, 100%, 40%);">+URI and header parameters. Both reading and writing</span><br><span style="color: hsl(120, 100%, 40%);">+parameters are supported.</span><br><span>diff --git a/res/res_pjsip_header_funcs.c b/res/res_pjsip_header_funcs.c</span><br><span>index cca2b78..8a60e36 100644</span><br><span>--- a/res/res_pjsip_header_funcs.c</span><br><span>+++ b/res/res_pjsip_header_funcs.c</span><br><span>@@ -5,6 +5,7 @@</span><br><span>  *</span><br><span>  * George Joseph <george.joseph@fairview5.com></span><br><span>  * José Lopes <jose.lopes@nfon.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * Naveen Albert <asterisk@phreaknet.org></span><br><span>  *</span><br><span>  * See http://www.asterisk.org for more information about</span><br><span>  * the Asterisk project. Please do not directly contact</span><br><span>@@ -250,7 +251,53 @@</span><br><span>                   <ref type="function">PJSIP_HEADERS</ref></span><br><span>               </see-also></span><br><span>    </function></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+     <function name="PJSIP_HEADER_PARAM" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+               <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Get or set header/URI parameters on a PJSIP channel.</span><br><span style="color: hsl(120, 100%, 40%);">+          </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+             <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+                        <parameter name="header_name" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                              <para>Header in which parameter should be read or set.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                             <para>Currently, the only supported header is <literal>From</literal>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                 </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                    <parameter name="parameter_type" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                           <para>The type of parameter to get or set.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                         <para>Default is header parameter.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                         <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                      <enum name="header"></span><br><span style="color: hsl(120, 100%, 40%);">+                                          <para>Header parameter.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                    </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <enum name="uri"></span><br><span style="color: hsl(120, 100%, 40%);">+                                             <para>URI parameter.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                       </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                         </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                     </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+                    <parameter name="parameter_name" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+                           <para>Name of parameter.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                   </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+            </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+               <description></span><br><span style="color: hsl(120, 100%, 40%);">+                   <para>PJSIP_HEADER_PARAM allows you to read or set parameters in a SIP header on a</span><br><span style="color: hsl(120, 100%, 40%);">+                      PJSIP channel.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                   <para>Both URI parameters and header parameters can be read and set using</span><br><span style="color: hsl(120, 100%, 40%);">+                       this function. URI parameters appear in the URI (inside the &lt;&gt; in the header)</span><br><span style="color: hsl(120, 100%, 40%);">+                   while header parameters appear afterwards.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                       <note><para>If you call PJSIP_HEADER_PARAM in a normal dialplan context you'll be</span><br><span style="color: hsl(120, 100%, 40%);">+                     operating on the <emphasis>caller's (incoming)</emphasis> channel which</span><br><span style="color: hsl(120, 100%, 40%);">+                       may not be what you want. To operate on the <emphasis>callee's (outgoing)</emphasis></span><br><span style="color: hsl(120, 100%, 40%);">+                  channel call PJSIP_HEADER_PARAM in a pre-dial handler. </para></note></span><br><span style="color: hsl(120, 100%, 40%);">+                     <example title="Set URI parameter in From header on outbound channel"></span><br><span style="color: hsl(120, 100%, 40%);">+                        [handler]</span><br><span style="color: hsl(120, 100%, 40%);">+                     exten => addheader,1,Set(PJSIP_HEADER_PARAM(From,uri,isup-oli)=27)</span><br><span style="color: hsl(120, 100%, 40%);">+                 same => n,Return()</span><br><span style="color: hsl(120, 100%, 40%);">+                 [somecontext]</span><br><span style="color: hsl(120, 100%, 40%);">+                 exten => 1,1,Dial(PJSIP/${EXTEN},,b(handler^addheader^1))</span><br><span style="color: hsl(120, 100%, 40%);">+                  </example></span><br><span style="color: hsl(120, 100%, 40%);">+                      <example title="Read URI parameter in From header on inbound channel"></span><br><span style="color: hsl(120, 100%, 40%);">+                        same => n,Set(value=${PJSIP_HEADER_PARAM(From,uri,isup-oli)})</span><br><span style="color: hsl(120, 100%, 40%);">+                      </example></span><br><span style="color: hsl(120, 100%, 40%);">+              </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></span><br><span>  ***/</span><br><span> </span><br><span> /*! \brief Linked list for accumulating headers */</span><br><span>@@ -996,6 +1043,223 @@</span><br><span>        .incoming_response = incoming_response,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+enum param_type {</span><br><span style="color: hsl(120, 100%, 40%);">+  PARAMETER_HEADER,</span><br><span style="color: hsl(120, 100%, 40%);">+     PARAMETER_URI,</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%);">+struct param_data {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_channel_pvt *channel;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *header_name;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *param_name;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *param_value; /* Only used for write */</span><br><span style="color: hsl(120, 100%, 40%);">+    enum param_type paramtype;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* For read function only */</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t len;</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 int read_param(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct param_data *data = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_sip_session *session = data->channel->session;</span><br><span style="color: hsl(120, 100%, 40%);">+       pj_str_t param_name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        pjsip_fromto_hdr *dlg_info;</span><br><span style="color: hsl(120, 100%, 40%);">+   pjsip_name_addr *dlg_info_name_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+  pjsip_sip_uri *dlg_info_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+  pjsip_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   dlg_info = session->inv_session->dlg->remote.info; /* Remote dialog for incoming */</span><br><span style="color: hsl(120, 100%, 40%);">+  dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;</span><br><span style="color: hsl(120, 100%, 40%);">+    dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       pj_cstr(&param_name, data->param_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (data->paramtype == PARAMETER_URI) { /* URI parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+                param = pjsip_param_find(&dlg_info_uri->other_param, &param_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { /* Header parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+               param = pjsip_param_find(&dlg_info->other_param, &param_name);</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 (!param) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_debug(1, "No %s parameter found named %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                    data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</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%);">+   param_len = pj_strlen(&param->value);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (param_len >= data->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Buffer is too small for parameter value (%zu > %zu)\n", param_len, data->len);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</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%);">+   ast_debug(2, "Successfully read %s parameter %s (length %zu)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_copy_string(data->buf, pj_strbuf(&param->value), data->len);</span><br><span style="color: hsl(120, 100%, 40%);">+ data->buf[pj_strlen(&param->value)] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</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 style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Implements PJSIP_HEADER_PARAM 'add' by adding the specified parameter.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note Unlike add_header, we can't add parameters in the outgoing_request callback: that's too late.</span><br><span style="color: hsl(120, 100%, 40%);">+ *       That's why we do it here and not in a callback.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int add_param(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct param_data *data = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_sip_session *session = data->channel->session;</span><br><span style="color: hsl(120, 100%, 40%);">+       pj_pool_t *pool = session->inv_session->dlg->pool;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_fromto_hdr *dlg_info;</span><br><span style="color: hsl(120, 100%, 40%);">+   pjsip_name_addr *dlg_info_name_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+  pjsip_sip_uri *dlg_info_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        dlg_info = session->inv_session->dlg->local.info; /* Local for outgoing */</span><br><span style="color: hsl(120, 100%, 40%);">+   dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;</span><br><span style="color: hsl(120, 100%, 40%);">+    dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!PJSIP_URI_SCHEME_IS_SIP(dlg_info_uri) && !PJSIP_URI_SCHEME_IS_SIPS(dlg_info_uri)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Non SIP/SIPS URI\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return -1;</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%);">+   ast_debug(1, "Adding custom %s param %s = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, data->param_value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* This works the same as doing this in set_from_header in res_pjsip_session.c</span><br><span style="color: hsl(120, 100%, 40%);">+         * The way that this maps to pjproject is a little confusing.</span><br><span style="color: hsl(120, 100%, 40%);">+  * Say we have <sip:foo@bar.com;p1=abc;p2=def?h1=qrs&h2=tuv>;o1=foo;o2=bar</span><br><span style="color: hsl(120, 100%, 40%);">+   * p1 and p2 are URI parameters.</span><br><span style="color: hsl(120, 100%, 40%);">+       * (h1 and h2 are URI headers)</span><br><span style="color: hsl(120, 100%, 40%);">+         * o1 and o2 are header parameters (and don't have anything to do with the URI)</span><br><span style="color: hsl(120, 100%, 40%);">+    * In pjproject, other_param is used for adding all custom parameters.</span><br><span style="color: hsl(120, 100%, 40%);">+         * We use the URI for URI stuff, including URI parameters, and the header directly for header parameters.</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%);">+#define param_add(pool, list, pname, pvalue) { \</span><br><span style="color: hsl(120, 100%, 40%);">+       pjsip_param *param; \</span><br><span style="color: hsl(120, 100%, 40%);">+ param = PJ_POOL_ALLOC_T(pool, pjsip_param); \</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_strdup2(pool, &param->name, pname); \</span><br><span style="color: hsl(120, 100%, 40%);">+       pj_strdup2(pool, &param->value, pvalue); \</span><br><span style="color: hsl(120, 100%, 40%);">+     pj_list_insert_before(list, param); \</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 (data->paramtype == PARAMETER_URI) { /* URI parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+                param_add(pool, &dlg_info_uri->other_param, data->param_name, S_OR(data->param_value, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+    } else { /* Header parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+               param_add(pool, &dlg_info->other_param, data->param_name, S_OR(data->param_value, ""));</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%);">+   return 0;</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 int func_read_param(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct param_data param_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_APP_ARG(header_name);</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_APP_ARG(param_type);</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_APP_ARG(param_name);</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%);">+  AST_STANDARD_APP_ARGS(args, data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  param_data.channel = channel;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(args.param_type)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(args.param_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</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%);">+   /* Currently, only From is supported, but this could be extended in the future. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "Only the From header is currently supported\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</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%);">+   param_data.param_name = args.param_name;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!strcasecmp(args.param_type, "header")) {</span><br><span style="color: hsl(120, 100%, 40%);">+               param_data.paramtype = PARAMETER_HEADER;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else if (!strcasecmp(args.param_type, "uri")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           param_data.paramtype = PARAMETER_URI;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</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%);">+   param_data.buf = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ param_data.len = len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return ast_sip_push_task_wait_serializer(channel->session->serializer, read_param, &param_data);</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 int func_write_param(struct ast_channel *chan, const char *cmd, char *data, const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct param_data param_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_APP_ARG(header_name);</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_APP_ARG(param_type);</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_APP_ARG(param_name);</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%);">+  AST_STANDARD_APP_ARGS(args, data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  param_data.channel = channel;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(args.param_type)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(args.param_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</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%);">+   /* Currently, only From is supported, but this could be extended in the future. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "Only the From header is currently supported\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</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%);">+   param_data.param_name = args.param_name;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!strcasecmp(args.param_type, "header")) {</span><br><span style="color: hsl(120, 100%, 40%);">+               param_data.paramtype = PARAMETER_HEADER;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else if (!strcasecmp(args.param_type, "uri")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           param_data.paramtype = PARAMETER_URI;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     param_data.param_value = value;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return ast_sip_push_task_wait_serializer(channel->session->serializer, add_param, &param_data);</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 struct ast_custom_function pjsip_header_param_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+     .name = "PJSIP_HEADER_PARAM",</span><br><span style="color: hsl(120, 100%, 40%);">+       .read = func_read_param,</span><br><span style="color: hsl(120, 100%, 40%);">+      .write = func_write_param,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int load_module(void)</span><br><span> {</span><br><span>        ast_sip_session_register_supplement(&header_funcs_supplement);</span><br><span>@@ -1003,6 +1267,7 @@</span><br><span>   ast_custom_function_register(&pjsip_headers_function);</span><br><span>   ast_custom_function_register(&pjsip_response_header_function);</span><br><span>   ast_custom_function_register(&pjsip_response_headers_function);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_custom_function_register(&pjsip_header_param_function);</span><br><span> </span><br><span>  return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span>@@ -1013,6 +1278,7 @@</span><br><span>         ast_custom_function_unregister(&pjsip_headers_function);</span><br><span>         ast_custom_function_unregister(&pjsip_response_header_function);</span><br><span>         ast_custom_function_unregister(&pjsip_response_headers_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_custom_function_unregister(&pjsip_header_param_function);</span><br><span>    ast_sip_session_unregister_supplement(&header_funcs_supplement);</span><br><span>         return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18856">change 18856</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/+/18856"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 20 </div>
<div style="display:none"> Gerrit-Change-Id: Ifb1bc3c512ad5f6faeaebd7817f004a2ecbd6428 </div>
<div style="display:none"> Gerrit-Change-Number: 18856 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: N A <asterisk@phreaknet.org> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </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-Reviewer: Sean Bright <sean@seanbright.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>