<p>Kirill Katsnelson has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6119">View Change</a></p><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_HEADER(Co)}' might return the string<br>'Contact,Content-Length,Content-Type'.<br><br>Practical use is rather '${SIP_HEADER(X-)}' to enumerate optional<br>extended headers sent by a peer.<br><br>ASTERISK-27163<br><br>Change-Id: I2076d3893d03a2f82429f393b5b46db6cf68a267<br>---<br>M channels/chan_sip.c<br>1 file changed, 109 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/19/6119/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/channels/chan_sip.c b/channels/chan_sip.c<br>index f2daf2b..4d6d1a3 100644<br>--- a/channels/chan_sip.c<br>+++ b/channels/chan_sip.c<br>@@ -381,6 +381,32 @@<br> SIP request) can't be accessed with this function.</para><br> </description><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_HEADER(Co)}</literal> might return<br>+ <literal>Contact,Content-Length,Content-Type</literal>. As a practical example,<br>+ you may use <literal>${SIP_HEADER(X-)}</literal> to enumerate optional extended<br>+ headers.</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> Gets SIP peer information.<br>@@ -23054,6 +23080,87 @@<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>+ AST_DECLARE_APP_ARGS(args,<br>+ AST_APP_ARG(pattern);<br>+ );<br>+<br>+ SCOPED_CHANNELLOCK(chanlock, chan);<br>+<br>+ if (!chan) {<br>+ return -1;<br>+ }<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>+ return -1;<br>+ }<br>+<br>+ pvt = ast_channel_tech_pvt(chan);<br>+ if (!pvt) {<br>+ return -1;<br>+ }<br>+<br>+ AST_STANDARD_APP_ARGS(args, data);<br>+ if (!args.pattern) {<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>+ struct ast_str *token = ast_str_alloca(100);<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>+ 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> {<br>@@ -35201,6 +35308,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 +35409,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: newchange </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: 1 </div>
<div style="display:none"> Gerrit-Owner: Kirill Katsnelson <kkm@smartaction.com> </div>