Asterisk - The Open Source Telephony Project GIT-master-545c459
Loading...
Searching...
No Matches
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"
30#include "asterisk/strings.h"
31#include "pjsip/sip_parser.h"
34#include "asterisk/logger.h"
35#include "asterisk/lock.h"
36#include "asterisk/utils.h"
37#include "asterisk/astobj2.h"
38#include "asterisk/module.h"
39#include "asterisk/serializer.h"
40#include "asterisk/taskpool.h"
42#include "asterisk/uuid.h"
43#include "asterisk/sorcery.h"
44#include "asterisk/file.h"
45#include "asterisk/causes.h"
46#include "asterisk/cli.h"
47#include "asterisk/callerid.h"
49#include "asterisk/test.h"
52#include "asterisk/utf8.h"
53#include "asterisk/acl.h"
54
55/*** MODULEINFO
56 <depend>pjproject</depend>
57 <depend>res_pjproject</depend>
58 <depend>res_sorcery_config</depend>
59 <depend>res_sorcery_memory</depend>
60 <depend>res_sorcery_astdb</depend>
61 <use type="module">res_statsd</use>
62 <use type="module">res_geolocation</use>
63 <support_level>core</support_level>
64 ***/
65
66#define MOD_DATA_CONTACT "contact"
67
68static pjsip_endpoint *ast_pjsip_endpoint;
69
71
72/*! Local host address for IPv4 */
73static pj_sockaddr host_ip_ipv4;
74
75/*! Local host address for IPv4 (string form) */
76static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN];
77
78/*! Local host address for IPv6 */
79static pj_sockaddr host_ip_ipv6;
80
81/*! Local host address for IPv6 (string form) */
82static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN];
83
84void ast_sip_add_date_header(pjsip_tx_data *tdata)
85{
86 char date[256];
87 struct tm tm;
88 time_t t = time(NULL);
89
90 gmtime_r(&t, &tm);
91 strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
92
93 ast_sip_add_header(tdata, "Date", date);
94}
95
96static int register_service(void *data)
97{
98 pjsip_module **module = data;
99 if (!ast_pjsip_endpoint) {
100 ast_log(LOG_ERROR, "There is no PJSIP endpoint. Unable to register services\n");
101 return -1;
102 }
103 if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
104 ast_log(LOG_ERROR, "Unable to register module %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
105 return -1;
106 }
107 ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
108 return 0;
109}
110
111int ast_sip_register_service(pjsip_module *module)
112{
114}
115
116static int unregister_service(void *data)
117{
118 pjsip_module **module = data;
119 if (!ast_pjsip_endpoint) {
120 return -1;
121 }
122 pjsip_endpt_unregister_module(ast_pjsip_endpoint, *module);
123 ast_debug(1, "Unregistered SIP service %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
124 return 0;
125}
126
127void ast_sip_unregister_service(pjsip_module *module)
128{
130}
131
133
135{
137 ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
138 return -1;
139 }
141 ast_debug(1, "Registered SIP authenticator module %p\n", auth);
142
143 return 0;
144}
145
147{
148 if (registered_authenticator != auth) {
149 ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
151 return;
152 }
154 ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
155}
156
157int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
158{
160 && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
161 ast_debug(3, "Skipping OPTIONS authentication due to endpoint configuration\n");
162 return 0;
163 }
164
166 ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
167 return 0;
168 }
169
170 return registered_authenticator->requires_authentication(endpoint, rdata);
171}
172
174 pjsip_rx_data *rdata, pjsip_tx_data *tdata)
175{
177 ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
179 }
180 return registered_authenticator->check_authentication(endpoint, rdata, tdata);
181}
182
184
186{
188 ast_log(LOG_WARNING, "Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
189 return -1;
190 }
192 ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
193
194 return 0;
195}
196
198{
200 ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
202 return;
203 }
205 ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
206}
207
208int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge,
209 pjsip_tx_data *old_request, pjsip_tx_data **new_request)
210{
212 ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
213 return -1;
214 }
215 return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
216}
217
224
226
228 const char *name)
229{
230 char *prev, *current, *identifier_order;
231 struct endpoint_identifier_list *iter, *id_list_item;
233
234 id_list_item = ast_calloc(1, sizeof(*id_list_item));
235 if (!id_list_item) {
236 ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
237 return -1;
238 }
239 id_list_item->identifier = identifier;
240 id_list_item->name = name;
241
242 ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
243
244 if (ast_strlen_zero(name)) {
245 /* if an identifier has no name then place in front */
247 return 0;
248 }
249
250 /* see if the name of the identifier is in the global endpoint_identifier_order list */
251 identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
252
253 if (ast_strlen_zero(identifier_order)) {
254 id_list_item->priority = UINT_MAX;
256 ast_free(identifier_order);
257 return 0;
258 }
259
260 id_list_item->priority = 0;
261 while ((current = strchr(current, ','))) {
262 ++id_list_item->priority;
263 if (!strncmp(prev, name, current - prev)
264 && strlen(name) == current - prev) {
265 break;
266 }
267 prev = ++current;
268 }
269
270 if (!current) {
271 /* check to see if it is the only or last item */
272 if (!strcmp(prev, name)) {
273 ++id_list_item->priority;
274 } else {
275 id_list_item->priority = UINT_MAX;
276 }
277 }
278
279 if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
280 /* if not in the endpoint_identifier_order list then consider it less in
281 priority and add it to the end */
283 ast_free(identifier_order);
284 return 0;
285 }
286
288 if (id_list_item->priority < iter->priority) {
290 break;
291 }
292
293 if (!AST_RWLIST_NEXT(iter, list)) {
295 break;
296 }
297 }
299
300 ast_free(identifier_order);
301 return 0;
302}
303
308
323
324struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata)
325{
326 struct endpoint_identifier_list *iter;
327 struct ast_sip_endpoint *endpoint = NULL;
331 endpoint = iter->identifier->identify_endpoint(rdata);
332 if (endpoint) {
333 break;
334 }
335 }
336 return endpoint;
337}
338
339char *ast_sip_rdata_get_header_value(pjsip_rx_data *rdata, const pj_str_t str)
340{
341 pjsip_generic_string_hdr *hdr;
342 pj_str_t hdr_val;
343
344 hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
345 if (!hdr) {
346 return NULL;
347 }
348
349 pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
350
351 return hdr_val.ptr;
352}
353
354static int do_cli_dump_endpt(void *v_a)
355{
356 struct ast_cli_args *a = v_a;
357
359 pj_log_set_level(3);
360 }
362 pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
364 pj_log_set_level(ast_option_pjproject_log_level);
365
366 return 0;
367}
368
369static char *cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
370{
371 switch (cmd) {
372 case CLI_INIT:
373#ifdef AST_DEVMODE
374 e->command = "pjsip dump endpt [details]";
375 e->usage =
376 "Usage: pjsip dump endpt [details]\n"
377 " Dump the res_pjsip endpt internals.\n"
378 "\n"
379 "Warning: PJPROJECT documents that the function used by this\n"
380 "CLI command may cause a crash when asking for details because\n"
381 "it tries to access all active memory pools.\n";
382#else
383 /*
384 * In non-developer mode we will not document or make easily accessible
385 * the details option even though it is still available. The user has
386 * to know it exists to use it. Presumably they would also be aware of
387 * the potential crash warning.
388 */
389 e->command = "pjsip dump endpt";
390 e->usage =
391 "Usage: pjsip dump endpt\n"
392 " Dump the res_pjsip endpt internals.\n";
393#endif /* AST_DEVMODE */
394 return NULL;
395 case CLI_GENERATE:
396 return NULL;
397 }
398
399 if (4 < a->argc
400 || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
401 return CLI_SHOWUSAGE;
402 }
403
405
406 return CLI_SUCCESS;
407}
408
409static char *cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
410{
411#define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
412 struct endpoint_identifier_list *iter;
413
414 switch (cmd) {
415 case CLI_INIT:
416 e->command = "pjsip show identifiers";
417 e->usage = "Usage: pjsip show identifiers\n"
418 " List all registered endpoint identifiers\n";
419 return NULL;
420 case CLI_GENERATE:
421 return NULL;
422 }
423
424 if (a->argc != 3) {
425 return CLI_SHOWUSAGE;
426 }
427
428 ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
429 {
433 iter->name ? iter->name : "name not specified");
434 }
435 }
436 return CLI_SUCCESS;
437#undef ENDPOINT_IDENTIFIER_FORMAT
438}
439
440static char *cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
441{
442 struct ast_sip_cli_context context;
443
444 switch (cmd) {
445 case CLI_INIT:
446 e->command = "pjsip show settings";
447 e->usage = "Usage: pjsip show settings\n"
448 " Show global and system configuration options\n";
449 return NULL;
450 case CLI_GENERATE:
451 return NULL;
452 }
453
454 context.output_buffer = ast_str_create(256);
455 if (!context.output_buffer) {
456 ast_cli(a->fd, "Could not allocate output buffer.\n");
457 return CLI_FAILURE;
458 }
459
460 if (sip_cli_print_global(&context) || sip_cli_print_system(&context)) {
461 ast_free(context.output_buffer);
462 ast_cli(a->fd, "Error retrieving settings.\n");
463 return CLI_FAILURE;
464 }
465
466 ast_cli(a->fd, "%s", ast_str_buffer(context.output_buffer));
467 ast_free(context.output_buffer);
468 return CLI_SUCCESS;
469}
470
471static struct ast_cli_entry cli_commands[] = {
472 AST_CLI_DEFINE(cli_dump_endpt, "Dump the res_pjsip endpt internals"),
473 AST_CLI_DEFINE(cli_show_settings, "Show global and system configuration options"),
474 AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
475};
476
478
484
498
500 struct ast_sip_ami *ami, int *count)
501{
502 int res = 0;
505 *count = 0;
507 if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
508 return res;
509 }
510
511 if (!res) {
512 (*count)++;
513 }
514 }
515 return 0;
516}
517
518pjsip_endpoint *ast_sip_get_pjsip_endpoint(void)
519{
520 return ast_pjsip_endpoint;
521}
522
523int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint,
524 pjsip_rx_data *rdata)
525{
526 pj_str_t host_name;
527 int result = 1;
528
529 /* Determine if the contact cannot survive a restart/boot. */
530 if (uri->port == rdata->pkt_info.src_port
531 && !pj_strcmp(&uri->host,
532 pj_cstr(&host_name, rdata->pkt_info.src_name))
533 /* We have already checked if the URI scheme is sip: or sips: */
534 && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
535 pj_str_t type_name;
536
537 /* Determine the transport parameter value */
538 if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
539 /* WSS is special, as it needs to be ws. */
540 pj_cstr(&type_name, "ws");
541 } else {
542 pj_cstr(&type_name, rdata->tp_info.transport->type_name);
543 }
544
545 if (!pj_stricmp(&uri->transport_param, &type_name)
546 && (endpoint->nat.rewrite_contact
547 /* Websockets are always rewritten */
548 || !pj_stricmp(&uri->transport_param,
549 pj_cstr(&type_name, "ws")))) {
550 /*
551 * The contact was rewritten to the reliable transport's
552 * source address. Disconnecting the transport for any
553 * reason invalidates the contact.
554 */
555 result = 0;
556 }
557 }
558
559 return result;
560}
561
562pjsip_sip_uri *ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
563{
564 pjsip_contact_hdr *contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
565
566 if (!contact || (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
567 return NULL;
568 }
569
570 return pjsip_uri_get_uri(contact->uri);
571}
572
573/*! \brief Callback function for finding the transport the request is going out on */
574static int find_transport_state_in_use(void *obj, void *arg, int flags)
575{
576 struct ast_sip_transport_state *transport_state = obj;
577 struct ast_sip_request_transport_details *details = arg;
578
579 /* If an explicit transport or factory matches then this is what is in use, if we are unavailable
580 * to compare based on that we make sure that the type is the same and the source IP address/port are the same
581 */
582 if (transport_state && ((details->transport && details->transport == transport_state->transport) ||
583 (details->factory && details->factory == transport_state->factory) ||
584 ((details->type == transport_state->type) && (transport_state->factory) &&
585 !pj_strcmp(&transport_state->factory->addr_name.host, &details->local_address) &&
586 transport_state->factory->addr_name.port == details->local_port))) {
587 return CMP_MATCH | CMP_STOP;
588 }
589
590 return 0;
591}
592
602
603int ast_sip_rewrite_uri_to_local(pjsip_sip_uri *uri, pjsip_tx_data *tdata) {
605 RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
606 struct ast_sip_request_transport_details details = { 0, };
607 pjsip_sip_uri *tmp_uri;
608 pjsip_dialog *dlg;
609 struct ast_sockaddr addr = { { 0, } };
610
611 if ((tmp_uri = ast_sip_get_contact_sip_uri(tdata))) {
612 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
613 uri->port = tmp_uri->port;
614 } else if ((dlg = pjsip_tdata_get_dlg(tdata))
615 && (tmp_uri = pjsip_uri_get_uri(dlg->local.info->uri))
616 && (PJSIP_URI_SCHEME_IS_SIP(tmp_uri) || PJSIP_URI_SCHEME_IS_SIPS(tmp_uri))) {
617 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
618 uri->port = tmp_uri->port;
619 }
620
621 if (ast_sip_set_request_transport_details(&details, tdata, 1)
622 || !(transport_state = ast_sip_find_transport_state_in_use(&details))
623 || !(transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))) {
624 return 0;
625 }
626
627 if (transport_state->localnet) {
628 ast_sockaddr_parse(&addr, tdata->tp_info.dst_name, PARSE_PORT_FORBID);
629 ast_sockaddr_set_port(&addr, tdata->tp_info.dst_port);
630 if (ast_sip_transport_is_local(transport_state, &addr)) {
631 return 0;
632 }
633 }
634
635 if (!ast_sockaddr_isnull(&transport_state->external_signaling_address)) {
636 pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
637 }
638
639 if (transport->external_signaling_port) {
640 uri->port = transport->external_signaling_port;
641 }
642
643 return 0;
644}
645
647 int use_ipv6) {
648 pjsip_sip_uri *uri;
649 pjsip_via_hdr *via;
650 long transport_type;
651
652 if (!details || !tdata) {
653 return -1;
654 }
655
656 /* If IPv6 should be considered, un-set Bit 7 to make TCP6 equal to TCP and TLS6 equal to TLS */
657 transport_type = use_ipv6 ? tdata->tp_info.transport->key.type & ~(PJSIP_TRANSPORT_IPV6)
658 : tdata->tp_info.transport->key.type;
659
660 if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
661 details->transport = tdata->tp_sel.u.transport;
662 } else if (tdata->tp_sel.type == PJSIP_TPSELECTOR_LISTENER) {
663 details->factory = tdata->tp_sel.u.listener;
664 } else if (transport_type == PJSIP_TRANSPORT_UDP || transport_type == PJSIP_TRANSPORT_UDP6) {
665 /* Connectionless uses the same transport for all requests */
666 details->type = AST_TRANSPORT_UDP;
667 details->transport = tdata->tp_info.transport;
668 } else {
669 if (transport_type == PJSIP_TRANSPORT_TCP) {
670 details->type = AST_TRANSPORT_TCP;
671 } else if (transport_type == PJSIP_TRANSPORT_TLS) {
672 details->type = AST_TRANSPORT_TLS;
673 } else {
674 /* Unknown transport type, we can't map. */
675 return -1;
676 }
677
678 if ((uri = ast_sip_get_contact_sip_uri(tdata))) {
679 details->local_address = uri->host;
680 details->local_port = uri->port;
681 } else if ((tdata->msg->type == PJSIP_REQUEST_MSG) &&
682 (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL))) {
683 details->local_address = via->sent_by.host;
684 details->local_port = via->sent_by.port;
685 } else {
686 return -1;
687 }
688
689 if (!details->local_port) {
690 details->local_port = (details->type == AST_TRANSPORT_TLS) ? 5061 : 5060;
691 }
692 }
693 return 0;
694}
695
697 pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
698{
699 char *host = NULL;
700 static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
701 pjsip_param *x_transport;
702
703 if (!ast_strlen_zero(endpoint->transport)) {
704 ast_copy_string(buf, endpoint->transport, buf_len);
705 return 0;
706 }
707
708 x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
709 if (!x_transport) {
710 return -1;
711 }
712
713 /* Only use x_transport if the uri host is an ip (4 or 6) address */
714 host = ast_alloca(sip_uri->host.slen + 1);
715 ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
717 return -1;
718 }
719
720 ast_copy_pj_str(buf, &x_transport->value, buf_len);
721
722 return 0;
723}
724
725int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,
726 pjsip_tpselector *selector)
727{
728 pjsip_sip_uri *uri;
729 pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
730
731 uri = pjsip_uri_get_uri(dlg->target);
732 if (!selector) {
733 selector = &sel;
734 }
735
736 ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
737
738 pjsip_dlg_set_transport(dlg, selector);
739
740 if (selector == &sel) {
742 }
743
744 return 0;
745}
746
747static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user,
748 const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
749{
750 pj_str_t tmp, local_addr;
751 pjsip_uri *uri;
752 pjsip_sip_uri *sip_uri;
753 pjsip_transport_type_e type;
754 int local_port;
755 char default_user[PJSIP_MAX_URL_SIZE];
756
757 if (ast_strlen_zero(user)) {
758 ast_sip_get_default_from_user(default_user, sizeof(default_user));
759 user = default_user;
760 }
761
762 /* Parse the provided target URI so we can determine what transport it will end up using */
763 pj_strdup_with_null(pool, &tmp, target);
764
765 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
766 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
767 return -1;
768 }
769
770 sip_uri = pjsip_uri_get_uri(uri);
771
772 /* Determine the transport type to use */
773 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
774 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
775 if (type == PJSIP_TRANSPORT_UNSPECIFIED
776 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
777 type = PJSIP_TRANSPORT_TLS;
778 }
779 } else if (!sip_uri->transport_param.slen) {
780 type = PJSIP_TRANSPORT_UDP;
781 } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
782 return -1;
783 }
784
785 /* If the host is IPv6 turn the transport into an IPv6 version */
786 if (pj_strchr(&sip_uri->host, ':')) {
787 type |= PJSIP_TRANSPORT_IPV6;
788 }
789
790 /* In multidomain scenario, username may contain @ with domain info */
791 if (!ast_sip_get_disable_multi_domain() && strchr(user, '@')) {
792 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
793 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
794 "<sip:%s%s%s>",
795 user,
796 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
797 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
798 return 0;
799 }
800
801 if (!ast_strlen_zero(domain)) {
802 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
803 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
804 "<sip:%s@%s%s%s>",
805 user,
806 domain,
807 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
808 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
809 return 0;
810 }
811
812 /* Get the local bound address for the transport that will be used when communicating with the provided URI */
813 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
814 &local_addr, &local_port) != PJ_SUCCESS) {
815
816 /* If no local address can be retrieved using the transport manager use the host one */
817 pj_strdup(pool, &local_addr, pj_gethostname());
818 local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
819 }
820
821 /* If IPv6 was specified in the transport, set the proper type */
822 if (pj_strchr(&local_addr, ':')) {
823 type |= PJSIP_TRANSPORT_IPV6;
824 }
825
826 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
827 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
828 "<sip:%s@%s%.*s%s:%d%s%s>",
829 user,
830 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
831 (int)local_addr.slen,
832 local_addr.ptr,
833 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
834 local_port,
835 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
836 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
837
838 return 0;
839}
840
841int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
842{
843 int res = 0;
844 struct ast_sip_transport_state *transport_state;
845
847 if (!transport_state) {
848 ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
850 return -1;
851 }
852
853 /* Only flows maintain dynamic state which needs protection */
854 if (transport_state->flow) {
855 ao2_lock(transport_state);
856 }
857
858 if (transport_state->transport) {
859 selector->type = PJSIP_TPSELECTOR_TRANSPORT;
860 selector->u.transport = transport_state->transport;
861 pjsip_transport_add_ref(selector->u.transport);
862 } else if (transport_state->factory) {
863 selector->type = PJSIP_TPSELECTOR_LISTENER;
864 selector->u.listener = transport_state->factory;
865 } else if (transport->type == AST_TRANSPORT_WS || transport->type == AST_TRANSPORT_WSS) {
866 /* The WebSocket transport has no factory as it can not create outgoing connections, so
867 * even if an endpoint is locked to a WebSocket transport we let the PJSIP logic
868 * find the existing connection if available and use it.
869 */
870 } else if (transport->flow) {
871 /* This is a child of another transport, so we need to establish a new connection */
872#ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
873 selector->disable_connection_reuse = PJ_TRUE;
874#else
875 ast_log(LOG_WARNING, "Connection reuse could not be disabled on transport '%s' as support is not available\n",
877#endif
878 } else {
879 res = -1;
880 }
881
882 if (transport_state->flow) {
883 ao2_unlock(transport_state);
884 }
885
886 ao2_ref(transport_state, -1);
887
888 return res;
889}
890
891int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
892{
894
895 if (ast_strlen_zero(transport_name)) {
896 return 0;
897 }
898
899 transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
900 if (!transport) {
901 ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
902 transport_name);
903 return -1;
904 }
905
907}
908
910 pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
911{
912 char transport_name[128];
913
914 if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name, sizeof(transport_name))) {
915 return 0;
916 }
917
918 return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
919}
920
921void ast_sip_tpselector_unref(pjsip_tpselector *selector)
922{
923 if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
924 pjsip_transport_dec_ref(selector->u.transport);
925 }
926}
927
928void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
929{
930 pjsip_sip_uri *sip_uri;
931 int i = 0;
932 static const pj_str_t STR_PHONE = { "phone", 5 };
933
934 if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
935 return;
936 }
937
938 sip_uri = pjsip_uri_get_uri(uri);
939
940 if (!pj_strlen(&sip_uri->user)) {
941 return;
942 }
943
944 if (pj_strbuf(&sip_uri->user)[0] == '+') {
945 i = 1;
946 }
947
948 /* Test URI user against allowed characters in AST_DIGIT_ANY */
949 for (; i < pj_strlen(&sip_uri->user); i++) {
950 if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
951 break;
952 }
953 }
954
955 if (i < pj_strlen(&sip_uri->user)) {
956 return;
957 }
958
959 sip_uri->user_param = STR_PHONE;
960}
961
962pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
963 const char *uri, const char *request_user)
964{
965 char enclosed_uri[PJSIP_MAX_URL_SIZE];
966 pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri, target_uri;
967 pj_status_t res;
968 pjsip_dialog *dlg = NULL;
969 const char *outbound_proxy = endpoint->outbound_proxy;
970 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
971 static const pj_str_t HCONTACT = { "Contact", 7 };
972
973 if (!ast_begins_with(uri, "<")) {
974 snprintf(enclosed_uri, sizeof(enclosed_uri), "<%s>", uri);
975 } else {
976 snprintf(enclosed_uri, sizeof(enclosed_uri), "%s", uri);
977 }
978 pj_cstr(&remote_uri, enclosed_uri);
979
980 pj_cstr(&target_uri, uri);
981
982 res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
983 if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
984 /* dlg->target is a pjsip_other_uri, but it's assumed to be a
985 * pjsip_sip_uri below. Fail fast. */
986 res = PJSIP_EINVALIDURI;
987 pjsip_dlg_terminate(dlg);
988 }
989 if (res != PJ_SUCCESS) {
990 if (res == PJSIP_EINVALIDURI) {
992 "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
993 ast_sorcery_object_get_id(endpoint), uri);
994 }
995 return NULL;
996 }
997
998 /* We have to temporarily bump up the sess_count here so the dialog is not prematurely destroyed */
999 dlg->sess_count++;
1000
1001 ast_sip_dlg_set_transport(endpoint, dlg, &selector);
1002
1003 if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->fromuser, endpoint->fromdomain, &remote_uri, &selector)) {
1004 dlg->sess_count--;
1005 pjsip_dlg_terminate(dlg);
1006 ast_sip_tpselector_unref(&selector);
1007 return NULL;
1008 }
1009
1010 ast_sip_tpselector_unref(&selector);
1011
1012 /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
1013 pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
1014 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
1015 if (!dlg->local.info->uri) {
1017 "Could not parse URI '%s' for endpoint '%s'\n",
1018 dlg->local.info_str.ptr, ast_sorcery_object_get_id(endpoint));
1019 dlg->sess_count--;
1020 pjsip_dlg_terminate(dlg);
1021 return NULL;
1022 }
1023
1024 dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
1025
1026 if (!ast_strlen_zero(endpoint->contact_user)) {
1027 pjsip_sip_uri *sip_uri;
1028
1029 sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
1030 pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
1031 }
1032
1033 /* If a request user has been specified and we are permitted to change it, do so */
1034 if (!ast_strlen_zero(request_user)) {
1035 pjsip_sip_uri *sip_uri;
1036
1037 if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
1038 sip_uri = pjsip_uri_get_uri(dlg->target);
1039 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1040 }
1041 if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
1042 sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
1043 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1044 }
1045 }
1046
1047 /* Add the user=phone parameter if applicable */
1048 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
1049 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.info->uri);
1050 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->local.info->uri);
1051
1052 if (!ast_strlen_zero(outbound_proxy)) {
1053 pjsip_route_hdr route_set, *route;
1054 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1055 pj_str_t tmp;
1056
1057 pj_list_init(&route_set);
1058
1059 pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
1060 if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1061 ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
1062 ast_sorcery_object_get_id(endpoint), outbound_proxy);
1063 dlg->sess_count--;
1064 pjsip_dlg_terminate(dlg);
1065 return NULL;
1066 }
1067 pj_list_insert_nodes_before(&route_set, route);
1068
1069 pjsip_dlg_set_route_set(dlg, &route_set);
1070 }
1071
1072 dlg->sess_count--;
1073
1074 return dlg;
1075}
1076
1077/*!
1078 * \brief Determine if a SIPS Contact header is required.
1079 *
1080 * This uses the guideline provided in RFC 3261 Section 12.1.1 to
1081 * determine if the Contact header must be a sips: URI.
1082 *
1083 * \param rdata The incoming dialog-starting request
1084 * \retval 0 SIPS not required
1085 * \retval 1 SIPS required
1086 */
1087static int uas_use_sips_contact(pjsip_rx_data *rdata)
1088{
1089 pjsip_rr_hdr *record_route;
1090
1091 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
1092 return 1;
1093 }
1094
1095 record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
1096 if (record_route) {
1097 if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
1098 return 1;
1099 }
1100 } else {
1101 pjsip_contact_hdr *contact;
1102
1103 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1104 ast_assert(contact != NULL);
1105 if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
1106 return 1;
1107 }
1108 }
1109
1110 return 0;
1111}
1112
1113typedef pj_status_t (*create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata,
1114 const pj_str_t *contact, pjsip_dialog **p_dlg);
1115
1116static pjsip_dialog *create_dialog_uas(const struct ast_sip_endpoint *endpoint,
1117 pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
1118{
1119 pjsip_dialog *dlg;
1120 pj_str_t contact;
1121 pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
1122 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1123 pjsip_transport *transport;
1124 pjsip_contact_hdr *contact_hdr;
1125
1127
1128 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1129 if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
1130 &selector)) {
1131 return NULL;
1132 }
1133
1134 transport = rdata->tp_info.transport;
1135 if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
1136 transport = selector.u.transport;
1137 }
1138 type = transport->key.type;
1139
1140 contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
1141 contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
1142 "<%s:%s%s%s%.*s%s:%d%s%s>",
1143 uas_use_sips_contact(rdata) ? "sips" : "sip",
1144 S_OR(endpoint->contact_user, ""),
1145 (!ast_strlen_zero(endpoint->contact_user)) ? "@" : "",
1146 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1147 (int)transport->local_name.host.slen,
1148 transport->local_name.host.ptr,
1149 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1150 transport->local_name.port,
1151 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1152 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
1153
1154 *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
1155 if (*status != PJ_SUCCESS) {
1156 char err[PJ_ERR_MSG_SIZE];
1157
1158 pj_strerror(*status, err, sizeof(err));
1159 ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
1160 ast_sorcery_object_get_id(endpoint), err);
1161 ast_sip_tpselector_unref(&selector);
1162 return NULL;
1163 }
1164
1165 dlg->sess_count++;
1166 pjsip_dlg_set_transport(dlg, &selector);
1167 dlg->sess_count--;
1168
1169 ast_sip_tpselector_unref(&selector);
1170
1171 return dlg;
1172}
1173
1174pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
1175{
1176#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1177 pjsip_dialog *dlg;
1178
1179 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1180 if (dlg) {
1181 pjsip_dlg_dec_lock(dlg);
1182 }
1183
1184 return dlg;
1185#else
1186 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1187#endif
1188}
1189
1190pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
1191 pjsip_rx_data *rdata, pj_status_t *status)
1192{
1193#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1194 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1195#else
1196 /*
1197 * This is put here in order to be compatible with older versions of pjproject.
1198 * Best we can do in this case is immediately lock after getting the dialog.
1199 * However, that does leave a "gap" between creating and locking.
1200 */
1201 pjsip_dialog *dlg;
1202
1203 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1204 if (dlg) {
1205 pjsip_dlg_inc_lock(dlg);
1206 }
1207
1208 return dlg;
1209#endif
1210 }
1211
1212int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
1213 char *transport_type, const char *local_name, int local_port, const char *contact)
1214{
1215 pj_str_t tmp;
1216
1217 /*
1218 * Initialize the error list in case there is a parse error
1219 * in the given packet.
1220 */
1221 pj_list_init(&rdata->msg_info.parse_err);
1222
1223 rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
1224 if (!rdata->tp_info.transport) {
1225 return -1;
1226 }
1227
1228 ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
1229 ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
1230 rdata->pkt_info.src_port = src_port;
1231 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
1232 pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
1233
1234 pjsip_parse_rdata(packet, strlen(packet), rdata);
1235 if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
1236 return -1;
1237 }
1238
1239 if (!ast_strlen_zero(contact)) {
1240 pjsip_contact_hdr *contact_hdr;
1241
1242 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1243 if (contact_hdr) {
1244 contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (char *)contact,
1245 strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
1246 if (!contact_hdr->uri) {
1247 ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact);
1248 return -1;
1249 }
1250 }
1251 }
1252
1253 pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
1254 rdata->msg_info.via->rport_param = -1;
1255
1256 rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
1257 rdata->tp_info.transport->type_name = transport_type;
1258 pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
1259 rdata->tp_info.transport->local_name.port = local_port;
1260
1261 return 0;
1262}
1263
1264int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
1265 char *transport_type, const char *local_name, int local_port)
1266{
1267 return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
1268 local_name, local_port, NULL);
1269}
1270
1271/* PJSIP doesn't know about the INFO method, so we have to define it ourselves */
1272static const pjsip_method info_method = {PJSIP_OTHER_METHOD, {"INFO", 4} };
1273static const pjsip_method message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} };
1274static const pjsip_method refer_method = {PJSIP_OTHER_METHOD, {"REFER", 5} };
1275
1276static struct {
1277 const char *method;
1278 const pjsip_method *pmethod;
1279} methods [] = {
1280 { "INVITE", &pjsip_invite_method },
1281 { "CANCEL", &pjsip_cancel_method },
1282 { "ACK", &pjsip_ack_method },
1283 { "BYE", &pjsip_bye_method },
1284 { "REGISTER", &pjsip_register_method },
1285 { "OPTIONS", &pjsip_options_method },
1286 { "SUBSCRIBE", &pjsip_subscribe_method },
1287 { "NOTIFY", &pjsip_notify_method },
1288 { "PUBLISH", &pjsip_publish_method },
1289 { "INFO", &info_method },
1290 { "MESSAGE", &message_method },
1291 { "REFER", &refer_method },
1293
1294static const pjsip_method *get_pjsip_method(const char *method)
1295{
1296 int i;
1297 for (i = 0; i < ARRAY_LEN(methods); ++i) {
1298 if (!strcmp(method, methods[i].method)) {
1299 return methods[i].pmethod;
1300 }
1301 }
1302 return NULL;
1303}
1304
1305static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
1306{
1307 if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
1308 ast_log(LOG_WARNING, "Unable to create in-dialog request.\n");
1309 return -1;
1310 }
1311
1312 return 0;
1313}
1314
1315static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata);
1316static pjsip_module supplement_module = {
1317 .name = { "Out of dialog supplement hook", 29 },
1318 .id = -1,
1319 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 1,
1320 .on_rx_request = supplement_on_rx_request,
1321};
1322
1323static int create_out_of_dialog_request(const pjsip_method *method, struct ast_sip_endpoint *endpoint,
1324 const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
1325{
1326 RAII_VAR(struct ast_sip_contact *, contact, ao2_bump(provided_contact), ao2_cleanup);
1327 pj_str_t remote_uri;
1328 pj_str_t from;
1329 pj_pool_t *pool;
1330 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1331 pjsip_uri *sip_uri;
1332 const char *fromuser;
1333
1334 if (ast_strlen_zero(uri)) {
1335 if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
1336 ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
1337 return -1;
1338 }
1339
1340 if (!contact) {
1342 }
1343 if (!contact || ast_strlen_zero(contact->uri)) {
1344 ast_log(LOG_WARNING, "Unable to retrieve contact for endpoint %s\n",
1345 ast_sorcery_object_get_id(endpoint));
1346 return -1;
1347 }
1348
1349 pj_cstr(&remote_uri, contact->uri);
1350 } else {
1351 pj_cstr(&remote_uri, uri);
1352 }
1353
1354 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
1355
1356 if (!pool) {
1357 ast_log(LOG_ERROR, "Unable to create PJLIB memory pool\n");
1358 return -1;
1359 }
1360
1361 sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
1362 if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
1363 ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
1364 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1365 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
1366 pj_strbuf(&remote_uri));
1367 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1368 return -1;
1369 }
1370
1371 ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
1372
1373 fromuser = endpoint ? (!ast_strlen_zero(endpoint->fromuser) ? endpoint->fromuser : ast_sorcery_object_get_id(endpoint)) : NULL;
1374 if (sip_dialog_create_from(pool, &from, fromuser,
1375 endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
1376 ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
1377 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1378 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1379 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1380 ast_sip_tpselector_unref(&selector);
1381 return -1;
1382 }
1383
1384 if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
1385 &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
1386 ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s\n",
1387 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1388 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1389 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1390 ast_sip_tpselector_unref(&selector);
1391 return -1;
1392 }
1393
1394 pjsip_tx_data_set_transport(*tdata, &selector);
1395
1396 ast_sip_tpselector_unref(&selector);
1397
1398 if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
1399 pjsip_contact_hdr *contact_hdr;
1400 pjsip_sip_uri *contact_uri;
1401 static const pj_str_t HCONTACT = { "Contact", 7 };
1402 static const pj_str_t HCONTACTSHORT = { "m", 1 };
1403
1404 contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
1405 if (contact_hdr) {
1406 contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
1407 pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->contact_user);
1408 }
1409 }
1410
1411 /* Add the user=phone parameter if applicable */
1412 ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
1413
1414 /* If an outbound proxy is specified on the endpoint apply it to this request */
1415 if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
1416 ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
1417 ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
1418 (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
1419 endpoint->outbound_proxy);
1420 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1421 return -1;
1422 }
1423
1424 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
1425
1426 /* We can release this pool since request creation copied all the necessary
1427 * data into the outbound request's pool
1428 */
1429 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1430 return 0;
1431}
1432
1433int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg,
1434 struct ast_sip_endpoint *endpoint, const char *uri,
1435 struct ast_sip_contact *contact, pjsip_tx_data **tdata)
1436{
1437 const pjsip_method *pmethod = get_pjsip_method(method);
1438
1439 if (!pmethod) {
1440 ast_log(LOG_WARNING, "Unknown method '%s'. Cannot send request\n", method);
1441 return -1;
1442 }
1443
1444 if (dlg) {
1445 return create_in_dialog_request(pmethod, dlg, tdata);
1446 } else {
1447 ast_assert(endpoint != NULL);
1448 return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
1449 }
1450}
1451
1453
1455{
1456 struct ast_sip_supplement *iter;
1457 int inserted = 0;
1459
1461 if (iter->priority > supplement->priority) {
1463 inserted = 1;
1464 break;
1465 }
1466 }
1468
1469 if (!inserted) {
1471 }
1472}
1473
1475{
1476 struct ast_sip_supplement *iter;
1478
1480 if (supplement == iter) {
1482 break;
1483 }
1484 }
1486}
1487
1488static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
1489{
1490 if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
1491 ast_log(LOG_WARNING, "Unable to send in-dialog request.\n");
1492 return -1;
1493 }
1494 return 0;
1495}
1496
1497static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
1498{
1499 pj_str_t method;
1500
1501 if (ast_strlen_zero(supplement_method)) {
1502 return PJ_TRUE;
1503 }
1504
1505 pj_cstr(&method, supplement_method);
1506
1507 return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
1508}
1509
1510#define TIMER_INACTIVE 0
1511#define TIMEOUT_TIMER2 5
1512
1513/*! \brief Structure to hold information about an outbound request */
1515 /*! The endpoint associated with this request */
1517 /*! Information to be provided to the callback upon receipt of a response */
1518 void *token;
1519 /*! The callback to be called upon receipt of a response */
1520 void (*callback)(void *token, pjsip_event *e);
1521 /*! Number of challenges received. */
1522 unsigned int challenge_count;
1523};
1524
1525static void send_request_data_destroy(void *obj)
1526{
1527 struct send_request_data *req_data = obj;
1528
1529 ao2_cleanup(req_data->endpoint);
1530}
1531
1533 void *token, void (*callback)(void *token, pjsip_event *e))
1534{
1535 struct send_request_data *req_data;
1536
1537 req_data = ao2_alloc_options(sizeof(*req_data), send_request_data_destroy,
1539 if (!req_data) {
1540 return NULL;
1541 }
1542
1543 req_data->endpoint = ao2_bump(endpoint);
1544 req_data->token = token;
1545 req_data->callback = callback;
1546
1547 return req_data;
1548}
1549
1551 /*! Information to be provided to the callback upon receipt of a response */
1552 void *token;
1553 /*! The callback to be called upon receipt of a response */
1554 void (*callback)(void *token, pjsip_event *e);
1555 /*! Non-zero when the callback is called. */
1556 unsigned int cb_called;
1557 /*! Non-zero if endpt_send_request_cb() was called. */
1558 unsigned int send_cb_called;
1559 /*! Timeout timer. */
1560 pj_timer_entry *timeout_timer;
1561 /*! Original timeout. */
1562 pj_int32_t timeout;
1563 /*! The transmit data. */
1564 pjsip_tx_data *tdata;
1565};
1566
1567/*! \internal This function gets called by pjsip when the transaction ends,
1568 * even if it timed out. The lock prevents a race condition if both the pjsip
1569 * transaction timer and our own timer expire simultaneously.
1570 */
1571static void endpt_send_request_cb(void *token, pjsip_event *e)
1572{
1573 struct send_request_wrapper *req_wrapper = token;
1574 unsigned int cb_called;
1575
1576 /*
1577 * Needed because we cannot otherwise tell if this callback was
1578 * called when pjsip_endpt_send_request() returns error.
1579 */
1580 req_wrapper->send_cb_called = 1;
1581
1582 if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
1583 ast_debug(2, "%p: PJSIP tsx timer expired\n", req_wrapper);
1584
1585 if (req_wrapper->timeout_timer
1586 && req_wrapper->timeout_timer->id != TIMEOUT_TIMER2) {
1587 ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1588 ao2_ref(req_wrapper, -1);
1589 return;
1590 }
1591 } else {
1592 ast_debug(2, "%p: PJSIP tsx response received\n", req_wrapper);
1593 }
1594
1595 ao2_lock(req_wrapper);
1596
1597 /* It's possible that our own timer was already processing while
1598 * we were waiting on the lock so check the timer id. If it's
1599 * still TIMER2 then we still need to process.
1600 */
1601 if (req_wrapper->timeout_timer
1602 && req_wrapper->timeout_timer->id == TIMEOUT_TIMER2) {
1603 int timers_cancelled = 0;
1604
1605 ast_debug(3, "%p: Cancelling timer\n", req_wrapper);
1606
1607 timers_cancelled = pj_timer_heap_cancel_if_active(
1608 pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
1609 req_wrapper->timeout_timer, TIMER_INACTIVE);
1610 if (timers_cancelled > 0) {
1611 /* If the timer was cancelled the callback will never run so
1612 * clean up its reference to the wrapper.
1613 */
1614 ast_debug(3, "%p: Timer cancelled\n", req_wrapper);
1615 ao2_ref(req_wrapper, -1);
1616 } else {
1617 /*
1618 * If it wasn't cancelled, it MAY be in the callback already
1619 * waiting on the lock. When we release the lock, it will
1620 * now know not to proceed.
1621 */
1622 ast_debug(3, "%p: Timer already expired\n", req_wrapper);
1623 }
1624 }
1625
1626 cb_called = req_wrapper->cb_called;
1627 req_wrapper->cb_called = 1;
1628 ao2_unlock(req_wrapper);
1629
1630 /* It's possible that our own timer expired and called the callbacks
1631 * so no need to call them again.
1632 */
1633 if (!cb_called && req_wrapper->callback) {
1634 req_wrapper->callback(req_wrapper->token, e);
1635 ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1636 }
1637
1638 ao2_ref(req_wrapper, -1);
1639}
1640
1641/*! \internal This function gets called by our own timer when it expires.
1642 * If the timer is cancelled however, the function does NOT get called.
1643 * The lock prevents a race condition if both the pjsip transaction timer
1644 * and our own timer expire simultaneously.
1645 */
1646static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
1647{
1648 struct send_request_wrapper *req_wrapper = entry->user_data;
1649 unsigned int cb_called;
1650
1651 ast_debug(2, "%p: Internal tsx timer expired after %d msec\n",
1652 req_wrapper, req_wrapper->timeout);
1653
1654 ao2_lock(req_wrapper);
1655 /*
1656 * If the id is not TIMEOUT_TIMER2 then the timer was cancelled
1657 * before we got the lock or it was already handled so just clean up.
1658 */
1659 if (entry->id != TIMEOUT_TIMER2) {
1660 ao2_unlock(req_wrapper);
1661 ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1662 ao2_ref(req_wrapper, -1);
1663 return;
1664 }
1665 entry->id = TIMER_INACTIVE;
1666
1667 ast_debug(3, "%p: Timer handled here\n", req_wrapper);
1668
1669 cb_called = req_wrapper->cb_called;
1670 req_wrapper->cb_called = 1;
1671 ao2_unlock(req_wrapper);
1672
1673 if (!cb_called && req_wrapper->callback) {
1674 pjsip_event event;
1675
1676 PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->tdata);
1677 event.body.tsx_state.type = PJSIP_EVENT_TIMER;
1678
1679 req_wrapper->callback(req_wrapper->token, &event);
1680 ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1681 }
1682
1683 ao2_ref(req_wrapper, -1);
1684}
1685
1687{
1688 struct send_request_wrapper *req_wrapper = obj;
1689
1690 pjsip_tx_data_dec_ref(req_wrapper->tdata);
1691 ast_debug(2, "%p: wrapper destroyed\n", req_wrapper);
1692}
1693
1694static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint,
1695 pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb,
1696 pjsip_transaction **tsx)
1697{
1698 struct send_request_wrapper *req_wrapper;
1699 pj_status_t ret_val;
1700 pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
1701
1702 if (tsx) {
1703 *tsx = NULL;
1704 }
1705
1706 if (!cb && token) {
1707 /* Silly. Without a callback we cannot do anything with token. */
1708 pjsip_tx_data_dec_ref(tdata);
1709 return PJ_EINVAL;
1710 }
1711
1712 /* Create wrapper to detect if the callback was actually called on an error. */
1713 req_wrapper = ao2_alloc(sizeof(*req_wrapper), send_request_wrapper_destructor);
1714 if (!req_wrapper) {
1715 pjsip_tx_data_dec_ref(tdata);
1716 return PJ_ENOMEM;
1717 }
1718
1719 ast_debug(2, "%p: Wrapper created\n", req_wrapper);
1720
1721 req_wrapper->token = token;
1722 req_wrapper->callback = cb;
1723 req_wrapper->timeout = timeout;
1724 req_wrapper->timeout_timer = NULL;
1725 req_wrapper->tdata = tdata;
1726 /* Add a reference to tdata. The wrapper destructor cleans it up. */
1727 pjsip_tx_data_add_ref(tdata);
1728
1729 if (timeout > 0) {
1730 pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
1731
1732 req_wrapper->timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
1733
1734 ast_debug(2, "%p: Set timer to %d msec\n", req_wrapper, timeout);
1735
1736 pj_timer_entry_init(req_wrapper->timeout_timer, TIMEOUT_TIMER2,
1737 req_wrapper, send_request_timer_callback);
1738
1739 /* We need to insure that the wrapper and tdata are available if/when the
1740 * timer callback is executed.
1741 */
1742 ao2_ref(req_wrapper, +1);
1743 ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
1744 req_wrapper->timeout_timer, &timeout_timer_val);
1745 if (ret_val != PJ_SUCCESS) {
1747 "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
1748 (int) pj_strlen(&tdata->msg->line.req.method.name),
1749 pj_strbuf(&tdata->msg->line.req.method.name),
1750 endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1751 ao2_t_ref(req_wrapper, -2, "Drop timer and routine ref");
1752 pjsip_tx_data_dec_ref(tdata);
1753 return ret_val;
1754 }
1755 }
1756
1757 /* We need to insure that the wrapper and tdata are available when the
1758 * transaction callback is executed.
1759 */
1760 ao2_ref(req_wrapper, +1);
1761 if (tsx) {
1762#ifdef HAVE_PJSIP_ENDPT_SEND_REQUEST2
1763 ret_val = pjsip_endpt_send_request2(endpt, tdata, -1, req_wrapper,
1765#else
1766 /*
1767 * Fallback for PJPROJECT builds that do not provide
1768 * pjsip_endpt_send_request2(). This means that any callers to
1769 * endpt_send_request will not receive a transaction pointer back,
1770 * and therefore will not be able to cancel the in-flight transaction.
1771 */
1772 ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper,
1774 *tsx = NULL;
1775#endif
1776 } else {
1777 ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper,
1779 }
1780
1781 if (ret_val != PJ_SUCCESS) {
1782 char errmsg[PJ_ERR_MSG_SIZE];
1783
1784 if (!req_wrapper->send_cb_called) {
1785 /* endpt_send_request_cb is not expected to ever be called now. */
1786 ao2_ref(req_wrapper, -1);
1787 }
1788
1789 /* Complain of failure to send the request. */
1790 pj_strerror(ret_val, errmsg, sizeof(errmsg));
1791 ast_log(LOG_ERROR, "Error %d '%s' sending %.*s request to endpoint %s\n",
1792 (int) ret_val, errmsg, (int) pj_strlen(&tdata->msg->line.req.method.name),
1793 pj_strbuf(&tdata->msg->line.req.method.name),
1794 endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1795
1796 if (timeout > 0) {
1797 int timers_cancelled;
1798
1799 ao2_lock(req_wrapper);
1800 timers_cancelled = pj_timer_heap_cancel_if_active(
1801 pjsip_endpt_get_timer_heap(endpt),
1802 req_wrapper->timeout_timer, TIMER_INACTIVE);
1803 if (timers_cancelled > 0) {
1804 ao2_ref(req_wrapper, -1);
1805 }
1806
1807 /* Was the callback called? */
1808 if (req_wrapper->cb_called) {
1809 /*
1810 * Yes so we cannot report any error. The callback
1811 * has already freed any resources associated with
1812 * token.
1813 */
1814 ret_val = PJ_SUCCESS;
1815 } else {
1816 /*
1817 * No so we claim it is called so our caller can free
1818 * any resources associated with token because of
1819 * failure.
1820 */
1821 req_wrapper->cb_called = 1;
1822 }
1823 ao2_unlock(req_wrapper);
1824 } else if (req_wrapper->cb_called) {
1825 /*
1826 * We cannot report any error. The callback has
1827 * already freed any resources associated with
1828 * token.
1829 */
1830 ret_val = PJ_SUCCESS;
1831 }
1832 }
1833
1834 ao2_ref(req_wrapper, -1);
1835 return ret_val;
1836}
1837
1839{
1840 pjsip_via_hdr *via;
1841
1842 if (!tdata || !tdata->dest_info.addr.count
1843 || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
1844 /* No more addresses to try */
1845 return 0;
1846 }
1847
1848 /* Try next address */
1849 ++tdata->dest_info.cur_addr;
1850
1851 via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1852 via->branch_param.slen = 0;
1853
1854 pjsip_tx_data_invalidate_msg(tdata);
1855
1856 return 1;
1857}
1858
1859static void send_request_cb(void *token, pjsip_event *e);
1860
1861static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
1862{
1863 struct ast_sip_endpoint *endpoint;
1864 pjsip_transaction *tsx;
1865 pjsip_tx_data *tdata;
1866 int res = 0;
1867
1868 if (!(endpoint = ao2_bump(req_data->endpoint))) {
1869 return 0;
1870 }
1871
1872 tsx = e->body.tsx_state.tsx;
1873
1874 switch (tsx->status_code) {
1875 case 401:
1876 case 407:
1877 /* Resend the request with a challenge response if we are challenged. */
1878 res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
1880 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
1881 break;
1882 case 408:
1883 case 503:
1884 if ((res = ast_sip_failover_request(tsx->last_tx))) {
1885 tdata = tsx->last_tx;
1886 /*
1887 * Bump the ref since it will be on a new transaction and
1888 * we don't want it to go away along with the old transaction.
1889 */
1890 pjsip_tx_data_add_ref(tdata);
1891 }
1892 break;
1893 }
1894
1895 if (res) {
1896 res = endpt_send_request(endpoint, tdata, -1,
1897 req_data, send_request_cb, NULL) == PJ_SUCCESS;
1898 }
1899
1900 ao2_ref(endpoint, -1);
1901 return res;
1902}
1903
1904static void send_request_cb(void *token, pjsip_event *e)
1905{
1906 struct send_request_data *req_data = token;
1907 pjsip_rx_data *challenge;
1908 struct ast_sip_supplement *supplement;
1909
1910 if (e->type == PJSIP_EVENT_TSX_STATE) {
1911 switch(e->body.tsx_state.type) {
1912 case PJSIP_EVENT_TRANSPORT_ERROR:
1913 case PJSIP_EVENT_TIMER:
1914 /*
1915 * Check the request status on transport error, timeout or user event
1916 * (triggered by a user cancel). A transport error can occur when a
1917 * TCP socket closes and that can be the result of a 503. Also we may
1918 * need to failover on a timeout (408).
1919 */
1920 if (check_request_status(req_data, e)) {
1921 return;
1922 }
1923 break;
1924 case PJSIP_EVENT_RX_MSG:
1925 challenge = e->body.tsx_state.src.rdata;
1926
1927 /*
1928 * Call any supplements that want to know about a response
1929 * with any received data.
1930 */
1932 AST_LIST_TRAVERSE(&supplements, supplement, next) {
1933 if (supplement->incoming_response
1934 && does_method_match(&challenge->msg_info.cseq->method.name,
1935 supplement->method)) {
1936 supplement->incoming_response(req_data->endpoint, challenge);
1937 }
1938 }
1940
1941 if (check_request_status(req_data, e)) {
1942 /*
1943 * Request with challenge response or failover sent.
1944 * Passed our req_data ref to the new request.
1945 */
1946 return;
1947 }
1948 break;
1949 case PJSIP_EVENT_USER:
1950 /*
1951 * User event is triggered by a user cancel. We don't need to do
1952 * anything here other than invoke the callback.
1953 */
1954 ast_debug(3, "User event received for request to endpoint %s\n",
1956 break;
1957 default:
1958 ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
1959 break;
1960 }
1961 }
1962
1963 if (req_data->callback) {
1964 req_data->callback(req_data->token, e);
1965 }
1966 ao2_ref(req_data, -1);
1967}
1968
1970 struct ast_sip_endpoint *endpoint, int timeout, void *token,
1971 void (*callback)(void *token, pjsip_event *e), pjsip_transaction **tsx)
1972{
1973 struct ast_sip_supplement *supplement;
1974 struct send_request_data *req_data;
1975 struct ast_sip_contact *contact;
1976
1977 if (tsx) {
1978 *tsx = NULL;
1979 }
1980
1981 req_data = send_request_data_alloc(endpoint, token, callback);
1982 if (!req_data) {
1983 pjsip_tx_data_dec_ref(tdata);
1984 return -1;
1985 }
1986
1987 if (endpoint) {
1989 }
1990
1991 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
1992
1994 AST_LIST_TRAVERSE(&supplements, supplement, next) {
1995 if (supplement->outgoing_request
1996 && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
1997 supplement->outgoing_request(endpoint, contact, tdata);
1998 }
1999 }
2001
2002 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2003 ao2_cleanup(contact);
2004
2005 if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb, tsx)
2006 != PJ_SUCCESS) {
2007 ao2_cleanup(req_data);
2008 return -1;
2009 }
2010
2011 return 0;
2012}
2013
2014int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata,
2015 struct ast_sip_endpoint *endpoint, int timeout, void *token,
2016 void (*callback)(void *token, pjsip_event *e))
2017{
2019 token, callback, NULL);
2020}
2021
2022int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg,
2023 struct ast_sip_endpoint *endpoint, void *token,
2024 void (*callback)(void *token, pjsip_event *e))
2025{
2026 ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
2027
2028 if (dlg) {
2029 return send_in_dialog_request(tdata, dlg);
2030 } else {
2031 return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
2032 }
2033}
2034
2035int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
2036{
2037 pjsip_route_hdr *route;
2038 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
2039 pj_str_t tmp;
2040
2041 pj_strdup2_with_null(tdata->pool, &tmp, proxy);
2042 if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
2043 return -1;
2044 }
2045
2046 pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
2047
2048 return 0;
2049}
2050
2051int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
2052{
2053 pj_str_t hdr_name;
2054 pj_str_t hdr_value;
2055 pjsip_generic_string_hdr *hdr;
2056
2057 pj_cstr(&hdr_name, name);
2058 pj_cstr(&hdr_value, value);
2059
2060 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2061
2062 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2063 return 0;
2064}
2065
2066pjsip_generic_string_hdr *ast_sip_add_header2(pjsip_tx_data *tdata,
2067 const char *name, const char *value)
2068{
2069 pj_str_t hdr_name;
2070 pj_str_t hdr_value;
2071 pjsip_generic_string_hdr *hdr;
2072
2073 pj_cstr(&hdr_name, name);
2074 pj_cstr(&hdr_value, value);
2075
2076 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2077
2078 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2079 return hdr;
2080}
2081
2082static pjsip_msg_body *ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
2083{
2084 pj_str_t type;
2085 pj_str_t subtype;
2086 pj_str_t body_text;
2087
2088 pj_cstr(&type, body->type);
2089 pj_cstr(&subtype, body->subtype);
2090 pj_cstr(&body_text, body->body_text);
2091
2092 return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
2093}
2094
2095int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
2096{
2097 pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
2098 tdata->msg->body = pjsip_body;
2099 return 0;
2100}
2101
2102int ast_sip_add_body_multipart(pjsip_tx_data *tdata, const struct ast_sip_body *bodies[], int num_bodies)
2103{
2104 int i;
2105 /* NULL for type and subtype automatically creates "multipart/mixed" */
2106 pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
2107
2108 for (i = 0; i < num_bodies; ++i) {
2109 pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
2110 part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
2111 pjsip_multipart_add_part(tdata->pool, body, part);
2112 }
2113
2114 tdata->msg->body = body;
2115 return 0;
2116}
2117
2118int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text)
2119{
2120 size_t combined_size = strlen(body_text) + tdata->msg->body->len;
2121 struct ast_str *body_buffer = ast_str_alloca(combined_size);
2122
2123 ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
2124
2125 tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
2126 pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
2127 tdata->msg->body->len = combined_size;
2128
2129 return 0;
2130}
2131
2136
2141
2142#undef ast_sip_push_task
2143int ast_sip_push_task(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data);
2144
2145int __ast_sip_push_task(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data,
2146 const char *file, int line, const char *function)
2147{
2148 if (!serializer) {
2149 return __ast_taskpool_push(sip_taskpool, sip_task, task_data, file, line, function);
2150 }
2151
2152 return __ast_taskprocessor_push(serializer, sip_task, task_data, file, line, function);
2153}
2154
2155/* ABI compatibility: Provide actual function symbol for external modules */
2156int ast_sip_push_task(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2157{
2158 return __ast_sip_push_task(serializer, sip_task, task_data, NULL, 0, NULL);
2159}
2160
2161/* ABI compatibility: Provide actual function symbols for wait functions */
2162#undef ast_sip_push_task_wait_servant
2163int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data);
2164
2165int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2166{
2168}
2169
2170#undef ast_sip_push_task_synchronous
2171int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data);
2172
2173int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data)
2174{
2176}
2177
2178#undef ast_sip_push_task_wait_serializer
2179int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data);
2180
2182{
2184}
2185
2186static int __ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data,
2187 const char *file, int line, const char *function)
2188{
2189 if (!serializer) {
2190 return __ast_taskpool_push_wait(sip_taskpool, sip_task, task_data, file, line, function);
2191 }
2192 return __ast_taskpool_serializer_push_wait(serializer, sip_task, task_data, file, line, function);
2193}
2194
2196 const char *file, int line, const char *function)
2197{
2199 return sip_task(task_data);
2200 }
2201
2202 return __ast_sip_push_task_wait(serializer, sip_task, task_data, file, line, function);
2203}
2204
2205int __ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int (*sip_task)(void *), void *task_data,
2206 const char *file, int line, const char *function)
2207{
2208 return __ast_sip_push_task_wait_servant(serializer, sip_task, task_data, file, line, function);
2209}
2210
2212 const char *file, int line, const char *function)
2213{
2214 if (!serializer) {
2215 return __ast_taskpool_push_wait(sip_taskpool, sip_task, task_data, file, line, function);
2216 }
2217
2218 return __ast_taskpool_serializer_push_wait(serializer, sip_task, task_data, file, line, function);
2219}
2220
2221void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
2222{
2223 size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2224 memcpy(dest, pj_strbuf(src), chars_to_copy);
2225 dest[chars_to_copy] = '\0';
2226}
2227
2228int ast_copy_pj_str2(char **dest, const pj_str_t *src)
2229{
2230 int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
2231
2232 if (res < 0) {
2233 *dest = NULL;
2234 }
2235
2236 return res;
2237}
2238
2239int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
2240{
2241 int rc = 0;
2242 if (a != NULL && b != NULL) {
2243 rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2244 }
2245 return rc;
2246}
2247
2248int ast_sip_is_media_type_in(pjsip_media_type *a, ...)
2249{
2250 int rc = 0;
2251 pjsip_media_type *b = NULL;
2252 va_list ap;
2253
2254 ast_assert(a != NULL);
2255 va_start(ap, a);
2256
2257 while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2258 if (pjsip_media_type_cmp(a, b, 0) == 0) {
2259 rc = 1;
2260 break;
2261 }
2262 }
2263 va_end(ap);
2264
2265 return rc;
2266}
2267
2268int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
2269{
2270 pjsip_media_type compare;
2271
2272 if (!content_type) {
2273 return 0;
2274 }
2275
2276 pjsip_media_type_init2(&compare, type, subtype);
2277
2278 return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2279}
2280
2281pj_caching_pool caching_pool;
2282pj_pool_t *memory_pool;
2283pj_thread_t *monitor_thread;
2285
2286static void *monitor_thread_exec(void *endpt)
2287{
2288 while (monitor_continue) {
2289 const pj_time_val delay = {0, 10};
2290 pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2291 }
2292 return NULL;
2293}
2294
2295static void stop_monitor_thread(void)
2296{
2297 monitor_continue = 0;
2298 pj_thread_join(monitor_thread);
2299}
2300
2301AST_THREADSTORAGE(pj_thread_storage);
2302AST_THREADSTORAGE(servant_id_storage);
2303#define SIP_SERVANT_ID 0x5E2F1D
2304
2305static void sip_thread_start(void)
2306{
2307 pj_thread_desc *desc;
2308 pj_thread_t *thread;
2309 uint32_t *servant_id;
2310
2311 servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2312 if (!servant_id) {
2313 ast_log(LOG_ERROR, "Could not set SIP servant ID in thread-local storage.\n");
2314 return;
2315 }
2316 *servant_id = SIP_SERVANT_ID;
2317
2318 desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
2319 if (!desc) {
2320 ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
2321 return;
2322 }
2323 pj_bzero(*desc, sizeof(*desc));
2324
2325 if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
2326 ast_log(LOG_ERROR, "Couldn't register thread with PJLIB.\n");
2327 }
2328}
2329
2331{
2332 uint32_t *servant_id;
2333
2334 if (monitor_thread &&
2335 pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
2336 return 1;
2337 }
2338
2339 servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2340 if (!servant_id) {
2341 return 0;
2342 }
2343
2344 return *servant_id == SIP_SERVANT_ID;
2345}
2346
2347void *ast_sip_dict_get(void *ht, const char *key)
2348{
2349 unsigned int hval = 0;
2350
2351 if (!ht) {
2352 return NULL;
2353 }
2354
2355 return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2356}
2357
2358void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
2359 const char *key, void *val)
2360{
2361 if (!ht) {
2362 ht = pj_hash_create(pool, 11);
2363 }
2364
2365 pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2366
2367 return ht;
2368}
2369
2370static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
2371{
2372 struct ast_sip_supplement *supplement;
2373
2374 if (pjsip_rdata_get_dlg(rdata)) {
2375 return PJ_FALSE;
2376 }
2377
2379 AST_LIST_TRAVERSE(&supplements, supplement, next) {
2380 if (supplement->incoming_request
2381 && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->method)) {
2382 struct ast_sip_endpoint *endpoint;
2383
2384 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2385 supplement->incoming_request(endpoint, rdata);
2386 ao2_cleanup(endpoint);
2387 }
2388 }
2390
2391 return PJ_FALSE;
2392}
2393
2394static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2395{
2396 struct ast_sip_supplement *supplement;
2397 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
2398 struct ast_sip_contact *contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2399
2400 if (sip_endpoint) {
2401 ast_sip_message_apply_transport(sip_endpoint->transport, tdata);
2402 }
2403
2405 AST_LIST_TRAVERSE(&supplements, supplement, next) {
2406 if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
2407 supplement->outgoing_response(sip_endpoint, contact, tdata);
2408 }
2409 }
2411
2412 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2413 ao2_cleanup(contact);
2414}
2415
2416int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2417{
2418 pj_status_t status;
2419
2420 supplement_outgoing_response(tdata, sip_endpoint);
2421 status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2422 if (status != PJ_SUCCESS) {
2423 pjsip_tx_data_dec_ref(tdata);
2424 }
2425
2426 return status == PJ_SUCCESS ? 0 : -1;
2427}
2428
2429static void pool_destroy_callback(void *arg)
2430{
2431 pj_pool_t *pool = (pj_pool_t *)arg;
2432 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2433}
2434
2435static void clean_contact_from_tdata(pjsip_tx_data *tdata)
2436{
2437 struct ast_sip_contact *contact;
2438 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2439 ao2_cleanup(contact);
2440 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2441 pjsip_tx_data_dec_ref(tdata);
2442}
2443
2444int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
2445{
2446 pjsip_transaction *tsx;
2447 pj_grp_lock_t *tsx_glock;
2448 pj_pool_t *pool;
2449
2450 /* Create and initialize global lock pool */
2451 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "stateful response", PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC);
2452 if (!pool){
2453 /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
2454 * We'll leak that reference if we don't get rid of it here.
2455 */
2457 return -1;
2458 }
2459 /* Create with handler so that we can release the pool once the glock derefs out */
2460 if(pj_grp_lock_create_w_handler(pool, NULL, pool, &pool_destroy_callback, &tsx_glock) != PJ_SUCCESS) {
2462 pool_destroy_callback((void *) pool);
2463 return -1;
2464 }
2465 /* We need an additional reference as the qualify thread may destroy this out
2466 * from under us. Add it now before it gets added to the tsx. */
2467 pj_grp_lock_add_ref(tsx_glock);
2468
2469 if (pjsip_tsx_create_uas2(NULL, rdata, tsx_glock, &tsx) != PJ_SUCCESS) {
2471 pj_grp_lock_dec_ref(tsx_glock);
2472 return -1;
2473 }
2474
2475 pjsip_tsx_recv_msg(tsx, rdata);
2476 supplement_outgoing_response(tdata, sip_endpoint);
2477
2478 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2479 pj_grp_lock_dec_ref(tsx_glock);
2480 pjsip_tx_data_dec_ref(tdata);
2481 return -1;
2482 }
2483
2484 pj_grp_lock_dec_ref(tsx_glock);
2485 return 0;
2486}
2487
2488int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code,
2489 struct ast_sip_contact *contact, pjsip_tx_data **tdata)
2490{
2491 int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2492
2493 if (!res) {
2494 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
2495 }
2496
2497 return res;
2498}
2499
2500int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
2501{
2502 if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2503 pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2504 return 0;
2505 } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2506 pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2507 return 0;
2508 }
2509
2510 return -1;
2511}
2512
2514{
2515 if (af == pj_AF_INET()) {
2516 return host_ip_ipv4_string;
2517 } else if (af == pj_AF_INET6()) {
2518 return host_ip_ipv6_string;
2519 }
2520
2521 return NULL;
2522}
2523
2525 char *buf, size_t buf_len)
2526{
2527 switch (dtmf) {
2528 case AST_SIP_DTMF_NONE:
2529 ast_copy_string(buf, "none", buf_len);
2530 break;
2532 ast_copy_string(buf, "rfc4733", buf_len);
2533 break;
2535 ast_copy_string(buf, "inband", buf_len);
2536 break;
2537 case AST_SIP_DTMF_INFO:
2538 ast_copy_string(buf, "info", buf_len);
2539 break;
2540 case AST_SIP_DTMF_AUTO:
2541 ast_copy_string(buf, "auto", buf_len);
2542 break;
2544 ast_copy_string(buf, "auto_info", buf_len);
2545 break;
2546 default:
2547 buf[0] = '\0';
2548 return -1;
2549 }
2550 return 0;
2551}
2552
2553int ast_sip_str_to_dtmf(const char * dtmf_mode)
2554{
2555 int result = -1;
2556
2557 if (!strcasecmp(dtmf_mode, "info")) {
2559 } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
2561 } else if (!strcasecmp(dtmf_mode, "inband")) {
2563 } else if (!strcasecmp(dtmf_mode, "none")) {
2565 } else if (!strcasecmp(dtmf_mode, "auto")) {
2567 } else if (!strcasecmp(dtmf_mode, "auto_info")) {
2569 }
2570
2571 return result;
2572}
2573
2575{
2576 const char *value;
2577
2578 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)) {
2579 value = "local";
2580 } 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)) {
2581 value = "local_merge";
2582 } 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)) {
2583 value = "local_first";
2584 } 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)) {
2585 value = "remote";
2586 } 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)) {
2587 value = "remote_merge";
2588 } 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)) {
2589 value = "remote_first";
2590 } else {
2591 value = "unknown";
2592 }
2593
2594 return value;
2595}
2596
2597int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str, int is_outgoing)
2598{
2599 pref->flags = 0;
2600
2601 if (strcmp(pref_str, "local") == 0) {
2603 } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
2605 } else if (strcmp(pref_str, "local_first") == 0) {
2607 } else if (strcmp(pref_str, "remote") == 0) {
2609 } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
2611 } else if (strcmp(pref_str, "remote_first") == 0) {
2613 } else {
2614 return -1;
2615 }
2616
2617 return 0;
2618}
2619
2620/*!
2621 * \internal
2622 * \brief Set an ast_party_id name and number based on an identity header.
2623 * \param hdr From, P-Asserted-Identity, or Remote-Party-ID header on incoming message
2624 * \param[out] id The ID to set data on
2625 */
2626static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
2627{
2628 char cid_name[AST_CHANNEL_NAME];
2629 char cid_num[AST_CHANNEL_NAME];
2630 size_t cid_name_size = AST_CHANNEL_NAME;
2631 pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
2632 char *semi;
2634
2635 ast_copy_pj_str(cid_num, ast_sip_pjsip_uri_get_username(hdr->uri), sizeof(cid_num));
2636 /* Always truncate caller-id number at a semicolon. */
2637 semi = strchr(cid_num, ';');
2638 if (semi) {
2639 /*
2640 * We need to be able to handle URI's looking like
2641 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
2642 *
2643 * Where the uri->user field will result in:
2644 * "1235557890;phone-context=national"
2645 *
2646 * People don't care about anything after the semicolon
2647 * showing up on their displays even though the RFC
2648 * allows the semicolon.
2649 */
2650 *semi = '\0';
2651 }
2652
2653 /*
2654 * It's safe to pass a NULL or empty string as the source.
2655 * The result will be an empty string assuming the destination
2656 * size was at least 1.
2657 */
2658 result = ast_utf8_replace_invalid_chars(cid_name, &cid_name_size,
2659 id_name_addr->display.ptr, id_name_addr->display.slen);
2660
2662 ast_log(LOG_WARNING, "CallerID Name '" PJSTR_PRINTF_SPEC
2663 "' for number '%s' has invalid UTF-8 characters which "
2664 "were replaced",
2665 PJSTR_PRINTF_VAR(id_name_addr->display), cid_num);
2666 }
2667
2668 ast_free(id->name.str);
2669 id->name.str = ast_strdup(cid_name);
2670 if (!ast_strlen_zero(cid_name)) {
2671 id->name.valid = 1;
2672 }
2673 ast_free(id->number.str);
2674 id->number.str = ast_strdup(cid_num);
2675 if (!ast_strlen_zero(cid_num)) {
2676 id->number.valid = 1;
2677 }
2678}
2679
2680/*!
2681 * \internal
2682 * \brief Get a P-Asserted-Identity or Remote-Party-ID header from an incoming message
2683 *
2684 * This function will parse the header as if it were a From header. This allows for us
2685 * to easily manipulate the URI, as well as add, modify, or remove parameters from the
2686 * header
2687 *
2688 * \param rdata The incoming message
2689 * \param header_name The name of the ID header to find
2690 * \retval NULL No ID header present or unable to parse ID header
2691 * \retval non-NULL The parsed ID header
2692 */
2693static pjsip_fromto_hdr *get_id_header(pjsip_rx_data *rdata, const pj_str_t *header_name)
2694{
2695 static const pj_str_t from = { "From", 4 };
2696 pj_str_t header_content;
2697 pjsip_fromto_hdr *parsed_hdr;
2698 pjsip_generic_string_hdr *ident = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2699 header_name, NULL);
2700 int parsed_len;
2701
2702 if (!ident) {
2703 return NULL;
2704 }
2705
2706 pj_strdup_with_null(rdata->tp_info.pool, &header_content, &ident->hvalue);
2707
2708 parsed_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from, header_content.ptr,
2709 pj_strlen(&header_content), &parsed_len);
2710
2711 if (!parsed_hdr) {
2712 return NULL;
2713 }
2714
2715 return parsed_hdr;
2716}
2717
2718/*!
2719 * \internal
2720 * \brief Set an ast_party_id structure based on data in a P-Asserted-Identity header
2721 *
2722 * This makes use of \ref set_id_from_hdr for setting name and number. It uses
2723 * the contents of a Privacy header in order to set presentation information.
2724 *
2725 * \param rdata The incoming message
2726 * \param[out] id The ID to set
2727 * \retval 0 Successfully set the party ID
2728 * \retval non-zero Could not set the party ID
2729 */
2730static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id)
2731{
2732 static const pj_str_t pai_str = { "P-Asserted-Identity", 19 };
2733 static const pj_str_t privacy_str = { "Privacy", 7 };
2734 pjsip_fromto_hdr *pai_hdr = get_id_header(rdata, &pai_str);
2735 pjsip_generic_string_hdr *privacy;
2736
2737 if (!pai_hdr) {
2738 return -1;
2739 }
2740
2741 set_id_from_hdr(pai_hdr, id);
2742
2743 if (!id->number.valid) {
2744 return -1;
2745 }
2746
2747 privacy = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &privacy_str, NULL);
2748 if (!privacy || !pj_stricmp2(&privacy->hvalue, "none")) {
2749 id->number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2750 id->name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2751 } else {
2752 id->number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2753 id->name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2754 }
2755
2756 return 0;
2757}
2758
2759/*!
2760 * \internal
2761 * \brief Set an ast_party_id structure based on data in a Remote-Party-ID header
2762 *
2763 * This makes use of \ref set_id_from_hdr for setting name and number. It uses
2764 * the privacy and screen parameters in order to set presentation information.
2765 *
2766 * \param rdata The incoming message
2767 * \param[out] id The ID to set
2768 * \retval 0 Succesfully set the party ID
2769 * \retval non-zero Could not set the party ID
2770 */
2771static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id)
2772{
2773 static const pj_str_t rpid_str = { "Remote-Party-ID", 15 };
2774 static const pj_str_t privacy_str = { "privacy", 7 };
2775 static const pj_str_t screen_str = { "screen", 6 };
2776 pjsip_fromto_hdr *rpid_hdr = get_id_header(rdata, &rpid_str);
2777 pjsip_param *screen;
2778 pjsip_param *privacy;
2779
2780 if (!rpid_hdr) {
2781 return -1;
2782 }
2783
2784 set_id_from_hdr(rpid_hdr, id);
2785
2786 if (!id->number.valid) {
2787 return -1;
2788 }
2789
2790 privacy = pjsip_param_find(&rpid_hdr->other_param, &privacy_str);
2791 screen = pjsip_param_find(&rpid_hdr->other_param, &screen_str);
2792 if (privacy && !pj_stricmp2(&privacy->value, "full")) {
2793 id->number.presentation = AST_PRES_RESTRICTED;
2794 id->name.presentation = AST_PRES_RESTRICTED;
2795 } else {
2796 id->number.presentation = AST_PRES_ALLOWED;
2797 id->name.presentation = AST_PRES_ALLOWED;
2798 }
2799 if (screen && !pj_stricmp2(&screen->value, "yes")) {
2800 id->number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2801 id->name.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2802 } else {
2803 id->number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2804 id->name.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2805 }
2806
2807 return 0;
2808}
2809
2810/*!
2811 * \internal
2812 * \brief Set an ast_party_id structure based on data in a From
2813 *
2814 * This makes use of \ref set_id_from_hdr for setting name and number. It uses
2815 * no information from the message in order to set privacy. It relies on endpoint
2816 * configuration for privacy information.
2817 *
2818 * \param rdata The incoming message
2819 * \param[out] id The ID to set
2820 * \retval 0 Succesfully set the party ID
2821 * \retval non-zero Could not set the party ID
2822 */
2823static int set_id_from_from(struct pjsip_rx_data *rdata, struct ast_party_id *id)
2824{
2825 pjsip_fromto_hdr *from = pjsip_msg_find_hdr(rdata->msg_info.msg,
2826 PJSIP_H_FROM, rdata->msg_info.msg->hdr.next);
2827
2828 if (!from) {
2829 /* This had better not happen */
2830 return -1;
2831 }
2832
2833 set_id_from_hdr(from, id);
2834
2835 if (!id->number.valid) {
2836 return -1;
2837 }
2838
2839 return 0;
2840}
2841
2842int ast_sip_set_id_connected_line(struct pjsip_rx_data *rdata, struct ast_party_id *id)
2843{
2844 return !set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id) ? 0 : -1;
2845}
2846
2847int ast_sip_set_id_from_invite(struct pjsip_rx_data *rdata, struct ast_party_id *id, struct ast_party_id *default_id, int trust_inbound)
2848{
2849 if (trust_inbound && (!set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id))) {
2850 /* Trusted: Check PAI and RPID */
2851 ast_free(id->tag);
2852 id->tag = ast_strdup(default_id->tag);
2853 return 0;
2854 }
2855 /* Not trusted: check the endpoint config or use From. */
2856 ast_party_id_copy(id, default_id);
2857 if (!default_id->number.valid) {
2858 set_id_from_from(rdata, id);
2859 }
2860 return 0;
2861}
2862
2863/*!
2864 * \brief Set name and number information on an identity header.
2865 *
2866 * \param pool Memory pool to use for string duplication
2867 * \param id_hdr A From, P-Asserted-Identity, or Remote-Party-ID header to modify
2868 * \param id The identity information to apply to the header
2869 */
2870void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id)
2871{
2872 pjsip_name_addr *id_name_addr;
2873 pjsip_sip_uri *id_uri;
2874
2875 id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2876 id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2877
2878 if (id->name.valid) {
2879 if (!ast_strlen_zero(id->name.str)) {
2880 int name_buf_len = strlen(id->name.str) * 2 + 1;
2881 char *name_buf = ast_alloca(name_buf_len);
2882
2883 ast_escape_quoted(id->name.str, name_buf, name_buf_len);
2884 pj_strdup2(pool, &id_name_addr->display, name_buf);
2885 } else {
2886 pj_strdup2(pool, &id_name_addr->display, NULL);
2887 }
2888 }
2889
2890 if (id->number.valid) {
2891 pj_strdup2(pool, &id_uri->user, id->number.str);
2892 }
2893}
2894
2895/*!
2896 * \brief Find a contact and insert a "user@" into its URI.
2897 *
2898 * \param to Original destination (for error messages only)
2899 * \param endpoint_name Endpoint name (for error messages only)
2900 * \param aors Command separated list of AORs
2901 * \param user The user to insert in the contact URI
2902 * \param uri Pointer to buffer in which to return the URI. Must be freed by caller.
2903 *
2904 * \return 0 Success
2905 * \return -1 Fail
2906 *
2907 * \note If the contact URI found for the endpoint already has a user in
2908 * its URI, it will be replaced by the user passed as an argument to this function.
2909 */
2910static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors,
2911 const char *user, char **uri)
2912{
2913 RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
2914 pj_pool_t *pool;
2915 pjsip_name_addr *name_addr;
2916 pjsip_sip_uri *sip_uri;
2917 int err = 0;
2918
2920 if (!contact) {
2921 ast_log(LOG_WARNING, "Dest: '%s'. Couldn't find contact for endpoint '%s'\n",
2922 to, endpoint_name);
2923 return -1;
2924 }
2925
2926 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "uri-user-insert", 128, 128);
2927 if (!pool) {
2928 ast_log(LOG_WARNING, "Failed to allocate ParseUri endpoint pool.\n");
2929 return -1;
2930 }
2931
2932 name_addr = (pjsip_name_addr *) pjsip_parse_uri(pool, (char*)contact->uri, strlen(contact->uri), PJSIP_PARSE_URI_AS_NAMEADDR);
2933 if (!name_addr || (!PJSIP_URI_SCHEME_IS_SIP(name_addr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(name_addr->uri))) {
2934 ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", contact->uri);
2935 err = -1;
2936 goto out;
2937 }
2938
2939 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' ContactURI: '%s'\n", to, user, endpoint_name, contact->uri);
2940
2941 sip_uri = pjsip_uri_get_uri(name_addr->uri);
2942 pj_strset2(&sip_uri->user, (char*)user);
2943
2944 *uri = ast_malloc(PJSIP_MAX_URL_SIZE);
2945 if (!(*uri)) {
2946 err = -1;
2947 goto out;
2948 }
2949 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, name_addr, *uri, PJSIP_MAX_URL_SIZE);
2950
2951out:
2952 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2953
2954 return err;
2955}
2956
2957/*!
2958 * \internal
2959 * \brief Get endpoint and URI when the destination is only a single token
2960 *
2961 * "destination" could be one of the following:
2962 * \verbatim
2963 endpoint_name
2964 hostname
2965 * \endverbatim
2966 *
2967 * \param to
2968 * \param destination
2969 * \param get_default_outbound If nonzero, try to retrieve the default
2970 * outbound endpoint if no endpoint was found.
2971 * Otherwise, return NULL if no endpoint was found.
2972 * \param uri Pointer to URI variable. Must be freed by caller - even if the return value is NULL!
2973 * \return endpoint
2974 */
2975static struct ast_sip_endpoint *handle_single_token(const char *to, char *destination, int get_default_outbound, char **uri) {
2976 RAII_VAR(struct ast_sip_contact*, contact, NULL, ao2_cleanup);
2977 char *endpoint_name = NULL;
2978 struct ast_sip_endpoint *endpoint = NULL;
2979
2980 /*
2981 * If "destination" is just one token, it could be an endpoint name
2982 * or a hostname without a scheme.
2983 */
2984
2985 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", destination);
2986 if (!endpoint) {
2987 /*
2988 * We can only assume it's a hostname.
2989 */
2990 char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
2991 if (!temp_uri) {
2992 goto failure;
2993 }
2994 sprintf(temp_uri, "sip:%s", destination);
2995 *uri = temp_uri;
2996 if (get_default_outbound) {
2998 }
2999 ast_debug(3, "Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s'%s\n",
3000 to, *uri, get_default_outbound ? " with default endpoint" : "");
3001 return endpoint;
3002 }
3003
3004 /*
3005 * It's an endpoint
3006 */
3007
3008 endpoint_name = destination;
3010 if (!contact) {
3011 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find an aor/contact for it\n",
3012 to, endpoint_name);
3013 ao2_cleanup(endpoint);
3014 goto failure;
3015 }
3016
3017 *uri = ast_strdup(contact->uri);
3018 if (!(*uri)) {
3019 ao2_cleanup(endpoint);
3020 goto failure;
3021 }
3022
3023 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",
3024 to, endpoint_name, *uri);
3025 return endpoint;
3026
3027failure:
3028 *uri = NULL;
3029 return NULL;
3030}
3031
3032/*!
3033 * \internal
3034 * \brief Get endpoint and URI when the destination contained a '/'
3035 *
3036 * "to" could be one of the following:
3037 * \verbatim
3038 endpoint/aor
3039 endpoint/<sip[s]:host>
3040 endpoint/<sip[s]:user@host>
3041 endpoint/"Bob" <sip[s]:host>
3042 endpoint/"Bob" <sip[s]:user@host>
3043 endpoint/sip[s]:host
3044 endpoint/sip[s]:user@host
3045 endpoint/host
3046 endpoint/user@host
3047 * \endverbatim
3048 *
3049 * \param to Destination
3050 * \param uri Pointer to URI variable. Must be freed by caller - even if the return value is NULL!
3051 * \param destination, slash, atsign, scheme
3052 * \return endpoint
3053 */
3054static struct ast_sip_endpoint *handle_slash(const char *to, char *destination, char **uri,
3055 char *slash, char *atsign, char *scheme)
3056{
3057 char *endpoint_name = NULL;
3058 struct ast_sip_endpoint *endpoint = NULL;
3059 struct ast_sip_contact *contact = NULL;
3060 char *user = NULL;
3061 char *afterslash = slash + 1;
3062 struct ast_sip_aor *aor;
3063
3064 if (ast_begins_with(destination, "PJSIP/")) {
3065 ast_debug(3, "Dest: '%s' Dialplan format'\n", to);
3066 /*
3067 * This has to be the form PJSIP/user@endpoint
3068 */
3069 if (!atsign || strchr(afterslash, '/')) {
3070 /*
3071 * If there's no "user@" or there's a slash somewhere after
3072 * "PJSIP/" then we go no further.
3073 */
3075 "Dest: '%s'. Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",
3076 to);
3077 goto failure;
3078 }
3079 *atsign = '\0';
3080 user = afterslash;
3081 endpoint_name = atsign + 1;
3082 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s'\n", to, user, endpoint_name);
3083 } else {
3084 /*
3085 * Either...
3086 * endpoint/aor
3087 * endpoint/uri
3088 */
3089 *slash = '\0';
3090 endpoint_name = destination;
3091 ast_debug(3, "Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);
3092 }
3093
3094 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);
3095 if (!endpoint) {
3096 ast_log(LOG_WARNING, "Dest: '%s'. Didn't find endpoint with name '%s'\n",
3097 to, endpoint_name);
3098 goto failure;
3099 }
3100
3101 if (scheme) {
3102 /*
3103 * If we found a scheme, then everything after the slash MUST be a URI.
3104 * We don't need to do any further modification.
3105 */
3106 *uri = ast_strdup(afterslash);
3107 if (!(*uri)) {
3108 goto failure;
3109 }
3110 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found URI '%s' after '/'\n",
3111 to, endpoint_name, *uri);
3112 return endpoint;
3113 }
3114
3115 if (user) {
3116 /*
3117 * This has to be the form PJSIP/user@endpoint
3118 */
3119 int rc;
3120
3121 /*
3122 * Set the return URI to be the endpoint's contact URI with the user
3123 * portion set to the user that was specified before the endpoint name.
3124 */
3125 rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->aors, user, uri);
3126 if (rc != 0) {
3127 /*
3128 * insert_user_in_contact_uri prints the warning message.
3129 */
3130 goto failure;
3131 }
3132 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' URI: '%s'\n", to, user,
3133 endpoint_name, *uri);
3134
3135 return endpoint;
3136 }
3137
3138 /*
3139 * We're now left with two possibilities...
3140 * endpoint/aor
3141 * endpoint/uri-without-scheme
3142 */
3143 aor = ast_sip_location_retrieve_aor(afterslash);
3144 if (!aor) {
3145 /*
3146 * It's probably a URI without a scheme but we don't have a way to tell
3147 * for sure. We're going to assume it is and prepend it with a scheme.
3148 */
3149 *uri = ast_malloc(strlen(afterslash) + strlen("sip:") + 1);
3150 if (!(*uri)) {
3151 goto failure;
3152 }
3153 sprintf(*uri, "sip:%s", afterslash);
3154 ast_debug(3, "Dest: '%s' Found endpoint '%s' but didn't find aor after '/' so using URI '%s'\n",
3155 to, endpoint_name, *uri);
3156 return endpoint;
3157 }
3158
3159 /*
3160 * Only one possibility left... There was an aor name after the slash.
3161 */
3162 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\n",
3163 to, endpoint_name, ast_sorcery_object_get_id(aor));
3164
3166 if (!contact) {
3167 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact for aor '%s'\n",
3168 to, endpoint_name, ast_sorcery_object_get_id(aor));
3169 ao2_cleanup(aor);
3170 goto failure;
3171 }
3172
3173 *uri = ast_strdup(contact->uri);
3174 ao2_cleanup(contact);
3175 ao2_cleanup(aor);
3176 if (!(*uri)) {
3177 goto failure;
3178 }
3179
3180 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",
3181 to, endpoint_name, *uri, ast_sorcery_object_get_id(aor));
3182
3183 return endpoint;
3184
3185failure:
3186 ao2_cleanup(endpoint);
3187 *uri = NULL;
3188 return NULL;
3189}
3190
3191/*!
3192 * \internal
3193 * \brief Get endpoint and URI when the destination contained a '@' but no '/' or scheme
3194 *
3195 * "to" could be one of the following:
3196 * \verbatim
3197 <sip[s]:user@host>
3198 "Bob" <sip[s]:user@host>
3199 sip[s]:user@host
3200 user@host
3201 * \endverbatim
3202 *
3203 * \param to Destination
3204 * \param uri Pointer to URI variable. Must be freed by caller - even if the return value is NULL!
3205 * \param destination, slash, atsign, scheme
3206 * \param get_default_outbound If nonzero, try to retrieve the default
3207 * outbound endpoint if no endpoint was found.
3208 * Otherwise, return NULL if no endpoint was found.
3209 * \return endpoint
3210 */
3211static struct ast_sip_endpoint *handle_atsign(const char *to, char *destination, char **uri,
3212 char *slash, char *atsign, char *scheme, int get_default_outbound)
3213{
3214 char *endpoint_name = NULL;
3215 struct ast_sip_endpoint *endpoint = NULL;
3216 struct ast_sip_contact *contact = NULL;
3217 char *afterat = atsign + 1;
3218
3219 *atsign = '\0';
3220 endpoint_name = destination;
3221
3222 /* Apparently there may be ';<user_options>' after the endpoint name ??? */
3225 if (!endpoint) {
3226 /*
3227 * It's probably a uri with a user but without a scheme but we don't have a way to tell.
3228 * We're going to assume it is and prepend it with a scheme.
3229 */
3230 *uri = ast_malloc(strlen(to) + strlen("sip:") + 1);
3231 if (!(*uri)) {
3232 goto failure;
3233 }
3234 sprintf(*uri, "sip:%s", to);
3235 if (get_default_outbound) {
3237 }
3238 ast_debug(3, "Dest: '%s' Didn't find endpoint before the '@' so using URI '%s'%s\n",
3239 to, *uri, get_default_outbound ? " with default endpoint" : "");
3240 return endpoint;
3241 }
3242
3243 /*
3244 * OK, it's an endpoint and a domain (which we ignore)
3245 */
3247 if (!contact) {
3248 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact\n",
3249 to, endpoint_name);
3250 goto failure;
3251 }
3252
3253 *uri = ast_strdup(contact->uri);
3254 ao2_cleanup(contact);
3255 if (!(*uri)) {
3256 goto failure;
3257 }
3258 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",
3259 to, endpoint_name, *uri, afterat);
3260
3261 return endpoint;
3262
3263failure:
3265 *uri = NULL;
3266 return NULL;
3267}
3268
3269struct ast_sip_endpoint *ast_sip_get_endpoint(const char *to, int get_default_outbound, char **uri)
3270{
3271 char *destination;
3272 char *slash = NULL;
3273 char *atsign = NULL;
3274 char *scheme = NULL;
3275 struct ast_sip_endpoint *endpoint = NULL;
3276
3277 destination = ast_strdupa(to);
3278
3279 slash = strchr(destination, '/');
3280 atsign = strchr(destination, '@');
3281 scheme = S_OR(strstr(destination, "sip:"), strstr(destination, "sips:"));
3282
3283 if (!slash && !atsign && !scheme) {
3284 /*
3285 * If there's only a single token, it can be either...
3286 * endpoint
3287 * host
3288 */
3289 return handle_single_token(to, destination, get_default_outbound, uri);
3290 }
3291
3292 if (slash) {
3293 /*
3294 * If there's a '/', then the form must be one of the following...
3295 * PJSIP/user@endpoint
3296 * endpoint/aor
3297 * endpoint/uri
3298 */
3299 return handle_slash(to, destination, uri, slash, atsign, scheme);
3300 }
3301
3302 if (atsign && !scheme) {
3303 /*
3304 * If there's an '@' but no scheme then it's either following an endpoint name
3305 * and being followed by a domain name (which we discard).
3306 * OR is's a user@host uri without a scheme. It's probably the latter but because
3307 * endpoint@domain looks just like user@host, we'll test for endpoint first.
3308 */
3309 return handle_atsign(to, destination, uri, slash, atsign, scheme, get_default_outbound);
3310 }
3311
3312 /*
3313 * If all else fails, we assume it's a URI or just a hostname.
3314 */
3315 if (scheme) {
3316 *uri = ast_strdup(destination);
3317 if (!(*uri)) {
3318 goto failure;
3319 }
3320 ast_debug(3, "Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s'%s\n",
3321 to, *uri, get_default_outbound ? " with default endpoint" : "");
3322 } else {
3323 *uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
3324 if (!(*uri)) {
3325 goto failure;
3326 }
3327 sprintf(*uri, "sip:%s", destination);
3328 ast_debug(3, "Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s'%s\n",
3329 to, *uri, get_default_outbound ? " with default endpoint" : "");
3330 }
3331 if (get_default_outbound) {
3333 }
3334
3335 return endpoint;
3336
3337failure:
3338 ao2_cleanup(endpoint);
3339 *uri = NULL;
3340 return NULL;
3341}
3342
3343int ast_sip_update_to_uri(pjsip_tx_data *tdata, const char *to)
3344{
3345 pjsip_name_addr *parsed_name_addr;
3346 pjsip_sip_uri *sip_uri;
3347 pjsip_name_addr *tdata_name_addr;
3348 pjsip_sip_uri *tdata_sip_uri;
3349 pjsip_to_hdr *to_hdr;
3350 char *buf = NULL;
3351#define DEBUG_BUF_SIZE 256
3352
3353 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, (char*)to, strlen(to),
3354 PJSIP_PARSE_URI_AS_NAMEADDR);
3355
3356 if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3357 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {
3358 ast_log(LOG_WARNING, "To address '%s' is not a valid SIP/SIPS URI\n", to);
3359 return -1;
3360 }
3361
3362 sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3363 if (DEBUG_ATLEAST(3)) {
3365 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);
3366 ast_debug(3, "Parsed To: %.*s %s\n", (int)parsed_name_addr->display.slen,
3367 parsed_name_addr->display.ptr, buf);
3368 }
3369
3370 to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);
3371 tdata_name_addr = to_hdr ? (pjsip_name_addr *) to_hdr->uri : NULL;
3372 if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)
3373 && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {
3374 /* Highly unlikely but we have to check */
3375 ast_log(LOG_WARNING, "tdata To address '%s' is not a valid SIP/SIPS URI\n", to);
3376 return -1;
3377 }
3378
3379 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
3380 if (DEBUG_ATLEAST(3)) {
3381 buf[0] = '\0';
3382 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);
3383 ast_debug(3, "Original tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3384 tdata_name_addr->display.ptr, buf);
3385 }
3386
3387 /* Replace the uri */
3388 pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);
3389 /* The display name isn't part of the URI so we need to replace it separately */
3390 pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);
3391
3392 if (DEBUG_ATLEAST(3)) {
3393 buf[0] = '\0';
3394 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);
3395 ast_debug(3, "New tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3396 tdata_name_addr->display.ptr, buf);
3397 }
3398
3399 return 0;
3400#undef DEBUG_BUF_SIZE
3401}
3402
3403int ast_sip_update_from(pjsip_tx_data *tdata, char *from)
3404{
3405 pjsip_name_addr *name_addr;
3406 pjsip_sip_uri *uri;
3407 pjsip_name_addr *parsed_name_addr;
3408 pjsip_from_hdr *from_hdr;
3409
3410 if (ast_strlen_zero(from)) {
3411 return 0;
3412 }
3413
3414 from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
3415 if (!from_hdr) {
3416 return -1;
3417 }
3418 name_addr = (pjsip_name_addr *) from_hdr->uri;
3419 uri = pjsip_uri_get_uri(name_addr);
3420
3421 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from,
3422 strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR);
3423 if (parsed_name_addr) {
3424 pjsip_sip_uri *parsed_uri;
3425
3426 if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3427 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {
3428 ast_log(LOG_WARNING, "From address '%s' is not a valid SIP/SIPS URI\n", from);
3429 return -1;
3430 }
3431
3432 parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3433
3434 if (pj_strlen(&parsed_name_addr->display)) {
3435 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
3436 }
3437
3438 /* Unlike the To header, we only want to replace the user, host and port */
3439 pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);
3440 pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
3441 uri->port = parsed_uri->port;
3442
3443 return 0;
3444 } else {
3445 /* assume it is 'user[@domain]' format */
3446 char *domain = strchr(from, '@');
3447
3448 if (domain) {
3449 pj_str_t pj_from;
3450
3451 pj_strset3(&pj_from, from, domain);
3452 pj_strdup(tdata->pool, &uri->user, &pj_from);
3453
3454 pj_strdup2(tdata->pool, &uri->host, domain + 1);
3455 } else {
3456 pj_strdup2(tdata->pool, &uri->user, from);
3457 }
3458
3459 return 0;
3460 }
3461
3462 return -1;
3463}
3464
3465static void remove_request_headers(pjsip_endpoint *endpt)
3466{
3467 const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
3468 pjsip_hdr *iter = request_headers->next;
3469
3470 while (iter != request_headers) {
3471 pjsip_hdr *to_erase = iter;
3472 iter = iter->next;
3473 pj_list_erase(to_erase);
3474 }
3475}
3476
3481
3483{
3484 return sip_taskpool;
3485}
3486
3487int ast_sip_is_uri_sip_sips(pjsip_uri *uri)
3488{
3489 return (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri));
3490}
3491
3492int ast_sip_is_allowed_uri(pjsip_uri *uri)
3493{
3494 return (ast_sip_is_uri_sip_sips(uri) || PJSIP_URI_SCHEME_IS_TEL(uri));
3495}
3496
3497const pj_str_t *ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
3498{
3499 if (ast_sip_is_uri_sip_sips(uri)) {
3500 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3501 if (!sip_uri) {
3502 return &AST_PJ_STR_EMPTY;
3503 }
3504 return &sip_uri->user;
3505 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3506 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3507 if (!tel_uri) {
3508 return &AST_PJ_STR_EMPTY;
3509 }
3510 return &tel_uri->number;
3511 }
3512
3513 return &AST_PJ_STR_EMPTY;
3514}
3515
3516const pj_str_t *ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
3517{
3518 if (ast_sip_is_uri_sip_sips(uri)) {
3519 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3520 if (!sip_uri) {
3521 return &AST_PJ_STR_EMPTY;
3522 }
3523 return &sip_uri->host;
3524 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3525 return &AST_PJ_STR_EMPTY;
3526 }
3527
3528 return &AST_PJ_STR_EMPTY;
3529}
3530
3531struct pjsip_param *ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_str_t *param_str)
3532{
3533 if (ast_sip_is_uri_sip_sips(uri)) {
3534 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3535 if (!sip_uri) {
3536 return NULL;
3537 }
3538 return pjsip_param_find(&sip_uri->other_param, param_str);
3539 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3540 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3541 if (!tel_uri) {
3542 return NULL;
3543 }
3544 return pjsip_param_find(&tel_uri->other_param, param_str);
3545 }
3546
3547 return NULL;
3548}
3549
3550float ast_sip_parse_qvalue(const char *q_value) {
3551 char *end = NULL;
3552 float ret = strtof(q_value, &end);
3553
3554 if (end == q_value) {
3555 return -1.0f; /* Not a number. */
3556 }
3557 if ('\0' != *end) {
3558 return -1.0f; /* Extra characters at end of input. */
3559 }
3560 if (!isfinite(ret)) {
3561 return -1.0f; /* NaN or Infinity. */
3562 }
3563 if (ret > 1.0f || ret < 0.0f) {
3564 return -1.0f; /* Out of valid range. */
3565 }
3566 return ret;
3567}
3568
3569/*! \brief Convert SIP hangup causes to Asterisk hangup causes */
3570const int ast_sip_hangup_sip2cause(int cause)
3571{
3572 /* Possible values taken from causes.h */
3573 switch(cause) {
3574 case 302: /* Redirect */
3576 case 401: /* Unauthorized */
3578 case 403: /* Not found */
3580 case 404: /* Not found */
3581 return AST_CAUSE_UNALLOCATED;
3582 case 405: /* Method not allowed */
3584 case 407: /* Proxy authentication required */
3586 case 408: /* No reaction */
3588 case 409: /* Conflict */
3590 case 410: /* Gone */
3592 case 411: /* Length required */
3594 case 413: /* Request entity too large */
3596 case 414: /* Request URI too large */
3598 case 415: /* Unsupported media type */
3600 case 420: /* Bad extension */
3602 case 480: /* No answer */
3603 return AST_CAUSE_NO_ANSWER;
3604 case 481: /* No answer */
3606 case 482: /* Loop detected */
3608 case 483: /* Too many hops */
3609 return AST_CAUSE_NO_ANSWER;
3610 case 484: /* Address incomplete */
3612 case 485: /* Ambiguous */
3613 return AST_CAUSE_UNALLOCATED;
3614 case 486: /* Busy everywhere */
3615 return AST_CAUSE_BUSY;
3616 case 487: /* Request terminated */
3618 case 488: /* No codecs approved */
3620 case 491: /* Request pending */
3622 case 493: /* Undecipherable */
3624 case 500: /* Server internal failure */
3625 return AST_CAUSE_FAILURE;
3626 case 501: /* Call rejected */
3628 case 502:
3630 case 503: /* Service unavailable */
3631 return AST_CAUSE_CONGESTION;
3632 case 504: /* Gateway timeout */
3634 case 505: /* SIP version not supported */
3636 case 600: /* Busy everywhere */
3637 return AST_CAUSE_USER_BUSY;
3638 case 603: /* Decline */
3640 case 604: /* Does not exist anywhere */
3641 return AST_CAUSE_UNALLOCATED;
3642 case 606: /* Not acceptable */
3644 default:
3645 if (cause < 500 && cause >= 400) {
3646 /* 4xx class error that is unknown - someting wrong with our request */
3648 } else if (cause < 600 && cause >= 500) {
3649 /* 5xx class error - problem in the remote end */
3650 return AST_CAUSE_CONGESTION;
3651 } else if (cause < 700 && cause >= 600) {
3652 /* 6xx - global errors in the 4xx class */
3654 }
3655 return AST_CAUSE_NORMAL;
3656 }
3657 /* Never reached */
3658 return 0;
3659}
3660
3662 int code;
3663 const char *long_name;
3664 const char *short_name;
3665};
3666
3667/*
3668 * This map was generated from sip_msg.h with
3669 *
3670 * sed -n -r -e 's/^\s+(PJSIP_SC_([^ =]+))\s*=\s*[0-9]+,/{ \1, "\1", "\2" },/gp' \
3671 * third-party/pjproject/source/pjsip/include/pjsip/sip_msg.h
3672 *
3673 */
3674static const struct response_code_map rc_map[] = {
3675 { PJSIP_SC_NULL, "PJSIP_SC_NULL", "NULL" },
3676 { PJSIP_SC_TRYING, "PJSIP_SC_TRYING", "TRYING" },
3677 { PJSIP_SC_RINGING, "PJSIP_SC_RINGING", "RINGING" },
3678 { PJSIP_SC_CALL_BEING_FORWARDED, "PJSIP_SC_CALL_BEING_FORWARDED", "CALL_BEING_FORWARDED" },
3679 { PJSIP_SC_QUEUED, "PJSIP_SC_QUEUED", "QUEUED" },
3680 { PJSIP_SC_PROGRESS, "PJSIP_SC_PROGRESS", "PROGRESS" },
3681 { PJSIP_SC_EARLY_DIALOG_TERMINATED, "PJSIP_SC_EARLY_DIALOG_TERMINATED", "EARLY_DIALOG_TERMINATED" },
3682 { PJSIP_SC_OK, "PJSIP_SC_OK", "OK" },
3683 { PJSIP_SC_ACCEPTED, "PJSIP_SC_ACCEPTED", "ACCEPTED" },
3684 { PJSIP_SC_NO_NOTIFICATION, "PJSIP_SC_NO_NOTIFICATION", "NO_NOTIFICATION" },
3685 { PJSIP_SC_MULTIPLE_CHOICES, "PJSIP_SC_MULTIPLE_CHOICES", "MULTIPLE_CHOICES" },
3686 { PJSIP_SC_MOVED_PERMANENTLY, "PJSIP_SC_MOVED_PERMANENTLY", "MOVED_PERMANENTLY" },
3687 { PJSIP_SC_MOVED_TEMPORARILY, "PJSIP_SC_MOVED_TEMPORARILY", "MOVED_TEMPORARILY" },
3688 { PJSIP_SC_USE_PROXY, "PJSIP_SC_USE_PROXY", "USE_PROXY" },
3689 { PJSIP_SC_ALTERNATIVE_SERVICE, "PJSIP_SC_ALTERNATIVE_SERVICE", "ALTERNATIVE_SERVICE" },
3690 { PJSIP_SC_BAD_REQUEST, "PJSIP_SC_BAD_REQUEST", "BAD_REQUEST" },
3691 { PJSIP_SC_UNAUTHORIZED, "PJSIP_SC_UNAUTHORIZED", "UNAUTHORIZED" },
3692 { PJSIP_SC_PAYMENT_REQUIRED, "PJSIP_SC_PAYMENT_REQUIRED", "PAYMENT_REQUIRED" },
3693 { PJSIP_SC_FORBIDDEN, "PJSIP_SC_FORBIDDEN", "FORBIDDEN" },
3694 { PJSIP_SC_NOT_FOUND, "PJSIP_SC_NOT_FOUND", "NOT_FOUND" },
3695 { PJSIP_SC_METHOD_NOT_ALLOWED, "PJSIP_SC_METHOD_NOT_ALLOWED", "METHOD_NOT_ALLOWED" },
3696 { PJSIP_SC_NOT_ACCEPTABLE, "PJSIP_SC_NOT_ACCEPTABLE", "NOT_ACCEPTABLE" },
3697 { PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED, "PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED", "PROXY_AUTHENTICATION_REQUIRED" },
3698 { PJSIP_SC_REQUEST_TIMEOUT, "PJSIP_SC_REQUEST_TIMEOUT", "REQUEST_TIMEOUT" },
3699 { PJSIP_SC_CONFLICT, "PJSIP_SC_CONFLICT", "CONFLICT" },
3700 { PJSIP_SC_GONE, "PJSIP_SC_GONE", "GONE" },
3701 { PJSIP_SC_LENGTH_REQUIRED, "PJSIP_SC_LENGTH_REQUIRED", "LENGTH_REQUIRED" },
3702 { PJSIP_SC_CONDITIONAL_REQUEST_FAILED, "PJSIP_SC_CONDITIONAL_REQUEST_FAILED", "CONDITIONAL_REQUEST_FAILED" },
3703 { PJSIP_SC_REQUEST_ENTITY_TOO_LARGE, "PJSIP_SC_REQUEST_ENTITY_TOO_LARGE", "REQUEST_ENTITY_TOO_LARGE" },
3704 { PJSIP_SC_REQUEST_URI_TOO_LONG, "PJSIP_SC_REQUEST_URI_TOO_LONG", "REQUEST_URI_TOO_LONG" },
3705 { PJSIP_SC_UNSUPPORTED_MEDIA_TYPE, "PJSIP_SC_UNSUPPORTED_MEDIA_TYPE", "UNSUPPORTED_MEDIA_TYPE" },
3706 { PJSIP_SC_UNSUPPORTED_URI_SCHEME, "PJSIP_SC_UNSUPPORTED_URI_SCHEME", "UNSUPPORTED_URI_SCHEME" },
3707 { PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY, "PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY", "UNKNOWN_RESOURCE_PRIORITY" },
3708 { PJSIP_SC_BAD_EXTENSION, "PJSIP_SC_BAD_EXTENSION", "BAD_EXTENSION" },
3709 { PJSIP_SC_EXTENSION_REQUIRED, "PJSIP_SC_EXTENSION_REQUIRED", "EXTENSION_REQUIRED" },
3710 { PJSIP_SC_SESSION_TIMER_TOO_SMALL, "PJSIP_SC_SESSION_TIMER_TOO_SMALL", "SESSION_TIMER_TOO_SMALL" },
3711 { PJSIP_SC_INTERVAL_TOO_BRIEF, "PJSIP_SC_INTERVAL_TOO_BRIEF", "INTERVAL_TOO_BRIEF" },
3712 { PJSIP_SC_BAD_LOCATION_INFORMATION, "PJSIP_SC_BAD_LOCATION_INFORMATION", "BAD_LOCATION_INFORMATION" },
3713 { PJSIP_SC_USE_IDENTITY_HEADER, "PJSIP_SC_USE_IDENTITY_HEADER", "USE_IDENTITY_HEADER" },
3714 { PJSIP_SC_PROVIDE_REFERRER_HEADER, "PJSIP_SC_PROVIDE_REFERRER_HEADER", "PROVIDE_REFERRER_HEADER" },
3715 { PJSIP_SC_FLOW_FAILED, "PJSIP_SC_FLOW_FAILED", "FLOW_FAILED" },
3716 { PJSIP_SC_ANONIMITY_DISALLOWED, "PJSIP_SC_ANONIMITY_DISALLOWED", "ANONIMITY_DISALLOWED" },
3717 { PJSIP_SC_BAD_IDENTITY_INFO, "PJSIP_SC_BAD_IDENTITY_INFO", "BAD_IDENTITY_INFO" },
3718 { PJSIP_SC_UNSUPPORTED_CERTIFICATE, "PJSIP_SC_UNSUPPORTED_CERTIFICATE", "UNSUPPORTED_CERTIFICATE" },
3719 { PJSIP_SC_INVALID_IDENTITY_HEADER, "PJSIP_SC_INVALID_IDENTITY_HEADER", "INVALID_IDENTITY_HEADER" },
3720 { PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT, "PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT", "FIRST_HOP_LACKS_OUTBOUND_SUPPORT" },
3721 { PJSIP_SC_MAX_BREADTH_EXCEEDED, "PJSIP_SC_MAX_BREADTH_EXCEEDED", "MAX_BREADTH_EXCEEDED" },
3722 { PJSIP_SC_BAD_INFO_PACKAGE, "PJSIP_SC_BAD_INFO_PACKAGE", "BAD_INFO_PACKAGE" },
3723 { PJSIP_SC_CONSENT_NEEDED, "PJSIP_SC_CONSENT_NEEDED", "CONSENT_NEEDED" },
3724 { PJSIP_SC_TEMPORARILY_UNAVAILABLE, "PJSIP_SC_TEMPORARILY_UNAVAILABLE", "TEMPORARILY_UNAVAILABLE" },
3725 { PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, "PJSIP_SC_CALL_TSX_DOES_NOT_EXIST", "CALL_TSX_DOES_NOT_EXIST" },
3726 { PJSIP_SC_LOOP_DETECTED, "PJSIP_SC_LOOP_DETECTED", "LOOP_DETECTED" },
3727 { PJSIP_SC_TOO_MANY_HOPS, "PJSIP_SC_TOO_MANY_HOPS", "TOO_MANY_HOPS" },
3728 { PJSIP_SC_ADDRESS_INCOMPLETE, "PJSIP_SC_ADDRESS_INCOMPLETE", "ADDRESS_INCOMPLETE" },
3729 { PJSIP_SC_BUSY_HERE, "PJSIP_SC_BUSY_HERE", "BUSY_HERE" },
3730 { PJSIP_SC_REQUEST_TERMINATED, "PJSIP_SC_REQUEST_TERMINATED", "REQUEST_TERMINATED" },
3731 { PJSIP_SC_NOT_ACCEPTABLE_HERE, "PJSIP_SC_NOT_ACCEPTABLE_HERE", "NOT_ACCEPTABLE_HERE" },
3732 { PJSIP_SC_BAD_EVENT, "PJSIP_SC_BAD_EVENT", "BAD_EVENT" },
3733 { PJSIP_SC_REQUEST_UPDATED, "PJSIP_SC_REQUEST_UPDATED", "REQUEST_UPDATED" },
3734 { PJSIP_SC_REQUEST_PENDING, "PJSIP_SC_REQUEST_PENDING", "REQUEST_PENDING" },
3735 { PJSIP_SC_UNDECIPHERABLE, "PJSIP_SC_UNDECIPHERABLE", "UNDECIPHERABLE" },
3736 { PJSIP_SC_SECURITY_AGREEMENT_NEEDED, "PJSIP_SC_SECURITY_AGREEMENT_NEEDED", "SECURITY_AGREEMENT_NEEDED" },
3737 { PJSIP_SC_INTERNAL_SERVER_ERROR, "PJSIP_SC_INTERNAL_SERVER_ERROR", "INTERNAL_SERVER_ERROR" },
3738 { PJSIP_SC_NOT_IMPLEMENTED, "PJSIP_SC_NOT_IMPLEMENTED", "NOT_IMPLEMENTED" },
3739 { PJSIP_SC_BAD_GATEWAY, "PJSIP_SC_BAD_GATEWAY", "BAD_GATEWAY" },
3740 { PJSIP_SC_SERVICE_UNAVAILABLE, "PJSIP_SC_SERVICE_UNAVAILABLE", "SERVICE_UNAVAILABLE" },
3741 { PJSIP_SC_SERVER_TIMEOUT, "PJSIP_SC_SERVER_TIMEOUT", "SERVER_TIMEOUT" },
3742 { PJSIP_SC_VERSION_NOT_SUPPORTED, "PJSIP_SC_VERSION_NOT_SUPPORTED", "VERSION_NOT_SUPPORTED" },
3743 { PJSIP_SC_MESSAGE_TOO_LARGE, "PJSIP_SC_MESSAGE_TOO_LARGE", "MESSAGE_TOO_LARGE" },
3744 { PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED, "PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED", "PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED" },
3745 { PJSIP_SC_PRECONDITION_FAILURE, "PJSIP_SC_PRECONDITION_FAILURE", "PRECONDITION_FAILURE" },
3746 { PJSIP_SC_BUSY_EVERYWHERE, "PJSIP_SC_BUSY_EVERYWHERE", "BUSY_EVERYWHERE" },
3747 { PJSIP_SC_DECLINE, "PJSIP_SC_DECLINE", "DECLINE" },
3748 { PJSIP_SC_DOES_NOT_EXIST_ANYWHERE, "PJSIP_SC_DOES_NOT_EXIST_ANYWHERE", "DOES_NOT_EXIST_ANYWHERE" },
3749 { PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE, "PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE", "NOT_ACCEPTABLE_ANYWHERE" },
3750 { PJSIP_SC_UNWANTED, "PJSIP_SC_UNWANTED", "UNWANTED" },
3751 { PJSIP_SC_REJECTED, "PJSIP_SC_REJECTED", "REJECTED" },
3752};
3753
3754int ast_sip_str2rc(const char *name)
3755{
3756 int i;
3757
3758 if (ast_strlen_zero(name)) {
3759 return -1;
3760 }
3761
3762 for (i = 0; i < ARRAY_LEN(rc_map); i++) {
3763 if (strcasecmp(rc_map[i].short_name, name) == 0 ||
3764 strcasecmp(rc_map[i].long_name, name) == 0) {
3765 return rc_map[i].code;
3766 }
3767 }
3768
3769 return -1;
3770}
3771
3772
3773#ifdef TEST_FRAMEWORK
3774AST_TEST_DEFINE(xml_sanitization_end_null)
3775{
3776 char sanitized[8];
3777
3778 switch (cmd) {
3779 case TEST_INIT:
3780 info->name = "xml_sanitization_end_null";
3781 info->category = "/res/res_pjsip/";
3782 info->summary = "Ensure XML sanitization works as expected with a long string";
3783 info->description = "This test sanitizes a string which exceeds the output\n"
3784 "buffer size. Once done the string is confirmed to be NULL terminated.";
3785 return AST_TEST_NOT_RUN;
3786 case TEST_EXECUTE:
3787 break;
3788 }
3789
3790 ast_sip_sanitize_xml("aaaaaaaaaaaa", sanitized, sizeof(sanitized));
3791 if (sanitized[7] != '\0') {
3792 ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
3793 return AST_TEST_FAIL;
3794 }
3795
3796 return AST_TEST_PASS;
3797}
3798
3799AST_TEST_DEFINE(xml_sanitization_exceeds_buffer)
3800{
3801 char sanitized[8];
3802
3803 switch (cmd) {
3804 case TEST_INIT:
3805 info->name = "xml_sanitization_exceeds_buffer";
3806 info->category = "/res/res_pjsip/";
3807 info->summary = "Ensure XML sanitization does not exceed buffer when output won't fit";
3808 info->description = "This test sanitizes a string which before sanitization would\n"
3809 "fit within the output buffer. After sanitization, however, the string would\n"
3810 "exceed the buffer. Once done the string is confirmed to be NULL terminated.";
3811 return AST_TEST_NOT_RUN;
3812 case TEST_EXECUTE:
3813 break;
3814 }
3815
3816 ast_sip_sanitize_xml("<><><>&", sanitized, sizeof(sanitized));
3817 if (sanitized[7] != '\0') {
3818 ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
3819 return AST_TEST_FAIL;
3820 }
3821
3822 return AST_TEST_PASS;
3823}
3824#endif
3825
3826/*!
3827 * \internal
3828 * \brief Reload configuration within a PJSIP thread
3829 */
3837
3838static int unload_pjsip(void *data)
3839{
3840 /*
3841 * These calls need the pjsip endpoint and serializer to clean up.
3842 * If they're not set, then there's nothing to clean up anyway.
3843 */
3844 if (ast_pjsip_endpoint) {
3854 }
3855
3856 if (monitor_thread) {
3859 }
3860
3861 if (memory_pool) {
3862 /* This mimics the behavior of pj_pool_safe_release
3863 * which was introduced in pjproject 2.6.
3864 */
3865 pj_pool_t *temp_pool = memory_pool;
3866
3867 memory_pool = NULL;
3868 pj_pool_release(temp_pool);
3869 }
3870
3872
3873 if (caching_pool.lock) {
3875 }
3876
3877 pj_shutdown();
3878
3879 return 0;
3880}
3881
3882static int load_pjsip(void)
3883{
3884 const unsigned int flags = 0; /* no port, no brackets */
3885 pj_status_t status;
3886
3887 /* The third parameter is just copied from
3888 * example code from PJLIB. This can be adjusted
3889 * if necessary.
3890 */
3892 if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
3893 ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
3894 goto error;
3895 }
3896
3897 /* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
3898 * we need to stop PJSIP from doing it automatically
3899 */
3901
3902 memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
3903 if (!memory_pool) {
3904 ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
3905 goto error;
3906 }
3907
3908 if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
3909 pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), flags);
3910 ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
3911 }
3912
3913 if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
3914 pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), flags);
3915 ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
3916 }
3917
3918 pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
3919 pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
3920
3921 monitor_continue = 1;
3922 status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
3923 NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
3924 if (status != PJ_SUCCESS) {
3925 ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
3926 goto error;
3927 }
3928
3930
3931error:
3933}
3934
3935/*
3936 * This is a place holder function to ensure that pjmedia_strerr() is at
3937 * least directly referenced by this module to ensure that the loader
3938 * linker will link to the function. If a module only indirectly
3939 * references a function from another module, such as a callback parameter
3940 * to a function, the loader linker has been known to miss the link.
3941 */
3942void never_called_res_pjsip(void);
3944{
3945 pjmedia_strerror(0, NULL, 0);
3946}
3947
3948/* Definitions of media types declared "extern" in res_pjsip.h */
3961
3962static int load_module(void)
3963{
3965
3966 /* pjproject and config_system need to be initialized before all else */
3967 if (pj_init() != PJ_SUCCESS) {
3969 }
3970
3971 if (pjlib_util_init() != PJ_SUCCESS) {
3972 goto error;
3973 }
3974
3975 /* Register PJMEDIA error codes for SDP parsing errors */
3976 if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
3977 != PJ_SUCCESS) {
3978 ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
3979 }
3980
3981 /* Initialize common media types */
3982 pjsip_media_type_init2(&pjsip_media_type_application_json, "application", "json");
3983 pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml, "application", "media_control+xml");
3984 pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml, "application", "pidf+xml");
3985 pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml, "application", "xpidf+xml");
3986 pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml, "application", "cpim-xpidf+xml");
3987 pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml, "application", "rlmi+xml");
3988 pjsip_media_type_init2(&pjsip_media_type_application_sdp, "application", "sdp");
3989 pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary, "application", "simple-message-summary");
3990 pjsip_media_type_init2(&pjsip_media_type_multipart_alternative, "multipart", "alternative");
3991 pjsip_media_type_init2(&pjsip_media_type_multipart_mixed, "multipart", "mixed");
3992 pjsip_media_type_init2(&pjsip_media_type_multipart_related, "multipart", "related");
3993 pjsip_media_type_init2(&pjsip_media_type_text_plain, "text", "plain");
3994
3995
3997 ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
3998 goto error;
3999 }
4000
4001 /* The serializer needs taskpool and taskpool needs pjproject to be initialized so it's next */
4003 options.thread_start = sip_thread_start;
4005 if (!sip_taskpool) {
4006 goto error;
4007 }
4008
4010 ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
4011 goto error;
4012 }
4013
4014 /* Now load all the pjproject infrastructure. */
4015 if (load_pjsip()) {
4016 goto error;
4017 }
4018
4020 ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
4021 goto error;
4022 }
4023
4026
4028 ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
4029 goto error;
4030 }
4031
4033 ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
4034 goto error;
4035 }
4036
4039
4041 ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
4042 goto error;
4043 }
4044
4046 ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
4047 goto error;
4048 }
4049
4051 ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
4052 goto error;
4053 }
4054
4056 ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
4057 goto error;
4058 }
4059
4060 /*
4061 * It is OK to prune the contacts now that
4062 * ast_res_pjsip_init_options_handling() has added the contact observer
4063 * of res/res_pjsip/pjsip_options.c to sorcery (to ensure that any
4064 * pruned contacts are removed from this module's data structure).
4065 */
4067
4069 ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
4070 goto error;
4071 }
4072
4074
4075 AST_TEST_REGISTER(xml_sanitization_end_null);
4076 AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
4077
4079
4080error:
4082
4083 /* These functions all check for NULLs and are safe to call at any time */
4086
4088}
4089
4090static int reload_module(void)
4091{
4092 /*
4093 * We must wait for the reload to complete so multiple
4094 * reloads cannot happen at the same time.
4095 */
4097 ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
4098 return -1;
4099 }
4100
4101 return 0;
4102}
4103
4104static int unload_module(void)
4105{
4106 AST_TEST_UNREGISTER(xml_sanitization_end_null);
4107 AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
4109
4110 /* The thread this is called from cannot call PJSIP/PJLIB functions,
4111 * so we have to push the work to the taskpool to handle
4112 */
4116
4117 return 0;
4118}
4119
4121 .support_level = AST_MODULE_SUPPORT_CORE,
4122 .load = load_module,
4123 .unload = unload_module,
4125 .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
4126 .requires = "dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb",
4127 .optional_modules = "res_geolocation,res_statsd",
Access Control of various sorts.
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
static int compare(const char *text, const char *template)
jack_status_t status
Definition app_jack.c:149
const char * str
Definition app_jack.c:150
enum queue_result id
Definition app_queue.c:1790
pthread_t thread
Definition app_sla.c:335
ast_mutex_t lock
Definition app_sla.c:337
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_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#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_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define ast_log
Definition astobj2.c:42
#define ao2_t_ref(o, delta, tag)
Definition astobj2.h:460
@ CMP_MATCH
Definition astobj2.h:1027
@ CMP_STOP
Definition astobj2.h:1028
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
#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
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED
Definition callerid.h:449
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition callerid.h:426
#define AST_PRES_USER_NUMBER_PASSED_SCREEN
Definition callerid.h:427
#define AST_PRES_RESTRICTED
Definition callerid.h:433
#define AST_PRES_ALLOWED
Definition callerid.h:432
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition callerid.h:437
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
Definition causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition causes.h:98
#define AST_CAUSE_INTERWORKING
Definition causes.h:146
#define AST_CAUSE_NUMBER_CHANGED
Definition causes.h:112
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition causes.h:130
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition causes.h:116
#define AST_CAUSE_FAILURE
Definition causes.h:150
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition causes.h:115
#define AST_CAUSE_NO_USER_RESPONSE
Definition causes.h:108
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition causes.h:122
#define AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION
Definition causes.h:113
#define AST_CAUSE_NORMAL
Definition causes.h:151
#define AST_CAUSE_CALL_REJECTED
Definition causes.h:111
#define AST_CAUSE_FACILITY_REJECTED
Definition causes.h:117
#define AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE
Definition causes.h:143
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition causes.h:100
#define AST_CAUSE_BUSY
Definition causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition causes.h:109
#define AST_CAUSE_USER_BUSY
Definition causes.h:107
static const char desc[]
Definition cdr_radius.c:84
static PGresult * result
Definition cel_pgsql.c:84
static const char type[]
#define AST_CHANNEL_NAME
Definition channel.h:173
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition channel.c:1752
size_t current
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
#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)
void sip_get_taskpool_options(struct ast_taskpool_options *taskpool_options)
int sip_cli_print_system(struct ast_sip_cli_context *context)
int ast_sip_initialize_system(void)
void ast_sip_initialize_dns(void)
static struct ao2_container * transport_states
char * end
Definition eagi_proxy.c:73
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_option_pjproject_log_level
Definition options.c:75
int __ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c:2205
#define ast_sip_push_task(serializer, sip_task, task_data)
Definition res_pjsip.h:2126
#define ast_sip_push_task_synchronous(serializer, sip_task, task_data)
Definition res_pjsip.h:2174
int __ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c:2195
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition res_pjsip.c:2137
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:2132
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
Definition res_pjsip.h:2221
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
Definition res_pjsip.c:2330
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2165
int __ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to the serializer and wait for it to complete.
Definition res_pjsip.c:2211
int __ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Pushes a task to SIP servants.
Definition res_pjsip.c:2145
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#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
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#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.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_INSERT_AFTER
#define AST_RWLIST_NEXT
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_RWLIST_INSERT_TAIL
#define AST_RWLIST_ENTRY
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Asterisk locking-related definitions:
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition lock.h:590
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition module.h:330
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition module.h:557
@ AST_MODPRI_CHANNEL_DEPEND
Definition module.h:340
@ 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
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition netsock2.h:327
@ AST_TRANSPORT_WSS
Definition netsock2.h:64
@ AST_TRANSPORT_WS
Definition netsock2.h:63
@ AST_TRANSPORT_UDP
Definition netsock2.h:60
@ AST_TRANSPORT_TLS
Definition netsock2.h:62
@ AST_TRANSPORT_TCP
Definition netsock2.h:61
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 int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition netsock2.h:127
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition netsock2.h:532
static struct header_list request_headers
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 const pjsip_method refer_method
Definition res_pjsip.c:1274
static pjsip_endpoint * ast_pjsip_endpoint
Definition res_pjsip.c:68
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, pjsip_transaction **tsx)
Definition res_pjsip.c:1694
void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
Unregister a an supplement to SIP out of dialog processing.
Definition res_pjsip.c:1474
static pj_sockaddr host_ip_ipv4
Definition res_pjsip.c:73
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:2248
struct ast_sip_endpoint * ast_sip_get_endpoint(const char *to, int get_default_outbound, char **uri)
Retrieves an endpoint and URI from the "to" string.
Definition res_pjsip.c:3269
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:928
static int unload_pjsip(void *data)
Definition res_pjsip.c:3838
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition res_pjsip.c:2394
struct pjsip_param * ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_str_t *param_str)
Find an 'other' SIP/SIPS URI parameter by name.
Definition res_pjsip.c:3531
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition res_pjsip.c:3497
static const pjsip_method info_method
Definition res_pjsip.c:1272
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:127
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition res_pjsip.c:2513
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:1113
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition res_pjsip.c:183
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition res_pjsip.c:3950
static struct ast_cli_entry cli_commands[]
Definition res_pjsip.c:471
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
Definition res_pjsip.c:1305
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:2597
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:339
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:1174
pjsip_media_type pjsip_media_type_application_json
Definition res_pjsip.c:3949
static char * cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_pjsip.c:369
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:157
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:1532
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:2416
pjsip_generic_string_hdr * ast_sip_add_header2(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message, returning a pointer to the header.
Definition res_pjsip.c:2066
static struct ast_taskpool * sip_taskpool
Definition res_pjsip.c:70
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:2228
int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
Retrieve the local host address in IP form.
Definition res_pjsip.c:2500
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition res_pjsip.c:111
static const pjsip_method * get_pjsip_method(const char *method)
Definition res_pjsip.c:1294
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:1323
static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
Definition res_pjsip.c:1646
static int reload_configuration_task(void *obj)
Definition res_pjsip.c:3830
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
Definition res_pjsip.c:3492
#define MOD_DATA_CONTACT
Definition res_pjsip.c:66
int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Register an outbound SIP authenticator.
Definition res_pjsip.c:185
static struct ast_sip_endpoint * handle_slash(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
Definition res_pjsip.c:3054
static struct ast_sip_endpoint * handle_single_token(const char *to, char *destination, int get_default_outbound, char **uri)
Definition res_pjsip.c:2975
static void send_request_wrapper_destructor(void *obj)
Definition res_pjsip.c:1686
static pjsip_fromto_hdr * get_id_header(pjsip_rx_data *rdata, const pj_str_t *header_name)
Definition res_pjsip.c:2693
static int unregister_service(void *data)
Definition res_pjsip.c:116
static void send_request_data_destroy(void *obj)
Definition res_pjsip.c:1525
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
Definition res_pjsip.c:1087
const int ast_sip_hangup_sip2cause(int cause)
Convert SIP hangup causes to Asterisk hangup causes.
Definition res_pjsip.c:3570
pj_pool_t * memory_pool
Definition res_pjsip.c:2282
int ast_sip_rewrite_uri_to_local(pjsip_sip_uri *uri, pjsip_tx_data *tdata)
Replace domain and port of SIP URI to point to (external) signaling address of this Asterisk instance...
Definition res_pjsip.c:603
int ast_sip_set_id_connected_line(struct pjsip_rx_data *rdata, struct ast_party_id *id)
Set the ID for a connected line update.
Definition res_pjsip.c:2842
pjsip_media_type pjsip_media_type_application_sdp
Definition res_pjsip.c:3956
void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
Register a supplement to SIP out of dialog processing.
Definition res_pjsip.c:1454
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:84
pjsip_media_type pjsip_media_type_text_plain
Definition res_pjsip.c:3960
pj_thread_t * monitor_thread
Definition res_pjsip.c:2283
void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Unregister an outbound SIP authenticator.
Definition res_pjsip.c:197
int ast_sip_set_id_from_invite(struct pjsip_rx_data *rdata, struct ast_party_id *id, struct ast_party_id *default_id, int trust_inbound)
Set the ID from an INVITE.
Definition res_pjsip.c:2847
pjsip_media_type pjsip_media_type_application_pidf_xml
Definition res_pjsip.c:3951
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:1264
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:173
#define SIP_SERVANT_ID
Definition res_pjsip.c:2303
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:518
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
Definition res_pjsip.c:304
static void send_request_cb(void *token, pjsip_event *e)
Definition res_pjsip.c:1904
void * ast_sip_dict_get(void *ht, const char *key)
Retrieves the value associated with the given key.
Definition res_pjsip.c:2347
int ast_sip_update_from(pjsip_tx_data *tdata, char *from)
Overwrite fields in the outbound 'From' header.
Definition res_pjsip.c:3403
static const pjsip_method message_method
Definition res_pjsip.c:1273
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:499
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:2524
int ast_sip_str2rc(const char *name)
Convert name to SIP response code.
Definition res_pjsip.c:3754
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:841
int ast_sip_is_uri_sip_sips(pjsip_uri *uri)
Check whether a pjsip_uri is SIP/SIPS or not.
Definition res_pjsip.c:3487
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:909
#define DEBUG_BUF_SIZE
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
Definition res_pjsip.c:1861
static void sip_thread_start(void)
Definition res_pjsip.c:2305
static char * cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_pjsip.c:409
static void clean_contact_from_tdata(pjsip_tx_data *tdata)
Definition res_pjsip.c:2435
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Definition res_pjsip.c:309
static int reload_module(void)
Definition res_pjsip.c:4090
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:2221
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
Definition res_pjsip.c:1488
static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors, const char *user, char **uri)
Find a contact and insert a "user@" into its URI.
Definition res_pjsip.c:2910
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:2574
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:324
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:2014
static struct ast_sip_endpoint * handle_atsign(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme, int get_default_outbound)
Definition res_pjsip.c:3211
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:1190
pjsip_media_type pjsip_media_type_application_simple_message_summary
Definition res_pjsip.c:3955
struct ast_sip_transport_state * ast_sip_find_transport_state_in_use(struct ast_sip_request_transport_details *details)
Returns the transport state currently in use based on request transport details.
Definition res_pjsip.c:593
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition res_pjsip.c:82
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:725
static pj_sockaddr host_ip_ipv6
Definition res_pjsip.c:79
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:962
const char * method
Definition res_pjsip.c:1277
long ast_sip_taskpool_queue_size(void)
Return the size of the SIP taskpool's task queue.
Definition res_pjsip.c:3477
void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
Unregister a SIP authenticator.
Definition res_pjsip.c:146
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:2022
int ast_sip_set_request_transport_details(struct ast_sip_request_transport_details *details, pjsip_tx_data *tdata, int use_ipv6)
Sets request transport details based on tdata.
Definition res_pjsip.c:646
static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
Definition res_pjsip.c:2370
static struct @486 methods[]
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition res_pjsip.c:2082
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition res_pjsip.c:479
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:2095
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:2358
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
Definition res_pjsip.c:2239
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition res_pjsip.c:921
void never_called_res_pjsip(void)
Definition res_pjsip.c:3943
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:696
static int set_id_from_from(struct pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2823
int ast_sip_send_out_of_dialog_request_with_tsx(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e), pjsip_transaction **tsx)
Send an Out-Of-Dialog SIP request and return its transaction.
Definition res_pjsip.c:1969
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition res_pjsip.c:485
static void * monitor_thread_exec(void *endpt)
Definition res_pjsip.c:2286
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_pjsip.c:440
int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
Register a SIP authenticator.
Definition res_pjsip.c:134
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:1212
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:2102
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:1116
pjsip_media_type pjsip_media_type_application_rlmi_xml
Definition res_pjsip.c:3954
static int monitor_continue
Definition res_pjsip.c:2284
static const struct response_code_map rc_map[]
Definition res_pjsip.c:3674
static void remove_request_headers(pjsip_endpoint *endpt)
Definition res_pjsip.c:3465
float ast_sip_parse_qvalue(const char *q_value)
Parses a string representing a q_value to a float.
Definition res_pjsip.c:3550
int ast_sip_update_to_uri(pjsip_tx_data *tdata, const char *to)
Replace the To URI in the tdata with the supplied one.
Definition res_pjsip.c:3343
pjsip_media_type pjsip_media_type_multipart_mixed
Definition res_pjsip.c:3958
static int register_service(void *data)
Definition res_pjsip.c:96
pjsip_media_type pjsip_media_type_application_xpidf_xml
Definition res_pjsip.c:3952
static int load_module(void)
Definition res_pjsip.c:3962
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:2035
static struct ast_sip_authenticator * registered_authenticator
Definition res_pjsip.c:132
int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Definition res_pjsip.c:523
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:227
pjsip_media_type pjsip_media_type_multipart_alternative
Definition res_pjsip.c:3957
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:891
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:1433
pj_caching_pool caching_pool
Definition res_pjsip.c:2281
static int find_transport_state_in_use(void *obj, void *arg, int flags)
Callback function for finding the transport the request is going out on.
Definition res_pjsip.c:574
static void endpt_send_request_cb(void *token, pjsip_event *e)
Definition res_pjsip.c:1571
const pjsip_method * pmethod
Definition res_pjsip.c:1278
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition res_pjsip.c:2553
static int do_cli_dump_endpt(void *v_a)
Definition res_pjsip.c:354
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:2051
static int unload_module(void)
Definition res_pjsip.c:4104
const pj_str_t * ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
Get the host portion of the pjsip_uri.
Definition res_pjsip.c:3516
static pjsip_module supplement_module
Definition res_pjsip.c:1316
static void pool_destroy_callback(void *arg)
Definition res_pjsip.c:2429
struct ast_taskpool * ast_sip_taskpool(void)
Retrieve the SIP taskpool object.
Definition res_pjsip.c:3482
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition res_pjsip.c:76
static int load_pjsip(void)
Definition res_pjsip.c:3882
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition res_pjsip.c:1497
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:2444
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:2268
#define TIMER_INACTIVE
Definition res_pjsip.c:1510
int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text)
Append body data to a SIP message.
Definition res_pjsip.c:2118
static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2730
#define TIMEOUT_TIMER2
Definition res_pjsip.c:1511
#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:208
static int __ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Definition res_pjsip.c:2186
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
Definition res_pjsip.c:3953
static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
Definition res_pjsip.c:2626
static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2771
static void stop_monitor_thread(void)
Definition res_pjsip.c:2295
pjsip_sip_uri * ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
Return the SIP URI of the Contact header.
Definition res_pjsip.c:562
pjsip_media_type pjsip_media_type_multipart_related
Definition res_pjsip.c:3959
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:1838
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:747
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:2870
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:2488
char * ast_sip_get_endpoint_identifier_order(void)
Retrieve the global endpoint_identifier_order setting.
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 ao2_container * ast_sip_get_transport_states(void)
Retrieves all transport states.
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition location.c:147
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition res_pjsip.h:799
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:1188
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition res_pjsip.h:3578
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.
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
#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:3173
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:547
@ AST_SIP_DTMF_NONE
Definition res_pjsip.h:549
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:560
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:554
@ AST_SIP_DTMF_INFO
Definition res_pjsip.h:556
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:552
static const pj_str_t AST_PJ_STR_EMPTY
Definition res_pjsip.h:112
#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:3141
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define MAX_RX_CHALLENGES
Definition res_pjsip.h:108
ast_sip_check_auth_result
Possible returns from ast_sip_check_authentication.
Definition res_pjsip.h:1339
@ AST_SIP_AUTHENTICATION_SUCCESS
Definition res_pjsip.h:1343
@ AST_SIP_CALL_CODEC_PREF_ALL
Definition res_pjsip.h:779
@ AST_SIP_CALL_CODEC_PREF_LOCAL
Definition res_pjsip.h:785
@ AST_SIP_CALL_CODEC_PREF_REMOTE
Definition res_pjsip.h:787
@ AST_SIP_CALL_CODEC_PREF_UNION
Definition res_pjsip.h:775
@ AST_SIP_CALL_CODEC_PREF_FIRST
Definition res_pjsip.h:781
@ AST_SIP_CALL_CODEC_PREF_INTERSECT
Definition res_pjsip.h:773
#define AST_SIP_X_AST_TXP_LEN
Definition res_pjsip.h:1189
#define PJSTR_PRINTF_VAR(_v)
Definition res_pjsip.h:72
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.
struct ast_sip_contact * ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
Retrieve the first bound contact for an AOR.
Definition location.c:194
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition location.c:470
#define ast_sip_transport_is_local(transport_state, addr)
Definition res_pjsip.h:213
#define PJSTR_PRINTF_SPEC
Definition res_pjsip.h:71
static void challenge(const char *endpoint_id, struct ast_sip_auth *auth, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale, const pjsip_auth_algorithm *algorithm)
Send a WWW-Authenticate challenge.
static struct ast_serializer_shutdown_group * shutdown_group
void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
Replace offensive XML characters with XML entities.
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
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
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:1917
String manipulation functions.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
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:848
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
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:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition strings.h:97
Generic container type.
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:220
unsigned int flags
Definition utils.h:221
Information needed to identify an endpoint in a call.
Definition channel.h:340
char * tag
User-set "tag".
Definition channel.h:356
struct ast_party_number number
Subscriber phone number.
Definition channel.h:344
unsigned char valid
TRUE if the number information is valid/present.
Definition channel.h:299
AMI variable container.
Definition res_pjsip.h:3274
A SIP address of record.
Definition res_pjsip.h:480
An interchangeable way of handling digest authentication for SIP.
Definition res_pjsip.h:1384
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:1399
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:1389
SIP body description.
Definition res_pjsip.h:2501
const char * type
Definition res_pjsip.h:2503
const char * body_text
Definition res_pjsip.h:2507
const char * subtype
Definition res_pjsip.h:2505
CLI Formatter Context passed to all formatters.
Contact associated with an address of record.
Definition res_pjsip.h:392
const ast_string_field uri
Definition res_pjsip.h:414
struct ast_sip_endpoint * endpoint
Definition res_pjsip.h:424
const ast_string_field endpoint_name
Definition res_pjsip.h:414
An entity responsible formatting endpoint information.
Definition res_pjsip.h:3300
struct ast_sip_endpoint_formatter * next
Definition res_pjsip.h:3306
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:3304
An entity responsible for identifying the source of a SIP message.
Definition res_pjsip.h:1427
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:1432
An entity with which Asterisk communicates.
Definition res_pjsip.h:1067
struct ast_sip_auth_vector outbound_auths
Definition res_pjsip.h:1114
const ast_string_field transport
Definition res_pjsip.h:1096
const ast_string_field aors
Definition res_pjsip.h:1096
const ast_string_field outbound_proxy
Definition res_pjsip.h:1096
const ast_string_field fromdomain
Definition res_pjsip.h:1096
unsigned int allow_unauthenticated_options
Definition res_pjsip.h:1170
unsigned int usereqphone
Definition res_pjsip.h:1138
const ast_string_field fromuser
Definition res_pjsip.h:1096
struct ast_sip_endpoint_nat_configuration nat
Definition res_pjsip.h:1104
struct ast_sip_endpoint_info_configuration info
Definition res_pjsip.h:1108
an interchangeable way of responding to authentication challenges
Definition res_pjsip.h:1409
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:1420
Structure which contains information about a transport.
Definition res_pjsip.h:337
int local_port
Local port for transport.
Definition res_pjsip.h:347
pjsip_transport * transport
Potential pointer to the transport itself, if UDP.
Definition res_pjsip.h:341
enum ast_transport type
Type of transport.
Definition res_pjsip.h:339
pjsip_tpfactory * factory
Potential pointer to the transport factory itself, if TCP/TLS.
Definition res_pjsip.h:343
pj_str_t local_address
Local address for transport.
Definition res_pjsip.h:345
A supplement to SIP message processing.
Definition res_pjsip.h:3425
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:3468
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:3447
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:3473
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:3463
const char * method
Definition res_pjsip.h:3427
enum ast_sip_supplement_priority priority
Definition res_pjsip.h:3429
struct ast_sip_supplement * next
Definition res_pjsip.h:3475
Structure for SIP transport information.
Definition res_pjsip.h:117
struct pjsip_tpfactory * factory
Transport factory.
Definition res_pjsip.h:121
enum ast_transport type
Definition res_pjsip.h:131
struct pjsip_transport * transport
Transport itself.
Definition res_pjsip.h:119
Transport to bind to.
Definition res_pjsip.h:219
Socket address structure.
Definition netsock2.h:97
Support for dynamic strings.
Definition strings.h:623
An opaque taskpool structure.
Definition taskpool.c:62
A ast_taskprocessor structure is a singleton by name.
struct ast_sip_endpoint_identifier * identifier
Definition res_pjsip.c:221
struct endpoint_identifier_list::@487 list
const char * short_name
Definition res_pjsip.c:3664
const char * long_name
Definition res_pjsip.c:3663
Structure to hold information about an outbound request.
Definition res_pjsip.c:1514
struct ast_sip_endpoint * endpoint
Definition res_pjsip.c:1516
unsigned int challenge_count
Definition res_pjsip.c:1522
void(* callback)(void *token, pjsip_event *e)
Definition res_pjsip.c:1520
unsigned int send_cb_called
Definition res_pjsip.c:1558
pjsip_tx_data * tdata
Definition res_pjsip.c:1564
unsigned int cb_called
Definition res_pjsip.c:1556
pj_timer_entry * timeout_timer
Definition res_pjsip.c:1560
void(* callback)(void *token, pjsip_event *e)
Definition res_pjsip.c:1554
userdata associated with baseline taskprocessor test
structure to hold users read from phoneprov_users.conf
int value
Definition syslog.c:37
int __ast_taskpool_push_wait(struct ast_taskpool *pool, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to the taskpool, and wait for completion.
Definition taskpool.c:652
int __ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to a serializer, and wait for completion.
Definition taskpool.c:899
void ast_taskpool_shutdown(struct ast_taskpool *pool)
Shut down a taskpool and remove the underlying taskprocessors.
Definition taskpool.c:692
int __ast_taskpool_push(struct ast_taskpool *pool, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to the taskpool.
Definition taskpool.c:544
struct ast_taskprocessor * ast_taskpool_serializer_group(const char *name, struct ast_taskpool *pool, struct ast_serializer_shutdown_group *shutdown_group)
Serialized execution of tasks within a ast_taskpool.
Definition taskpool.c:847
struct ast_taskpool * ast_taskpool_create(const char *name, const struct ast_taskpool_options *options)
Create a new taskpool.
Definition taskpool.c:341
long ast_taskpool_queue_size(struct ast_taskpool *pool)
Get the current number of queued tasks in the taskpool.
Definition taskpool.c:481
An API for managing task processing threads that can be shared across modules.
int __ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap, const char *file, int line, const char *function) 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_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
UTF-8 information and validation functions.
ast_utf8_replace_result
Definition utf8.h:70
@ AST_UTF8_REPLACE_VALID
Source contained fully valid UTF-8.
Definition utf8.h:76
enum ast_utf8_replace_result ast_utf8_replace_invalid_chars(char *dst, size_t *dst_size, const char *src, size_t src_len)
Copy a string safely replacing any invalid UTF-8 sequences.
Definition utf8.c:173
FILE * out
Definition utils/frame.c:33
int error(const char *format,...)
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:981
#define ast_assert(a)
Definition utils.h:779
#define MIN(a, b)
Definition utils.h:252
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition utils.c:815
#define ast_set_flag(p, flag)
Definition utils.h:71
#define ARRAY_LEN(a)
Definition utils.h:706
Universally unique identifier support.