Asterisk - The Open Source Telephony Project  GIT-master-a24979a
res_pjsip.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Mark Michelson <mmichelson@digium.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 #include "asterisk.h"
20 
21 #include <pjsip.h>
22 /* Needed for SUBSCRIBE, NOTIFY, and PUBLISH method definitions */
23 #include <pjsip_simple.h>
24 #include <pjsip/sip_transaction.h>
25 #include <pj/timer.h>
26 #include <pjlib.h>
27 #include <pjmedia/errno.h>
28 
29 #include "asterisk/res_pjsip.h"
31 #include "asterisk/linkedlists.h"
32 #include "asterisk/logger.h"
33 #include "asterisk/lock.h"
34 #include "asterisk/utils.h"
35 #include "asterisk/astobj2.h"
36 #include "asterisk/module.h"
37 #include "asterisk/serializer.h"
38 #include "asterisk/threadpool.h"
39 #include "asterisk/taskprocessor.h"
40 #include "asterisk/uuid.h"
41 #include "asterisk/sorcery.h"
42 #include "asterisk/file.h"
43 #include "asterisk/cli.h"
44 #include "asterisk/res_pjsip_cli.h"
45 #include "asterisk/test.h"
47 #include "asterisk/res_pjproject.h"
48 
49 /*** MODULEINFO
50  <depend>pjproject</depend>
51  <depend>res_pjproject</depend>
52  <depend>res_sorcery_config</depend>
53  <depend>res_sorcery_memory</depend>
54  <depend>res_sorcery_astdb</depend>
55  <use type="module">res_statsd</use>
56  <support_level>core</support_level>
57  ***/
58 
59 #define MOD_DATA_CONTACT "contact"
60 
61 /*! Number of serializers in pool if one not supplied. */
62 #define SERIALIZER_POOL_SIZE 8
63 
64 /*! Pool of serializers to use if not supplied. */
66 
67 static pjsip_endpoint *ast_pjsip_endpoint;
68 
70 
71 /*! Local host address for IPv4 */
72 static pj_sockaddr host_ip_ipv4;
73 
74 /*! Local host address for IPv4 (string form) */
75 static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN];
76 
77 /*! Local host address for IPv6 */
78 static pj_sockaddr host_ip_ipv6;
79 
80 /*! Local host address for IPv6 (string form) */
81 static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN];
82 
83 void ast_sip_add_date_header(pjsip_tx_data *tdata)
84 {
85  char date[256];
86  struct tm tm;
87  time_t t = time(NULL);
88 
89  gmtime_r(&t, &tm);
90  strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
91 
92  ast_sip_add_header(tdata, "Date", date);
93 }
94 
95 static int register_service(void *data)
96 {
97  pjsip_module **module = data;
98  if (!ast_pjsip_endpoint) {
99  ast_log(LOG_ERROR, "There is no PJSIP endpoint. Unable to register services\n");
100  return -1;
101  }
102  if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
103  ast_log(LOG_ERROR, "Unable to register module %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
104  return -1;
105  }
106  ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
107  return 0;
108 }
109 
110 int ast_sip_register_service(pjsip_module *module)
111 {
113 }
114 
115 static int unregister_service(void *data)
116 {
117  pjsip_module **module = data;
118  if (!ast_pjsip_endpoint) {
119  return -1;
120  }
121  pjsip_endpt_unregister_module(ast_pjsip_endpoint, *module);
122  ast_debug(1, "Unregistered SIP service %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
123  return 0;
124 }
125 
126 void ast_sip_unregister_service(pjsip_module *module)
127 {
129 }
130 
132 
134 {
136  ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
137  return -1;
138  }
140  ast_debug(1, "Registered SIP authenticator module %p\n", auth);
141 
142  return 0;
143 }
144 
146 {
147  if (registered_authenticator != auth) {
148  ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
150  return;
151  }
153  ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
154 }
155 
156 int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
157 {
158  if (endpoint->allow_unauthenticated_options
159  && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
160  ast_debug(3, "Skipping OPTIONS authentication due to endpoint configuration\n");
161  return 0;
162  }
163 
165  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
166  return 0;
167  }
168 
169  return registered_authenticator->requires_authentication(endpoint, rdata);
170 }
171 
173  pjsip_rx_data *rdata, pjsip_tx_data *tdata)
174 {
176  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
178  }
179  return registered_authenticator->check_authentication(endpoint, rdata, tdata);
180 }
181 
183 
185 {
187  ast_log(LOG_WARNING, "Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
188  return -1;
189  }
191  ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
192 
193  return 0;
194 }
195 
197 {
198  if (registered_outbound_authenticator != auth) {
199  ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
201  return;
202  }
204  ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
205 }
206 
207 int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge,
208  pjsip_tx_data *old_request, pjsip_tx_data **new_request)
209 {
211  ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
212  return -1;
213  }
214  return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
215 }
216 
218  const char *name;
219  unsigned int priority;
222 };
223 
225 
227  const char *name)
228 {
229  char *prev, *current, *identifier_order;
230  struct endpoint_identifier_list *iter, *id_list_item;
232 
233  id_list_item = ast_calloc(1, sizeof(*id_list_item));
234  if (!id_list_item) {
235  ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
236  return -1;
237  }
238  id_list_item->identifier = identifier;
239  id_list_item->name = name;
240 
241  ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
242 
243  if (ast_strlen_zero(name)) {
244  /* if an identifier has no name then place in front */
245  AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
246  return 0;
247  }
248 
249  /* see if the name of the identifier is in the global endpoint_identifier_order list */
250  identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
251 
252  if (ast_strlen_zero(identifier_order)) {
253  id_list_item->priority = UINT_MAX;
254  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
255  ast_free(identifier_order);
256  return 0;
257  }
258 
259  id_list_item->priority = 0;
260  while ((current = strchr(current, ','))) {
261  ++id_list_item->priority;
262  if (!strncmp(prev, name, current - prev)
263  && strlen(name) == current - prev) {
264  break;
265  }
266  prev = ++current;
267  }
268 
269  if (!current) {
270  /* check to see if it is the only or last item */
271  if (!strcmp(prev, name)) {
272  ++id_list_item->priority;
273  } else {
274  id_list_item->priority = UINT_MAX;
275  }
276  }
277 
278  if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
279  /* if not in the endpoint_identifier_order list then consider it less in
280  priority and add it to the end */
281  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
282  ast_free(identifier_order);
283  return 0;
284  }
285 
287  if (id_list_item->priority < iter->priority) {
288  AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
289  break;
290  }
291 
292  if (!AST_RWLIST_NEXT(iter, list)) {
293  AST_RWLIST_INSERT_AFTER(&endpoint_identifiers, iter, id_list_item, list);
294  break;
295  }
296  }
298 
299  ast_free(identifier_order);
300  return 0;
301 }
302 
304 {
306 }
307 
309 {
310  struct endpoint_identifier_list *iter;
313  if (iter->identifier == identifier) {
315  ast_free(iter);
316  ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
317  break;
318  }
319  }
321 }
322 
323 struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata)
324 {
325  struct endpoint_identifier_list *iter;
326  struct ast_sip_endpoint *endpoint = NULL;
330  endpoint = iter->identifier->identify_endpoint(rdata);
331  if (endpoint) {
332  break;
333  }
334  }
335  return endpoint;
336 }
337 
338 char *ast_sip_rdata_get_header_value(pjsip_rx_data *rdata, const pj_str_t str)
339 {
340  pjsip_generic_string_hdr *hdr;
341  pj_str_t hdr_val;
342 
343  hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
344  if (!hdr) {
345  return NULL;
346  }
347 
348  pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
349 
350  return hdr_val.ptr;
351 }
352 
353 static int do_cli_dump_endpt(void *v_a)
354 {
355  struct ast_cli_args *a = v_a;
356 
358  pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
360 
361  return 0;
362 }
363 
364 static char *cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
365 {
366  switch (cmd) {
367  case CLI_INIT:
368 #ifdef AST_DEVMODE
369  e->command = "pjsip dump endpt [details]";
370  e->usage =
371  "Usage: pjsip dump endpt [details]\n"
372  " Dump the res_pjsip endpt internals.\n"
373  "\n"
374  "Warning: PJPROJECT documents that the function used by this\n"
375  "CLI command may cause a crash when asking for details because\n"
376  "it tries to access all active memory pools.\n";
377 #else
378  /*
379  * In non-developer mode we will not document or make easily accessible
380  * the details option even though it is still available. The user has
381  * to know it exists to use it. Presumably they would also be aware of
382  * the potential crash warning.
383  */
384  e->command = "pjsip dump endpt";
385  e->usage =
386  "Usage: pjsip dump endpt\n"
387  " Dump the res_pjsip endpt internals.\n";
388 #endif /* AST_DEVMODE */
389  return NULL;
390  case CLI_GENERATE:
391  return NULL;
392  }
393 
394  if (4 < a->argc
395  || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
396  return CLI_SHOWUSAGE;
397  }
398 
400 
401  return CLI_SUCCESS;
402 }
403 
404 static char *cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
405 {
406 #define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
407  struct endpoint_identifier_list *iter;
408 
409  switch (cmd) {
410  case CLI_INIT:
411  e->command = "pjsip show identifiers";
412  e->usage = "Usage: pjsip show identifiers\n"
413  " List all registered endpoint identifiers\n";
414  return NULL;
415  case CLI_GENERATE:
416  return NULL;
417  }
418 
419  if (a->argc != 3) {
420  return CLI_SHOWUSAGE;
421  }
422 
423  ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
424  {
428  iter->name ? iter->name : "name not specified");
429  }
430  }
431  return CLI_SUCCESS;
432 #undef ENDPOINT_IDENTIFIER_FORMAT
433 }
434 
435 static char *cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
436 {
438 
439  switch (cmd) {
440  case CLI_INIT:
441  e->command = "pjsip show settings";
442  e->usage = "Usage: pjsip show settings\n"
443  " Show global and system configuration options\n";
444  return NULL;
445  case CLI_GENERATE:
446  return NULL;
447  }
448 
449  context.output_buffer = ast_str_create(256);
450  if (!context.output_buffer) {
451  ast_cli(a->fd, "Could not allocate output buffer.\n");
452  return CLI_FAILURE;
453  }
454 
456  ast_free(context.output_buffer);
457  ast_cli(a->fd, "Error retrieving settings.\n");
458  return CLI_FAILURE;
459  }
460 
461  ast_cli(a->fd, "%s", ast_str_buffer(context.output_buffer));
462  ast_free(context.output_buffer);
463  return CLI_SUCCESS;
464 }
465 
466 static struct ast_cli_entry cli_commands[] = {
467  AST_CLI_DEFINE(cli_dump_endpt, "Dump the res_pjsip endpt internals"),
468  AST_CLI_DEFINE(cli_show_settings, "Show global and system configuration options"),
469  AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
470 };
471 
473 
475 {
478 }
479 
481 {
482  struct ast_sip_endpoint_formatter *i;
484 
486  if (i == obj) {
488  break;
489  }
490  }
492 }
493 
495  struct ast_sip_ami *ami, int *count)
496 {
497  int res = 0;
498  struct ast_sip_endpoint_formatter *i;
500  *count = 0;
502  if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
503  return res;
504  }
505 
506  if (!res) {
507  (*count)++;
508  }
509  }
510  return 0;
511 }
512 
513 pjsip_endpoint *ast_sip_get_pjsip_endpoint(void)
514 {
515  return ast_pjsip_endpoint;
516 }
517 
518 int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint,
519  pjsip_rx_data *rdata)
520 {
521  pj_str_t host_name;
522  int result = 1;
523 
524  /* Determine if the contact cannot survive a restart/boot. */
525  if (uri->port == rdata->pkt_info.src_port
526  && !pj_strcmp(&uri->host,
527  pj_cstr(&host_name, rdata->pkt_info.src_name))
528  /* We have already checked if the URI scheme is sip: or sips: */
529  && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
530  pj_str_t type_name;
531 
532  /* Determine the transport parameter value */
533  if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
534  /* WSS is special, as it needs to be ws. */
535  pj_cstr(&type_name, "ws");
536  } else {
537  pj_cstr(&type_name, rdata->tp_info.transport->type_name);
538  }
539 
540  if (!pj_stricmp(&uri->transport_param, &type_name)
541  && (endpoint->nat.rewrite_contact
542  /* Websockets are always rewritten */
543  || !pj_stricmp(&uri->transport_param,
544  pj_cstr(&type_name, "ws")))) {
545  /*
546  * The contact was rewritten to the reliable transport's
547  * source address. Disconnecting the transport for any
548  * reason invalidates the contact.
549  */
550  result = 0;
551  }
552  }
553 
554  return result;
555 }
556 
557 int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint,
558  pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
559 {
560  char *host = NULL;
561  static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
562  pjsip_param *x_transport;
563 
564  if (!ast_strlen_zero(endpoint->transport)) {
565  ast_copy_string(buf, endpoint->transport, buf_len);
566  return 0;
567  }
568 
569  x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
570  if (!x_transport) {
571  return -1;
572  }
573 
574  /* Only use x_transport if the uri host is an ip (4 or 6) address */
575  host = ast_alloca(sip_uri->host.slen + 1);
576  ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
578  return -1;
579  }
580 
581  ast_copy_pj_str(buf, &x_transport->value, buf_len);
582 
583  return 0;
584 }
585 
586 int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,
587  pjsip_tpselector *selector)
588 {
589  pjsip_sip_uri *uri;
590  pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
591 
592  uri = pjsip_uri_get_uri(dlg->target);
593  if (!selector) {
594  selector = &sel;
595  }
596 
597  ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
598 
599  pjsip_dlg_set_transport(dlg, selector);
600 
601  if (selector == &sel) {
603  }
604 
605  return 0;
606 }
607 
608 static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user,
609  const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
610 {
611  pj_str_t tmp, local_addr;
612  pjsip_uri *uri;
613  pjsip_sip_uri *sip_uri;
614  pjsip_transport_type_e type;
615  int local_port;
616  char default_user[PJSIP_MAX_URL_SIZE];
617 
618  if (ast_strlen_zero(user)) {
619  ast_sip_get_default_from_user(default_user, sizeof(default_user));
620  user = default_user;
621  }
622 
623  /* Parse the provided target URI so we can determine what transport it will end up using */
624  pj_strdup_with_null(pool, &tmp, target);
625 
626  if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
627  (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
628  return -1;
629  }
630 
631  sip_uri = pjsip_uri_get_uri(uri);
632 
633  /* Determine the transport type to use */
634  type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
635  if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
636  if (type == PJSIP_TRANSPORT_UNSPECIFIED
637  || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
638  type = PJSIP_TRANSPORT_TLS;
639  }
640  } else if (!sip_uri->transport_param.slen) {
641  type = PJSIP_TRANSPORT_UDP;
642  } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
643  return -1;
644  }
645 
646  /* If the host is IPv6 turn the transport into an IPv6 version */
647  if (pj_strchr(&sip_uri->host, ':')) {
648  type |= PJSIP_TRANSPORT_IPV6;
649  }
650 
651  /* In multidomain scenario, username may contain @ with domain info */
652  if (!ast_sip_get_disable_multi_domain() && strchr(user, '@')) {
653  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
654  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
655  "<sip:%s%s%s>",
656  user,
657  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
658  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
659  return 0;
660  }
661 
662  if (!ast_strlen_zero(domain)) {
663  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
664  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
665  "<sip:%s@%s%s%s>",
666  user,
667  domain,
668  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
669  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
670  return 0;
671  }
672 
673  /* Get the local bound address for the transport that will be used when communicating with the provided URI */
674  if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
675  &local_addr, &local_port) != PJ_SUCCESS) {
676 
677  /* If no local address can be retrieved using the transport manager use the host one */
678  pj_strdup(pool, &local_addr, pj_gethostname());
679  local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
680  }
681 
682  /* If IPv6 was specified in the transport, set the proper type */
683  if (pj_strchr(&local_addr, ':')) {
684  type |= PJSIP_TRANSPORT_IPV6;
685  }
686 
687  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
688  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
689  "<sip:%s@%s%.*s%s:%d%s%s>",
690  user,
691  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
692  (int)local_addr.slen,
693  local_addr.ptr,
694  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
695  local_port,
696  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
697  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
698 
699  return 0;
700 }
701 
702 int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
703 {
704  int res = 0;
705  struct ast_sip_transport_state *transport_state;
706 
708  if (!transport_state) {
709  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
711  return -1;
712  }
713 
714  /* Only flows maintain dynamic state which needs protection */
715  if (transport_state->flow) {
716  ao2_lock(transport_state);
717  }
718 
719  if (transport_state->transport) {
720  selector->type = PJSIP_TPSELECTOR_TRANSPORT;
721  selector->u.transport = transport_state->transport;
722  pjsip_transport_add_ref(selector->u.transport);
723  } else if (transport_state->factory) {
724  selector->type = PJSIP_TPSELECTOR_LISTENER;
725  selector->u.listener = transport_state->factory;
726  } else if (transport->type == AST_TRANSPORT_WS || transport->type == AST_TRANSPORT_WSS) {
727  /* The WebSocket transport has no factory as it can not create outgoing connections, so
728  * even if an endpoint is locked to a WebSocket transport we let the PJSIP logic
729  * find the existing connection if available and use it.
730  */
731  } else if (transport->flow) {
732  /* This is a child of another transport, so we need to establish a new connection */
733 #ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
734  selector->disable_connection_reuse = PJ_TRUE;
735 #else
736  ast_log(LOG_WARNING, "Connection reuse could not be disabled on transport '%s' as support is not available\n",
738 #endif
739  } else {
740  res = -1;
741  }
742 
743  if (transport_state->flow) {
744  ao2_unlock(transport_state);
745  }
746 
747  ao2_ref(transport_state, -1);
748 
749  return res;
750 }
751 
752 int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
753 {
755 
756  if (ast_strlen_zero(transport_name)) {
757  return 0;
758  }
759 
760  transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
761  if (!transport) {
762  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
763  transport_name);
764  return -1;
765  }
766 
768 }
769 
771  pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
772 {
773  char transport_name[128];
774 
775  if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name, sizeof(transport_name))) {
776  return 0;
777  }
778 
779  return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
780 }
781 
782 void ast_sip_tpselector_unref(pjsip_tpselector *selector)
783 {
784  if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
785  pjsip_transport_dec_ref(selector->u.transport);
786  }
787 }
788 
789 void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
790 {
791  pjsip_sip_uri *sip_uri;
792  int i = 0;
793  static const pj_str_t STR_PHONE = { "phone", 5 };
794 
795  if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
796  return;
797  }
798 
799  sip_uri = pjsip_uri_get_uri(uri);
800 
801  if (!pj_strlen(&sip_uri->user)) {
802  return;
803  }
804 
805  if (pj_strbuf(&sip_uri->user)[0] == '+') {
806  i = 1;
807  }
808 
809  /* Test URI user against allowed characters in AST_DIGIT_ANY */
810  for (; i < pj_strlen(&sip_uri->user); i++) {
811  if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
812  break;
813  }
814  }
815 
816  if (i < pj_strlen(&sip_uri->user)) {
817  return;
818  }
819 
820  sip_uri->user_param = STR_PHONE;
821 }
822 
823 pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
824  const char *uri, const char *request_user)
825 {
826  char enclosed_uri[PJSIP_MAX_URL_SIZE];
827  pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri, target_uri;
828  pj_status_t res;
829  pjsip_dialog *dlg = NULL;
830  const char *outbound_proxy = endpoint->outbound_proxy;
831  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
832  static const pj_str_t HCONTACT = { "Contact", 7 };
833 
834  snprintf(enclosed_uri, sizeof(enclosed_uri), "<%s>", uri);
835  pj_cstr(&remote_uri, enclosed_uri);
836 
837  pj_cstr(&target_uri, uri);
838 
839  res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
840  if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
841  /* dlg->target is a pjsip_other_uri, but it's assumed to be a
842  * pjsip_sip_uri below. Fail fast. */
843  res = PJSIP_EINVALIDURI;
844  pjsip_dlg_terminate(dlg);
845  }
846  if (res != PJ_SUCCESS) {
847  if (res == PJSIP_EINVALIDURI) {
849  "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
850  ast_sorcery_object_get_id(endpoint), uri);
851  }
852  return NULL;
853  }
854 
855  /* We have to temporarily bump up the sess_count here so the dialog is not prematurely destroyed */
856  dlg->sess_count++;
857 
858  ast_sip_dlg_set_transport(endpoint, dlg, &selector);
859 
860  if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->fromuser, endpoint->fromdomain, &remote_uri, &selector)) {
861  dlg->sess_count--;
862  pjsip_dlg_terminate(dlg);
863  ast_sip_tpselector_unref(&selector);
864  return NULL;
865  }
866 
867  ast_sip_tpselector_unref(&selector);
868 
869  /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
870  pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
871  dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
872  if (!dlg->local.info->uri) {
874  "Could not parse URI '%s' for endpoint '%s'\n",
875  dlg->local.info_str.ptr, ast_sorcery_object_get_id(endpoint));
876  dlg->sess_count--;
877  pjsip_dlg_terminate(dlg);
878  return NULL;
879  }
880 
881  dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
882 
883  if (!ast_strlen_zero(endpoint->contact_user)) {
884  pjsip_sip_uri *sip_uri;
885 
886  sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
887  pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
888  }
889 
890  /* If a request user has been specified and we are permitted to change it, do so */
891  if (!ast_strlen_zero(request_user)) {
892  pjsip_sip_uri *sip_uri;
893 
894  if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
895  sip_uri = pjsip_uri_get_uri(dlg->target);
896  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
897  }
898  if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
899  sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
900  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
901  }
902  }
903 
904  /* Add the user=phone parameter if applicable */
905  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
906  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.info->uri);
907 
908  if (!ast_strlen_zero(outbound_proxy)) {
909  pjsip_route_hdr route_set, *route;
910  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
911  pj_str_t tmp;
912 
913  pj_list_init(&route_set);
914 
915  pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
916  if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
917  ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
918  ast_sorcery_object_get_id(endpoint), outbound_proxy);
919  dlg->sess_count--;
920  pjsip_dlg_terminate(dlg);
921  return NULL;
922  }
923  pj_list_insert_nodes_before(&route_set, route);
924 
925  pjsip_dlg_set_route_set(dlg, &route_set);
926  }
927 
928  dlg->sess_count--;
929 
930  return dlg;
931 }
932 
933 /*!
934  * \brief Determine if a SIPS Contact header is required.
935  *
936  * This uses the guideline provided in RFC 3261 Section 12.1.1 to
937  * determine if the Contact header must be a sips: URI.
938  *
939  * \param rdata The incoming dialog-starting request
940  * \retval 0 SIPS not required
941  * \retval 1 SIPS required
942  */
943 static int uas_use_sips_contact(pjsip_rx_data *rdata)
944 {
945  pjsip_rr_hdr *record_route;
946 
947  if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
948  return 1;
949  }
950 
951  record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
952  if (record_route) {
953  if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
954  return 1;
955  }
956  } else {
957  pjsip_contact_hdr *contact;
958 
959  contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
960  ast_assert(contact != NULL);
961  if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
962  return 1;
963  }
964  }
965 
966  return 0;
967 }
968 
969 typedef pj_status_t (*create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata,
970  const pj_str_t *contact, pjsip_dialog **p_dlg);
971 
972 static pjsip_dialog *create_dialog_uas(const struct ast_sip_endpoint *endpoint,
973  pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
974 {
975  pjsip_dialog *dlg;
976  pj_str_t contact;
977  pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
978  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
979  pjsip_transport *transport;
980  pjsip_contact_hdr *contact_hdr;
981 
982  ast_assert(status != NULL);
983 
984  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
985  if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
986  &selector)) {
987  return NULL;
988  }
989 
990  transport = rdata->tp_info.transport;
991  if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
992  transport = selector.u.transport;
993  }
994  type = transport->key.type;
995 
996  contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
997  contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
998  "<%s:%s%.*s%s:%d%s%s>",
999  uas_use_sips_contact(rdata) ? "sips" : "sip",
1000  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1001  (int)transport->local_name.host.slen,
1002  transport->local_name.host.ptr,
1003  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1004  transport->local_name.port,
1005  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1006  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
1007 
1008  *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
1009  if (*status != PJ_SUCCESS) {
1010  char err[PJ_ERR_MSG_SIZE];
1011 
1012  pj_strerror(*status, err, sizeof(err));
1013  ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
1014  ast_sorcery_object_get_id(endpoint), err);
1015  ast_sip_tpselector_unref(&selector);
1016  return NULL;
1017  }
1018 
1019  dlg->sess_count++;
1020  pjsip_dlg_set_transport(dlg, &selector);
1021  dlg->sess_count--;
1022 
1023  ast_sip_tpselector_unref(&selector);
1024 
1025  return dlg;
1026 }
1027 
1028 pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
1029 {
1030 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1031  pjsip_dialog *dlg;
1032 
1033  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1034  if (dlg) {
1035  pjsip_dlg_dec_lock(dlg);
1036  }
1037 
1038  return dlg;
1039 #else
1040  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1041 #endif
1042 }
1043 
1044 pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
1045  pjsip_rx_data *rdata, pj_status_t *status)
1046 {
1047 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1048  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1049 #else
1050  /*
1051  * This is put here in order to be compatible with older versions of pjproject.
1052  * Best we can do in this case is immediately lock after getting the dialog.
1053  * However, that does leave a "gap" between creating and locking.
1054  */
1055  pjsip_dialog *dlg;
1056 
1057  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1058  if (dlg) {
1059  pjsip_dlg_inc_lock(dlg);
1060  }
1061 
1062  return dlg;
1063 #endif
1064  }
1065 
1066 int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
1067  char *transport_type, const char *local_name, int local_port, const char *contact)
1068 {
1069  pj_str_t tmp;
1070 
1071  /*
1072  * Initialize the error list in case there is a parse error
1073  * in the given packet.
1074  */
1075  pj_list_init(&rdata->msg_info.parse_err);
1076 
1077  rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
1078  if (!rdata->tp_info.transport) {
1079  return -1;
1080  }
1081 
1082  ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
1083  ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
1084  rdata->pkt_info.src_port = src_port;
1085  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
1086  pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
1087 
1088  pjsip_parse_rdata(packet, strlen(packet), rdata);
1089  if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
1090  return -1;
1091  }
1092 
1093  if (!ast_strlen_zero(contact)) {
1094  pjsip_contact_hdr *contact_hdr;
1095 
1096  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1097  if (contact_hdr) {
1098  contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (char *)contact,
1099  strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
1100  if (!contact_hdr->uri) {
1101  ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact);
1102  return -1;
1103  }
1104  }
1105  }
1106 
1107  pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
1108  rdata->msg_info.via->rport_param = -1;
1109 
1110  rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
1111  rdata->tp_info.transport->type_name = transport_type;
1112  pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
1113  rdata->tp_info.transport->local_name.port = local_port;
1114 
1115  return 0;
1116 }
1117 
1118 int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
1119  char *transport_type, const char *local_name, int local_port)
1120 {
1121  return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
1122  local_name, local_port, NULL);
1123 }
1124 
1125 /* PJSIP doesn't know about the INFO method, so we have to define it ourselves */
1126 static const pjsip_method info_method = {PJSIP_OTHER_METHOD, {"INFO", 4} };
1127 static const pjsip_method message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} };
1128 
1129 static struct {
1130  const char *method;
1131  const pjsip_method *pmethod;
1132 } methods [] = {
1133  { "INVITE", &pjsip_invite_method },
1134  { "CANCEL", &pjsip_cancel_method },
1135  { "ACK", &pjsip_ack_method },
1136  { "BYE", &pjsip_bye_method },
1137  { "REGISTER", &pjsip_register_method },
1138  { "OPTIONS", &pjsip_options_method },
1139  { "SUBSCRIBE", &pjsip_subscribe_method },
1140  { "NOTIFY", &pjsip_notify_method },
1141  { "PUBLISH", &pjsip_publish_method },
1142  { "INFO", &info_method },
1143  { "MESSAGE", &message_method },
1144 };
1145 
1146 static const pjsip_method *get_pjsip_method(const char *method)
1147 {
1148  int i;
1149  for (i = 0; i < ARRAY_LEN(methods); ++i) {
1150  if (!strcmp(method, methods[i].method)) {
1151  return methods[i].pmethod;
1152  }
1153  }
1154  return NULL;
1155 }
1156 
1157 static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
1158 {
1159  if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
1160  ast_log(LOG_WARNING, "Unable to create in-dialog request.\n");
1161  return -1;
1162  }
1163 
1164  return 0;
1165 }
1166 
1167 static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata);
1168 static pjsip_module supplement_module = {
1169  .name = { "Out of dialog supplement hook", 29 },
1170  .id = -1,
1171  .priority = PJSIP_MOD_PRIORITY_APPLICATION - 1,
1172  .on_rx_request = supplement_on_rx_request,
1173 };
1174 
1175 static int create_out_of_dialog_request(const pjsip_method *method, struct ast_sip_endpoint *endpoint,
1176  const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
1177 {
1178  RAII_VAR(struct ast_sip_contact *, contact, ao2_bump(provided_contact), ao2_cleanup);
1179  pj_str_t remote_uri;
1180  pj_str_t from;
1181  pj_pool_t *pool;
1182  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1183  pjsip_uri *sip_uri;
1184  const char *fromuser;
1185 
1186  if (ast_strlen_zero(uri)) {
1187  if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
1188  ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
1189  return -1;
1190  }
1191 
1192  if (!contact) {
1194  }
1195  if (!contact || ast_strlen_zero(contact->uri)) {
1196  ast_log(LOG_WARNING, "Unable to retrieve contact for endpoint %s\n",
1197  ast_sorcery_object_get_id(endpoint));
1198  return -1;
1199  }
1200 
1201  pj_cstr(&remote_uri, contact->uri);
1202  } else {
1203  pj_cstr(&remote_uri, uri);
1204  }
1205 
1206  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
1207 
1208  if (!pool) {
1209  ast_log(LOG_ERROR, "Unable to create PJLIB memory pool\n");
1210  return -1;
1211  }
1212 
1213  sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
1214  if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
1215  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
1216  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1217  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
1218  pj_strbuf(&remote_uri));
1219  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1220  return -1;
1221  }
1222 
1223  ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
1224 
1225  fromuser = endpoint ? (!ast_strlen_zero(endpoint->fromuser) ? endpoint->fromuser : ast_sorcery_object_get_id(endpoint)) : NULL;
1226  if (sip_dialog_create_from(pool, &from, fromuser,
1227  endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
1228  ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
1229  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1230  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1231  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1232  ast_sip_tpselector_unref(&selector);
1233  return -1;
1234  }
1235 
1236  if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
1237  &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
1238  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s\n",
1239  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1240  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1241  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1242  ast_sip_tpselector_unref(&selector);
1243  return -1;
1244  }
1245 
1246  pjsip_tx_data_set_transport(*tdata, &selector);
1247 
1248  ast_sip_tpselector_unref(&selector);
1249 
1250  if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
1251  pjsip_contact_hdr *contact_hdr;
1252  pjsip_sip_uri *contact_uri;
1253  static const pj_str_t HCONTACT = { "Contact", 7 };
1254  static const pj_str_t HCONTACTSHORT = { "m", 1 };
1255 
1256  contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
1257  if (contact_hdr) {
1258  contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
1259  pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->contact_user);
1260  }
1261  }
1262 
1263  /* Add the user=phone parameter if applicable */
1264  ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
1265 
1266  /* If an outbound proxy is specified on the endpoint apply it to this request */
1267  if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
1268  ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
1269  ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
1270  (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
1271  endpoint->outbound_proxy);
1272  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1273  return -1;
1274  }
1275 
1276  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
1277 
1278  /* We can release this pool since request creation copied all the necessary
1279  * data into the outbound request's pool
1280  */
1281  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1282  return 0;
1283 }
1284 
1285 int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg,
1286  struct ast_sip_endpoint *endpoint, const char *uri,
1287  struct ast_sip_contact *contact, pjsip_tx_data **tdata)
1288 {
1289  const pjsip_method *pmethod = get_pjsip_method(method);
1290 
1291  if (!pmethod) {
1292  ast_log(LOG_WARNING, "Unknown method '%s'. Cannot send request\n", method);
1293  return -1;
1294  }
1295 
1296  if (dlg) {
1297  return create_in_dialog_request(pmethod, dlg, tdata);
1298  } else {
1299  ast_assert(endpoint != NULL);
1300  return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
1301  }
1302 }
1303 
1305 
1307 {
1308  struct ast_sip_supplement *iter;
1309  int inserted = 0;
1311 
1313  if (iter->priority > supplement->priority) {
1315  inserted = 1;
1316  break;
1317  }
1318  }
1320 
1321  if (!inserted) {
1322  AST_RWLIST_INSERT_TAIL(&supplements, supplement, next);
1323  }
1324 }
1325 
1327 {
1328  struct ast_sip_supplement *iter;
1330 
1332  if (supplement == iter) {
1334  break;
1335  }
1336  }
1338 }
1339 
1340 static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
1341 {
1342  if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
1343  ast_log(LOG_WARNING, "Unable to send in-dialog request.\n");
1344  return -1;
1345  }
1346  return 0;
1347 }
1348 
1349 static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
1350 {
1351  pj_str_t method;
1352 
1353  if (ast_strlen_zero(supplement_method)) {
1354  return PJ_TRUE;
1355  }
1356 
1357  pj_cstr(&method, supplement_method);
1358 
1359  return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
1360 }
1361 
1362 #define TIMER_INACTIVE 0
1363 #define TIMEOUT_TIMER2 5
1364 
1365 /*! \brief Structure to hold information about an outbound request */
1367  /*! The endpoint associated with this request */
1369  /*! Information to be provided to the callback upon receipt of a response */
1370  void *token;
1371  /*! The callback to be called upon receipt of a response */
1372  void (*callback)(void *token, pjsip_event *e);
1373  /*! Number of challenges received. */
1374  unsigned int challenge_count;
1375 };
1376 
1377 static void send_request_data_destroy(void *obj)
1378 {
1379  struct send_request_data *req_data = obj;
1380 
1381  ao2_cleanup(req_data->endpoint);
1382 }
1383 
1385  void *token, void (*callback)(void *token, pjsip_event *e))
1386 {
1387  struct send_request_data *req_data;
1388 
1389  req_data = ao2_alloc_options(sizeof(*req_data), send_request_data_destroy,
1391  if (!req_data) {
1392  return NULL;
1393  }
1394 
1395  req_data->endpoint = ao2_bump(endpoint);
1396  req_data->token = token;
1397  req_data->callback = callback;
1398 
1399  return req_data;
1400 }
1401 
1403  /*! Information to be provided to the callback upon receipt of a response */
1404  void *token;
1405  /*! The callback to be called upon receipt of a response */
1406  void (*callback)(void *token, pjsip_event *e);
1407  /*! Non-zero when the callback is called. */
1408  unsigned int cb_called;
1409  /*! Non-zero if endpt_send_request_cb() was called. */
1410  unsigned int send_cb_called;
1411  /*! Timeout timer. */
1412  pj_timer_entry *timeout_timer;
1413  /*! Original timeout. */
1414  pj_int32_t timeout;
1415  /*! The transmit data. */
1416  pjsip_tx_data *tdata;
1417 };
1418 
1419 /*! \internal This function gets called by pjsip when the transaction ends,
1420  * even if it timed out. The lock prevents a race condition if both the pjsip
1421  * transaction timer and our own timer expire simultaneously.
1422  */
1423 static void endpt_send_request_cb(void *token, pjsip_event *e)
1424 {
1425  struct send_request_wrapper *req_wrapper = token;
1426  unsigned int cb_called;
1427 
1428  /*
1429  * Needed because we cannot otherwise tell if this callback was
1430  * called when pjsip_endpt_send_request() returns error.
1431  */
1432  req_wrapper->send_cb_called = 1;
1433 
1434  if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
1435  ast_debug(2, "%p: PJSIP tsx timer expired\n", req_wrapper);
1436 
1437  if (req_wrapper->timeout_timer
1438  && req_wrapper->timeout_timer->id != TIMEOUT_TIMER2) {
1439  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1440  ao2_ref(req_wrapper, -1);
1441  return;
1442  }
1443  } else {
1444  ast_debug(2, "%p: PJSIP tsx response received\n", req_wrapper);
1445  }
1446 
1447  ao2_lock(req_wrapper);
1448 
1449  /* It's possible that our own timer was already processing while
1450  * we were waiting on the lock so check the timer id. If it's
1451  * still TIMER2 then we still need to process.
1452  */
1453  if (req_wrapper->timeout_timer
1454  && req_wrapper->timeout_timer->id == TIMEOUT_TIMER2) {
1455  int timers_cancelled = 0;
1456 
1457  ast_debug(3, "%p: Cancelling timer\n", req_wrapper);
1458 
1459  timers_cancelled = pj_timer_heap_cancel_if_active(
1460  pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
1461  req_wrapper->timeout_timer, TIMER_INACTIVE);
1462  if (timers_cancelled > 0) {
1463  /* If the timer was cancelled the callback will never run so
1464  * clean up its reference to the wrapper.
1465  */
1466  ast_debug(3, "%p: Timer cancelled\n", req_wrapper);
1467  ao2_ref(req_wrapper, -1);
1468  } else {
1469  /*
1470  * If it wasn't cancelled, it MAY be in the callback already
1471  * waiting on the lock. When we release the lock, it will
1472  * now know not to proceed.
1473  */
1474  ast_debug(3, "%p: Timer already expired\n", req_wrapper);
1475  }
1476  }
1477 
1478  cb_called = req_wrapper->cb_called;
1479  req_wrapper->cb_called = 1;
1480  ao2_unlock(req_wrapper);
1481 
1482  /* It's possible that our own timer expired and called the callbacks
1483  * so no need to call them again.
1484  */
1485  if (!cb_called && req_wrapper->callback) {
1486  req_wrapper->callback(req_wrapper->token, e);
1487  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1488  }
1489 
1490  ao2_ref(req_wrapper, -1);
1491 }
1492 
1493 /*! \internal This function gets called by our own timer when it expires.
1494  * If the timer is cancelled however, the function does NOT get called.
1495  * The lock prevents a race condition if both the pjsip transaction timer
1496  * and our own timer expire simultaneously.
1497  */
1498 static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
1499 {
1500  struct send_request_wrapper *req_wrapper = entry->user_data;
1501  unsigned int cb_called;
1502 
1503  ast_debug(2, "%p: Internal tsx timer expired after %d msec\n",
1504  req_wrapper, req_wrapper->timeout);
1505 
1506  ao2_lock(req_wrapper);
1507  /*
1508  * If the id is not TIMEOUT_TIMER2 then the timer was cancelled
1509  * before we got the lock or it was already handled so just clean up.
1510  */
1511  if (entry->id != TIMEOUT_TIMER2) {
1512  ao2_unlock(req_wrapper);
1513  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1514  ao2_ref(req_wrapper, -1);
1515  return;
1516  }
1517  entry->id = TIMER_INACTIVE;
1518 
1519  ast_debug(3, "%p: Timer handled here\n", req_wrapper);
1520 
1521  cb_called = req_wrapper->cb_called;
1522  req_wrapper->cb_called = 1;
1523  ao2_unlock(req_wrapper);
1524 
1525  if (!cb_called && req_wrapper->callback) {
1526  pjsip_event event;
1527 
1528  PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->tdata);
1529  event.body.tsx_state.type = PJSIP_EVENT_TIMER;
1530 
1531  req_wrapper->callback(req_wrapper->token, &event);
1532  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1533  }
1534 
1535  ao2_ref(req_wrapper, -1);
1536 }
1537 
1538 static void send_request_wrapper_destructor(void *obj)
1539 {
1540  struct send_request_wrapper *req_wrapper = obj;
1541 
1542  pjsip_tx_data_dec_ref(req_wrapper->tdata);
1543  ast_debug(2, "%p: wrapper destroyed\n", req_wrapper);
1544 }
1545 
1546 static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint,
1547  pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
1548 {
1549  struct send_request_wrapper *req_wrapper;
1550  pj_status_t ret_val;
1551  pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
1552 
1553  if (!cb && token) {
1554  /* Silly. Without a callback we cannot do anything with token. */
1555  pjsip_tx_data_dec_ref(tdata);
1556  return PJ_EINVAL;
1557  }
1558 
1559  /* Create wrapper to detect if the callback was actually called on an error. */
1560  req_wrapper = ao2_alloc(sizeof(*req_wrapper), send_request_wrapper_destructor);
1561  if (!req_wrapper) {
1562  pjsip_tx_data_dec_ref(tdata);
1563  return PJ_ENOMEM;
1564  }
1565 
1566  ast_debug(2, "%p: Wrapper created\n", req_wrapper);
1567 
1568  req_wrapper->token = token;
1569  req_wrapper->callback = cb;
1570  req_wrapper->timeout = timeout;
1571  req_wrapper->timeout_timer = NULL;
1572  req_wrapper->tdata = tdata;
1573  /* Add a reference to tdata. The wrapper destructor cleans it up. */
1574  pjsip_tx_data_add_ref(tdata);
1575 
1576  if (timeout > 0) {
1577  pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
1578 
1579  req_wrapper->timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
1580 
1581  ast_debug(2, "%p: Set timer to %d msec\n", req_wrapper, timeout);
1582 
1583  pj_timer_entry_init(req_wrapper->timeout_timer, TIMEOUT_TIMER2,
1584  req_wrapper, send_request_timer_callback);
1585 
1586  /* We need to insure that the wrapper and tdata are available if/when the
1587  * timer callback is executed.
1588  */
1589  ao2_ref(req_wrapper, +1);
1590  ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
1591  req_wrapper->timeout_timer, &timeout_timer_val);
1592  if (ret_val != PJ_SUCCESS) {
1594  "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
1595  (int) pj_strlen(&tdata->msg->line.req.method.name),
1596  pj_strbuf(&tdata->msg->line.req.method.name),
1597  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1598  ao2_t_ref(req_wrapper, -2, "Drop timer and routine ref");
1599  pjsip_tx_data_dec_ref(tdata);
1600  return ret_val;
1601  }
1602  }
1603 
1604  /* We need to insure that the wrapper and tdata are available when the
1605  * transaction callback is executed.
1606  */
1607  ao2_ref(req_wrapper, +1);
1608  ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper, endpt_send_request_cb);
1609  if (ret_val != PJ_SUCCESS) {
1610  char errmsg[PJ_ERR_MSG_SIZE];
1611 
1612  if (!req_wrapper->send_cb_called) {
1613  /* endpt_send_request_cb is not expected to ever be called now. */
1614  ao2_ref(req_wrapper, -1);
1615  }
1616 
1617  /* Complain of failure to send the request. */
1618  pj_strerror(ret_val, errmsg, sizeof(errmsg));
1619  ast_log(LOG_ERROR, "Error %d '%s' sending %.*s request to endpoint %s\n",
1620  (int) ret_val, errmsg, (int) pj_strlen(&tdata->msg->line.req.method.name),
1621  pj_strbuf(&tdata->msg->line.req.method.name),
1622  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1623 
1624  if (timeout > 0) {
1625  int timers_cancelled;
1626 
1627  ao2_lock(req_wrapper);
1628  timers_cancelled = pj_timer_heap_cancel_if_active(
1629  pjsip_endpt_get_timer_heap(endpt),
1630  req_wrapper->timeout_timer, TIMER_INACTIVE);
1631  if (timers_cancelled > 0) {
1632  ao2_ref(req_wrapper, -1);
1633  }
1634 
1635  /* Was the callback called? */
1636  if (req_wrapper->cb_called) {
1637  /*
1638  * Yes so we cannot report any error. The callback
1639  * has already freed any resources associated with
1640  * token.
1641  */
1642  ret_val = PJ_SUCCESS;
1643  } else {
1644  /*
1645  * No so we claim it is called so our caller can free
1646  * any resources associated with token because of
1647  * failure.
1648  */
1649  req_wrapper->cb_called = 1;
1650  }
1651  ao2_unlock(req_wrapper);
1652  } else if (req_wrapper->cb_called) {
1653  /*
1654  * We cannot report any error. The callback has
1655  * already freed any resources associated with
1656  * token.
1657  */
1658  ret_val = PJ_SUCCESS;
1659  }
1660  }
1661 
1662  ao2_ref(req_wrapper, -1);
1663  return ret_val;
1664 }
1665 
1666 int ast_sip_failover_request(pjsip_tx_data *tdata)
1667 {
1668  pjsip_via_hdr *via;
1669 
1670  if (!tdata || !tdata->dest_info.addr.count
1671  || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
1672  /* No more addresses to try */
1673  return 0;
1674  }
1675 
1676  /* Try next address */
1677  ++tdata->dest_info.cur_addr;
1678 
1679  via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1680  via->branch_param.slen = 0;
1681 
1682  pjsip_tx_data_invalidate_msg(tdata);
1683 
1684  return 1;
1685 }
1686 
1687 static void send_request_cb(void *token, pjsip_event *e);
1688 
1689 static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
1690 {
1691  struct ast_sip_endpoint *endpoint;
1692  pjsip_transaction *tsx;
1693  pjsip_tx_data *tdata;
1694  int res = 0;
1695 
1696  if (!(endpoint = ao2_bump(req_data->endpoint))) {
1697  return 0;
1698  }
1699 
1700  tsx = e->body.tsx_state.tsx;
1701 
1702  switch (tsx->status_code) {
1703  case 401:
1704  case 407:
1705  /* Resend the request with a challenge response if we are challenged. */
1706  res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
1708  e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
1709  break;
1710  case 408:
1711  case 503:
1712  if ((res = ast_sip_failover_request(tsx->last_tx))) {
1713  tdata = tsx->last_tx;
1714  /*
1715  * Bump the ref since it will be on a new transaction and
1716  * we don't want it to go away along with the old transaction.
1717  */
1718  pjsip_tx_data_add_ref(tdata);
1719  }
1720  break;
1721  }
1722 
1723  if (res) {
1724  res = endpt_send_request(endpoint, tdata, -1,
1725  req_data, send_request_cb) == PJ_SUCCESS;
1726  }
1727 
1728  ao2_ref(endpoint, -1);
1729  return res;
1730 }
1731 
1732 static void send_request_cb(void *token, pjsip_event *e)
1733 {
1734  struct send_request_data *req_data = token;
1735  pjsip_rx_data *challenge;
1736  struct ast_sip_supplement *supplement;
1737 
1738  if (e->type == PJSIP_EVENT_TSX_STATE) {
1739  switch(e->body.tsx_state.type) {
1740  case PJSIP_EVENT_TRANSPORT_ERROR:
1741  case PJSIP_EVENT_TIMER:
1742  /*
1743  * Check the request status on transport error or timeout. A transport
1744  * error can occur when a TCP socket closes and that can be the result
1745  * of a 503. Also we may need to failover on a timeout (408).
1746  */
1747  if (check_request_status(req_data, e)) {
1748  return;
1749  }
1750  break;
1751  case PJSIP_EVENT_RX_MSG:
1752  challenge = e->body.tsx_state.src.rdata;
1753 
1754  /*
1755  * Call any supplements that want to know about a response
1756  * with any received data.
1757  */
1759  AST_LIST_TRAVERSE(&supplements, supplement, next) {
1760  if (supplement->incoming_response
1761  && does_method_match(&challenge->msg_info.cseq->method.name,
1762  supplement->method)) {
1763  supplement->incoming_response(req_data->endpoint, challenge);
1764  }
1765  }
1767 
1768  if (check_request_status(req_data, e)) {
1769  /*
1770  * Request with challenge response or failover sent.
1771  * Passed our req_data ref to the new request.
1772  */
1773  return;
1774  }
1775  break;
1776  default:
1777  ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
1778  break;
1779  }
1780  }
1781 
1782  if (req_data->callback) {
1783  req_data->callback(req_data->token, e);
1784  }
1785  ao2_ref(req_data, -1);
1786 }
1787 
1788 int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata,
1789  struct ast_sip_endpoint *endpoint, int timeout, void *token,
1790  void (*callback)(void *token, pjsip_event *e))
1791 {
1792  struct ast_sip_supplement *supplement;
1793  struct send_request_data *req_data;
1794  struct ast_sip_contact *contact;
1795 
1796  req_data = send_request_data_alloc(endpoint, token, callback);
1797  if (!req_data) {
1798  pjsip_tx_data_dec_ref(tdata);
1799  return -1;
1800  }
1801 
1802  if (endpoint) {
1804  }
1805 
1807 
1809  AST_LIST_TRAVERSE(&supplements, supplement, next) {
1810  if (supplement->outgoing_request
1811  && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
1812  supplement->outgoing_request(endpoint, contact, tdata);
1813  }
1814  }
1816 
1817  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
1819 
1820  if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
1821  != PJ_SUCCESS) {
1822  ao2_cleanup(req_data);
1823  return -1;
1824  }
1825 
1826  return 0;
1827 }
1828 
1829 int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg,
1830  struct ast_sip_endpoint *endpoint, void *token,
1831  void (*callback)(void *token, pjsip_event *e))
1832 {
1833  ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
1834 
1835  if (dlg) {
1836  return send_in_dialog_request(tdata, dlg);
1837  } else {
1838  return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
1839  }
1840 }
1841 
1842 int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
1843 {
1844  pjsip_route_hdr *route;
1845  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1846  pj_str_t tmp;
1847 
1848  pj_strdup2_with_null(tdata->pool, &tmp, proxy);
1849  if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1850  return -1;
1851  }
1852 
1853  pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
1854 
1855  return 0;
1856 }
1857 
1858 int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
1859 {
1860  pj_str_t hdr_name;
1861  pj_str_t hdr_value;
1862  pjsip_generic_string_hdr *hdr;
1863 
1864  pj_cstr(&hdr_name, name);
1865  pj_cstr(&hdr_value, value);
1866 
1867  hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
1868 
1869  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
1870  return 0;
1871 }
1872 
1873 static pjsip_msg_body *ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
1874 {
1875  pj_str_t type;
1876  pj_str_t subtype;
1877  pj_str_t body_text;
1878 
1879  pj_cstr(&type, body->type);
1880  pj_cstr(&subtype, body->subtype);
1881  pj_cstr(&body_text, body->body_text);
1882 
1883  return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
1884 }
1885 
1886 int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
1887 {
1888  pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
1889  tdata->msg->body = pjsip_body;
1890  return 0;
1891 }
1892 
1893 int ast_sip_add_body_multipart(pjsip_tx_data *tdata, const struct ast_sip_body *bodies[], int num_bodies)
1894 {
1895  int i;
1896  /* NULL for type and subtype automatically creates "multipart/mixed" */
1897  pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
1898 
1899  for (i = 0; i < num_bodies; ++i) {
1900  pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
1901  part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
1902  pjsip_multipart_add_part(tdata->pool, body, part);
1903  }
1904 
1905  tdata->msg->body = body;
1906  return 0;
1907 }
1908 
1909 int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text)
1910 {
1911  size_t combined_size = strlen(body_text) + tdata->msg->body->len;
1912  struct ast_str *body_buffer = ast_str_alloca(combined_size);
1913 
1914  ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
1915 
1916  tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
1917  pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
1918  tdata->msg->body->len = combined_size;
1919 
1920  return 0;
1921 }
1922 
1924 {
1926 }
1927 
1929 {
1931 }
1932 
1933 int ast_sip_push_task(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
1934 {
1935  if (!serializer) {
1937  }
1938 
1939  return ast_taskprocessor_push(serializer, sip_task, task_data);
1940 }
1941 
1942 struct sync_task_data {
1943  ast_mutex_t lock;
1944  ast_cond_t cond;
1945  int complete;
1946  int fail;
1947  int (*task)(void *);
1948  void *task_data;
1949 };
1950 
1951 static int sync_task(void *data)
1952 {
1953  struct sync_task_data *std = data;
1954  int ret;
1955 
1956  std->fail = std->task(std->task_data);
1957 
1958  /*
1959  * Once we unlock std->lock after signaling, we cannot access
1960  * std again. The thread waiting within ast_sip_push_task_wait()
1961  * is free to continue and release its local variable (std).
1962  */
1963  ast_mutex_lock(&std->lock);
1964  std->complete = 1;
1965  ast_cond_signal(&std->cond);
1966  ret = std->fail;
1967  ast_mutex_unlock(&std->lock);
1968  return ret;
1969 }
1970 
1971 static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
1972 {
1973  /* This method is an onion */
1974  struct sync_task_data std;
1975 
1976  memset(&std, 0, sizeof(std));
1977  ast_mutex_init(&std.lock);
1978  ast_cond_init(&std.cond, NULL);
1979  std.task = sip_task;
1980  std.task_data = task_data;
1981 
1982  if (ast_sip_push_task(serializer, sync_task, &std)) {
1983  ast_mutex_destroy(&std.lock);
1984  ast_cond_destroy(&std.cond);
1985  return -1;
1986  }
1987 
1988  ast_mutex_lock(&std.lock);
1989  while (!std.complete) {
1990  ast_cond_wait(&std.cond, &std.lock);
1991  }
1992  ast_mutex_unlock(&std.lock);
1993 
1994  ast_mutex_destroy(&std.lock);
1995  ast_cond_destroy(&std.cond);
1996  return std.fail;
1997 }
1998 
1999 int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2000 {
2001  if (ast_sip_thread_is_servant()) {
2002  return sip_task(task_data);
2003  }
2004 
2005  return ast_sip_push_task_wait(serializer, sip_task, task_data);
2006 }
2007 
2008 int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2009 {
2011 }
2012 
2013 int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2014 {
2015  if (!serializer) {
2016  /* Caller doesn't care which PJSIP serializer the task executes under. */
2018  if (!serializer) {
2019  /* No serializer picked to execute the task */
2020  return -1;
2021  }
2022  }
2024  /*
2025  * We are the requested serializer so we must execute
2026  * the task now or deadlock waiting on ourself to
2027  * execute it.
2028  */
2029  return sip_task(task_data);
2030  }
2031 
2032  return ast_sip_push_task_wait(serializer, sip_task, task_data);
2033 }
2034 
2035 void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
2036 {
2037  size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2038  memcpy(dest, pj_strbuf(src), chars_to_copy);
2039  dest[chars_to_copy] = '\0';
2040 }
2041 
2042 int ast_copy_pj_str2(char **dest, const pj_str_t *src)
2043 {
2044  int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
2045 
2046  if (res < 0) {
2047  *dest = NULL;
2048  }
2049 
2050  return res;
2051 }
2052 
2053 int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
2054 {
2055  int rc = 0;
2056  if (a != NULL && b != NULL) {
2057  rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2058  }
2059  return rc;
2060 }
2061 
2062 int ast_sip_is_media_type_in(pjsip_media_type *a, ...)
2063 {
2064  int rc = 0;
2065  pjsip_media_type *b = NULL;
2066  va_list ap;
2067 
2068  ast_assert(a != NULL);
2069  va_start(ap, a);
2070 
2071  while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2072  if (pjsip_media_type_cmp(a, b, 0) == 0) {
2073  rc = 1;
2074  break;
2075  }
2076  }
2077  va_end(ap);
2078 
2079  return rc;
2080 }
2081 
2082 int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
2083 {
2084  pjsip_media_type compare;
2085 
2086  if (!content_type) {
2087  return 0;
2088  }
2089 
2090  pjsip_media_type_init2(&compare, type, subtype);
2091 
2092  return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2093 }
2094 
2095 pj_caching_pool caching_pool;
2096 pj_pool_t *memory_pool;
2097 pj_thread_t *monitor_thread;
2098 static int monitor_continue;
2099 
2100 static void *monitor_thread_exec(void *endpt)
2101 {
2102  while (monitor_continue) {
2103  const pj_time_val delay = {0, 10};
2104  pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2105  }
2106  return NULL;
2107 }
2108 
2109 static void stop_monitor_thread(void)
2110 {
2111  monitor_continue = 0;
2112  pj_thread_join(monitor_thread);
2113 }
2114 
2117 #define SIP_SERVANT_ID 0x5E2F1D
2118 
2119 static void sip_thread_start(void)
2120 {
2121  pj_thread_desc *desc;
2122  pj_thread_t *thread;
2123  uint32_t *servant_id;
2124 
2125  servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2126  if (!servant_id) {
2127  ast_log(LOG_ERROR, "Could not set SIP servant ID in thread-local storage.\n");
2128  return;
2129  }
2130  *servant_id = SIP_SERVANT_ID;
2131 
2132  desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
2133  if (!desc) {
2134  ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
2135  return;
2136  }
2137  pj_bzero(*desc, sizeof(*desc));
2138 
2139  if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
2140  ast_log(LOG_ERROR, "Couldn't register thread with PJLIB.\n");
2141  }
2142 }
2143 
2145 {
2146  uint32_t *servant_id;
2147 
2148  if (monitor_thread &&
2149  pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
2150  return 1;
2151  }
2152 
2153  servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2154  if (!servant_id) {
2155  return 0;
2156  }
2157 
2158  return *servant_id == SIP_SERVANT_ID;
2159 }
2160 
2161 void *ast_sip_dict_get(void *ht, const char *key)
2162 {
2163  unsigned int hval = 0;
2164 
2165  if (!ht) {
2166  return NULL;
2167  }
2168 
2169  return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2170 }
2171 
2172 void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
2173  const char *key, void *val)
2174 {
2175  if (!ht) {
2176  ht = pj_hash_create(pool, 11);
2177  }
2178 
2179  pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2180 
2181  return ht;
2182 }
2183 
2184 static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
2185 {
2186  struct ast_sip_supplement *supplement;
2187 
2188  if (pjsip_rdata_get_dlg(rdata)) {
2189  return PJ_FALSE;
2190  }
2191 
2193  AST_LIST_TRAVERSE(&supplements, supplement, next) {
2194  if (supplement->incoming_request
2195  && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->method)) {
2196  struct ast_sip_endpoint *endpoint;
2197 
2198  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2199  supplement->incoming_request(endpoint, rdata);
2200  ao2_cleanup(endpoint);
2201  }
2202  }
2204 
2205  return PJ_FALSE;
2206 }
2207 
2208 static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2209 {
2210  struct ast_sip_supplement *supplement;
2211  pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
2213 
2214  if (sip_endpoint) {
2215  ast_sip_message_apply_transport(sip_endpoint->transport, tdata);
2216  }
2217 
2219  AST_LIST_TRAVERSE(&supplements, supplement, next) {
2220  if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
2221  supplement->outgoing_response(sip_endpoint, contact, tdata);
2222  }
2223  }
2225 
2226  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2228 }
2229 
2230 int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2231 {
2232  pj_status_t status;
2233 
2234  supplement_outgoing_response(tdata, sip_endpoint);
2235  status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2236  if (status != PJ_SUCCESS) {
2237  pjsip_tx_data_dec_ref(tdata);
2238  }
2239 
2240  return status == PJ_SUCCESS ? 0 : -1;
2241 }
2242 
2243 int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2244 {
2245  pjsip_transaction *tsx;
2246 
2247  if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) {
2248  struct ast_sip_contact *contact;
2249 
2250  /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
2251  * We'll leak that reference if we don't get rid of it here.
2252  */
2255  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2256  pjsip_tx_data_dec_ref(tdata);
2257  return -1;
2258  }
2259  pjsip_tsx_recv_msg(tsx, rdata);
2260 
2261  supplement_outgoing_response(tdata, sip_endpoint);
2262 
2263  if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2264  pjsip_tx_data_dec_ref(tdata);
2265  return -1;
2266  }
2267 
2268  return 0;
2269 }
2270 
2271 int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code,
2272  struct ast_sip_contact *contact, pjsip_tx_data **tdata)
2273 {
2274  int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2275 
2276  if (!res) {
2277  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
2278  }
2279 
2280  return res;
2281 }
2282 
2283 int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
2284 {
2285  if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2286  pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2287  return 0;
2288  } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2289  pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2290  return 0;
2291  }
2292 
2293  return -1;
2294 }
2295 
2296 const char *ast_sip_get_host_ip_string(int af)
2297 {
2298  if (af == pj_AF_INET()) {
2299  return host_ip_ipv4_string;
2300  } else if (af == pj_AF_INET6()) {
2301  return host_ip_ipv6_string;
2302  }
2303 
2304  return NULL;
2305 }
2306 
2308  char *buf, size_t buf_len)
2309 {
2310  switch (dtmf) {
2311  case AST_SIP_DTMF_NONE:
2312  ast_copy_string(buf, "none", buf_len);
2313  break;
2314  case AST_SIP_DTMF_RFC_4733:
2315  ast_copy_string(buf, "rfc4733", buf_len);
2316  break;
2317  case AST_SIP_DTMF_INBAND:
2318  ast_copy_string(buf, "inband", buf_len);
2319  break;
2320  case AST_SIP_DTMF_INFO:
2321  ast_copy_string(buf, "info", buf_len);
2322  break;
2323  case AST_SIP_DTMF_AUTO:
2324  ast_copy_string(buf, "auto", buf_len);
2325  break;
2327  ast_copy_string(buf, "auto_info", buf_len);
2328  break;
2329  default:
2330  buf[0] = '\0';
2331  return -1;
2332  }
2333  return 0;
2334 }
2335 
2336 int ast_sip_str_to_dtmf(const char * dtmf_mode)
2337 {
2338  int result = -1;
2339 
2340  if (!strcasecmp(dtmf_mode, "info")) {
2342  } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
2344  } else if (!strcasecmp(dtmf_mode, "inband")) {
2346  } else if (!strcasecmp(dtmf_mode, "none")) {
2348  } else if (!strcasecmp(dtmf_mode, "auto")) {
2350  } else if (!strcasecmp(dtmf_mode, "auto_info")) {
2352  }
2353 
2354  return result;
2355 }
2356 
2358 {
2359  const char *value;
2360 
2361  if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, ALL)) {
2362  value = "local";
2363  } else if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, ALL)) {
2364  value = "local_merge";
2365  } else if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, FIRST)) {
2366  value = "local_first";
2367  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, ALL)) {
2368  value = "remote";
2369  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, ALL)) {
2370  value = "remote_merge";
2371  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, FIRST)) {
2372  value = "remote_first";
2373  } else {
2374  value = "unknown";
2375  }
2376 
2377  return value;
2378 }
2379 
2380 int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str, int is_outgoing)
2381 {
2382  pref->flags = 0;
2383 
2384  if (strcmp(pref_str, "local") == 0) {
2386  } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
2388  } else if (strcmp(pref_str, "local_first") == 0) {
2390  } else if (strcmp(pref_str, "remote") == 0) {
2392  } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
2394  } else if (strcmp(pref_str, "remote_first") == 0) {
2396  } else {
2397  return -1;
2398  }
2399 
2400  return 0;
2401 }
2402 
2403 /*!
2404  * \brief Set name and number information on an identity header.
2405  *
2406  * \param pool Memory pool to use for string duplication
2407  * \param id_hdr A From, P-Asserted-Identity, or Remote-Party-ID header to modify
2408  * \param id The identity information to apply to the header
2409  */
2410 void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id)
2411 {
2412  pjsip_name_addr *id_name_addr;
2413  pjsip_sip_uri *id_uri;
2414 
2415  id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2416  id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2417 
2418  if (id->name.valid) {
2419  if (!ast_strlen_zero(id->name.str)) {
2420  int name_buf_len = strlen(id->name.str) * 2 + 1;
2421  char *name_buf = ast_alloca(name_buf_len);
2422 
2423  ast_escape_quoted(id->name.str, name_buf, name_buf_len);
2424  pj_strdup2(pool, &id_name_addr->display, name_buf);
2425  } else {
2426  pj_strdup2(pool, &id_name_addr->display, NULL);
2427  }
2428  }
2429 
2430  if (id->number.valid) {
2431  pj_strdup2(pool, &id_uri->user, id->number.str);
2432  }
2433 }
2434 
2435 
2436 static void remove_request_headers(pjsip_endpoint *endpt)
2437 {
2438  const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
2439  pjsip_hdr *iter = request_headers->next;
2440 
2441  while (iter != request_headers) {
2442  pjsip_hdr *to_erase = iter;
2443  iter = iter->next;
2444  pj_list_erase(to_erase);
2445  }
2446 }
2447 
2449 {
2451 }
2452 
2454 {
2455  return sip_threadpool;
2456 }
2457 
2458 #ifdef TEST_FRAMEWORK
2459 AST_TEST_DEFINE(xml_sanitization_end_null)
2460 {
2461  char sanitized[8];
2462 
2463  switch (cmd) {
2464  case TEST_INIT:
2465  info->name = "xml_sanitization_end_null";
2466  info->category = "/res/res_pjsip/";
2467  info->summary = "Ensure XML sanitization works as expected with a long string";
2468  info->description = "This test sanitizes a string which exceeds the output\n"
2469  "buffer size. Once done the string is confirmed to be NULL terminated.";
2470  return AST_TEST_NOT_RUN;
2471  case TEST_EXECUTE:
2472  break;
2473  }
2474 
2475  ast_sip_sanitize_xml("aaaaaaaaaaaa", sanitized, sizeof(sanitized));
2476  if (sanitized[7] != '\0') {
2477  ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
2478  return AST_TEST_FAIL;
2479  }
2480 
2481  return AST_TEST_PASS;
2482 }
2483 
2484 AST_TEST_DEFINE(xml_sanitization_exceeds_buffer)
2485 {
2486  char sanitized[8];
2487 
2488  switch (cmd) {
2489  case TEST_INIT:
2490  info->name = "xml_sanitization_exceeds_buffer";
2491  info->category = "/res/res_pjsip/";
2492  info->summary = "Ensure XML sanitization does not exceed buffer when output won't fit";
2493  info->description = "This test sanitizes a string which before sanitization would\n"
2494  "fit within the output buffer. After sanitization, however, the string would\n"
2495  "exceed the buffer. Once done the string is confirmed to be NULL terminated.";
2496  return AST_TEST_NOT_RUN;
2497  case TEST_EXECUTE:
2498  break;
2499  }
2500 
2501  ast_sip_sanitize_xml("<><><>&", sanitized, sizeof(sanitized));
2502  if (sanitized[7] != '\0') {
2503  ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
2504  return AST_TEST_FAIL;
2505  }
2506 
2507  return AST_TEST_PASS;
2508 }
2509 #endif
2510 
2511 /*!
2512  * \internal
2513  * \brief Reload configuration within a PJSIP thread
2514  */
2515 static int reload_configuration_task(void *obj)
2516 {
2520  return 0;
2521 }
2522 
2523 static int unload_pjsip(void *data)
2524 {
2525  /*
2526  * These calls need the pjsip endpoint and serializer to clean up.
2527  * If they're not set, then there's nothing to clean up anyway.
2528  */
2539  }
2540 
2541  if (monitor_thread) {
2543  monitor_thread = NULL;
2544  }
2545 
2546  if (memory_pool) {
2547  /* This mimics the behavior of pj_pool_safe_release
2548  * which was introduced in pjproject 2.6.
2549  */
2550  pj_pool_t *temp_pool = memory_pool;
2551 
2552  memory_pool = NULL;
2553  pj_pool_release(temp_pool);
2554  }
2555 
2557 
2558  if (caching_pool.lock) {
2560  }
2561 
2562  pj_shutdown();
2563 
2564  return 0;
2565 }
2566 
2567 static int load_pjsip(void)
2568 {
2569  const unsigned int flags = 0; /* no port, no brackets */
2570  pj_status_t status;
2571 
2572  /* The third parameter is just copied from
2573  * example code from PJLIB. This can be adjusted
2574  * if necessary.
2575  */
2577  if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
2578  ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
2579  goto error;
2580  }
2581 
2582  /* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
2583  * we need to stop PJSIP from doing it automatically
2584  */
2586 
2587  memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
2588  if (!memory_pool) {
2589  ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
2590  goto error;
2591  }
2592 
2593  if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
2594  pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), flags);
2595  ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
2596  }
2597 
2598  if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
2599  pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), flags);
2600  ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
2601  }
2602 
2603  pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
2604  pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
2605 
2606  monitor_continue = 1;
2607  status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
2608  NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
2609  if (status != PJ_SUCCESS) {
2610  ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
2611  goto error;
2612  }
2613 
2614  return AST_MODULE_LOAD_SUCCESS;
2615 
2616 error:
2617  return AST_MODULE_LOAD_DECLINE;
2618 }
2619 
2620 /*
2621  * This is a place holder function to ensure that pjmedia_strerr() is at
2622  * least directly referenced by this module to ensure that the loader
2623  * linker will link to the function. If a module only indirectly
2624  * references a function from another module, such as a callback parameter
2625  * to a function, the loader linker has been known to miss the link.
2626  */
2627 void never_called_res_pjsip(void);
2629 {
2630  pjmedia_strerror(0, NULL, 0);
2631 }
2632 
2633 /* Definitions of media types declared "extern" in res_pjsip.h */
2646 
2647 static int load_module(void)
2648 {
2650 
2651  /* pjproject and config_system need to be initialized before all else */
2652  if (pj_init() != PJ_SUCCESS) {
2653  return AST_MODULE_LOAD_DECLINE;
2654  }
2655 
2656  if (pjlib_util_init() != PJ_SUCCESS) {
2657  goto error;
2658  }
2659 
2660  /* Register PJMEDIA error codes for SDP parsing errors */
2661  if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
2662  != PJ_SUCCESS) {
2663  ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
2664  }
2665 
2666  /* Initialize common media types */
2667  pjsip_media_type_init2(&pjsip_media_type_application_json, "application", "json");
2668  pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml, "application", "media_control+xml");
2669  pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml, "application", "pidf+xml");
2670  pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml, "application", "xpidf+xml");
2671  pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml, "application", "cpim-xpidf+xml");
2672  pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml, "application", "rlmi+xml");
2673  pjsip_media_type_init2(&pjsip_media_type_application_sdp, "application", "sdp");
2674  pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary, "application", "simple-message-summary");
2675  pjsip_media_type_init2(&pjsip_media_type_multipart_alternative, "multipart", "alternative");
2676  pjsip_media_type_init2(&pjsip_media_type_multipart_mixed, "multipart", "mixed");
2677  pjsip_media_type_init2(&pjsip_media_type_multipart_related, "multipart", "related");
2678  pjsip_media_type_init2(&pjsip_media_type_text_plain, "text", "plain");
2679 
2680 
2681  if (ast_sip_initialize_system()) {
2682  ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
2683  goto error;
2684  }
2685 
2686  /* The serializer needs threadpool and threadpool needs pjproject to be initialized so it's next */
2688  options.thread_start = sip_thread_start;
2690  if (!sip_threadpool) {
2691  goto error;
2692  }
2693 
2695  "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);
2696  if (!sip_serializer_pool) {
2697  ast_log(LOG_ERROR, "Failed to create SIP serializer pool. Aborting load\n");
2698  goto error;
2699  }
2700 
2702  ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
2703  goto error;
2704  }
2705 
2706  /* Now load all the pjproject infrastructure. */
2707  if (load_pjsip()) {
2708  goto error;
2709  }
2710 
2712  ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
2713  goto error;
2714  }
2715 
2718 
2720  ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
2721  goto error;
2722  }
2723 
2725  ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
2726  goto error;
2727  }
2728 
2731 
2733  ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
2734  goto error;
2735  }
2736 
2738  ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
2739  goto error;
2740  }
2741 
2743  ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
2744  goto error;
2745  }
2746 
2748  ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
2749  goto error;
2750  }
2751 
2753  ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
2754  goto error;
2755  }
2756 
2758 
2759  AST_TEST_REGISTER(xml_sanitization_end_null);
2760  AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
2761 
2762  return AST_MODULE_LOAD_SUCCESS;
2763 
2764 error:
2765  unload_pjsip(NULL);
2766 
2767  /* These functions all check for NULLs and are safe to call at any time */
2771 
2772  return AST_MODULE_LOAD_DECLINE;
2773 }
2774 
2775 static int reload_module(void)
2776 {
2777  /*
2778  * We must wait for the reload to complete so multiple
2779  * reloads cannot happen at the same time.
2780  */
2782  ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
2783  return -1;
2784  }
2785 
2786  return 0;
2787 }
2788 
2789 static int unload_module(void)
2790 {
2791  AST_TEST_UNREGISTER(xml_sanitization_end_null);
2792  AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
2794 
2795  /* The thread this is called from cannot call PJSIP/PJLIB functions,
2796  * so we have to push the work to the threadpool to handle
2797  */
2802 
2803  return 0;
2804 }
2805 
2807  .support_level = AST_MODULE_SUPPORT_CORE,
2808  .load = load_module,
2809  .unload = unload_module,
2810  .reload = reload_module,
2811  .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
2812  .requires = "dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb",
2813  .optional_modules = "res_statsd",
2814 );
static int compare(const char *text, const char *template)
jack_status_t status
Definition: app_jack.c:146
const char * str
Definition: app_jack.c:147
pthread_t thread
Definition: app_meetme.c:1091
ast_mutex_t lock
Definition: app_meetme.c:1093
enum queue_result id
Definition: app_queue.c:1640
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
#define ao2_t_ref(o, delta, tag)
Definition: astobj2.h:460
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static int tmp()
Definition: bt_open.c:389
static const char desc[]
Definition: cdr_radius.c:84
static PGresult * result
Definition: cel_pgsql.c:84
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
static const char type[]
Definition: chan_ooh323.c:109
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define SENTINEL
Definition: compiler.h:87
int sip_cli_print_global(struct ast_sip_cli_context *context)
void ast_sip_destroy_system(void)
int sip_cli_print_system(struct ast_sip_cli_context *context)
int ast_sip_initialize_system(void)
void ast_sip_initialize_dns(void)
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options)
Definition: config_system.c:70
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Generic File Format Support. Should be included by clients of the file handling routines....
#define AST_DIGIT_ANY
Definition: file.h:48
static const char name[]
Definition: format_mp3.c:68
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:1933
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:1923
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
Definition: res_pjsip.c:2144
int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:2008
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:1999
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:2013
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:1928
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:452
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:702
#define AST_RWLIST_NEXT
Definition: linkedlists.h:441
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
Asterisk locking-related definitions:
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
size_t current
Definition: main/cli.c:113
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:326
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
def info(msg)
@ AST_TRANSPORT_WSS
Definition: netsock2.h:64
@ AST_TRANSPORT_WS
Definition: netsock2.h:63
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static struct header_list request_headers
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
static int reload(void)
void ast_pjproject_log_intercept_begin(int fd)
Begin PJPROJECT log interception for CLI output.
void ast_pjproject_log_intercept_end(void)
End PJPROJECT log interception for CLI output.
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static pjsip_dialog * create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
Definition: res_pjsip.c:972
struct ast_threadpool * ast_sip_threadpool(void)
Retrieve the SIP threadpool object.
Definition: res_pjsip.c:2453
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:67
void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
Unregister a an supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1326
static pj_sockaddr host_ip_ipv4
Definition: res_pjsip.c:72
int ast_sip_is_media_type_in(pjsip_media_type *a,...)
Check if a media type is in a list of others.
Definition: res_pjsip.c:2062
void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
Add 'user=phone' parameter to URI if enabled and user is a phone number.
Definition: res_pjsip.c:789
static int unload_pjsip(void *data)
Definition: res_pjsip.c:2523
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition: res_pjsip.c:2208
static const pjsip_method info_method
Definition: res_pjsip.c:1126
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:126
static void * monitor_thread_exec(void *endpt)
Definition: res_pjsip.c:2100
pj_status_t(* create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
Definition: res_pjsip.c:969
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:182
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition: res_pjsip.c:2635
static struct ast_cli_entry cli_commands[]
Definition: res_pjsip.c:466
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
Definition: res_pjsip.c:1157
int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str, int is_outgoing)
Convert a call codec preference string to preference flags.
Definition: res_pjsip.c:2380
pjsip_media_type pjsip_media_type_application_json
Definition: res_pjsip.c:2634
int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Determine if an incoming request requires authentication.
Definition: res_pjsip.c:156
int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a response to an out of dialog request.
Definition: res_pjsip.c:2230
int ast_copy_pj_str2(char **dest, const pj_str_t *src)
Create and copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2042
int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
Retrieve the local host address in IP form.
Definition: res_pjsip.c:2283
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:110
static int create_out_of_dialog_request(const pjsip_method *method, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
Definition: res_pjsip.c:1175
static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
Definition: res_pjsip.c:1498
static int reload_configuration_task(void *obj)
Definition: res_pjsip.c:2515
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:59
int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Register an outbound SIP authenticator.
Definition: res_pjsip.c:184
static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Definition: res_pjsip.c:1971
static void send_request_wrapper_destructor(void *obj)
Definition: res_pjsip.c:1538
static int unregister_service(void *data)
Definition: res_pjsip.c:115
static void send_request_data_destroy(void *obj)
Definition: res_pjsip.c:1377
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
Definition: res_pjsip.c:943
pj_pool_t * memory_pool
Definition: res_pjsip.c:2096
pjsip_media_type pjsip_media_type_application_sdp
Definition: res_pjsip.c:2641
const char * ast_sip_call_codec_pref_to_str(struct ast_flags pref)
Convert the call codec preference flags to a string.
Definition: res_pjsip.c:2357
pjsip_dialog * ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
General purpose method for creating a UAS dialog with an endpoint.
Definition: res_pjsip.c:1028
void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
Register a supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1306
static char * cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:404
void ast_sip_add_date_header(pjsip_tx_data *tdata)
Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.
Definition: res_pjsip.c:83
pjsip_media_type pjsip_media_type_text_plain
Definition: res_pjsip.c:2645
pj_thread_t * monitor_thread
Definition: res_pjsip.c:2097
void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Unregister an outbound SIP authenticator.
Definition: res_pjsip.c:196
pjsip_media_type pjsip_media_type_application_pidf_xml
Definition: res_pjsip.c:2636
static char * cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:364
void * ast_sip_dict_get(void *ht, const char *key)
Retrieves the value associated with the given key.
Definition: res_pjsip.c:2161
int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port)
General purpose method for creating an rdata structure using specific information.
Definition: res_pjsip.c:1118
enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Method to determine authentication status of an incoming request.
Definition: res_pjsip.c:172
#define SIP_SERVANT_ID
Definition: res_pjsip.c:2117
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
Definition: res_pjsip.c:303
static void send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1732
pjsip_dialog * ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user)
General purpose method for creating a UAC dialog with an endpoint.
Definition: res_pjsip.c:823
static const pjsip_method message_method
Definition: res_pjsip.c:1127
int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami, int *count)
Formats the endpoint and sends over AMI.
Definition: res_pjsip.c:494
int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
Convert the DTMF mode enum value into a string.
Definition: res_pjsip.c:2307
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:69
int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition: res_pjsip.c:702
int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
Sets pjsip_tpselector from an endpoint or uri.
Definition: res_pjsip.c:770
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
Definition: res_pjsip.c:1689
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:513
static void sip_thread_start(void)
Definition: res_pjsip.c:2119
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Definition: res_pjsip.c:308
static int reload_module(void)
Definition: res_pjsip.c:2775
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2035
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
Definition: res_pjsip.c:1340
#define SERIALIZER_POOL_SIZE
Definition: res_pjsip.c:62
int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending an Out-Of-Dialog SIP request.
Definition: res_pjsip.c:1788
pjsip_media_type pjsip_media_type_application_simple_message_summary
Definition: res_pjsip.c:2640
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:81
char * ast_sip_rdata_get_header_value(pjsip_rx_data *rdata, const pj_str_t str)
Get a specific header value from rdata.
Definition: res_pjsip.c:338
static struct ast_threadstorage pj_thread_storage
Definition: res_pjsip.c:2115
int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, pjsip_tpselector *selector)
Set the transport on a dialog.
Definition: res_pjsip.c:586
static struct @485 methods[]
static pj_sockaddr host_ip_ipv6
Definition: res_pjsip.c:78
const char * method
Definition: res_pjsip.c:1130
static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint, pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
Definition: res_pjsip.c:1546
void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
Unregister a SIP authenticator.
Definition: res_pjsip.c:145
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
Definition: res_pjsip.c:1829
long ast_sip_threadpool_queue_size(void)
Return the size of the SIP threadpool's task queue.
Definition: res_pjsip.c:2448
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:435
static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
Definition: res_pjsip.c:2184
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:474
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
Definition: res_pjsip.c:1886
pjsip_dialog * ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
General purpose method for creating a UAS dialog with an endpoint.
Definition: res_pjsip.c:1044
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
Definition: res_pjsip.c:2053
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:782
void never_called_res_pjsip(void)
Definition: res_pjsip.c:2628
int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
Get the transport name from an endpoint or request uri.
Definition: res_pjsip.c:557
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:480
int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
Register a SIP authenticator.
Definition: res_pjsip.c:133
static const pjsip_method * get_pjsip_method(const char *method)
Definition: res_pjsip.c:1146
int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port, const char *contact)
General purpose method for creating an rdata structure using specific information.
Definition: res_pjsip.c:1066
int ast_sip_add_body_multipart(pjsip_tx_data *tdata, const struct ast_sip_body *bodies[], int num_bodies)
Add a multipart body to an outbound SIP message.
Definition: res_pjsip.c:1893
pjsip_media_type pjsip_media_type_application_rlmi_xml
Definition: res_pjsip.c:2639
static int monitor_continue
Definition: res_pjsip.c:2098
static void remove_request_headers(pjsip_endpoint *endpt)
Definition: res_pjsip.c:2436
pjsip_media_type pjsip_media_type_multipart_mixed
Definition: res_pjsip.c:2643
static int register_service(void *data)
Definition: res_pjsip.c:95
pjsip_media_type pjsip_media_type_application_xpidf_xml
Definition: res_pjsip.c:2637
static int load_module(void)
Definition: res_pjsip.c:2647
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
Definition: res_pjsip.c:1842
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:131
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:2296
int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Definition: res_pjsip.c:518
int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_identifier *identifier, const char *name)
Register a SIP endpoint identifier with a name.
Definition: res_pjsip.c:226
pjsip_media_type pjsip_media_type_multipart_alternative
Definition: res_pjsip.c:2642
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition: res_pjsip.c:752
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition: res_pjsip.c:1285
pj_caching_pool caching_pool
Definition: res_pjsip.c:2095
struct ast_sip_endpoint * ast_sip_identify_endpoint(pjsip_rx_data *rdata)
Determine the endpoint that has sent a SIP message.
Definition: res_pjsip.c:323
static void endpt_send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1423
const pjsip_method * pmethod
Definition: res_pjsip.c:1131
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition: res_pjsip.c:2336
void * ast_sip_dict_set(pj_pool_t *pool, void *ht, const char *key, void *val)
Set the value for the given key.
Definition: res_pjsip.c:2172
static int do_cli_dump_endpt(void *v_a)
Definition: res_pjsip.c:353
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:1858
static int unload_module(void)
Definition: res_pjsip.c:2789
static pjsip_module supplement_module
Definition: res_pjsip.c:1168
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:75
static int load_pjsip(void)
Definition: res_pjsip.c:2567
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition: res_pjsip.c:1873
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:1349
static struct ast_threadstorage servant_id_storage
Definition: res_pjsip.c:2116
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a stateful response to an out of dialog request.
Definition: res_pjsip.c:2243
int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
Checks if the given content type matches type/subtype.
Definition: res_pjsip.c:2082
#define TIMER_INACTIVE
Definition: res_pjsip.c:1362
int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text)
Append body data to a SIP message.
Definition: res_pjsip.c:1909
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:1363
#define ENDPOINT_IDENTIFIER_FORMAT
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
Definition: res_pjsip.c:207
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
Definition: res_pjsip.c:2638
static struct send_request_data * send_request_data_alloc(struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
Definition: res_pjsip.c:1384
static void stop_monitor_thread(void)
Definition: res_pjsip.c:2109
static int sync_task(void *data)
Definition: res_pjsip.c:1951
pjsip_media_type pjsip_media_type_multipart_related
Definition: res_pjsip.c:2644
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:65
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
Definition: res_pjsip.c:1666
static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user, const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
Definition: res_pjsip.c:608
void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id)
Set name and number information on an identity header.
Definition: res_pjsip.c:2410
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP response.
Definition: res_pjsip.c:2271
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
Definition: location.c:304
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
char * ast_sip_get_endpoint_identifier_order(void)
Retrieve the global endpoint_identifier_order setting.
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition: res_pjsip.h:590
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
void ast_sip_message_apply_transport(const char *transport_name, pjsip_tx_data *tdata)
Apply the configuration for a transport to an outgoing message.
#define AST_SIP_X_AST_TXP
Definition: res_pjsip.h:955
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key.
Definition: res_pjsip.h:2752
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting 'disable multi domain'.
ast_sip_dtmf_mode
DTMF modes for SIP endpoints.
Definition: res_pjsip.h:427
@ AST_SIP_DTMF_NONE
Definition: res_pjsip.h:429
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:440
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:438
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:434
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:436
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:432
#define ast_sip_mod_data_get(mod_data, id, key)
Using the dictionary stored in mod_data array at a given id, retrieve the value associated with the g...
Definition: res_pjsip.h:2720
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
#define MAX_RX_CHALLENGES
Definition: res_pjsip.h:96
ast_sip_check_auth_result
Possible returns from ast_sip_check_authentication.
Definition: res_pjsip.h:1012
@ AST_SIP_AUTHENTICATION_SUCCESS
Definition: res_pjsip.h:1016
@ AST_SIP_CALL_CODEC_PREF_ALL
Definition: res_pjsip.h:570
@ AST_SIP_CALL_CODEC_PREF_LOCAL
Definition: res_pjsip.h:576
@ AST_SIP_CALL_CODEC_PREF_REMOTE
Definition: res_pjsip.h:578
@ AST_SIP_CALL_CODEC_PREF_UNION
Definition: res_pjsip.h:566
@ AST_SIP_CALL_CODEC_PREF_FIRST
Definition: res_pjsip.h:572
@ AST_SIP_CALL_CODEC_PREF_INTERSECT
Definition: res_pjsip.h:564
#define AST_SIP_X_AST_TXP_LEN
Definition: res_pjsip.h:956
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses
void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
Replace offensive XML characters with XML entities.
Definition: presence_xml.c:29
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
int ast_res_pjsip_preinit_options_handling(void)
int ast_sip_initialize_transport_management(void)
void ast_sip_initialize_resolver(void)
int ast_res_pjsip_init_options_handling(int reload)
int ast_sip_initialize_distributor(void)
int ast_res_pjsip_reload_configuration(void)
int ast_sip_destroy_scheduler(void)
void ast_sip_initialize_global_headers(void)
void ast_res_pjsip_cleanup_options_handling(void)
void ast_sip_destroy_transport_management(void)
int ast_sip_initialize_transport_events(void)
void ast_sip_destroy_distributor(void)
int ast_res_pjsip_initialize_configuration(void)
void ast_sip_destroy_global_headers(void)
void ast_res_pjsip_destroy_configuration(void)
int ast_res_pjsip_init_message_filter(void)
void ast_sip_destroy_transport_events(void)
void ast_res_pjsip_cleanup_message_filter(void)
const pjsip_method pjsip_publish_method
Defined method for PUBLISH.
#define NULL
Definition: resample.c:96
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
struct ast_serializer_pool * ast_serializer_pool_create(const char *name, unsigned int size, struct ast_threadpool *threadpool, int timeout)
Create a serializer pool.
Definition: serializer.c:76
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
Sorcery Data Access Layer API.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_alloca(init_len)
Definition: strings.h:826
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1091
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
descriptor for a cli entry.
Definition: cli.h:171
struct ast_cli_entry * next
Definition: cli.h:189
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Structure for mutex and tracking information.
Definition: lock.h:135
Information needed to identify an endpoint in a call.
Definition: channel.h:338
AMI variable container.
Definition: res_pjsip.h:2819
An interchangeable way of handling digest authentication for SIP.
Definition: res_pjsip.h:1030
enum ast_sip_check_auth_result(* check_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Check that an incoming request passes authentication.
Definition: res_pjsip.h:1045
int(* requires_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Check if a request requires authentication See ast_sip_requires_authentication for more details.
Definition: res_pjsip.h:1035
SIP body description.
Definition: res_pjsip.h:2108
const char * type
Definition: res_pjsip.h:2110
const char * body_text
Definition: res_pjsip.h:2114
const char * subtype
Definition: res_pjsip.h:2112
CLI Formatter Context passed to all formatters.
Definition: res_pjsip_cli.h:34
Contact associated with an address of record.
Definition: res_pjsip.h:297
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:329
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2845
int(* format_ami)(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Callback used to format endpoint information over AMI.
Definition: res_pjsip.h:2849
An entity responsible for identifying the source of a SIP message.
Definition: res_pjsip.h:1073
struct ast_sip_endpoint *(* identify_endpoint)(pjsip_rx_data *rdata)
Callback used to identify the source of a message. See ast_sip_identify_endpoint for more details.
Definition: res_pjsip.h:1078
An entity with which Asterisk communicates.
Definition: res_pjsip.h:854
struct ast_sip_auth_vector outbound_auths
Definition: res_pjsip.h:901
char * contact_user
Definition: res_pjsip.h:933
const ast_string_field transport
Definition: res_pjsip.h:883
const ast_string_field aors
Definition: res_pjsip.h:883
const ast_string_field outbound_proxy
Definition: res_pjsip.h:883
const ast_string_field fromdomain
Definition: res_pjsip.h:883
unsigned int allow_unauthenticated_options
Definition: res_pjsip.h:951
unsigned int usereqphone
Definition: res_pjsip.h:923
const ast_string_field fromuser
Definition: res_pjsip.h:883
struct ast_sip_endpoint_nat_configuration nat
Definition: res_pjsip.h:891
struct ast_sip_endpoint_info_configuration info
Definition: res_pjsip.h:895
an interchangeable way of responding to authentication challenges
Definition: res_pjsip.h:1055
int(* create_request_with_auth)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge, struct pjsip_tx_data *old_request, struct pjsip_tx_data **new_request)
Create a new request with authentication credentials.
Definition: res_pjsip.h:1066
A supplement to SIP message processing.
Definition: res_pjsip.h:2970
void(* outgoing_request)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
Called on an outgoing SIP request This method is always called from a SIP servant thread.
Definition: res_pjsip.h:3013
int(* incoming_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return....
Definition: res_pjsip.h:2992
void(* outgoing_response)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
Called on an outgoing SIP response This method is always called from a SIP servant thread.
Definition: res_pjsip.h:3018
void(* incoming_response)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread.
Definition: res_pjsip.h:3008
const char * method
Definition: res_pjsip.h:2972
enum ast_sip_supplement_priority priority
Definition: res_pjsip.h:2974
struct ast_sip_supplement * next
Definition: res_pjsip.h:3020
Structure for SIP transport information.
Definition: res_pjsip.h:103
struct pjsip_tpfactory * factory
Transport factory.
Definition: res_pjsip.h:107
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:105
Transport to bind to.
Definition: res_pjsip.h:187
Support for dynamic strings.
Definition: strings.h:604
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
An opaque threadpool structure.
Definition: threadpool.c:36
Domain data structure.
Definition: sip.h:887
unsigned int priority
Definition: res_pjsip.c:219
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:220
Definition: search.h:40
Definition: astman.c:222
Structure to hold information about an outbound request.
Definition: res_pjsip.c:1366
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:1368
unsigned int challenge_count
Definition: res_pjsip.c:1374
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:1372
pj_int32_t timeout
Definition: res_pjsip.c:1414
unsigned int send_cb_called
Definition: res_pjsip.c:1410
pjsip_tx_data * tdata
Definition: res_pjsip.c:1416
unsigned int cb_called
Definition: res_pjsip.c:1408
pj_timer_entry * timeout_timer
Definition: res_pjsip.c:1412
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:1406
ast_cond_t cond
Definition: stasis.c:1278
int(* task)(void *)
Definition: res_pjsip.c:1947
void * task_data
Definition: stasis.c:1280
ast_mutex_t lock
Definition: stasis.c:1277
userdata associated with baseline taskprocessor test
structure to hold users read from users.conf
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
An API for managing task processing threads that can be shared across modules.
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor's current task.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
#define AST_TEST_DEFINE(hdr)
Definition: test.h:126
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static struct test_options options
static struct test_val b
static struct test_val a
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
Definition: threadpool.c:966
struct ast_taskprocessor * ast_threadpool_serializer_group(const char *name, struct ast_threadpool *pool, struct ast_serializer_shutdown_group *shutdown_group)
Serialized execution of tasks within a ast_threadpool.
Definition: threadpool.c:1398
long ast_threadpool_queue_size(struct ast_threadpool *pool)
Return the size of the threadpool's task queue.
Definition: threadpool.c:1433
struct ast_threadpool * ast_threadpool_create(const char *name, struct ast_threadpool_listener *listener, const struct ast_threadpool_options *options)
Create a new threadpool.
Definition: threadpool.c:916
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
int error(const char *format,...)
Definition: utils/frame.c:999
Utility functions.
#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:936
#define ast_assert(a)
Definition: utils.h:734
#define MIN(a, b)
Definition: utils.h:226
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:781
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:661
Universally unique identifier support.