Asterisk - The Open Source Telephony Project  21.4.1
res_pjsip_header_funcs.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Fairview 5 Engineering, LLC
5  *
6  * George Joseph <george.joseph@fairview5.com>
7  * José Lopes <jose.lopes@nfon.com>
8  * Naveen Albert <asterisk@phreaknet.org>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20 
21 /*** MODULEINFO
22  <depend>pjproject</depend>
23  <depend>res_pjsip</depend>
24  <depend>res_pjsip_session</depend>
25  <support_level>core</support_level>
26  ***/
27 
28 #include "asterisk.h"
29 
30 #include <pjsip.h>
31 #include <pjsip_ua.h>
32 
33 #include "asterisk/res_pjsip.h"
34 #include "asterisk/res_pjsip_session.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/app.h"
38 #include "asterisk/module.h"
39 #include "asterisk/utils.h"
40 
41 /*** DOCUMENTATION
42  <function name="PJSIP_HEADER" language="en_US">
43  <synopsis>
44  Gets headers from an inbound PJSIP channel. Adds, updates or removes the
45  specified SIP header from an outbound PJSIP channel.
46  </synopsis>
47  <syntax>
48  <parameter name="action" required="true">
49  <enumlist>
50  <enum name="read"><para>Returns instance <replaceable>number</replaceable>
51  of header <replaceable>name</replaceable>. A <literal>*</literal>
52  may be appended to <replaceable>name</replaceable> to iterate over all
53  headers <emphasis>beginning with</emphasis> <replaceable>name</replaceable>.
54  </para></enum>
55 
56  <enum name="add"><para>Adds a new header <replaceable>name</replaceable>
57  to this session.</para></enum>
58 
59  <enum name="update"><para>Updates instance <replaceable>number</replaceable>
60  of header <replaceable>name</replaceable> to a new value.
61  The header must already exist.</para></enum>
62 
63  <enum name="remove"><para>Removes all instances of previously added headers
64  whose names match <replaceable>name</replaceable>. A <literal>*</literal>
65  may be appended to <replaceable>name</replaceable> to remove all headers
66  <emphasis>beginning with</emphasis> <replaceable>name</replaceable>.
67  <replaceable>name</replaceable> may be set to a single <literal>*</literal>
68  to clear <emphasis>all</emphasis> previously added headers. In all cases,
69  the number of headers actually removed is returned.</para></enum>
70  </enumlist>
71  </parameter>
72 
73  <parameter name="name" required="true"><para>The name of the header.</para></parameter>
74 
75  <parameter name="number" required="false">
76  <para>If there's more than 1 header with the same name, this specifies which header
77  to read or update. If not specified, defaults to <literal>1</literal> meaning
78  the first matching header. Not valid for <literal>add</literal> or
79  <literal>remove</literal>.</para>
80  </parameter>
81 
82  </syntax>
83  <description>
84  <para>PJSIP_HEADER allows you to read specific SIP headers from the inbound
85  PJSIP channel as well as write(add, update, remove) headers on the outbound
86  channel. One exception is that you can read headers that you have already
87  added on the outbound channel.</para>
88  <para>Examples:</para>
89  <example title="Set somevar to the value of the From header">
90  exten => 1,1,Set(somevar=${PJSIP_HEADER(read,From)})
91  </example>
92  <example title="Set via2 to the value of the 2nd Via header">
93  exten => 1,1,Set(via2=${PJSIP_HEADER(read,Via,2)})
94  </example>
95  <example title="Set xhdr to the value of the 1st X-header">
96  exten => 1,1,Set(xhdr=${PJSIP_HEADER(read,X-*,1)})
97  </example>
98  <example title="Add an X-Myheader header with the value of myvalue">
99  exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)
100  </example>
101  <example title="Add an X-Myheader header with an empty value">
102  exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=)
103  </example>
104  <example title="Update the value of the header named X-Myheader to newvalue">
105  ; 'X-Myheader' must already exist or the call will fail.
106  exten => 1,1,Set(PJSIP_HEADER(update,X-MyHeader)=newvalue)
107  </example>
108  <example title="Remove all headers whose names exactly match X-MyHeader">
109  exten => 1,1,Set(PJSIP_HEADER(remove,X-MyHeader)=)
110  </example>
111  <example title="Remove all headers that begin with X-My">
112  exten => 1,1,Set(PJSIP_HEADER(remove,X-My*)=)
113  </example>
114  <example title="Remove all previously added headers">
115  exten => 1,1,Set(PJSIP_HEADER(remove,*)=)
116  </example>
117  <note><para>The <literal>remove</literal> action can be called by reading
118  <emphasis>or</emphasis> writing PJSIP_HEADER.</para></note>
119  <example title="Display the number of headers removed">
120  exten => 1,1,Verbose( Removed ${PJSIP_HEADER(remove,X-MyHeader)} headers)
121  </example>
122  <example title="Set a variable to the number of headers removed">
123  exten => 1,1,Set(count=${PJSIP_HEADER(remove,X-MyHeader)})
124  </example>
125  <example title="Just remove them ignoring any count">
126  exten => 1,1,Set(=${PJSIP_HEADER(remove,X-MyHeader)})
127  exten => 1,1,Set(PJSIP_HEADER(remove,X-MyHeader)=)
128  </example>
129 
130  <note><para>If you call PJSIP_HEADER in a normal dialplan context you'll be
131  operating on the <emphasis>caller's (incoming)</emphasis> channel which
132  may not be what you want. To operate on the <emphasis>callee's (outgoing)</emphasis>
133  channel call PJSIP_HEADER in a pre-dial handler. </para></note>
134  <example title="Set headers on callee channel">
135  [handler]
136  exten => addheader,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)
137  exten => addheader,2,Set(PJSIP_HEADER(add,X-MyHeader2)=myvalue2)
138 
139  [somecontext]
140  exten => 1,1,Dial(PJSIP/${EXTEN},,b(handler^addheader^1))
141  </example>
142  </description>
143  </function>
144  <function name="PJSIP_HEADERS" language="en_US">
145  <since>
146  <version>16.20.0</version>
147  <version>18.6.0</version>
148  <version>19.0.0</version>
149  </since>
150  <synopsis>
151  Gets the list of SIP header names from an INVITE message.
152  </synopsis>
153  <syntax>
154  <parameter name="prefix">
155  <para>If specified, only the headers matching the given prefix are returned.</para>
156  </parameter>
157  </syntax>
158  <description>
159  <para>Returns a comma-separated list of header names (without values) from the
160  INVITE message. Multiple headers with the same name are included in the list only once.
161  </para>
162  <para>For example, <literal>${PJSIP_HEADERS(Co)}</literal> might return
163  <literal>Contact,Content-Length,Content-Type</literal>. As a practical example,
164  you may use <literal>${PJSIP_HEADERS(X-)}</literal> to enumerate optional extended
165  headers.</para>
166  </description>
167  <see-also>
168  <ref type="function">PJSIP_HEADER</ref>
169  </see-also>
170  </function>
171  <function name="PJSIP_RESPONSE_HEADER" language="en_US">
172  <synopsis>
173  Gets headers of 200 response from an outbound PJSIP channel.
174  </synopsis>
175  <syntax>
176  <parameter name="action" required="true">
177  <enumlist>
178  <enum name="read">
179  <para>Returns instance <replaceable>number</replaceable>
180  of response header <replaceable>name</replaceable>.</para>
181  </enum>
182  </enumlist>
183  </parameter>
184 
185  <parameter name="name" required="true">
186  <para>The <replaceable>name</replaceable> of the response header.
187  A <literal>*</literal> can be appended to the <replaceable>name</replaceable>
188  to iterate over all response headers <emphasis>beginning with</emphasis>
189  <replaceable>name</replaceable>.</para>
190  </parameter>
191 
192  <parameter name="number" required="false">
193  <para>If there's more than 1 header with the same name, this specifies which header
194  to read. If not specified, defaults to <literal>1</literal> meaning
195  the first matching header.
196  </para>
197  </parameter>
198 
199  </syntax>
200  <description>
201  <para>PJSIP_RESPONSE_HEADER allows you to read specific SIP headers of 200 response
202  from the outbound PJSIP channel.</para>
203  <para>Examples:</para>
204  <example title="Set 'somevar' to the value of the 'From' header">
205  exten => 1,1,Set(somevar=${PJSIP_RESPONSE_HEADER(read,From)})
206  </example>
207  <example title="Set 'via2' to the value of the 2nd 'Via' header">
208  exten => 1,1,Set(via2=${PJSIP_RESPONSE_HEADER(read,Via,2)})
209  </example>
210  <example title="Set 'xhdr' to the value of the 1sx X-header">
211  exten => 1,1,Set(xhdr=${PJSIP_RESPONSE_HEADER(read,X-*,1)})
212  </example>
213 
214  <note><para>If you call PJSIP_RESPONSE_HEADER in a normal dialplan context you'll be
215  operating on the <emphasis>caller's (incoming)</emphasis> channel which
216  may not be what you want. To operate on the <emphasis>callee's (outgoing)</emphasis>
217  channel call PJSIP_RESPONSE_HEADER in a pre-connect handler.</para>
218  </note>
219  <example title="Usage on pre-connect handler">
220  [handler]
221  exten => readheader,1,NoOp(PJSIP_RESPONSE_HEADER(read,X-MyHeader))
222  [somecontext]
223  exten => 1,1,Dial(PJSIP/${EXTEN},,U(handler^readheader^1))
224  </example>
225  </description>
226  <see-also>
227  <ref type="function">PJSIP_RESPONSE_HEADERS</ref>
228  <ref type="function">PJSIP_HEADER</ref>
229  </see-also>
230  </function>
231  <function name="PJSIP_RESPONSE_HEADERS" language="en_US">
232  <synopsis>
233  Gets the list of SIP header names from the 200 response of INVITE message.
234  </synopsis>
235  <syntax>
236  <parameter name="prefix">
237  <para>If specified, only the headers matching the given prefix are returned.</para>
238  </parameter>
239  </syntax>
240  <description>
241  <para>Returns a comma-separated list of header names (without values) from the 200
242  response of INVITE message. Multiple headers with the same name are included in the
243  list only once.</para>
244  <para>For example, <literal>${PJSIP_RESPONSE_HEADERS(Co)}</literal> might return
245  <literal>Contact,Content-Length,Content-Type</literal>. As a practical example,
246  you may use <literal>${PJSIP_RESPONSE_HEADERS(X-)}</literal> to enumerate optional
247  extended headers.</para>
248  </description>
249  <see-also>
250  <ref type="function">PJSIP_RESPONSE_HEADER</ref>
251  <ref type="function">PJSIP_HEADERS</ref>
252  </see-also>
253  </function>
254  <function name="PJSIP_HEADER_PARAM" language="en_US">
255  <synopsis>
256  Get or set header/URI parameters on a PJSIP channel.
257  </synopsis>
258  <syntax>
259  <parameter name="header_name" required="true">
260  <para>Header in which parameter should be read or set.</para>
261  <para>Currently, the only supported header is <literal>From</literal>.</para>
262  </parameter>
263  <parameter name="parameter_type" required="true">
264  <para>The type of parameter to get or set.</para>
265  <para>Default is header parameter.</para>
266  <enumlist>
267  <enum name="header">
268  <para>Header parameter.</para>
269  </enum>
270  <enum name="uri">
271  <para>URI parameter.</para>
272  </enum>
273  </enumlist>
274  </parameter>
275  <parameter name="parameter_name" required="true">
276  <para>Name of parameter.</para>
277  </parameter>
278  </syntax>
279  <description>
280  <para>PJSIP_HEADER_PARAM allows you to read or set parameters in a SIP header on a
281  PJSIP channel.</para>
282  <para>Both URI parameters and header parameters can be read and set using
283  this function. URI parameters appear in the URI (inside the &lt;&gt; in the header)
284  while header parameters appear afterwards.</para>
285  <note><para>If you call PJSIP_HEADER_PARAM in a normal dialplan context you'll be
286  operating on the <emphasis>caller's (incoming)</emphasis> channel which
287  may not be what you want. To operate on the <emphasis>callee's (outgoing)</emphasis>
288  channel call PJSIP_HEADER_PARAM in a pre-dial handler. </para></note>
289  <example title="Set URI parameter in From header on outbound channel">
290  [handler]
291  exten => addheader,1,Set(PJSIP_HEADER_PARAM(From,uri,isup-oli)=27)
292  same => n,Return()
293  [somecontext]
294  exten => 1,1,Dial(PJSIP/${EXTEN},,b(handler^addheader^1))
295  </example>
296  <example title="Read URI parameter in From header on inbound channel">
297  same => n,Set(value=${PJSIP_HEADER_PARAM(From,uri,isup-oli)})
298  </example>
299  </description>
300  </function>
301  ***/
302 
303 /*! \brief Linked list for accumulating headers */
305  pjsip_hdr *hdr;
307 };
309 
310 /*! \brief Datastore for saving headers */
311 static const struct ast_datastore_info header_datastore = {
312  .type = "header_datastore",
313 };
314 /*! \brief Datastore for saving response headers */
315 static const struct ast_datastore_info response_header_datastore = {
316  .type = "response_header_datastore",
317 };
318 
319 /*! \brief Data structure used for ast_sip_push_task_wait_serializer */
320 struct header_data {
321  struct ast_sip_channel_pvt *channel;
322  char *header_name;
323  const char *header_value;
324  char *buf;
325  int header_number;
326  size_t len;
327  const struct ast_datastore_info *header_datastore;
328 };
329 
330 /*!
331  * \internal
332  * \brief Insert the header pointers into the linked list.
333  *
334  * For each header in the message, allocate a list entry,
335  * clone the header, then insert the entry.
336  */
337 static int insert_headers(pj_pool_t * pool, struct hdr_list *list, pjsip_msg * msg)
338 {
339  pjsip_hdr *hdr = msg->hdr.next;
340  struct hdr_list_entry *le;
341 
342  while (hdr && hdr != &msg->hdr) {
343  le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
344  le->hdr = pjsip_hdr_clone(pool, hdr);
345  AST_LIST_INSERT_TAIL(list, le, nextptr);
346  hdr = hdr->next;
347  }
348 
349  return 0;
350 }
351 
352 /*!
353  * \internal
354  * \brief Session supplement callback on an incoming INVITE request
355  *
356  * Retrieve the header_datastore from the session or create one if it doesn't exist.
357  * Create and initialize the list if needed.
358  * Insert the headers.
359  */
360 static int incoming_request(struct ast_sip_session *session, pjsip_rx_data * rdata)
361 {
362  pj_pool_t *pool = session->inv_session->dlg->pool;
363  RAII_VAR(struct ast_datastore *, datastore,
364  ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);
365 
366  if (!datastore) {
367  if (!(datastore =
368  ast_sip_session_alloc_datastore(&header_datastore, header_datastore.type))
369  ||
370  !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) ||
371  ast_sip_session_add_datastore(session, datastore)) {
372  ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
373  return 0;
374  }
375  AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
376  }
377  insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
378 
379  return 0;
380 }
381 
382 /*!
383  * \internal
384  * \brief Session supplement callback on an incoming INVITE response
385  *
386  * Retrieve the response_header_datastore from the session or create one if it doesn't exist.
387  * Create and initialize the list if needed.
388  * Insert the headers.
389  */
390 static void incoming_response(struct ast_sip_session *session, pjsip_rx_data * rdata)
391 {
392  pj_pool_t *pool = session->inv_session->dlg->pool;
393  RAII_VAR(struct ast_datastore *, datastore,
394  ast_sip_session_get_datastore(session, response_header_datastore.type), ao2_cleanup);
395  pjsip_status_line status = rdata->msg_info.msg->line.status;
396 
397  /* Skip responses different of 200 OK, when 2xx is received. */
398  if (session->inv_session->state != PJSIP_INV_STATE_CONNECTING || status.code!=200) {
399  return;
400  }
401 
402  if (!datastore) {
403  if (!(datastore =
404  ast_sip_session_alloc_datastore(&response_header_datastore, response_header_datastore.type))
405  ||
406  !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) ||
407  ast_sip_session_add_datastore(session, datastore)) {
408  ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
409  return;
410  }
411  AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
412  }
413  insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
414 
415  return;
416 }
417 
418 /*!
419  * \internal
420  * \brief Search list for nth occurrence of specific header.
421  */
422 static pjsip_hdr *find_header(struct hdr_list *list, const char *header_name,
423  int header_number)
424 {
425  struct hdr_list_entry *le;
426  pjsip_hdr *hdr = NULL;
427  int i = 1;
428 
429  if (!list || ast_strlen_zero(header_name) || header_number < 1) {
430  return NULL;
431  }
432 
433  AST_LIST_TRAVERSE(list, le, nextptr) {
434  if (pj_stricmp2(&le->hdr->name, header_name) == 0 && i++ == header_number) {
435  hdr = le->hdr;
436  break;
437  }
438  }
439 
440  return hdr;
441 }
442 
443 /*!
444  * \internal
445  * \brief Implements PJSIP_HEADERS/PJSIP_RESPONSE_HEADERS by searching for the requested header prefix.
446  *
447  * Retrieve the header_datastore.
448  * Search for the all matching headers.
449  * Validate the pjsip_hdr found.
450  * Parse pjsip_hdr into a name and copy to the buffer.
451  * Return the value.
452  */
453 static int read_headers(void *obj)
454 {
455  struct header_data *data = obj;
456  size_t len = !ast_strlen_zero(data->header_name) ? strlen(data->header_name) : 0;
457  pjsip_hdr *hdr = NULL;
458  char *pj_hdr_string;
459  int pj_hdr_string_len;
460  char *p;
461  char *pos;
462  size_t plen, wlen = 0;
463  struct hdr_list_entry *le;
464  struct hdr_list *list;
465 
466  RAII_VAR(struct ast_datastore *, datastore,
467  ast_sip_session_get_datastore(data->channel->session, data->header_datastore->type),
468  ao2_cleanup);
469 
470  if (!datastore || !datastore->data) {
471  ast_debug(1, "There was no datastore from which to read headers.\n");
472  return -1;
473  }
474 
475  list = datastore->data;
476  pj_hdr_string = ast_alloca(data->len);
477  AST_LIST_TRAVERSE(list, le, nextptr) {
478  if (!len || pj_strnicmp2(&le->hdr->name, data->header_name, len) == 0) {
479  /* Found matched header, append to buf */
480  hdr = le->hdr;
481 
482  pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
483  if (pj_hdr_string_len == -1) {
484  ast_log(AST_LOG_ERROR,
485  "Not enough buffer space in pjsip_hdr_print_on\n");
486  return -1;
487  }
488  pj_hdr_string[pj_hdr_string_len] = '\0';
489  p = strchr(pj_hdr_string, ':');
490  if (!p) {
491  ast_log(AST_LOG_WARNING,
492  "A malformed header was returned from pjsip_hdr_print_on\n");
493  continue;
494  }
495 
496  pj_hdr_string[p - pj_hdr_string] = '\0';
497  p = ast_strip(pj_hdr_string);
498  plen = strlen(p);
499  if (wlen + plen + 1 > data->len) {
500  ast_log(AST_LOG_ERROR,
501  "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
502  data->len);
503  return -1;
504  }
505  pos = strstr(data->buf, p);
506  if (pos && pos[1] == ',') {
507  if (pos == data->buf) {
508  continue;
509  } else if (pos[-1] == ',') {
510  continue;
511  }
512  }
513  ast_copy_string(data->buf + wlen, p, data->len - wlen);
514  wlen += plen;
515  ast_copy_string(data->buf + wlen, ",", data->len - wlen);
516  wlen++;
517  }
518  }
519 
520  if (wlen == 0) {
521  if (!len) {
522  /* No headers at all on this channel */
523  return 0;
524  } else {
525  ast_debug(1, "There was no header beginning with %s.\n", data->header_name);
526  return -1;
527  }
528  } else {
529  data->buf[wlen-1] = '\0';
530  }
531  return 0;
532 }
533 
534 /*!
535  * \internal
536  * \brief Implements PJSIP_HEADER/PJSIP_RESPONSE_HEADER 'read' by searching the for the requested header.
537  *
538  * Retrieve the header_datastore.
539  * Search for the nth matching header.
540  * Validate the pjsip_hdr found.
541  * Parse pjsip_hdr into a name and value.
542  * Return the value.
543  */
544 static int read_header(void *obj)
545 {
546  struct header_data *data = obj;
547  size_t len = strlen(data->header_name);
548  pjsip_hdr *hdr = NULL;
549  char *pj_hdr_string;
550  int pj_hdr_string_len;
551  char *p;
552  size_t plen;
553  struct hdr_list_entry *le;
554  struct hdr_list *list;
555  int i = 1;
556  RAII_VAR(struct ast_datastore *, datastore,
557  ast_sip_session_get_datastore(data->channel->session, data->header_datastore->type),
558  ao2_cleanup);
559 
560  if (!datastore || !datastore->data) {
561  ast_debug(1, "There was no datastore from which to read headers.\n");
562  return -1;
563  }
564 
565  list = datastore->data;
566  AST_LIST_TRAVERSE(list, le, nextptr) {
567  if (data->header_name[len - 1] == '*') {
568  if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0 && i++ == data->header_number) {
569  hdr = le->hdr;
570  break;
571  }
572  } else {
573  if (pj_stricmp2(&le->hdr->name, data->header_name) == 0 && i++ == data->header_number) {
574  hdr = le->hdr;
575  break;
576  }
577  }
578  }
579 
580  if (!hdr) {
581  ast_debug(1, "There was no header named %s.\n", data->header_name);
582  return -1;
583  }
584 
585  pj_hdr_string = ast_alloca(data->len);
586  pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len - 1);
587  if (pj_hdr_string_len == -1) {
588  ast_log(AST_LOG_ERROR,
589  "Not enough buffer space in pjsip_hdr_print_on\n");
590  return -1;
591  }
592 
593  pj_hdr_string[pj_hdr_string_len] = '\0';
594 
595  p = strchr(pj_hdr_string, ':');
596  if (!p) {
597  ast_log(AST_LOG_ERROR,
598  "A malformed header was returned from pjsip_hdr_print_on.\n");
599  return -1;
600  }
601 
602  ++p;
603  p = ast_strip(p);
604  plen = strlen(p);
605  if (plen + 1 > data->len) {
606  ast_log(AST_LOG_ERROR,
607  "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1,
608  data->len);
609  return -1;
610  }
611 
612  ast_copy_string(data->buf, p, data->len);
613 
614  return 0;
615 }
616 
617 /*!
618  * \internal
619  * \brief Implements PJSIP_HEADER 'add' by inserting the specified header into the list.
620  *
621  * Retrieve the header_datastore from the session or create one if it doesn't exist.
622  * Create and initialize the list if needed.
623  * Create the pj_strs for name and value.
624  * Create pjsip_msg and hdr_list_entry.
625  * Add the entry to the list.
626  */
627 static int add_header(void *obj)
628 {
629  struct header_data *data = obj;
630  struct ast_sip_session *session = data->channel->session;
631  pj_pool_t *pool = session->inv_session->dlg->pool;
632  pj_str_t pj_header_name;
633  pj_str_t pj_header_value;
634  struct hdr_list_entry *le;
635  struct hdr_list *list;
636 
637  RAII_VAR(struct ast_datastore *, datastore,
638  ast_sip_session_get_datastore(session, data->header_datastore->type), ao2_cleanup);
639 
640  if (!datastore) {
641  if (!(datastore = ast_sip_session_alloc_datastore(data->header_datastore,
642  data->header_datastore->type))
643  || !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list)))
644  || ast_sip_session_add_datastore(session, datastore)) {
645  ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
646  return -1;
647  }
648  AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
649  }
650 
651  ast_debug(1, "Adding header %s with value %s\n", data->header_name,
652  data->header_value);
653 
654  pj_cstr(&pj_header_name, data->header_name);
655  pj_cstr(&pj_header_value, data->header_value);
656  le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
657  le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name,
658  &pj_header_value);
659  list = datastore->data;
660 
661  AST_LIST_INSERT_TAIL(list, le, nextptr);
662 
663  return 0;
664 }
665 
666 /*!
667  * \internal
668  * \brief Implements PJSIP_HEADER 'update' by finding the specified header and updating it.
669  *
670  * Retrieve the header_datastore from the session or create one if it doesn't exist.
671  * Create and initialize the list if needed.
672  * Create the pj_strs for name and value.
673  * Create pjsip_msg and hdr_list_entry.
674  * Add the entry to the list.
675  */
676 static int update_header(void *obj)
677 {
678  struct header_data *data = obj;
679  pj_pool_t *pool = data->channel->session->inv_session->dlg->pool;
680  pjsip_hdr *hdr = NULL;
681  RAII_VAR(struct ast_datastore *, datastore,
682  ast_sip_session_get_datastore(data->channel->session, data->header_datastore->type),
683  ao2_cleanup);
684 
685  if (!datastore || !datastore->data) {
686  ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
687  return -1;
688  }
689 
690  hdr = find_header((struct hdr_list *) datastore->data, data->header_name,
691  data->header_number);
692 
693  if (!hdr) {
694  ast_log(AST_LOG_ERROR, "There was no header named %s.\n", data->header_name);
695  return -1;
696  }
697 
698  pj_strdup2(pool, &((pjsip_generic_string_hdr *) hdr)->hvalue, data->header_value);
699 
700  return 0;
701 }
702 
703 /*!
704  * \internal
705  * \brief Implements PJSIP_HEADER 'remove' by finding the specified header and removing it.
706  *
707  * Retrieve the header_datastore from the session. Fail if it doesn't exist.
708  * If the header_name is exactly '*', the entire list is simply destroyed.
709  * Otherwise search the list for the matching header name which may be a partial name.
710  */
711 static int remove_header(void *obj)
712 {
713  struct header_data *data = obj;
714  size_t len = strlen(data->header_name);
715  struct hdr_list *list;
716  struct hdr_list_entry *le;
717  int removed_count = 0;
718  RAII_VAR(struct ast_datastore *, datastore,
719  ast_sip_session_get_datastore(data->channel->session, data->header_datastore->type),
720  ao2_cleanup);
721 
722  if (!datastore || !datastore->data) {
723  ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
724  return -1;
725  }
726 
727  list = datastore->data;
728  AST_LIST_TRAVERSE_SAFE_BEGIN(list, le, nextptr) {
729  if (data->header_name[len - 1] == '*') {
730  if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0) {
731  AST_LIST_REMOVE_CURRENT(nextptr);
732  removed_count++;
733  }
734  } else {
735  if (pj_stricmp2(&le->hdr->name, data->header_name) == 0) {
736  AST_LIST_REMOVE_CURRENT(nextptr);
737  removed_count++;
738  }
739  }
740  }
742 
743  if (data->buf && data->len) {
744  snprintf(data->buf, data->len, "%d", removed_count);
745  }
746 
747  return 0;
748 }
749 
750 /*!
751  * \brief Read list of unique SIP headers
752  */
753 static int func_read_headers(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
754 {
755  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
756  struct header_data header_data;
758  AST_APP_ARG(header_pattern);
759  );
760  AST_STANDARD_APP_ARGS(args, data);
761 
762  if (!chan || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
763  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
764  return -1;
765  }
766 
767  header_data.channel = channel;
768  header_data.header_name = args.header_pattern;
769  header_data.header_value = NULL;
770  header_data.buf = buf;
771  header_data.len = len;
772  header_data.header_datastore = &header_datastore;
773 
774  return ast_sip_push_task_wait_serializer(channel->session->serializer, read_headers, &header_data);
775 
776 }
777 
778 /*!
779  * \brief Read list of unique SIP response headers
780  */
781 static int func_response_read_headers(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
782 {
783  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
784  struct header_data header_data;
786  AST_APP_ARG(header_pattern);
787  );
788  AST_STANDARD_APP_ARGS(args, data);
789 
790  if (!chan || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
791  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
792  return -1;
793  }
794 
795  if (ast_strlen_zero(args.header_pattern)) {
796  ast_log(AST_LOG_ERROR, "This function requires a pattern.\n");
797  return -1;
798  }
799 
800  header_data.channel = channel;
801  header_data.header_name = args.header_pattern;
802  header_data.header_value = NULL;
803  header_data.buf = buf;
804  header_data.len = len;
805  header_data.header_datastore = &response_header_datastore;
806 
807  return ast_sip_push_task_wait_serializer(channel->session->serializer, read_headers, &header_data);
808 
809 }
810 
811 /*!
812  * \brief Implements PJSIP_HEADER function 'read' callback.
813  *
814  * Valid actions are 'read' and 'remove'.
815  */
816 static int func_read_header(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
817 {
818  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
819  struct header_data header_data;
820  int number;
822  AST_APP_ARG(action);
823  AST_APP_ARG(header_name); AST_APP_ARG(header_number););
824  AST_STANDARD_APP_ARGS(args, data);
825 
826  if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
827  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
828  return -1;
829  }
830 
831  if (ast_strlen_zero(args.action)) {
832  ast_log(AST_LOG_ERROR, "This function requires an action.\n");
833  return -1;
834  }
835  if (ast_strlen_zero(args.header_name)) {
836  ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
837  return -1;
838  }
839  if (!args.header_number) {
840  number = 1;
841  } else {
842  sscanf(args.header_number, "%30d", &number);
843  if (number < 1) {
844  number = 1;
845  }
846  }
847 
848  header_data.channel = channel;
849  header_data.header_name = args.header_name;
850  header_data.header_number = number;
851  header_data.header_value = NULL;
852  header_data.buf = buf;
853  header_data.len = len;
854  header_data.header_datastore = &header_datastore;
855 
856  if (!strcasecmp(args.action, "read")) {
857  return ast_sip_push_task_wait_serializer(channel->session->serializer, read_header, &header_data);
858  } else if (!strcasecmp(args.action, "remove")) {
860  remove_header, &header_data);
861  } else {
862  ast_log(AST_LOG_ERROR,
863  "Unknown action '%s' is not valid, must be 'read' or 'remove'.\n",
864  args.action);
865  return -1;
866  }
867 }
868 
869 /*!
870  * \brief Implements PJSIP_RESPONSE_HEADER function 'read' callback.
871  *
872  * Valid actions are 'read'
873  */
874 static int func_response_read_header(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
875 {
876  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
877  struct header_data header_data;
878  int number;
880  AST_APP_ARG(action);
881  AST_APP_ARG(header_name); AST_APP_ARG(header_number););
882  AST_STANDARD_APP_ARGS(args, data);
883 
884  if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
885  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
886  return -1;
887  }
888 
889  if (ast_strlen_zero(args.action)) {
890  ast_log(AST_LOG_ERROR, "This function requires an action.\n");
891  return -1;
892  }
893  if (ast_strlen_zero(args.header_name)) {
894  ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
895  return -1;
896  }
897  if (!args.header_number) {
898  number = 1;
899  } else {
900  sscanf(args.header_number, "%30d", &number);
901  if (number < 1) {
902  number = 1;
903  }
904  }
905 
906  header_data.channel = channel;
907  header_data.header_name = args.header_name;
908  header_data.header_number = number;
909  header_data.header_value = NULL;
910  header_data.buf = buf;
911  header_data.len = len;
912  header_data.header_datastore = &response_header_datastore;
913 
914  if (!strcasecmp(args.action, "read")) {
915  return ast_sip_push_task_wait_serializer(channel->session->serializer, read_header, &header_data);
916  } else {
917  ast_log(AST_LOG_ERROR,
918  "Unknown action '%s' is not valid, must be 'read'.\n",
919  args.action);
920  return -1;
921  }
922 }
923 
924 /*!
925  * \brief Implements PJSIP_HEADER function 'write' callback.
926  *
927  * Valid actions are 'add', 'update' and 'remove'.
928  */
929 static int func_write_header(struct ast_channel *chan, const char *cmd, char *data,
930  const char *value)
931 {
932  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
933  struct header_data header_data;
934  int header_number;
936  AST_APP_ARG(action);
937  AST_APP_ARG(header_name); AST_APP_ARG(header_number););
938  AST_STANDARD_APP_ARGS(args, data);
939 
940  if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
941  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
942  return -1;
943  }
944 
945  if (ast_strlen_zero(args.action)) {
946  ast_log(AST_LOG_ERROR, "This function requires an action.\n");
947  return -1;
948  }
949  if (ast_strlen_zero(args.header_name)) {
950  ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
951  return -1;
952  }
953  if (!args.header_number) {
954  header_number = 1;
955  } else {
956  sscanf(args.header_number, "%30d", &header_number);
957  if (header_number < 1) {
958  header_number = 1;
959  }
960  }
961 
962  header_data.channel = channel;
963  header_data.header_name = args.header_name;
964  header_data.header_number = header_number;
965  header_data.header_value = value;
966  header_data.buf = NULL;
967  header_data.len = 0;
968  header_data.header_datastore = &header_datastore;
969 
970  if (!strcasecmp(args.action, "add")) {
972  add_header, &header_data);
973  } else if (!strcasecmp(args.action, "update")) {
975  update_header, &header_data);
976  } else if (!strcasecmp(args.action, "remove")) {
978  remove_header, &header_data);
979  } else {
980  ast_log(AST_LOG_ERROR,
981  "Unknown action '%s' is not valid, must be 'add', 'update', or 'remove'.\n",
982  args.action);
983  return -1;
984  }
985 }
986 
987 static struct ast_custom_function pjsip_header_function = {
988  .name = "PJSIP_HEADER",
989  .read = func_read_header,
990  .write = func_write_header,
991 };
992 
993 static struct ast_custom_function pjsip_headers_function = {
994  .name = "PJSIP_HEADERS",
995  .read = func_read_headers
996 };
997 
998 static struct ast_custom_function pjsip_response_header_function = {
999  .name = "PJSIP_RESPONSE_HEADER",
1000  .read = func_response_read_header
1001 };
1002 
1003 static struct ast_custom_function pjsip_response_headers_function = {
1004  .name = "PJSIP_RESPONSE_HEADERS",
1005  .read = func_response_read_headers
1006 };
1007 
1008 /*!
1009  * \internal
1010  * \brief Session supplement callback for outgoing INVITE requests
1011  *
1012  * Retrieve the header_datastore from the session.
1013  * Add each header in the list to the outgoing message.
1014  *
1015  * These pjsip_hdr structures will have been created by add_header.
1016  * Because outgoing_request may be called more than once with the same header
1017  * list (as in the case of an authentication exchange), each pjsip_hdr structure
1018  * MUST be newly cloned for each outgoing message.
1019  */
1020 static void outgoing_request(struct ast_sip_session *session, pjsip_tx_data * tdata)
1021 {
1022  struct hdr_list *list;
1023  struct hdr_list_entry *le;
1024  RAII_VAR(struct ast_datastore *, datastore,
1025  ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);
1026 
1027  if (!datastore || !datastore->data ||
1028  (session->inv_session->state >= PJSIP_INV_STATE_CONFIRMED)) {
1029  return;
1030  }
1031 
1032  list = datastore->data;
1033  AST_LIST_TRAVERSE(list, le, nextptr) {
1034  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) pjsip_hdr_clone(tdata->pool, le->hdr));
1035  }
1036  ast_sip_session_remove_datastore(session, datastore->uid);
1037 }
1038 
1039 static struct ast_sip_session_supplement header_funcs_supplement = {
1040  .method = "INVITE",
1041  .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 1000,
1042  .incoming_request = incoming_request,
1043  .outgoing_request = outgoing_request,
1044  .incoming_response = incoming_response,
1045 };
1046 
1047 enum param_type {
1048  PARAMETER_HEADER,
1049  PARAMETER_URI,
1050 };
1051 
1052 struct param_data {
1053  struct ast_sip_channel_pvt *channel;
1054  char *header_name;
1055  char *param_name;
1056  const char *param_value; /* Only used for write */
1057  enum param_type paramtype;
1058  /* For read function only */
1059  char *buf;
1060  size_t len;
1061 };
1062 
1063 static int read_param(void *obj)
1064 {
1065  struct param_data *data = obj;
1066  struct ast_sip_session *session = data->channel->session;
1067  pj_str_t param_name;
1068 
1069  pjsip_fromto_hdr *dlg_info;
1070  pjsip_name_addr *dlg_info_name_addr;
1071  pjsip_sip_uri *dlg_info_uri;
1072  pjsip_param *param;
1073  size_t param_len;
1074 
1075  dlg_info = session->inv_session->dlg->remote.info; /* Remote dialog for incoming */
1076  dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1077  dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1078 
1079  pj_cstr(&param_name, data->param_name);
1080 
1081  if (data->paramtype == PARAMETER_URI) { /* URI parameter */
1082  param = pjsip_param_find(&dlg_info_uri->other_param, &param_name);
1083  } else { /* Header parameter */
1084  param = pjsip_param_find(&dlg_info->other_param, &param_name);
1085  }
1086 
1087  if (!param) {
1088  ast_debug(1, "No %s parameter found named %s\n",
1089  data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name);
1090  return -1;
1091  }
1092 
1093  param_len = pj_strlen(&param->value);
1094  if (param_len >= data->len) {
1095  ast_log(LOG_ERROR, "Buffer is too small for parameter value (%zu > %zu)\n", param_len, data->len);
1096  return -1;
1097  }
1098 
1099  ast_debug(2, "Successfully read %s parameter %s (length %zu)\n",
1100  data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, param_len);
1101  if (param_len) {
1102  ast_copy_string(data->buf, pj_strbuf(&param->value), data->len);
1103  }
1104  data->buf[param_len] = '\0';
1105 
1106  return 0;
1107 }
1108 
1109 /*!
1110  * \internal
1111  * \brief Implements PJSIP_HEADER_PARAM 'add' by adding the specified parameter.
1112  * \note Unlike add_header, we can't add parameters in the outgoing_request callback: that's too late.
1113  * That's why we do it here and not in a callback.
1114  */
1115 static int add_param(void *obj)
1116 {
1117  struct param_data *data = obj;
1118  struct ast_sip_session *session = data->channel->session;
1119  pj_pool_t *pool = session->inv_session->dlg->pool;
1120 
1121  pjsip_fromto_hdr *dlg_info;
1122  pjsip_name_addr *dlg_info_name_addr;
1123  pjsip_sip_uri *dlg_info_uri;
1124 
1125  dlg_info = session->inv_session->dlg->local.info; /* Local for outgoing */
1126  dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1127  dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1128  if (!PJSIP_URI_SCHEME_IS_SIP(dlg_info_uri) && !PJSIP_URI_SCHEME_IS_SIPS(dlg_info_uri)) {
1129  ast_log(LOG_WARNING, "Non SIP/SIPS URI\n");
1130  return -1;
1131  }
1132 
1133  ast_debug(1, "Adding custom %s param %s = %s\n",
1134  data->paramtype == PARAMETER_URI ? "URI" : "header", data->param_name, data->param_value);
1135 
1136  /* This works the same as doing this in set_from_header in res_pjsip_session.c
1137  * The way that this maps to pjproject is a little confusing.
1138  * Say we have <sip:foo@bar.com;p1=abc;p2=def?h1=qrs&h2=tuv>;o1=foo;o2=bar
1139  * p1 and p2 are URI parameters.
1140  * (h1 and h2 are URI headers)
1141  * o1 and o2 are header parameters (and don't have anything to do with the URI)
1142  * In pjproject, other_param is used for adding all custom parameters.
1143  * We use the URI for URI stuff, including URI parameters, and the header directly for header parameters.
1144  */
1145 
1146 #define param_add(pool, list, pname, pvalue) { \
1147  pjsip_param *param; \
1148  param = PJ_POOL_ALLOC_T(pool, pjsip_param); \
1149  pj_strdup2(pool, &param->name, pname); \
1150  pj_strdup2(pool, &param->value, pvalue); \
1151  pj_list_insert_before(list, param); \
1152 }
1153 
1154  if (data->paramtype == PARAMETER_URI) { /* URI parameter */
1155  param_add(pool, &dlg_info_uri->other_param, data->param_name, S_OR(data->param_value, ""));
1156  } else { /* Header parameter */
1157  param_add(pool, &dlg_info->other_param, data->param_name, S_OR(data->param_value, ""));
1158  }
1159 
1160  return 0;
1161 }
1162 
1163 static int func_read_param(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
1164 {
1165  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
1166  struct param_data param_data;
1167 
1168  AST_DECLARE_APP_ARGS(args,
1169  AST_APP_ARG(header_name);
1170  AST_APP_ARG(param_type);
1171  AST_APP_ARG(param_name);
1172  );
1173 
1174  AST_STANDARD_APP_ARGS(args, data);
1175 
1176  param_data.channel = channel;
1177 
1178  if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
1179  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
1180  return -1;
1181  }
1182  if (ast_strlen_zero(args.param_type)) {
1183  ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");
1184  return -1;
1185  }
1186  if (ast_strlen_zero(args.param_name)) {
1187  ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");
1188  return -1;
1189  }
1190 
1191  /* Currently, only From is supported, but this could be extended in the future. */
1192  if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {
1193  ast_log(LOG_WARNING, "Only the From header is currently supported\n");
1194  return -1;
1195  }
1196 
1197  param_data.param_name = args.param_name;
1198  if (!strcasecmp(args.param_type, "header")) {
1199  param_data.paramtype = PARAMETER_HEADER;
1200  } else if (!strcasecmp(args.param_type, "uri")) {
1201  param_data.paramtype = PARAMETER_URI;
1202  } else {
1203  ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1204  return -1;
1205  }
1206 
1207  param_data.buf = buf;
1208  param_data.len = len;
1209 
1210  return ast_sip_push_task_wait_serializer(channel->session->serializer, read_param, &param_data);
1211 }
1212 
1213 static int func_write_param(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1214 {
1215  struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
1216  struct param_data param_data;
1217  AST_DECLARE_APP_ARGS(args,
1218  AST_APP_ARG(header_name);
1219  AST_APP_ARG(param_type);
1220  AST_APP_ARG(param_name);
1221  );
1222 
1223  AST_STANDARD_APP_ARGS(args, data);
1224 
1225  param_data.channel = channel;
1226 
1227  if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
1228  ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
1229  return -1;
1230  }
1231  if (ast_strlen_zero(args.param_type)) {
1232  ast_log(AST_LOG_ERROR, "This function requires a parameter type.\n");
1233  return -1;
1234  }
1235  if (ast_strlen_zero(args.param_name)) {
1236  ast_log(AST_LOG_ERROR, "This function requires a parameter name.\n");
1237  return -1;
1238  }
1239 
1240  /* Currently, only From is supported, but this could be extended in the future. */
1241  if (ast_strlen_zero(args.header_name) || strcasecmp(args.header_name, "From")) {
1242  ast_log(LOG_WARNING, "Only the From header is currently supported\n");
1243  return -1;
1244  }
1245 
1246  param_data.param_name = args.param_name;
1247  if (!strcasecmp(args.param_type, "header")) {
1248  param_data.paramtype = PARAMETER_HEADER;
1249  } else if (!strcasecmp(args.param_type, "uri")) {
1250  param_data.paramtype = PARAMETER_URI;
1251  } else {
1252  ast_log(LOG_WARNING, "Parameter type '%s' is invalid: must be 'header' or 'uri'\n", args.param_type);
1253  return -1;
1254  }
1255  param_data.param_value = value;
1256 
1257  return ast_sip_push_task_wait_serializer(channel->session->serializer, add_param, &param_data);
1258 }
1259 
1260 static struct ast_custom_function pjsip_header_param_function = {
1261  .name = "PJSIP_HEADER_PARAM",
1262  .read = func_read_param,
1263  .write = func_write_param,
1264 };
1265 
1266 static int load_module(void)
1267 {
1268  ast_sip_session_register_supplement(&header_funcs_supplement);
1269  ast_custom_function_register(&pjsip_header_function);
1270  ast_custom_function_register(&pjsip_headers_function);
1271  ast_custom_function_register(&pjsip_response_header_function);
1272  ast_custom_function_register(&pjsip_response_headers_function);
1273  ast_custom_function_register(&pjsip_header_param_function);
1274 
1275  return AST_MODULE_LOAD_SUCCESS;
1276 }
1277 
1278 static int unload_module(void)
1279 {
1280  ast_custom_function_unregister(&pjsip_header_function);
1281  ast_custom_function_unregister(&pjsip_headers_function);
1282  ast_custom_function_unregister(&pjsip_response_header_function);
1283  ast_custom_function_unregister(&pjsip_response_headers_function);
1284  ast_custom_function_unregister(&pjsip_header_param_function);
1285  ast_sip_session_unregister_supplement(&header_funcs_supplement);
1286  return 0;
1287 }
1288 
1289 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Header Functions",
1290  .support_level = AST_MODULE_SUPPORT_CORE,
1291  .load = load_module,
1292  .unload = unload_module,
1293  .load_pri = AST_MODPRI_APP_DEPEND,
1294  .requires = "res_pjsip,res_pjsip_session",
1295 );
const char * name
Definition: pbx.h:119
const char * type
Definition: datastore.h:32
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int(* incoming_request)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return...
static pj_pool_t * pool
Global memory pool for configuration and timers.
Structure for a data store type.
Definition: datastore.h:31
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
Data structure used for ast_sip_push_task_wait_serializer.
Structure for a data store object.
Definition: datastore.h:64
struct pjsip_inv_session * inv_session
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
A structure describing a SIP session.
void(* outgoing_request)(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Called on an outgoing SIP request This method is always called from a SIP servant thread...
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Utility functions.
Number structure.
Definition: app_followme.c:154
General Asterisk PBX channel definitions.
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:2179
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
void(* incoming_response)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread...
#define ast_debug(level,...)
Log a DEBUG message.
Core PBX routines and definitions.
struct ast_taskprocessor * serializer
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
A supplement to SIP message processing.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
Linked list for accumulating headers.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
#define AST_APP_ARG(name)
Define an application argument.