<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/6119">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_sip: Add dialplan function SIP_HEADERS<br><br>Syntax: SIP_HEADERS([prefix])<br><br>If the argument is specified, only the headers matching the given prefix<br>are returned.<br><br>The function returns a comma-separated list of SIP header names from an<br>incoming INVITE message. Multiple headers with the same name are included<br>in the list only once. The returned list can be iterated over using the<br>functions POP() and SIP_HEADER().<br><br>For example, '${SIP_HEADERS(Co)}' might return the string<br>'Contact,Content-Length,Content-Type'.<br><br>Practical use is rather '${SIP_HEADERS(X-)}' to enumerate optional<br>extended headers sent by a peer.<br><br>ASTERISK-27163<br><br>Change-Id: I2076d3893d03a2f82429f393b5b46db6cf68a267<br>---<br>M CHANGES<br>M channels/chan_sip.c<br>2 files changed, 129 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index 71166ef..4f5225a 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -9,6 +9,14 @@<br> ==============================================================================<br> <br> ------------------------------------------------------------------------------<br>+--- Functionality changes from Asterisk 15 to Asterisk 16 --------------------<br>+------------------------------------------------------------------------------<br>+<br>+chan_sip<br>+------------------<br>+ * New function SIP_HEADERS() enumerates all headers in the incoming INVITE.<br>+<br>+------------------------------------------------------------------------------<br> --- Functionality changes from Asterisk 14 to Asterisk 15 --------------------<br> ------------------------------------------------------------------------------<br> <br>@@ -1539,7 +1547,7 @@<br> ------------------<br> * New CLI commands have been added: "pjsip show identif(y|ies)", which lists<br> all configured PJSIP identify objects<br>- <br>+<br> ------------------------------------------------------------------------------<br> --- Functionality changes from Asterisk 12 to Asterisk 13 --------------------<br> ------------------------------------------------------------------------------<br>diff --git a/channels/chan_sip.c b/channels/chan_sip.c<br>index beaa3de..941a1e9 100644<br>--- a/channels/chan_sip.c<br>+++ b/channels/chan_sip.c<br>@@ -380,6 +380,37 @@<br> <para>Please observe that contents of the SDP (an attachment to the<br> SIP request) can't be accessed with this function.</para><br> </description><br>+ <see-also><br>+ <ref type="function">SIP_HEADERS</ref><br>+ </see-also><br>+ </function><br>+ <function name="SIP_HEADERS" language="en_US"><br>+ <synopsis><br>+ Gets the list of SIP header names from an incoming INVITE message.<br>+ </synopsis><br>+ <syntax><br>+ <parameter name="prefix"><br>+ <para>If specified, only the headers matching the given prefix are returned.</para><br>+ </parameter><br>+ </syntax><br>+ <description><br>+ <para>Returns a comma-separated list of header names (without values) from the<br>+ INVITE message that originated the current channel. Multiple headers with the<br>+ same name are included in the list only once. The returned list can be iterated<br>+ over using the functions POP() and SIP_HEADER().</para><br>+ <para>For example, <literal>${SIP_HEADERS(Co)}</literal> might return<br>+ <literal>Contact,Content-Length,Content-Type</literal>. As a practical example,<br>+ you may use <literal>${SIP_HEADERS(X-)}</literal> to enumerate optional extended<br>+ headers.</para><br>+ <para>This function does not access headers from the incoming SIP REFER message;<br>+ see the documentation of the function SIP_HEADER for how to access them.</para><br>+ <para>Please observe that contents of the SDP (an attachment to the<br>+ SIP request) can't be accessed with this function.</para><br>+ </description><br>+ <see-also><br>+ <ref type="function">SIP_HEADER</ref><br>+ <ref type="function">POP</ref><br>+ </see-also><br> </function><br> <function name="SIPPEER" language="en_US"><br> <synopsis><br>@@ -22995,6 +23026,7 @@<br> {<br> struct sip_pvt *p;<br> const char *content = NULL;<br>+ char *mutable_data = ast_strdupa(data);<br> AST_DECLARE_APP_ARGS(args,<br> AST_APP_ARG(header);<br> AST_APP_ARG(number);<br>@@ -23018,7 +23050,7 @@<br> return -1;<br> }<br> <br>- AST_STANDARD_APP_ARGS(args, data);<br>+ AST_STANDARD_APP_ARGS(args, mutable_data);<br> if (!args.number) {<br> number = 1;<br> } else {<br>@@ -23053,6 +23085,91 @@<br> .name = "SIP_HEADER",<br> .read = func_header_read,<br> };<br>+<br>+/*! \brief Read unique list of SIP headers (dialplan function) */<br>+static int func_headers_read2(struct ast_channel *chan, const char *function, char *data, struct ast_str **buf, ssize_t maxlen)<br>+{<br>+ int i;<br>+ struct sip_pvt *pvt;<br>+ char *mutable_data = ast_strdupa(data);<br>+ struct ast_str *token = ast_str_alloca(100);<br>+ AST_DECLARE_APP_ARGS(args,<br>+ AST_APP_ARG(pattern);<br>+ );<br>+<br>+ if (!chan) {<br>+ return -1;<br>+ }<br>+<br>+ ast_channel_lock(chan);<br>+<br>+ if (!IS_SIP_TECH(ast_channel_tech(chan))) {<br>+ ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ pvt = ast_channel_tech_pvt(chan);<br>+ if (!pvt) {<br>+ ast_channel_unlock(chan);<br>+ return -1;<br>+ }<br>+<br>+ AST_STANDARD_APP_ARGS(args, mutable_data);<br>+ if (!args.pattern || strcmp(args.pattern, "*") == 0) {<br>+ args.pattern = "";<br>+ }<br>+<br>+ for (i = 0; i < pvt->initreq.headers; i++) {<br>+ const char *header = REQ_OFFSET_TO_STR(&pvt->initreq, header[i]);<br>+ if (ast_begins_with(header, args.pattern)) {<br>+ int hdrlen = strcspn(header, " \t:,"); /* Comma will break our logic, and illegal per RFC. */<br>+ const char *term = ast_skip_blanks(header + hdrlen);<br>+ if (hdrlen > 0 && *term == ':') { /* Header is malformed otherwise! */<br>+ const char *s = NULL;<br>+<br>+ /* Return short headers in full form always. */<br>+ if (hdrlen == 1) {<br>+ char short_hdr[2] = { header[0], '\0' };<br>+ s = find_full_alias(short_hdr, NULL);<br>+ }<br>+ if (s) {<br>+ /* Short header was found and expanded. */<br>+ ast_str_set(&token, -1, "%s,", s);<br>+ } else {<br>+ /* Return the header as is, whether 1-character or not. */<br>+ ast_str_set(&token, -1, "%.*s,", hdrlen, header);<br>+ }<br>+<br>+ /* Has the same header been already added? */<br>+ s = ast_str_buffer(*buf);<br>+ while ((s = strstr(s, ast_str_buffer(token))) != NULL) {<br>+ /* Found suffix, but is it the full token? */<br>+ if (s == ast_str_buffer(*buf) || s[-1] == ',')<br>+ break;<br>+ /* Only suffix matched, go on with the search after the comma. */<br>+ s += hdrlen + 1;<br>+ }<br>+<br>+ /* s is null iff not broken from the loop, hence header not yet added. */<br>+ if (s == NULL) {<br>+ ast_str_append(buf, maxlen, "%s", ast_str_buffer(token));<br>+ }<br>+ }<br>+ }<br>+ }<br>+<br>+ ast_str_truncate(*buf, -1); /* Trim the last comma. Safe if empty. */<br>+<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+}<br>+<br>+static struct ast_custom_function sip_headers_function = {<br>+ .name = "SIP_HEADERS",<br>+ .read2 = func_headers_read2,<br>+};<br>+<br> <br> /*! \brief Dial plan function to check if domain is local */<br> static int func_check_sipdomain(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)<br>@@ -35201,6 +35318,7 @@<br> <br> /* Register dialplan functions */<br> ast_custom_function_register(&sip_header_function);<br>+ ast_custom_function_register(&sip_headers_function);<br> ast_custom_function_register(&sippeer_function);<br> ast_custom_function_register(&checksipdomain_function);<br> <br>@@ -35301,6 +35419,7 @@<br> <br> /* Unregister dial plan functions */<br> ast_custom_function_unregister(&sippeer_function);<br>+ ast_custom_function_unregister(&sip_headers_function);<br> ast_custom_function_unregister(&sip_header_function);<br> ast_custom_function_unregister(&checksipdomain_function);<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6119">change 6119</a>. To unsubscribe, 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/6119"/><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-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I2076d3893d03a2f82429f393b5b46db6cf68a267 </div>
<div style="display:none"> Gerrit-Change-Number: 6119 </div>
<div style="display:none"> Gerrit-PatchSet: 6 </div>
<div style="display:none"> Gerrit-Owner: Kirill Katsnelson <kkm@smartaction.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kirill Katsnelson <kkm@smartaction.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>