Fix stuck channel in ARI through the introduction of synchronous bridge actions.
[asterisk/asterisk.git] / res / 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  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjsip</depend>
22         <depend>res_pjsip_session</depend>
23         <support_level>core</support_level>
24  ***/
25
26 #include "asterisk.h"
27
28 #include <pjsip.h>
29 #include <pjsip_ua.h>
30
31 #include "asterisk/res_pjsip.h"
32 #include "asterisk/res_pjsip_session.h"
33 #include "asterisk/channel.h"
34 #include "asterisk/pbx.h"
35 #include "asterisk/app.h"
36 #include "asterisk/module.h"
37 #include "asterisk/utils.h"
38
39 /*** DOCUMENTATION
40         <function name="PJSIP_HEADER" language="en_US">
41                 <synopsis>
42                         Gets, adds, updates or removes the specified SIP header from a PJSIP session.
43                 </synopsis>
44                 <syntax>
45                         <parameter name="action" required="true">
46                                 <enumlist>
47                                         <enum name="read"><para>Returns instance <replaceable>number</replaceable>
48                                         of header <replaceable>name</replaceable>.</para></enum>
49
50                                         <enum name="add"><para>Adds a new header <replaceable>name</replaceable>
51                                         to this session.</para></enum>
52
53                                         <enum name="update"><para>Updates instance <replaceable>number</replaceable>
54                                         of header <replaceable>name</replaceable> to a new value.
55                                         The header must already exist.</para></enum>
56
57                                         <enum name="remove"><para>Removes all instances of previously added headers
58                                         whose names match <replaceable>name</replaceable>. A <literal>*</literal>
59                                         may be appended to <replaceable>name</replaceable> to remove all headers
60                                         <emphasis>beginning with</emphasis> <replaceable>name</replaceable>.
61                                         <replaceable>name</replaceable> may be set to a single <literal>*</literal>
62                                         to clear <emphasis>all</emphasis> previously added headers. In all cases,
63                                         the number of headers actually removed is returned.</para></enum>
64                                 </enumlist>
65                         </parameter>
66
67                         <parameter name="name" required="true"><para>The name of the header.</para></parameter>
68
69                         <parameter name="number" required="false">
70                                 <para>If there's more than 1 header with the same name, this specifies which header
71                                 to read or update.  If not specified, defaults to <literal>1</literal> meaning
72                                 the first matching header.  Not valid for <literal>add</literal> or
73                                 <literal>remove</literal>.</para>
74                         </parameter>
75
76                 </syntax>
77                 <description>
78                         <para>Examples:</para>
79                         <para>;</para>
80                         <para>; Set 'somevar' to the value of the 'From' header.</para>
81                         <para>exten => 1,1,Set(somevar=${PJSIP_HEADER(read,From)})</para>
82                         <para>;</para>
83                         <para>; Set 'via2' to the value of the 2nd 'Via' header.</para>
84                         <para>exten => 1,1,Set(via2=${PJSIP_HEADER(read,Via,2)})</para>
85                         <para>;</para>
86                         <para>; Add an 'X-Myheader' header with the value of 'myvalue'.</para>
87                         <para>exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)</para>
88                         <para>;</para>
89                         <para>; Add an 'X-Myheader' header with an empty value.</para>
90                         <para>exten => 1,1,Set(PJSIP_HEADER(add,X-MyHeader)=)</para>
91                         <para>;</para>
92                         <para>; Update the value of the header named 'X-Myheader' to 'newvalue'.</para>
93                         <para>; 'X-Myheader' must already exist or the call will fail.</para>
94                         <para>exten => 1,1,Set(PJSIP_HEADER(update,X-MyHeader)=newvalue)</para>
95                         <para>;</para>
96                         <para>; Remove all headers whose names exactly match 'X-MyHeader'.</para>
97                         <para>exten => 1,1,Set(PJSIP_HEADER(remove,X-MyHeader)=)</para>
98                         <para>;</para>
99                         <para>; Remove all headers that begin with 'X-My'.</para>
100                         <para>exten => 1,1,Set(PJSIP_HEADER(remove,X-My*)=)</para>
101                         <para>;</para>
102                         <para>; Remove all previously added headers.</para>
103                         <para>exten => 1,1,Set(PJSIP_HEADER(remove,*)=)</para>
104                         <para>;</para>
105
106                         <note><para>The <literal>remove</literal> action can be called by reading
107                         <emphasis>or</emphasis> writing PJSIP_HEADER.</para>
108                         <para>;</para>
109                         <para>; Display the number of headers removed</para>
110                         <para>exten => 1,1,Verbose( Removed ${PJSIP_HEADER(remove,X-MyHeader)} headers)</para>
111                         <para>;</para>
112                         <para>; Set a variable to the number of headers removed</para>
113                         <para>exten => 1,1,Set(count=${PJSIP_HEADER(remove,X-MyHeader)})</para>
114                         <para>;</para>
115                         <para>; Just remove them ignoring any count</para>
116                         <para>exten => 1,1,Set(=${PJSIP_HEADER(remove,X-MyHeader)})</para>
117                         <para>exten => 1,1,Set(PJSIP_HEADER(remove,X-MyHeader)=)</para>
118                         <para>;</para>
119                         </note>
120
121                         <note><para>If you call PJSIP_HEADER in a normal dialplan context you'll be
122                         operating on the <emphasis>caller's (incoming)</emphasis> channel which
123                         may not be what you want.  To operate on the <emphasis>callee's (outgoing)</emphasis>
124                         channel call PJSIP_HEADER in a pre-dial handler. </para>
125                         <para>Example:</para>
126                         <para>;</para>
127                         <para>[handler]</para>
128                         <para>exten => addheader,1,Set(PJSIP_HEADER(add,X-MyHeader)=myvalue)</para>
129                         <para>exten => addheader,2,Set(PJSIP_HEADER(add,X-MyHeader2)=myvalue2)</para>
130                         <para>;</para>
131                         <para>[somecontext]</para>
132                         <para>exten => 1,1,Dial(PJSIP/${EXTEN},,b(handler^addheader^1))</para>
133                         <para>;</para>
134                         </note>
135                 </description>
136         </function>
137  ***/
138
139 /*! \brief Linked list for accumulating headers */
140 struct hdr_list_entry {
141         pjsip_hdr *hdr;
142         AST_LIST_ENTRY(hdr_list_entry) nextptr;
143 };
144 AST_LIST_HEAD(hdr_list, hdr_list_entry);
145
146 /*! \brief Destructor for hdr_list */
147 static void hdr_list_destroy(void *obj)
148 {
149         AST_LIST_HEAD_DESTROY((struct hdr_list *) obj);
150 }
151
152 /*! \brief Datastore for saving headers */
153 static const struct ast_datastore_info header_datastore = {
154         .type = "header_datastore",
155         .destroy = hdr_list_destroy,
156 };
157
158 /*! \brief Data structure used for ast_sip_push_task_synchronous  */
159 struct header_data {
160         struct ast_sip_channel_pvt *channel;
161         char *header_name;
162         const char *header_value;
163         char *buf;
164         int header_number;
165         size_t len;
166 };
167
168 /*!
169  * \internal
170  * \brief Insert the header pointers into the linked list.
171  *
172  * For each header in the message, allocate a list entry,
173  * clone the header, then insert the entry.
174  */
175 static int insert_headers(pj_pool_t * pool, struct hdr_list *list, pjsip_msg * msg)
176 {
177         pjsip_hdr *hdr = msg->hdr.next;
178         struct hdr_list_entry *le;
179
180         while (hdr && hdr != &msg->hdr) {
181                 le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
182                 le->hdr = pjsip_hdr_clone(pool, hdr);
183                 AST_LIST_INSERT_TAIL(list, le, nextptr);
184                 hdr = hdr->next;
185         }
186
187         return 0;
188 }
189
190 /*!
191  * \internal
192  * \brief Session supplement callback on an incoming INVITE request
193  *
194  * Retrieve the header_datastore from the session or create one if it doesn't exist.
195  * Create and initialize the list if needed.
196  * Insert the headers.
197  */
198 static int incoming_request(struct ast_sip_session *session, pjsip_rx_data * rdata)
199 {
200         pj_pool_t *pool = session->inv_session->dlg->pool;
201         RAII_VAR(struct ast_datastore *, datastore,
202                          ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);
203
204         if (!datastore) {
205                 if (!(datastore =
206                           ast_sip_session_alloc_datastore(&header_datastore, header_datastore.type))
207                         ||
208                         !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list))) ||
209                         ast_sip_session_add_datastore(session, datastore)) {
210                         ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
211                         return 0;
212                 }
213                 AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data);
214         }
215         insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
216
217         return 0;
218 }
219
220 /*!
221  * \internal
222  * \brief Search list for nth occurrence of specific header.
223  */
224 static pjsip_hdr *find_header(struct hdr_list *list, const char *header_name,
225                                                           int header_number)
226 {
227         struct hdr_list_entry *le;
228         pjsip_hdr *hdr = NULL;
229         int i = 1;
230
231         if (!list || ast_strlen_zero(header_name) || header_number < 1) {
232                 return NULL;
233         }
234
235         AST_LIST_TRAVERSE(list, le, nextptr) {
236                 if (pj_stricmp2(&le->hdr->name, header_name) == 0 && i++ == header_number) {
237                         hdr = le->hdr;
238                         break;
239                 }
240         }
241
242         return hdr;
243 }
244
245
246 /*!
247  * \internal
248  * \brief Implements PJSIP_HEADER 'read' by searching the for the requested header.
249  *
250  * Retrieve the header_datastore.
251  * Search for the nth matching header.
252  * Validate the pjsip_hdr found.
253  * Parse pjsip_hdr into a name and value.
254  * Return the value.
255  */
256 static int read_header(void *obj)
257 {
258         struct header_data *data = obj;
259         pjsip_hdr *hdr = NULL;
260         char *pj_hdr_string;
261         size_t pj_hdr_string_len;
262         char *p;
263         size_t plen;
264         RAII_VAR(struct ast_datastore *, datastore,
265                          ast_sip_session_get_datastore(data->channel->session, header_datastore.type),
266                          ao2_cleanup);
267
268         if (!datastore || !datastore->data) {
269                 ast_debug(1, "There was no datastore from which to read headers.\n");
270                 return -1;
271         }
272
273         hdr = find_header((struct hdr_list *) datastore->data, data->header_name,
274                                           data->header_number);
275
276         if (!hdr) {
277                 ast_debug(1, "There was no header named %s.\n", data->header_name);
278                 return -1;
279         }
280
281         pj_hdr_string = ast_alloca(data->len);
282         pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len);
283         pj_hdr_string[pj_hdr_string_len] = '\0';
284
285         p = strchr(pj_hdr_string, ':');
286         if (!p) {
287                 ast_log(AST_LOG_ERROR,
288                                 "A malformed header was returned from pjsip_hdr_print_on.\n");
289                 return -1;
290         }
291
292         ++p;
293         p = ast_strip(p);
294         plen = strlen(p);
295         if (plen + 1 > data->len) {
296                 ast_log(AST_LOG_ERROR,
297                                 "Buffer isn't big enough to hold header value.  %zu > %zu\n", plen + 1,
298                                 data->len);
299                 return -1;
300         }
301
302         ast_copy_string(data->buf, p, data->len);
303
304         return 0;
305 }
306
307 /*!
308  * \internal
309  * \brief Implements PJSIP_HEADER 'add' by inserting the specified header into thge list.
310  *
311  * Retrieve the header_datastore from the session or create one if it doesn't exist.
312  * Create and initialize the list if needed.
313  * Create the pj_strs for name and value.
314  * Create pjsip_msg and hdr_list_entry.
315  * Add the entry to the list.
316  */
317 static int add_header(void *obj)
318 {
319         struct header_data *data = obj;
320         struct ast_sip_session *session = data->channel->session;
321         pj_pool_t *pool = session->inv_session->dlg->pool;
322         pj_str_t pj_header_name;
323         pj_str_t pj_header_value;
324         struct hdr_list_entry *le;
325         struct hdr_list *list;
326
327         RAII_VAR(struct ast_datastore *, datastore,
328                          ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);
329
330         if (!datastore) {
331                 if (!(datastore = ast_sip_session_alloc_datastore(&header_datastore,
332                                                                                                                   header_datastore.type))
333                         || !(datastore->data = pj_pool_alloc(pool, sizeof(struct hdr_list)))
334                         || ast_sip_session_add_datastore(session, datastore)) {
335                         ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
336                         return -1;
337                 }
338                 AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data);
339         }
340
341         ast_debug(1, "Adding header %s with value %s\n", data->header_name,
342                           data->header_value);
343
344         pj_cstr(&pj_header_name, data->header_name);
345         pj_cstr(&pj_header_value, data->header_value);
346         le = pj_pool_zalloc(pool, sizeof(struct hdr_list_entry));
347         le->hdr = (pjsip_hdr *) pjsip_generic_string_hdr_create(pool, &pj_header_name,
348                                                                                                                         &pj_header_value);
349         list = datastore->data;
350
351         AST_LIST_INSERT_TAIL(list, le, nextptr);
352
353         return 0;
354 }
355
356 /*!
357  * \internal
358  * \brief Implements PJSIP_HEADER 'update' by finding the specified header and updating it.
359  *
360  * Retrieve the header_datastore from the session or create one if it doesn't exist.
361  * Create and initialize the list if needed.
362  * Create the pj_strs for name and value.
363  * Create pjsip_msg and hdr_list_entry.
364  * Add the entry to the list.
365  */
366 static int update_header(void *obj)
367 {
368         struct header_data *data = obj;
369         pjsip_hdr *hdr = NULL;
370         RAII_VAR(struct ast_datastore *, datastore,
371                          ast_sip_session_get_datastore(data->channel->session, header_datastore.type),
372                          ao2_cleanup);
373
374         if (!datastore || !datastore->data) {
375                 ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
376                 return -1;
377         }
378
379         hdr = find_header((struct hdr_list *) datastore->data, data->header_name,
380                                           data->header_number);
381
382         if (!hdr) {
383                 ast_log(AST_LOG_ERROR, "There was no header named %s.\n", data->header_name);
384                 return -1;
385         }
386
387         pj_strcpy2(&((pjsip_generic_string_hdr *) hdr)->hvalue, data->header_value);
388
389         return 0;
390 }
391
392 /*!
393  * \internal
394  * \brief Implements PJSIP_HEADER 'remove' by finding the specified header and removing it.
395  *
396  * Retrieve the header_datastore from the session.  Fail if it doesn't exist.
397  * If the header_name is exactly '*', the entire list is simply destroyed.
398  * Otherwise search the list for the matching header name which may be a partial name.
399  */
400 static int remove_header(void *obj)
401 {
402         struct header_data *data = obj;
403         size_t len = strlen(data->header_name);
404         struct hdr_list *list;
405         struct hdr_list_entry *le;
406         int removed_count = 0;
407         RAII_VAR(struct ast_datastore *, datastore,
408                          ast_sip_session_get_datastore(data->channel->session, header_datastore.type),
409                          ao2_cleanup);
410
411         if (!datastore || !datastore->data) {
412                 ast_log(AST_LOG_ERROR, "No headers had been previously added to this session.\n");
413                 return -1;
414         }
415
416         list = datastore->data;
417         AST_LIST_TRAVERSE_SAFE_BEGIN(list, le, nextptr) {
418                 if (data->header_name[len - 1] == '*') {
419                         if (pj_strnicmp2(&le->hdr->name, data->header_name, len - 1) == 0) {
420                                 AST_LIST_REMOVE_CURRENT(nextptr);
421                                 removed_count++;
422                         }
423                 } else {
424                         if (pj_stricmp2(&le->hdr->name, data->header_name) == 0) {
425                                 AST_LIST_REMOVE_CURRENT(nextptr);
426                                 removed_count++;
427                         }
428                 }
429         }
430         AST_LIST_TRAVERSE_SAFE_END;
431
432         if (data->buf && data->len) {
433                 snprintf(data->buf, data->len, "%d", removed_count);
434         }
435
436         return 0;
437 }
438
439 /*!
440  * \brief Implements function 'read' callback.
441  *
442  * Valid actions are 'read' and 'remove'.
443  */
444 static int func_read_header(struct ast_channel *chan, const char *function, char *data,
445                                                         char *buf, size_t len)
446 {
447         struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
448         struct header_data header_data;
449         int number;
450         AST_DECLARE_APP_ARGS(args,
451                                                  AST_APP_ARG(action);
452                                                  AST_APP_ARG(header_name); AST_APP_ARG(header_number););
453         AST_STANDARD_APP_ARGS(args, data);
454
455         if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
456                 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
457                 return -1;
458         }
459
460         if (ast_strlen_zero(args.action)) {
461                 ast_log(AST_LOG_ERROR, "This function requires an action.\n");
462                 return -1;
463         }
464         if (ast_strlen_zero(args.header_name)) {
465                 ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
466                 return -1;
467         }
468         if (!args.header_number) {
469                 number = 1;
470         } else {
471                 sscanf(args.header_number, "%30d", &number);
472                 if (number < 1) {
473                         number = 1;
474                 }
475         }
476
477         header_data.channel = channel;
478         header_data.header_name = args.header_name;
479         header_data.header_number = number;
480         header_data.header_value = NULL;
481         header_data.buf = buf;
482         header_data.len = len;
483
484         if (stricmp(args.action, "read") == 0) {
485                 return ast_sip_push_task_synchronous(channel->session->serializer, read_header,
486                                                                                          &header_data);
487         } else if (stricmp(args.action, "remove") == 0) {
488                 return ast_sip_push_task_synchronous(channel->session->serializer, remove_header,
489                                                                                          &header_data);
490         } else {
491                 ast_log(AST_LOG_ERROR,
492                                 "Unknown action \'%s\' is not valid,  Must be \'read\' or \'remove\'.\n",
493                                 args.action);
494                 return -1;
495         }
496 }
497
498 /*!
499  * \brief Implements function 'write' callback.
500  *
501  * Valid actions are 'add', 'update' and 'remove'.
502  */
503 static int func_write_header(struct ast_channel *chan, const char *cmd, char *data,
504                                                          const char *value)
505 {
506         struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
507         struct header_data header_data;
508         int header_number;
509         AST_DECLARE_APP_ARGS(args,
510                                                  AST_APP_ARG(action);
511                                                  AST_APP_ARG(header_name); AST_APP_ARG(header_number););
512         AST_STANDARD_APP_ARGS(args, data);
513
514         if (!channel || strncmp(ast_channel_name(chan), "PJSIP/", 6)) {
515                 ast_log(LOG_ERROR, "This function requires a PJSIP channel.\n");
516                 return -1;
517         }
518
519         if (ast_strlen_zero(args.action)) {
520                 ast_log(AST_LOG_ERROR, "This function requires an action.\n");
521                 return -1;
522         }
523         if (ast_strlen_zero(args.header_name)) {
524                 ast_log(AST_LOG_ERROR, "This function requires a header name.\n");
525                 return -1;
526         }
527         if (!args.header_number) {
528                 header_number = 1;
529         } else {
530                 sscanf(args.header_number, "%30d", &header_number);
531                 if (header_number < 1) {
532                         header_number = 1;
533                 }
534         }
535
536         header_data.channel = channel;
537         header_data.header_name = args.header_name;
538         header_data.header_number = header_number;
539         header_data.header_value = value;
540         header_data.buf = NULL;
541         header_data.len = 0;
542
543         if (stricmp(args.action, "add") == 0) {
544                 return ast_sip_push_task_synchronous(channel->session->serializer, add_header,
545                                                                                          &header_data);
546         } else if (stricmp(args.action, "update") == 0) {
547                 return ast_sip_push_task_synchronous(channel->session->serializer, update_header,
548                                                                                          &header_data);
549         } else if (stricmp(args.action, "remove") == 0) {
550                 return ast_sip_push_task_synchronous(channel->session->serializer, remove_header,
551                                                                                          &header_data);
552         } else {
553                 ast_log(AST_LOG_ERROR,
554                                 "Unknown action \'%s\' is not valid,  Must be \'add\', \'update\', or \'remove\'.\n",
555                                 args.action);
556                 return -1;
557         }
558 }
559
560 static struct ast_custom_function pjsip_header_function = {
561         .name = "PJSIP_HEADER",
562         .read = func_read_header,
563         .write = func_write_header,
564 };
565
566 /*!
567  * \internal
568  * \brief Session supplement callback for outgoing INVITE requests
569  *
570  * Retrieve the header_datastore from the session.
571  * Add each header in the list to the outgoing message.
572  *
573  * These pjsip_hdr structures will have been created by add_header.
574  * Because outgoing_request may be called more than once with the same header
575  * list (as in the case of an authentication exchange), each pjsip_hdr structure
576  * MUST be newly cloned for each outgoing message.
577  */
578 static void outgoing_request(struct ast_sip_session *session, pjsip_tx_data * tdata)
579 {
580         pj_pool_t *pool = session->inv_session->dlg->pool;
581         struct hdr_list *list;
582         struct hdr_list_entry *le;
583         RAII_VAR(struct ast_datastore *, datastore,
584                          ast_sip_session_get_datastore(session, header_datastore.type), ao2_cleanup);
585
586         if (!datastore || !datastore->data ||
587                 (session->inv_session->state >= PJSIP_INV_STATE_CONFIRMED)) {
588                 return;
589         }
590
591         list = datastore->data;
592         AST_LIST_TRAVERSE(list, le, nextptr) {
593                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) pjsip_hdr_clone(pool, le->hdr));
594         }
595 }
596
597 static struct ast_sip_session_supplement header_funcs_supplement = {
598         .method = "INVITE",
599         .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 1000,
600         .incoming_request = incoming_request,
601         .outgoing_request = outgoing_request,
602 };
603
604 static int load_module(void)
605 {
606         ast_sip_session_register_supplement(&header_funcs_supplement);
607         ast_custom_function_register(&pjsip_header_function);
608
609         return AST_MODULE_LOAD_SUCCESS;
610 }
611
612 static int unload_module(void)
613 {
614         ast_custom_function_unregister(&pjsip_header_function);
615         ast_sip_session_unregister_supplement(&header_funcs_supplement);
616         return 0;
617 }
618
619 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Header Functions",.load =
620                                 load_module,.unload = unload_module,.load_pri = AST_MODPRI_APP_DEPEND,);