23 #include <pjsip_simple.h>
24 #include <pjsip/sip_transaction.h>
27 #include <pjmedia/errno.h>
29 #include "asterisk/res_pjsip.h"
31 #include "pjsip/sip_parser.h"
32 #include "res_pjsip/include/res_pjsip_private.h"
39 #include "asterisk/serializer.h"
40 #include "asterisk/threadpool.h"
48 #include "asterisk/res_pjsip_cli.h"
50 #include "asterisk/res_pjsip_presence_xml.h"
51 #include "asterisk/res_pjproject.h"
66 #define MOD_DATA_CONTACT "contact"
69 #define SERIALIZER_POOL_SIZE 8
74 static pjsip_endpoint *ast_pjsip_endpoint;
79 static pj_sockaddr host_ip_ipv4;
82 static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN];
85 static pj_sockaddr host_ip_ipv6;
88 static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN];
90 void ast_sip_add_date_header(pjsip_tx_data *tdata)
94 time_t t = time(NULL);
97 strftime(date,
sizeof(date),
"%a, %d %b %Y %T GMT", &tm);
99 ast_sip_add_header(tdata,
"Date", date);
102 static int register_service(
void *data)
104 pjsip_module **module = data;
105 if (!ast_pjsip_endpoint) {
106 ast_log(LOG_ERROR,
"There is no PJSIP endpoint. Unable to register services\n");
109 if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
110 ast_log(LOG_ERROR,
"Unable to register module %.*s\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
113 ast_debug(1,
"Registered SIP service %.*s (%p)\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
117 int ast_sip_register_service(pjsip_module *module)
122 static int unregister_service(
void *data)
124 pjsip_module **module = data;
125 if (!ast_pjsip_endpoint) {
128 pjsip_endpt_unregister_module(ast_pjsip_endpoint, *module);
129 ast_debug(1,
"Unregistered SIP service %.*s\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
133 void ast_sip_unregister_service(pjsip_module *module)
142 if (registered_authenticator) {
143 ast_log(LOG_WARNING,
"Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
146 registered_authenticator = auth;
147 ast_debug(1,
"Registered SIP authenticator module %p\n", auth);
154 if (registered_authenticator != auth) {
155 ast_log(LOG_WARNING,
"Trying to unregister authenticator %p but authenticator %p registered\n",
156 auth, registered_authenticator);
159 registered_authenticator = NULL;
160 ast_debug(1,
"Unregistered SIP authenticator %p\n", auth);
163 int ast_sip_requires_authentication(
struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
166 && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
167 ast_debug(3,
"Skipping OPTIONS authentication due to endpoint configuration\n");
171 if (!registered_authenticator) {
172 ast_log(LOG_WARNING,
"No SIP authenticator registered. Assuming authentication is not required\n");
179 enum ast_sip_check_auth_result ast_sip_check_authentication(
struct ast_sip_endpoint *endpoint,
180 pjsip_rx_data *rdata, pjsip_tx_data *tdata)
182 if (!registered_authenticator) {
183 ast_log(LOG_WARNING,
"No SIP authenticator registered. Assuming authentication is successful\n");
184 return AST_SIP_AUTHENTICATION_SUCCESS;
193 if (registered_outbound_authenticator) {
194 ast_log(LOG_WARNING,
"Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
197 registered_outbound_authenticator = auth;
198 ast_debug(1,
"Registered SIP outbound authenticator module %p\n", auth);
205 if (registered_outbound_authenticator != auth) {
206 ast_log(LOG_WARNING,
"Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
207 auth, registered_outbound_authenticator);
210 registered_outbound_authenticator = NULL;
211 ast_debug(1,
"Unregistered SIP outbound authenticator %p\n", auth);
214 int ast_sip_create_request_with_auth(
const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge,
215 pjsip_tx_data *old_request, pjsip_tx_data **new_request)
217 if (!registered_outbound_authenticator) {
218 ast_log(LOG_WARNING,
"No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
226 unsigned int priority;
236 char *prev, *current, *identifier_order;
240 id_list_item =
ast_calloc(1,
sizeof(*id_list_item));
242 ast_log(LOG_ERROR,
"Unable to add endpoint identifier. Out of memory.\n");
245 id_list_item->identifier = identifier;
246 id_list_item->name = name;
248 ast_debug(1,
"Register endpoint identifier %s(%p)\n", name ?:
"", identifier);
250 if (ast_strlen_zero(name)) {
257 identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
259 if (ast_strlen_zero(identifier_order)) {
260 id_list_item->priority = UINT_MAX;
262 ast_free(identifier_order);
266 id_list_item->priority = 0;
267 while ((current = strchr(current,
','))) {
268 ++id_list_item->priority;
269 if (!strncmp(prev, name, current - prev)
270 && strlen(name) == current - prev) {
278 if (!strcmp(prev, name)) {
279 ++id_list_item->priority;
281 id_list_item->priority = UINT_MAX;
289 ast_free(identifier_order);
294 if (id_list_item->priority < iter->priority) {
295 AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
299 if (!AST_RWLIST_NEXT(iter, list)) {
304 AST_RWLIST_TRAVERSE_SAFE_END;
306 ast_free(identifier_order);
312 return ast_sip_register_endpoint_identifier_with_name(identifier, NULL);
320 if (iter->identifier == identifier) {
321 AST_RWLIST_REMOVE_CURRENT(list);
323 ast_debug(1,
"Unregistered endpoint identifier %p\n", identifier);
327 AST_RWLIST_TRAVERSE_SAFE_END;
345 char *ast_sip_rdata_get_header_value(pjsip_rx_data *rdata,
const pj_str_t str)
347 pjsip_generic_string_hdr *hdr;
350 hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
355 pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
360 static int do_cli_dump_endpt(
void *v_a)
365 pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
376 e->
command =
"pjsip dump endpt [details]";
378 "Usage: pjsip dump endpt [details]\n"
379 " Dump the res_pjsip endpt internals.\n"
381 "Warning: PJPROJECT documents that the function used by this\n"
382 "CLI command may cause a crash when asking for details because\n"
383 "it tries to access all active memory pools.\n";
391 e->
command =
"pjsip dump endpt";
393 "Usage: pjsip dump endpt\n"
394 " Dump the res_pjsip endpt internals.\n";
402 || (a->argc == 4 && strcasecmp(a->argv[3],
"details"))) {
403 return CLI_SHOWUSAGE;
413 #define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
418 e->
command =
"pjsip show identifiers";
419 e->
usage =
"Usage: pjsip show identifiers\n"
420 " List all registered endpoint identifiers\n";
427 return CLI_SHOWUSAGE;
430 ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT,
"Identifier Names:");
434 ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT,
435 iter->name ? iter->name :
"name not specified");
439 #undef ENDPOINT_IDENTIFIER_FORMAT
448 e->
command =
"pjsip show settings";
449 e->
usage =
"Usage: pjsip show settings\n"
450 " Show global and system configuration options\n";
457 if (!context.output_buffer) {
458 ast_cli(a->fd,
"Could not allocate output buffer.\n");
462 if (sip_cli_print_global(&context) || sip_cli_print_system(&context)) {
463 ast_free(context.output_buffer);
464 ast_cli(a->fd,
"Error retrieving settings.\n");
469 ast_free(context.output_buffer);
474 AST_CLI_DEFINE(cli_dump_endpt,
"Dump the res_pjsip endpt internals"),
475 AST_CLI_DEFINE(cli_show_settings,
"Show global and system configuration options"),
476 AST_CLI_DEFINE(cli_show_endpoint_identifiers,
"List registered endpoint identifiers")
494 AST_RWLIST_REMOVE_CURRENT(next);
498 AST_RWLIST_TRAVERSE_SAFE_END;
520 pjsip_endpoint *ast_sip_get_pjsip_endpoint(
void)
522 return ast_pjsip_endpoint;
525 int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri,
struct ast_sip_endpoint *endpoint,
526 pjsip_rx_data *rdata)
532 if (uri->port == rdata->pkt_info.src_port
533 && !pj_strcmp(&uri->host,
534 pj_cstr(&host_name, rdata->pkt_info.src_name))
536 && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
540 if (!strcasecmp(
"WSS", rdata->tp_info.transport->type_name)) {
542 pj_cstr(&type_name,
"ws");
544 pj_cstr(&type_name, rdata->tp_info.transport->type_name);
547 if (!pj_stricmp(&uri->transport_param, &type_name)
550 || !pj_stricmp(&uri->transport_param,
551 pj_cstr(&type_name,
"ws")))) {
564 pjsip_sip_uri *ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
566 pjsip_contact_hdr *contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
568 if (!contact || (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
572 return pjsip_uri_get_uri(contact->uri);
576 static int find_transport_state_in_use(
void *obj,
void *arg,
int flags)
586 ((details->
type == transport_state->
type) && (transport_state->
factory) &&
598 if (!(transport_states = ast_sip_get_transport_states())) {
602 return ao2_callback(transport_states, 0, find_transport_state_in_use, details);
605 int ast_sip_rewrite_uri_to_local(pjsip_sip_uri *uri, pjsip_tx_data *tdata) {
609 pjsip_sip_uri *tmp_uri;
613 if ((tmp_uri = ast_sip_get_contact_sip_uri(tdata))) {
614 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
615 uri->port = tmp_uri->port;
616 }
else if ((dlg = pjsip_tdata_get_dlg(tdata))
617 && (tmp_uri = pjsip_uri_get_uri(dlg->local.info->uri))
618 && (PJSIP_URI_SCHEME_IS_SIP(tmp_uri) || PJSIP_URI_SCHEME_IS_SIPS(tmp_uri))) {
619 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
620 uri->port = tmp_uri->port;
623 if (ast_sip_set_request_transport_details(&details, tdata, 1)
624 || !(transport_state = ast_sip_find_transport_state_in_use(&details))
632 if (ast_sip_transport_is_local(transport_state, &addr)) {
641 if (transport->external_signaling_port) {
642 uri->port = transport->external_signaling_port;
654 if (!details || !tdata) {
659 transport_type = use_ipv6 ? tdata->tp_info.transport->key.type & ~(PJSIP_TRANSPORT_IPV6)
660 : tdata->tp_info.transport->key.type;
662 if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
663 details->
transport = tdata->tp_sel.u.transport;
664 }
else if (tdata->tp_sel.type == PJSIP_TPSELECTOR_LISTENER) {
665 details->
factory = tdata->tp_sel.u.listener;
666 }
else if (transport_type == PJSIP_TRANSPORT_UDP || transport_type == PJSIP_TRANSPORT_UDP6) {
668 details->
type = AST_TRANSPORT_UDP;
669 details->
transport = tdata->tp_info.transport;
671 if (transport_type == PJSIP_TRANSPORT_TCP) {
672 details->
type = AST_TRANSPORT_TCP;
673 }
else if (transport_type == PJSIP_TRANSPORT_TLS) {
674 details->
type = AST_TRANSPORT_TLS;
680 if ((uri = ast_sip_get_contact_sip_uri(tdata))) {
683 }
else if ((tdata->msg->type == PJSIP_REQUEST_MSG) &&
684 (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL))) {
692 details->
local_port = (details->
type == AST_TRANSPORT_TLS) ? 5061 : 5060;
699 pjsip_sip_uri *sip_uri,
char *buf,
size_t buf_len)
702 static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
703 pjsip_param *x_transport;
705 if (!ast_strlen_zero(endpoint->
transport)) {
710 x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
717 ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
722 ast_copy_pj_str(buf, &x_transport->value, buf_len);
727 int ast_sip_dlg_set_transport(
const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg,
728 pjsip_tpselector *selector)
731 pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
733 uri = pjsip_uri_get_uri(dlg->target);
738 ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
740 pjsip_dlg_set_transport(dlg, selector);
742 if (selector == &sel) {
743 ast_sip_tpselector_unref(&sel);
749 static int sip_dialog_create_from(pj_pool_t *
pool, pj_str_t *from,
const char *
user,
750 const char *domain,
const pj_str_t *target, pjsip_tpselector *selector)
752 pj_str_t tmp, local_addr;
754 pjsip_sip_uri *sip_uri;
755 pjsip_transport_type_e type;
757 char default_user[PJSIP_MAX_URL_SIZE];
759 if (ast_strlen_zero(user)) {
760 ast_sip_get_default_from_user(default_user,
sizeof(default_user));
765 pj_strdup_with_null(pool, &tmp, target);
767 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
768 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
772 sip_uri = pjsip_uri_get_uri(uri);
775 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
776 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
777 if (type == PJSIP_TRANSPORT_UNSPECIFIED
778 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
779 type = PJSIP_TRANSPORT_TLS;
781 }
else if (!sip_uri->transport_param.slen) {
782 type = PJSIP_TRANSPORT_UDP;
783 }
else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
788 if (pj_strchr(&sip_uri->host,
':')) {
789 type |= PJSIP_TRANSPORT_IPV6;
793 if (!ast_sip_get_disable_multi_domain() && strchr(user,
'@')) {
794 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
795 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
798 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
799 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
803 if (!ast_strlen_zero(domain)) {
804 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
805 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
809 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
810 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
815 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
816 &local_addr, &local_port) != PJ_SUCCESS) {
819 pj_strdup(pool, &local_addr, pj_gethostname());
820 local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
824 if (pj_strchr(&local_addr,
':')) {
825 type |= PJSIP_TRANSPORT_IPV6;
828 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
829 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
830 "<sip:%s@%s%.*s%s:%d%s%s>",
832 (type & PJSIP_TRANSPORT_IPV6) ?
"[" :
"",
833 (
int)local_addr.slen,
835 (type & PJSIP_TRANSPORT_IPV6) ?
"]" :
"",
837 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
838 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
843 int ast_sip_set_tpselector_from_transport(
const struct ast_sip_transport *transport, pjsip_tpselector *selector)
849 if (!transport_state) {
850 ast_log(LOG_ERROR,
"Unable to retrieve PJSIP transport state for '%s'\n",
856 if (transport_state->
flow) {
857 ao2_lock(transport_state);
861 selector->type = PJSIP_TPSELECTOR_TRANSPORT;
862 selector->u.transport = transport_state->
transport;
863 pjsip_transport_add_ref(selector->u.transport);
864 }
else if (transport_state->
factory) {
865 selector->type = PJSIP_TPSELECTOR_LISTENER;
866 selector->u.listener = transport_state->
factory;
867 }
else if (transport->
type == AST_TRANSPORT_WS || transport->
type == AST_TRANSPORT_WSS) {
872 }
else if (transport->
flow) {
874 #ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
875 selector->disable_connection_reuse = PJ_TRUE;
877 ast_log(LOG_WARNING,
"Connection reuse could not be disabled on transport '%s' as support is not available\n",
884 if (transport_state->
flow) {
885 ao2_unlock(transport_state);
893 int ast_sip_set_tpselector_from_transport_name(
const char *transport_name, pjsip_tpselector *selector)
897 if (ast_strlen_zero(transport_name)) {
903 ast_log(LOG_ERROR,
"Unable to retrieve PJSIP transport '%s'\n",
908 return ast_sip_set_tpselector_from_transport(transport, selector);
911 int ast_sip_set_tpselector_from_ep_or_uri(
const struct ast_sip_endpoint *endpoint,
912 pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
914 char transport_name[128];
916 if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name,
sizeof(transport_name))) {
920 return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
923 void ast_sip_tpselector_unref(pjsip_tpselector *selector)
925 if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
926 pjsip_transport_dec_ref(selector->u.transport);
930 void ast_sip_add_usereqphone(
const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
932 pjsip_sip_uri *sip_uri;
934 static const pj_str_t STR_PHONE = {
"phone", 5 };
936 if (!endpoint || !endpoint->
usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
940 sip_uri = pjsip_uri_get_uri(uri);
942 if (!pj_strlen(&sip_uri->user)) {
946 if (pj_strbuf(&sip_uri->user)[0] ==
'+') {
951 for (; i < pj_strlen(&sip_uri->user); i++) {
952 if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
957 if (i < pj_strlen(&sip_uri->user)) {
961 sip_uri->user_param = STR_PHONE;
964 pjsip_dialog *ast_sip_create_dialog_uac(
const struct ast_sip_endpoint *endpoint,
965 const char *uri,
const char *request_user)
967 char enclosed_uri[PJSIP_MAX_URL_SIZE];
968 pj_str_t local_uri = {
"sip:temp@temp", 13 }, remote_uri, target_uri;
970 pjsip_dialog *dlg = NULL;
972 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
973 static const pj_str_t HCONTACT = {
"Contact", 7 };
976 snprintf(enclosed_uri,
sizeof(enclosed_uri),
"<%s>", uri);
978 snprintf(enclosed_uri,
sizeof(enclosed_uri),
"%s", uri);
980 pj_cstr(&remote_uri, enclosed_uri);
982 pj_cstr(&target_uri, uri);
984 res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
985 if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
988 res = PJSIP_EINVALIDURI;
989 pjsip_dlg_terminate(dlg);
991 if (res != PJ_SUCCESS) {
992 if (res == PJSIP_EINVALIDURI) {
994 "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
1003 ast_sip_dlg_set_transport(endpoint, dlg, &selector);
1005 if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->
fromuser, endpoint->
fromdomain, &remote_uri, &selector)) {
1007 pjsip_dlg_terminate(dlg);
1008 ast_sip_tpselector_unref(&selector);
1012 ast_sip_tpselector_unref(&selector);
1015 pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
1016 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
1017 if (!dlg->local.info->uri) {
1019 "Could not parse URI '%s' for endpoint '%s'\n",
1022 pjsip_dlg_terminate(dlg);
1026 dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
1029 pjsip_sip_uri *sip_uri;
1031 sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
1032 pj_strdup2(dlg->pool, &sip_uri->user, endpoint->
contact_user);
1036 if (!ast_strlen_zero(request_user)) {
1037 pjsip_sip_uri *sip_uri;
1039 if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
1040 sip_uri = pjsip_uri_get_uri(dlg->target);
1041 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1043 if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
1044 sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
1045 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1050 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
1051 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.
info->uri);
1052 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->local.
info->uri);
1054 if (!ast_strlen_zero(outbound_proxy)) {
1055 pjsip_route_hdr route_set, *route;
1056 static const pj_str_t ROUTE_HNAME = {
"Route", 5 };
1059 pj_list_init(&route_set);
1061 pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
1062 if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1063 ast_log(LOG_ERROR,
"Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
1066 pjsip_dlg_terminate(dlg);
1069 pj_list_insert_nodes_before(&route_set, route);
1071 pjsip_dlg_set_route_set(dlg, &route_set);
1089 static int uas_use_sips_contact(pjsip_rx_data *rdata)
1091 pjsip_rr_hdr *record_route;
1093 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
1097 record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
1099 if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
1103 pjsip_contact_hdr *contact;
1105 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1106 ast_assert(contact != NULL);
1107 if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
1115 typedef pj_status_t (*create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata,
1116 const pj_str_t *contact, pjsip_dialog **p_dlg);
1118 static pjsip_dialog *create_dialog_uas(
const struct ast_sip_endpoint *endpoint,
1119 pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
1123 pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
1124 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1126 pjsip_contact_hdr *contact_hdr;
1128 ast_assert(status != NULL);
1130 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1131 if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
1136 transport = rdata->tp_info.transport;
1137 if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
1138 transport = selector.u.transport;
1140 type = transport->key.type;
1142 contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
1143 contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
1144 "<%s:%s%s%s%.*s%s:%d%s%s>",
1145 uas_use_sips_contact(rdata) ?
"sips" :
"sip",
1146 (type & PJSIP_TRANSPORT_IPV6) ?
"[" :
"",
1149 (
int)transport->local_name.host.slen,
1150 transport->local_name.host.ptr,
1151 (type & PJSIP_TRANSPORT_IPV6) ?
"]" :
"",
1152 transport->local_name.port,
1153 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
1154 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
1156 *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
1157 if (*status != PJ_SUCCESS) {
1158 char err[PJ_ERR_MSG_SIZE];
1160 pj_strerror(*status, err,
sizeof(err));
1161 ast_log(LOG_ERROR,
"Could not create dialog with endpoint %s. %s\n",
1163 ast_sip_tpselector_unref(&selector);
1168 pjsip_dlg_set_transport(dlg, &selector);
1171 ast_sip_tpselector_unref(&selector);
1176 pjsip_dialog *ast_sip_create_dialog_uas(
const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
1178 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1181 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1183 pjsip_dlg_dec_lock(dlg);
1188 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1192 pjsip_dialog *ast_sip_create_dialog_uas_locked(
const struct ast_sip_endpoint *endpoint,
1193 pjsip_rx_data *rdata, pj_status_t *status)
1195 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1196 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1205 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1207 pjsip_dlg_inc_lock(dlg);
1214 int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata,
char *packet,
const char *src_name,
int src_port,
1215 char *transport_type,
const char *local_name,
int local_port,
const char *contact)
1223 pj_list_init(&rdata->msg_info.parse_err);
1225 rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
1226 if (!rdata->tp_info.transport) {
1230 ast_copy_string(rdata->pkt_info.packet, packet,
sizeof(rdata->pkt_info.packet));
1231 ast_copy_string(rdata->pkt_info.src_name, src_name,
sizeof(rdata->pkt_info.src_name));
1232 rdata->pkt_info.src_port = src_port;
1233 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
1234 pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
1236 pjsip_parse_rdata(packet, strlen(packet), rdata);
1237 if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
1241 if (!ast_strlen_zero(contact)) {
1242 pjsip_contact_hdr *contact_hdr;
1244 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1246 contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (
char *)contact,
1247 strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
1248 if (!contact_hdr->uri) {
1249 ast_log(LOG_WARNING,
"Unable to parse contact URI from '%s'.\n", contact);
1255 pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
1256 rdata->msg_info.via->rport_param = -1;
1258 rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
1259 rdata->tp_info.transport->type_name = transport_type;
1260 pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
1261 rdata->tp_info.transport->local_name.port = local_port;
1266 int ast_sip_create_rdata(pjsip_rx_data *rdata,
char *packet,
const char *src_name,
int src_port,
1267 char *transport_type,
const char *local_name,
int local_port)
1269 return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
1270 local_name, local_port, NULL);
1274 static const pjsip_method info_method = {PJSIP_OTHER_METHOD, {
"INFO", 4} };
1275 static const pjsip_method message_method = {PJSIP_OTHER_METHOD, {
"MESSAGE", 7} };
1276 static const pjsip_method refer_method = {PJSIP_OTHER_METHOD, {
"REFER", 5} };
1280 const pjsip_method *pmethod;
1282 {
"INVITE", &pjsip_invite_method },
1283 {
"CANCEL", &pjsip_cancel_method },
1284 {
"ACK", &pjsip_ack_method },
1285 {
"BYE", &pjsip_bye_method },
1286 {
"REGISTER", &pjsip_register_method },
1287 {
"OPTIONS", &pjsip_options_method },
1288 {
"SUBSCRIBE", &pjsip_subscribe_method },
1289 {
"NOTIFY", &pjsip_notify_method },
1290 {
"PUBLISH", &pjsip_publish_method },
1291 {
"INFO", &info_method },
1292 {
"MESSAGE", &message_method },
1293 {
"REFER", &refer_method },
1296 static const pjsip_method *get_pjsip_method(
const char *method)
1299 for (i = 0; i < ARRAY_LEN(methods); ++i) {
1300 if (!strcmp(method, methods[i].method)) {
1301 return methods[i].pmethod;
1307 static int create_in_dialog_request(
const pjsip_method *method,
struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
1309 if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
1310 ast_log(LOG_WARNING,
"Unable to create in-dialog request.\n");
1317 static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata);
1318 static pjsip_module supplement_module = {
1319 .name = {
"Out of dialog supplement hook", 29 },
1321 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 1,
1322 .on_rx_request = supplement_on_rx_request,
1325 static int create_out_of_dialog_request(
const pjsip_method *method,
struct ast_sip_endpoint *endpoint,
1326 const char *uri,
struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
1329 pj_str_t remote_uri;
1332 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1334 const char *fromuser;
1336 if (ast_strlen_zero(uri)) {
1337 if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
1338 ast_log(LOG_ERROR,
"An endpoint and/or uri must be specified\n");
1343 contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->
aors);
1345 if (!contact || ast_strlen_zero(contact->uri)) {
1346 ast_log(LOG_WARNING,
"Unable to retrieve contact for endpoint %s\n",
1351 pj_cstr(&remote_uri, contact->uri);
1353 pj_cstr(&remote_uri, uri);
1356 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
"Outbound request", 256, 256);
1359 ast_log(LOG_ERROR,
"Unable to create PJLIB memory pool\n");
1363 sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
1364 if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
1365 ast_log(LOG_ERROR,
"Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
1366 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
1368 pj_strbuf(&remote_uri));
1369 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1373 ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
1376 if (sip_dialog_create_from(pool, &from, fromuser,
1377 endpoint ? endpoint->
fromdomain : NULL, &remote_uri, &selector)) {
1378 ast_log(LOG_ERROR,
"Unable to create From header for %.*s request to endpoint %s\n",
1379 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
1381 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1382 ast_sip_tpselector_unref(&selector);
1386 if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
1387 &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
1388 ast_log(LOG_ERROR,
"Unable to create outbound %.*s request to endpoint %s\n",
1389 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
1391 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1392 ast_sip_tpselector_unref(&selector);
1396 pjsip_tx_data_set_transport(*tdata, &selector);
1398 ast_sip_tpselector_unref(&selector);
1400 if (endpoint && !ast_strlen_zero(endpoint->
contact_user)){
1401 pjsip_contact_hdr *contact_hdr;
1402 pjsip_sip_uri *contact_uri;
1403 static const pj_str_t HCONTACT = {
"Contact", 7 };
1404 static const pj_str_t HCONTACTSHORT = {
"m", 1 };
1406 contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
1408 contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
1409 pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->
contact_user);
1414 ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
1418 ast_sip_set_outbound_proxy((*tdata), endpoint->
outbound_proxy)) {
1419 ast_log(LOG_ERROR,
"Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
1422 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1426 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT,
ao2_bump(contact));
1431 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1435 int ast_sip_create_request(
const char *method,
struct pjsip_dialog *dlg,
1439 const pjsip_method *pmethod = get_pjsip_method(method);
1442 ast_log(LOG_WARNING,
"Unknown method '%s'. Cannot send request\n", method);
1447 return create_in_dialog_request(pmethod, dlg, tdata);
1449 ast_assert(endpoint != NULL);
1450 return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
1462 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
supplements, iter, next) {
1464 AST_RWLIST_INSERT_BEFORE_CURRENT(supplement, next);
1469 AST_RWLIST_TRAVERSE_SAFE_END;
1472 AST_RWLIST_INSERT_TAIL(&
supplements, supplement, next);
1481 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
supplements, iter, next) {
1482 if (supplement == iter) {
1483 AST_RWLIST_REMOVE_CURRENT(next);
1487 AST_RWLIST_TRAVERSE_SAFE_END;
1490 static int send_in_dialog_request(pjsip_tx_data *tdata,
struct pjsip_dialog *dlg)
1492 if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
1493 ast_log(LOG_WARNING,
"Unable to send in-dialog request.\n");
1499 static pj_bool_t does_method_match(
const pj_str_t *message_method,
const char *supplement_method)
1503 if (ast_strlen_zero(supplement_method)) {
1507 pj_cstr(&method, supplement_method);
1509 return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
1512 #define TIMER_INACTIVE 0
1513 #define TIMEOUT_TIMER2 5
1527 static void send_request_data_destroy(
void *obj)
1539 req_data = ao2_alloc_options(
sizeof(*req_data), send_request_data_destroy,
1573 static void endpt_send_request_cb(
void *token, pjsip_event *e)
1584 if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
1585 ast_debug(2,
"%p: PJSIP tsx timer expired\n", req_wrapper);
1589 ast_debug(3,
"%p: Timeout already handled\n", req_wrapper);
1594 ast_debug(2,
"%p: PJSIP tsx response received\n", req_wrapper);
1597 ao2_lock(req_wrapper);
1605 int timers_cancelled = 0;
1607 ast_debug(3,
"%p: Cancelling timer\n", req_wrapper);
1609 timers_cancelled = pj_timer_heap_cancel_if_active(
1610 pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
1612 if (timers_cancelled > 0) {
1616 ast_debug(3,
"%p: Timer cancelled\n", req_wrapper);
1624 ast_debug(3,
"%p: Timer already expired\n", req_wrapper);
1630 ao2_unlock(req_wrapper);
1635 if (!cb_called && req_wrapper->
callback) {
1637 ast_debug(2,
"%p: Callbacks executed\n", req_wrapper);
1648 static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *
entry)
1653 ast_debug(2,
"%p: Internal tsx timer expired after %d msec\n",
1654 req_wrapper, req_wrapper->
timeout);
1656 ao2_lock(req_wrapper);
1661 if (entry->id != TIMEOUT_TIMER2) {
1662 ao2_unlock(req_wrapper);
1663 ast_debug(3,
"%p: Timeout already handled\n", req_wrapper);
1667 entry->id = TIMER_INACTIVE;
1669 ast_debug(3,
"%p: Timer handled here\n", req_wrapper);
1673 ao2_unlock(req_wrapper);
1675 if (!cb_called && req_wrapper->
callback) {
1678 PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->
tdata);
1679 event.body.tsx_state.type = PJSIP_EVENT_TIMER;
1682 ast_debug(2,
"%p: Callbacks executed\n", req_wrapper);
1688 static void send_request_wrapper_destructor(
void *obj)
1692 pjsip_tx_data_dec_ref(req_wrapper->
tdata);
1693 ast_debug(2,
"%p: wrapper destroyed\n", req_wrapper);
1697 pjsip_tx_data *tdata, pj_int32_t
timeout,
void *token, pjsip_endpt_send_callback cb)
1700 pj_status_t ret_val;
1701 pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
1705 pjsip_tx_data_dec_ref(tdata);
1710 req_wrapper = ao2_alloc(
sizeof(*req_wrapper), send_request_wrapper_destructor);
1712 pjsip_tx_data_dec_ref(tdata);
1716 ast_debug(2,
"%p: Wrapper created\n", req_wrapper);
1724 pjsip_tx_data_add_ref(tdata);
1727 pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
1729 req_wrapper->
timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
1731 ast_debug(2,
"%p: Set timer to %d msec\n", req_wrapper, timeout);
1733 pj_timer_entry_init(req_wrapper->
timeout_timer, TIMEOUT_TIMER2,
1734 req_wrapper, send_request_timer_callback);
1740 ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
1742 if (ret_val != PJ_SUCCESS) {
1744 "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
1745 (
int) pj_strlen(&tdata->msg->line.req.method.name),
1746 pj_strbuf(&tdata->msg->line.req.method.name),
1748 ao2_t_ref(req_wrapper, -2,
"Drop timer and routine ref");
1749 pjsip_tx_data_dec_ref(tdata);
1758 ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper, endpt_send_request_cb);
1759 if (ret_val != PJ_SUCCESS) {
1760 char errmsg[PJ_ERR_MSG_SIZE];
1768 pj_strerror(ret_val, errmsg,
sizeof(errmsg));
1769 ast_log(LOG_ERROR,
"Error %d '%s' sending %.*s request to endpoint %s\n",
1770 (
int) ret_val, errmsg, (
int) pj_strlen(&tdata->msg->line.req.method.name),
1771 pj_strbuf(&tdata->msg->line.req.method.name),
1775 int timers_cancelled;
1777 ao2_lock(req_wrapper);
1778 timers_cancelled = pj_timer_heap_cancel_if_active(
1779 pjsip_endpt_get_timer_heap(endpt),
1781 if (timers_cancelled > 0) {
1792 ret_val = PJ_SUCCESS;
1801 ao2_unlock(req_wrapper);
1808 ret_val = PJ_SUCCESS;
1816 int ast_sip_failover_request(pjsip_tx_data *tdata)
1820 if (!tdata || !tdata->dest_info.addr.count
1821 || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
1827 ++tdata->dest_info.cur_addr;
1829 via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1830 via->branch_param.slen = 0;
1832 pjsip_tx_data_invalidate_msg(tdata);
1837 static void send_request_cb(
void *token, pjsip_event *e);
1839 static int check_request_status(
struct send_request_data *req_data, pjsip_event *e)
1842 pjsip_transaction *tsx;
1843 pjsip_tx_data *tdata;
1850 tsx = e->body.tsx_state.tsx;
1852 switch (tsx->status_code) {
1858 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
1862 if ((res = ast_sip_failover_request(tsx->last_tx))) {
1863 tdata = tsx->last_tx;
1868 pjsip_tx_data_add_ref(tdata);
1874 res = endpt_send_request(endpoint, tdata, -1,
1875 req_data, send_request_cb) == PJ_SUCCESS;
1882 static void send_request_cb(
void *token, pjsip_event *e)
1885 pjsip_rx_data *challenge;
1888 if (e->type == PJSIP_EVENT_TSX_STATE) {
1889 switch(e->body.tsx_state.type) {
1890 case PJSIP_EVENT_TRANSPORT_ERROR:
1891 case PJSIP_EVENT_TIMER:
1897 if (check_request_status(req_data, e)) {
1901 case PJSIP_EVENT_RX_MSG:
1902 challenge = e->body.tsx_state.src.rdata;
1911 && does_method_match(&challenge->msg_info.cseq->method.name,
1918 if (check_request_status(req_data, e)) {
1927 ast_log(LOG_ERROR,
"Unexpected PJSIP event %u\n", e->body.tsx_state.type);
1938 int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata,
1940 void (*callback)(
void *token, pjsip_event *e))
1946 req_data = send_request_data_alloc(endpoint, token, callback);
1948 pjsip_tx_data_dec_ref(tdata);
1953 ast_sip_message_apply_transport(endpoint->
transport, tdata);
1956 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
1961 && does_method_match(&tdata->msg->line.req.method.name, supplement->
method)) {
1967 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
1968 ao2_cleanup(contact);
1970 if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
1972 ao2_cleanup(req_data);
1979 int ast_sip_send_request(pjsip_tx_data *tdata,
struct pjsip_dialog *dlg,
1981 void (*callback)(
void *token, pjsip_event *e))
1983 ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
1986 return send_in_dialog_request(tdata, dlg);
1988 return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
1992 int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata,
const char *proxy)
1994 pjsip_route_hdr *route;
1995 static const pj_str_t ROUTE_HNAME = {
"Route", 5 };
1998 pj_strdup2_with_null(tdata->pool, &tmp, proxy);
1999 if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
2003 pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
2008 int ast_sip_add_header(pjsip_tx_data *tdata,
const char *name,
const char *value)
2012 pjsip_generic_string_hdr *hdr;
2014 pj_cstr(&hdr_name, name);
2015 pj_cstr(&hdr_value, value);
2017 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2019 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2023 pjsip_generic_string_hdr *ast_sip_add_header2(pjsip_tx_data *tdata,
2024 const char *name,
const char *value)
2028 pjsip_generic_string_hdr *hdr;
2030 pj_cstr(&hdr_name, name);
2031 pj_cstr(&hdr_value, value);
2033 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2035 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2039 static pjsip_msg_body *ast_body_to_pjsip_body(pj_pool_t *pool,
const struct ast_sip_body *body)
2045 pj_cstr(&type, body->
type);
2046 pj_cstr(&subtype, body->
subtype);
2049 return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
2052 int ast_sip_add_body(pjsip_tx_data *tdata,
const struct ast_sip_body *body)
2054 pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
2055 tdata->msg->body = pjsip_body;
2059 int ast_sip_add_body_multipart(pjsip_tx_data *tdata,
const struct ast_sip_body *bodies[],
int num_bodies)
2063 pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
2065 for (i = 0; i < num_bodies; ++i) {
2066 pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
2067 part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
2068 pjsip_multipart_add_part(tdata->pool, body, part);
2071 tdata->msg->body = body;
2075 int ast_sip_append_body(pjsip_tx_data *tdata,
const char *body_text)
2077 size_t combined_size = strlen(body_text) + tdata->msg->body->len;
2078 struct ast_str *body_buffer = ast_str_alloca(combined_size);
2080 ast_str_set(&body_buffer, 0,
"%.*s%s", (
int) tdata->msg->body->len, (
char *) tdata->msg->body->data, body_text);
2082 tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
2083 pj_memcpy(tdata->msg->body->data,
ast_str_buffer(body_buffer), combined_size);
2084 tdata->msg->body->len = combined_size;
2091 return ast_threadpool_serializer_group(name, sip_threadpool, shutdown_group);
2102 serializer = ast_serializer_pool_get(sip_serializer_pool);
2113 int (*task)(
void *);
2117 static int sync_task(
void *data)
2122 std->fail = std->task(std->task_data);
2129 ast_mutex_lock(&std->lock);
2131 ast_cond_signal(&std->cond);
2133 ast_mutex_unlock(&std->lock);
2142 memset(&std, 0,
sizeof(std));
2143 ast_mutex_init(&std.lock);
2144 ast_cond_init(&std.cond, NULL);
2145 std.task = sip_task;
2146 std.task_data = task_data;
2149 ast_mutex_destroy(&std.lock);
2150 ast_cond_destroy(&std.cond);
2154 ast_mutex_lock(&std.lock);
2155 while (!std.complete) {
2156 ast_cond_wait(&std.cond, &std.lock);
2158 ast_mutex_unlock(&std.lock);
2160 ast_mutex_destroy(&std.lock);
2161 ast_cond_destroy(&std.cond);
2168 return sip_task(task_data);
2171 return ast_sip_push_task_wait(serializer, sip_task, task_data);
2183 serializer = ast_serializer_pool_get(sip_serializer_pool);
2195 return sip_task(task_data);
2198 return ast_sip_push_task_wait(serializer, sip_task, task_data);
2201 void ast_copy_pj_str(
char *dest,
const pj_str_t *src,
size_t size)
2203 size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2204 memcpy(dest, pj_strbuf(src), chars_to_copy);
2205 dest[chars_to_copy] =
'\0';
2208 int ast_copy_pj_str2(
char **dest,
const pj_str_t *src)
2210 int res =
ast_asprintf(dest,
"%.*s", (
int)pj_strlen(src), pj_strbuf(src));
2219 int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
2222 if (a != NULL && b != NULL) {
2223 rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2228 int ast_sip_is_media_type_in(pjsip_media_type *a, ...)
2231 pjsip_media_type *b = NULL;
2234 ast_assert(a != NULL);
2237 while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2238 if (pjsip_media_type_cmp(a, b, 0) == 0) {
2248 int ast_sip_is_content_type(pjsip_media_type *content_type,
char *type,
char *subtype)
2250 pjsip_media_type compare;
2252 if (!content_type) {
2256 pjsip_media_type_init2(&compare, type, subtype);
2258 return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2261 pj_caching_pool caching_pool;
2262 pj_pool_t *memory_pool;
2264 static int monitor_continue;
2266 static void *monitor_thread_exec(
void *endpt)
2268 while (monitor_continue) {
2269 const pj_time_val delay = {0, 10};
2270 pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2275 static void stop_monitor_thread(
void)
2277 monitor_continue = 0;
2278 pj_thread_join(monitor_thread);
2283 #define SIP_SERVANT_ID 0x5E2F1D
2285 static void sip_thread_start(
void)
2287 pj_thread_desc *desc;
2289 uint32_t *servant_id;
2293 ast_log(LOG_ERROR,
"Could not set SIP servant ID in thread-local storage.\n");
2296 *servant_id = SIP_SERVANT_ID;
2300 ast_log(LOG_ERROR,
"Could not get thread desc from thread-local storage. Expect awful things to occur\n");
2303 pj_bzero(*desc,
sizeof(*desc));
2305 if (pj_thread_register(
"Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
2306 ast_log(LOG_ERROR,
"Couldn't register thread with PJLIB.\n");
2312 uint32_t *servant_id;
2314 if (monitor_thread &&
2315 pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
2324 return *servant_id == SIP_SERVANT_ID;
2327 void *ast_sip_dict_get(
void *ht,
const char *key)
2329 unsigned int hval = 0;
2335 return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2338 void *ast_sip_dict_set(pj_pool_t* pool,
void *ht,
2339 const char *key,
void *
val)
2342 ht = pj_hash_create(pool, 11);
2345 pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2350 static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
2354 if (pjsip_rdata_get_dlg(rdata)) {
2361 && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->
method)) {
2364 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2366 ao2_cleanup(endpoint);
2374 static void supplement_outgoing_response(pjsip_tx_data *tdata,
struct ast_sip_endpoint *sip_endpoint)
2377 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
2378 struct ast_sip_contact *contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2381 ast_sip_message_apply_transport(sip_endpoint->
transport, tdata);
2392 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2393 ao2_cleanup(contact);
2396 int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata,
struct ast_sip_endpoint *sip_endpoint)
2400 supplement_outgoing_response(tdata, sip_endpoint);
2401 status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2402 if (status != PJ_SUCCESS) {
2403 pjsip_tx_data_dec_ref(tdata);
2406 return status == PJ_SUCCESS ? 0 : -1;
2409 static void pool_destroy_callback(
void *arg)
2411 pj_pool_t *pool = (pj_pool_t *)arg;
2412 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2415 static void clean_contact_from_tdata(pjsip_tx_data *tdata)
2418 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2419 ao2_cleanup(contact);
2420 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2421 pjsip_tx_data_dec_ref(tdata);
2424 int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata,
struct ast_sip_endpoint *sip_endpoint)
2426 pjsip_transaction *tsx;
2427 pj_grp_lock_t *tsx_glock;
2431 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
"stateful response", PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC);
2436 clean_contact_from_tdata(tdata);
2440 if(pj_grp_lock_create_w_handler(pool, NULL, pool, &pool_destroy_callback, &tsx_glock) != PJ_SUCCESS) {
2441 clean_contact_from_tdata(tdata);
2442 pool_destroy_callback((
void *) pool);
2447 pj_grp_lock_add_ref(tsx_glock);
2449 if (pjsip_tsx_create_uas2(NULL, rdata, tsx_glock, &tsx) != PJ_SUCCESS) {
2450 clean_contact_from_tdata(tdata);
2451 pj_grp_lock_dec_ref(tsx_glock);
2455 pjsip_tsx_recv_msg(tsx, rdata);
2456 supplement_outgoing_response(tdata, sip_endpoint);
2458 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2459 pj_grp_lock_dec_ref(tsx_glock);
2460 pjsip_tx_data_dec_ref(tdata);
2464 pj_grp_lock_dec_ref(tsx_glock);
2468 int ast_sip_create_response(
const pjsip_rx_data *rdata,
int st_code,
2471 int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2474 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT,
ao2_bump(contact));
2480 int ast_sip_get_host_ip(
int af, pj_sockaddr *addr)
2482 if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2483 pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2485 }
else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2486 pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2493 const char *ast_sip_get_host_ip_string(
int af)
2495 if (af == pj_AF_INET()) {
2496 return host_ip_ipv4_string;
2497 }
else if (af == pj_AF_INET6()) {
2498 return host_ip_ipv6_string;
2504 int ast_sip_dtmf_to_str(
const enum ast_sip_dtmf_mode dtmf,
2505 char *buf,
size_t buf_len)
2508 case AST_SIP_DTMF_NONE:
2511 case AST_SIP_DTMF_RFC_4733:
2514 case AST_SIP_DTMF_INBAND:
2517 case AST_SIP_DTMF_INFO:
2520 case AST_SIP_DTMF_AUTO:
2523 case AST_SIP_DTMF_AUTO_INFO:
2533 int ast_sip_str_to_dtmf(
const char * dtmf_mode)
2537 if (!strcasecmp(dtmf_mode,
"info")) {
2538 result = AST_SIP_DTMF_INFO;
2539 }
else if (!strcasecmp(dtmf_mode,
"rfc4733")) {
2540 result = AST_SIP_DTMF_RFC_4733;
2541 }
else if (!strcasecmp(dtmf_mode,
"inband")) {
2542 result = AST_SIP_DTMF_INBAND;
2543 }
else if (!strcasecmp(dtmf_mode,
"none")) {
2544 result = AST_SIP_DTMF_NONE;
2545 }
else if (!strcasecmp(dtmf_mode,
"auto")) {
2546 result = AST_SIP_DTMF_AUTO;
2547 }
else if (!strcasecmp(dtmf_mode,
"auto_info")) {
2548 result = AST_SIP_DTMF_AUTO_INFO;
2554 const char *ast_sip_call_codec_pref_to_str(
struct ast_flags pref)
2558 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)) {
2560 }
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)) {
2561 value =
"local_merge";
2562 }
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)) {
2563 value =
"local_first";
2564 }
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)) {
2566 }
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)) {
2567 value =
"remote_merge";
2568 }
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)) {
2569 value =
"remote_first";
2577 int ast_sip_call_codec_str_to_pref(
struct ast_flags *pref,
const char *pref_str,
int is_outgoing)
2581 if (strcmp(pref_str,
"local") == 0) {
2582 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_LOCAL | AST_SIP_CALL_CODEC_PREF_INTERSECT | AST_SIP_CALL_CODEC_PREF_ALL);
2583 }
else if (is_outgoing && strcmp(pref_str,
"local_merge") == 0) {
2584 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_LOCAL | AST_SIP_CALL_CODEC_PREF_UNION | AST_SIP_CALL_CODEC_PREF_ALL);
2585 }
else if (strcmp(pref_str,
"local_first") == 0) {
2586 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_LOCAL | AST_SIP_CALL_CODEC_PREF_INTERSECT | AST_SIP_CALL_CODEC_PREF_FIRST);
2587 }
else if (strcmp(pref_str,
"remote") == 0) {
2588 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_REMOTE | AST_SIP_CALL_CODEC_PREF_INTERSECT | AST_SIP_CALL_CODEC_PREF_ALL);
2589 }
else if (is_outgoing && strcmp(pref_str,
"remote_merge") == 0) {
2590 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_REMOTE | AST_SIP_CALL_CODEC_PREF_UNION | AST_SIP_CALL_CODEC_PREF_ALL);
2591 }
else if (strcmp(pref_str,
"remote_first") == 0) {
2592 ast_set_flag(pref, AST_SIP_CALL_CODEC_PREF_REMOTE | AST_SIP_CALL_CODEC_PREF_UNION | AST_SIP_CALL_CODEC_PREF_FIRST);
2606 static void set_id_from_hdr(pjsip_fromto_hdr *hdr,
struct ast_party_id *
id)
2611 pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
2615 ast_copy_pj_str(cid_num, ast_sip_pjsip_uri_get_username(hdr->uri),
sizeof(cid_num));
2617 semi = strchr(cid_num,
';');
2639 id_name_addr->display.ptr, id_name_addr->display.slen);
2642 ast_log(LOG_WARNING,
"CallerID Name '" PJSTR_PRINTF_SPEC
2643 "' for number '%s' has invalid UTF-8 characters which "
2645 PJSTR_PRINTF_VAR(id_name_addr->display), cid_num);
2650 if (!ast_strlen_zero(cid_name)) {
2655 if (!ast_strlen_zero(cid_num)) {
2656 id->number.valid = 1;
2673 static pjsip_fromto_hdr *get_id_header(pjsip_rx_data *rdata,
const pj_str_t *header_name)
2675 static const pj_str_t from = {
"From", 4 };
2676 pj_str_t header_content;
2677 pjsip_fromto_hdr *parsed_hdr;
2678 pjsip_generic_string_hdr *ident = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2686 pj_strdup_with_null(rdata->tp_info.pool, &header_content, &ident->hvalue);
2688 parsed_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from, header_content.ptr,
2689 pj_strlen(&header_content), &parsed_len);
2710 static int set_id_from_pai(pjsip_rx_data *rdata,
struct ast_party_id *
id)
2712 static const pj_str_t pai_str = {
"P-Asserted-Identity", 19 };
2713 static const pj_str_t privacy_str = {
"Privacy", 7 };
2714 pjsip_fromto_hdr *pai_hdr = get_id_header(rdata, &pai_str);
2715 pjsip_generic_string_hdr *privacy;
2721 set_id_from_hdr(pai_hdr,
id);
2727 privacy = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &privacy_str, NULL);
2728 if (!privacy || !pj_stricmp2(&privacy->hvalue,
"none")) {
2729 id->number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2730 id->name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2732 id->number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2733 id->name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2751 static int set_id_from_rpid(pjsip_rx_data *rdata,
struct ast_party_id *
id)
2753 static const pj_str_t rpid_str = {
"Remote-Party-ID", 15 };
2754 static const pj_str_t privacy_str = {
"privacy", 7 };
2755 static const pj_str_t screen_str = {
"screen", 6 };
2756 pjsip_fromto_hdr *rpid_hdr = get_id_header(rdata, &rpid_str);
2757 pjsip_param *screen;
2758 pjsip_param *privacy;
2764 set_id_from_hdr(rpid_hdr,
id);
2770 privacy = pjsip_param_find(&rpid_hdr->other_param, &privacy_str);
2771 screen = pjsip_param_find(&rpid_hdr->other_param, &screen_str);
2772 if (privacy && !pj_stricmp2(&privacy->value,
"full")) {
2773 id->number.presentation = AST_PRES_RESTRICTED;
2774 id->name.presentation = AST_PRES_RESTRICTED;
2776 id->number.presentation = AST_PRES_ALLOWED;
2777 id->name.presentation = AST_PRES_ALLOWED;
2779 if (screen && !pj_stricmp2(&screen->value,
"yes")) {
2780 id->number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2781 id->name.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2783 id->number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2784 id->name.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2803 static int set_id_from_from(
struct pjsip_rx_data *rdata,
struct ast_party_id *
id)
2805 pjsip_fromto_hdr *from = pjsip_msg_find_hdr(rdata->msg_info.msg,
2806 PJSIP_H_FROM, rdata->msg_info.msg->hdr.next);
2813 set_id_from_hdr(from,
id);
2822 int ast_sip_set_id_connected_line(
struct pjsip_rx_data *rdata,
struct ast_party_id *
id)
2824 return !set_id_from_pai(rdata,
id) || !set_id_from_rpid(rdata,
id) ? 0 : -1;
2827 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)
2829 if (trust_inbound && (!set_id_from_pai(rdata,
id) || !set_id_from_rpid(rdata,
id))) {
2838 set_id_from_from(rdata,
id);
2850 void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr,
const struct ast_party_id *
id)
2852 pjsip_name_addr *id_name_addr;
2853 pjsip_sip_uri *id_uri;
2855 id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2856 id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2859 if (!ast_strlen_zero(id->
name.
str)) {
2860 int name_buf_len = strlen(id->
name.
str) * 2 + 1;
2864 pj_strdup2(pool, &id_name_addr->display, name_buf);
2866 pj_strdup2(pool, &id_name_addr->display, NULL);
2871 pj_strdup2(pool, &id_uri->user, id->
number.
str);
2890 static int insert_user_in_contact_uri(
const char *to,
const char *
endpoint_name,
const char *aors,
2891 const char *user,
char **uri)
2895 pjsip_name_addr *name_addr;
2896 pjsip_sip_uri *sip_uri;
2899 contact = ast_sip_location_retrieve_contact_from_aor_list(aors);
2901 ast_log(LOG_WARNING,
"Dest: '%s'. Couldn't find contact for endpoint '%s'\n",
2906 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
"uri-user-insert", 128, 128);
2908 ast_log(LOG_WARNING,
"Failed to allocate ParseUri endpoint pool.\n");
2912 name_addr = (pjsip_name_addr *) pjsip_parse_uri(pool, (
char*)contact->
uri, strlen(contact->
uri), PJSIP_PARSE_URI_AS_NAMEADDR);
2913 if (!name_addr || (!PJSIP_URI_SCHEME_IS_SIP(name_addr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(name_addr->uri))) {
2914 ast_log(LOG_WARNING,
"Failed to parse URI '%s'\n", contact->
uri);
2919 ast_debug(3,
"Dest: '%s' User: '%s' Endpoint: '%s' ContactURI: '%s'\n", to, user, endpoint_name, contact->
uri);
2921 sip_uri = pjsip_uri_get_uri(name_addr->uri);
2922 pj_strset2(&sip_uri->user, (
char*)user);
2929 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, name_addr, *uri, PJSIP_MAX_URL_SIZE);
2932 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2955 static struct ast_sip_endpoint *handle_single_token(
const char *to,
char *destination,
int get_default_outbound,
char **uri) {
2957 char *endpoint_name = NULL;
2970 char *temp_uri =
ast_malloc(strlen(destination) + strlen(
"sip:") + 1);
2974 sprintf(temp_uri,
"sip:%s", destination);
2976 if (get_default_outbound) {
2977 endpoint = ast_sip_default_outbound_endpoint();
2979 ast_debug(3,
"Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s'%s\n",
2980 to, *uri, get_default_outbound ?
" with default endpoint" :
"");
2988 endpoint_name = destination;
2989 contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->
aors);
2991 ast_log(LOG_WARNING,
"Dest: '%s'. Found endpoint '%s' but didn't find an aor/contact for it\n",
2993 ao2_cleanup(endpoint);
2999 ao2_cleanup(endpoint);
3003 ast_debug(3,
"Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",
3004 to, endpoint_name, *uri);
3034 static struct ast_sip_endpoint *handle_slash(
const char *to,
char *destination,
char **uri,
3035 char *slash,
char *atsign,
char *scheme)
3037 char *endpoint_name = NULL;
3041 char *afterslash = slash + 1;
3045 ast_debug(3,
"Dest: '%s' Dialplan format'\n", to);
3049 if (!atsign || strchr(afterslash,
'/')) {
3054 ast_log(LOG_WARNING,
3055 "Dest: '%s'. Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",
3061 endpoint_name = atsign + 1;
3062 ast_debug(3,
"Dest: '%s' User: '%s' Endpoint: '%s'\n", to, user, endpoint_name);
3070 endpoint_name = destination;
3071 ast_debug(3,
"Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);
3076 ast_log(LOG_WARNING,
"Dest: '%s'. Didn't find endpoint with name '%s'\n",
3090 ast_debug(3,
"Dest: '%s' Found endpoint '%s' and found URI '%s' after '/'\n",
3091 to, endpoint_name, *uri);
3105 rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->
aors, user, uri);
3112 ast_debug(3,
"Dest: '%s' User: '%s' Endpoint: '%s' URI: '%s'\n", to, user,
3113 endpoint_name, *uri);
3123 aor = ast_sip_location_retrieve_aor(afterslash);
3129 *uri =
ast_malloc(strlen(afterslash) + strlen(
"sip:") + 1);
3133 sprintf(*uri,
"sip:%s", afterslash);
3134 ast_debug(3,
"Dest: '%s' Found endpoint '%s' but didn't find aor after '/' so using URI '%s'\n",
3135 to, endpoint_name, *uri);
3142 ast_debug(3,
"Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\n",
3145 contact = ast_sip_location_retrieve_first_aor_contact(aor);
3147 ast_log(LOG_WARNING,
"Dest: '%s'. Found endpoint '%s' but didn't find contact for aor '%s'\n",
3154 ao2_cleanup(contact);
3160 ast_debug(3,
"Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",
3166 ao2_cleanup(endpoint);
3191 static struct ast_sip_endpoint *handle_atsign(
const char *to,
char *destination,
char **uri,
3192 char *slash,
char *atsign,
char *scheme,
int get_default_outbound)
3194 char *endpoint_name = NULL;
3197 char *afterat = atsign + 1;
3200 endpoint_name = destination;
3203 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(endpoint_name);
3210 *uri =
ast_malloc(strlen(to) + strlen(
"sip:") + 1);
3214 sprintf(*uri,
"sip:%s", to);
3215 if (get_default_outbound) {
3216 endpoint = ast_sip_default_outbound_endpoint();
3218 ast_debug(3,
"Dest: '%s' Didn't find endpoint before the '@' so using URI '%s'%s\n",
3219 to, *uri, get_default_outbound ?
" with default endpoint" :
"");
3226 contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->
aors);
3228 ast_log(LOG_WARNING,
"Dest: '%s'. Found endpoint '%s' but didn't find contact\n",
3234 ao2_cleanup(contact);
3238 ast_debug(3,
"Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",
3239 to, endpoint_name, *uri, afterat);
3244 ao2_cleanup(endpoint);
3249 struct ast_sip_endpoint *ast_sip_get_endpoint(
const char *to,
int get_default_outbound,
char **uri)
3253 char *atsign = NULL;
3254 char *scheme = NULL;
3259 slash = strchr(destination,
'/');
3260 atsign = strchr(destination,
'@');
3261 scheme =
S_OR(strstr(destination,
"sip:"), strstr(destination,
"sips:"));
3263 if (!slash && !atsign && !scheme) {
3269 return handle_single_token(to, destination, get_default_outbound, uri);
3279 return handle_slash(to, destination, uri, slash, atsign, scheme);
3282 if (atsign && !scheme) {
3289 return handle_atsign(to, destination, uri, slash, atsign, scheme, get_default_outbound);
3300 ast_debug(3,
"Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s'%s\n",
3301 to, *uri, get_default_outbound ?
" with default endpoint" :
"");
3303 *uri =
ast_malloc(strlen(destination) + strlen(
"sip:") + 1);
3307 sprintf(*uri,
"sip:%s", destination);
3308 ast_debug(3,
"Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s'%s\n",
3309 to, *uri, get_default_outbound ?
" with default endpoint" :
"");
3311 if (get_default_outbound) {
3312 endpoint = ast_sip_default_outbound_endpoint();
3318 ao2_cleanup(endpoint);
3323 int ast_sip_update_to_uri(pjsip_tx_data *tdata,
const char *to)
3325 pjsip_name_addr *parsed_name_addr;
3326 pjsip_sip_uri *sip_uri;
3327 pjsip_name_addr *tdata_name_addr;
3328 pjsip_sip_uri *tdata_sip_uri;
3329 pjsip_to_hdr *to_hdr;
3331 #define DEBUG_BUF_SIZE 256
3333 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, (
char*)to, strlen(to),
3334 PJSIP_PARSE_URI_AS_NAMEADDR);
3336 if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3337 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {
3338 ast_log(LOG_WARNING,
"To address '%s' is not a valid SIP/SIPS URI\n", to);
3342 sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3343 if (DEBUG_ATLEAST(3)) {
3345 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);
3346 ast_debug(3,
"Parsed To: %.*s %s\n", (
int)parsed_name_addr->display.slen,
3347 parsed_name_addr->display.ptr, buf);
3350 to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);
3351 tdata_name_addr = to_hdr ? (pjsip_name_addr *) to_hdr->uri : NULL;
3352 if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)
3353 && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {
3355 ast_log(LOG_WARNING,
"tdata To address '%s' is not a valid SIP/SIPS URI\n", to);
3359 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
3360 if (DEBUG_ATLEAST(3)) {
3362 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);
3363 ast_debug(3,
"Original tdata To: %.*s %s\n", (
int)tdata_name_addr->display.slen,
3364 tdata_name_addr->display.ptr, buf);
3368 pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);
3370 pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);
3372 if (DEBUG_ATLEAST(3)) {
3374 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);
3375 ast_debug(3,
"New tdata To: %.*s %s\n", (
int)tdata_name_addr->display.slen,
3376 tdata_name_addr->display.ptr, buf);
3380 #undef DEBUG_BUF_SIZE
3383 int ast_sip_update_from(pjsip_tx_data *tdata,
char *from)
3385 pjsip_name_addr *name_addr;
3387 pjsip_name_addr *parsed_name_addr;
3388 pjsip_from_hdr *from_hdr;
3390 if (ast_strlen_zero(from)) {
3394 from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
3398 name_addr = (pjsip_name_addr *) from_hdr->uri;
3399 uri = pjsip_uri_get_uri(name_addr);
3401 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from,
3402 strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR);
3403 if (parsed_name_addr) {
3404 pjsip_sip_uri *parsed_uri;
3406 if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3407 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {
3408 ast_log(LOG_WARNING,
"From address '%s' is not a valid SIP/SIPS URI\n", from);
3412 parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3414 if (pj_strlen(&parsed_name_addr->display)) {
3415 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
3419 pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);
3420 pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
3421 uri->port = parsed_uri->port;
3426 char *domain = strchr(from,
'@');
3431 pj_strset3(&pj_from, from, domain);
3432 pj_strdup(tdata->pool, &uri->user, &pj_from);
3434 pj_strdup2(tdata->pool, &uri->host, domain + 1);
3436 pj_strdup2(tdata->pool, &uri->user, from);
3445 static void remove_request_headers(pjsip_endpoint *endpt)
3447 const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
3448 pjsip_hdr *iter = request_headers->next;
3450 while (iter != request_headers) {
3451 pjsip_hdr *to_erase = iter;
3453 pj_list_erase(to_erase);
3457 long ast_sip_threadpool_queue_size(
void)
3459 return ast_threadpool_queue_size(sip_threadpool);
3464 return sip_threadpool;
3467 int ast_sip_is_uri_sip_sips(pjsip_uri *uri)
3469 return (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri));
3472 int ast_sip_is_allowed_uri(pjsip_uri *uri)
3474 return (ast_sip_is_uri_sip_sips(uri) || PJSIP_URI_SCHEME_IS_TEL(uri));
3477 const pj_str_t *ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
3479 if (ast_sip_is_uri_sip_sips(uri)) {
3480 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3482 return &AST_PJ_STR_EMPTY;
3484 return &sip_uri->user;
3485 }
else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3486 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3488 return &AST_PJ_STR_EMPTY;
3490 return &tel_uri->number;
3493 return &AST_PJ_STR_EMPTY;
3496 const pj_str_t *ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
3498 if (ast_sip_is_uri_sip_sips(uri)) {
3499 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3501 return &AST_PJ_STR_EMPTY;
3503 return &sip_uri->host;
3504 }
else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3505 return &AST_PJ_STR_EMPTY;
3508 return &AST_PJ_STR_EMPTY;
3511 struct pjsip_param *ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri,
const pj_str_t *param_str)
3513 if (ast_sip_is_uri_sip_sips(uri)) {
3514 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3518 return pjsip_param_find(&sip_uri->other_param, param_str);
3519 }
else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3520 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3524 return pjsip_param_find(&tel_uri->other_param, param_str);
3531 const int ast_sip_hangup_sip2cause(
int cause)
3537 return AST_CAUSE_CALL_REJECTED;
3539 return AST_CAUSE_CALL_REJECTED;
3541 return AST_CAUSE_UNALLOCATED;
3543 return AST_CAUSE_INTERWORKING;
3545 return AST_CAUSE_CALL_REJECTED;
3547 return AST_CAUSE_NO_USER_RESPONSE;
3549 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
3551 return AST_CAUSE_NUMBER_CHANGED;
3553 return AST_CAUSE_INTERWORKING;
3555 return AST_CAUSE_INTERWORKING;
3557 return AST_CAUSE_INTERWORKING;
3559 return AST_CAUSE_INTERWORKING;
3561 return AST_CAUSE_NO_ROUTE_DESTINATION;
3563 return AST_CAUSE_NO_ANSWER;
3565 return AST_CAUSE_INTERWORKING;
3567 return AST_CAUSE_INTERWORKING;
3569 return AST_CAUSE_NO_ANSWER;
3571 return AST_CAUSE_INVALID_NUMBER_FORMAT;
3573 return AST_CAUSE_UNALLOCATED;
3575 return AST_CAUSE_BUSY;
3577 return AST_CAUSE_INTERWORKING;
3579 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
3581 return AST_CAUSE_INTERWORKING;
3583 return AST_CAUSE_INTERWORKING;
3585 return AST_CAUSE_FAILURE;
3587 return AST_CAUSE_FACILITY_REJECTED;
3589 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
3591 return AST_CAUSE_CONGESTION;
3593 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
3595 return AST_CAUSE_INTERWORKING;
3597 return AST_CAUSE_USER_BUSY;
3599 return AST_CAUSE_CALL_REJECTED;
3601 return AST_CAUSE_UNALLOCATED;
3603 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
3605 if (cause < 500 && cause >= 400) {
3607 return AST_CAUSE_INTERWORKING;
3608 }
else if (cause < 600 && cause >= 500) {
3610 return AST_CAUSE_CONGESTION;
3611 }
else if (cause < 700 && cause >= 600) {
3613 return AST_CAUSE_INTERWORKING;
3615 return AST_CAUSE_NORMAL;
3623 const char *long_name;
3624 const char *short_name;
3635 { PJSIP_SC_NULL,
"PJSIP_SC_NULL",
"NULL" },
3636 { PJSIP_SC_TRYING,
"PJSIP_SC_TRYING",
"TRYING" },
3637 { PJSIP_SC_RINGING,
"PJSIP_SC_RINGING",
"RINGING" },
3638 { PJSIP_SC_CALL_BEING_FORWARDED,
"PJSIP_SC_CALL_BEING_FORWARDED",
"CALL_BEING_FORWARDED" },
3639 { PJSIP_SC_QUEUED,
"PJSIP_SC_QUEUED",
"QUEUED" },
3640 { PJSIP_SC_PROGRESS,
"PJSIP_SC_PROGRESS",
"PROGRESS" },
3641 { PJSIP_SC_EARLY_DIALOG_TERMINATED,
"PJSIP_SC_EARLY_DIALOG_TERMINATED",
"EARLY_DIALOG_TERMINATED" },
3642 { PJSIP_SC_OK,
"PJSIP_SC_OK",
"OK" },
3643 { PJSIP_SC_ACCEPTED,
"PJSIP_SC_ACCEPTED",
"ACCEPTED" },
3644 { PJSIP_SC_NO_NOTIFICATION,
"PJSIP_SC_NO_NOTIFICATION",
"NO_NOTIFICATION" },
3645 { PJSIP_SC_MULTIPLE_CHOICES,
"PJSIP_SC_MULTIPLE_CHOICES",
"MULTIPLE_CHOICES" },
3646 { PJSIP_SC_MOVED_PERMANENTLY,
"PJSIP_SC_MOVED_PERMANENTLY",
"MOVED_PERMANENTLY" },
3647 { PJSIP_SC_MOVED_TEMPORARILY,
"PJSIP_SC_MOVED_TEMPORARILY",
"MOVED_TEMPORARILY" },
3648 { PJSIP_SC_USE_PROXY,
"PJSIP_SC_USE_PROXY",
"USE_PROXY" },
3649 { PJSIP_SC_ALTERNATIVE_SERVICE,
"PJSIP_SC_ALTERNATIVE_SERVICE",
"ALTERNATIVE_SERVICE" },
3650 { PJSIP_SC_BAD_REQUEST,
"PJSIP_SC_BAD_REQUEST",
"BAD_REQUEST" },
3651 { PJSIP_SC_UNAUTHORIZED,
"PJSIP_SC_UNAUTHORIZED",
"UNAUTHORIZED" },
3652 { PJSIP_SC_PAYMENT_REQUIRED,
"PJSIP_SC_PAYMENT_REQUIRED",
"PAYMENT_REQUIRED" },
3653 { PJSIP_SC_FORBIDDEN,
"PJSIP_SC_FORBIDDEN",
"FORBIDDEN" },
3654 { PJSIP_SC_NOT_FOUND,
"PJSIP_SC_NOT_FOUND",
"NOT_FOUND" },
3655 { PJSIP_SC_METHOD_NOT_ALLOWED,
"PJSIP_SC_METHOD_NOT_ALLOWED",
"METHOD_NOT_ALLOWED" },
3656 { PJSIP_SC_NOT_ACCEPTABLE,
"PJSIP_SC_NOT_ACCEPTABLE",
"NOT_ACCEPTABLE" },
3657 { PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED,
"PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED",
"PROXY_AUTHENTICATION_REQUIRED" },
3658 { PJSIP_SC_REQUEST_TIMEOUT,
"PJSIP_SC_REQUEST_TIMEOUT",
"REQUEST_TIMEOUT" },
3659 { PJSIP_SC_CONFLICT,
"PJSIP_SC_CONFLICT",
"CONFLICT" },
3660 { PJSIP_SC_GONE,
"PJSIP_SC_GONE",
"GONE" },
3661 { PJSIP_SC_LENGTH_REQUIRED,
"PJSIP_SC_LENGTH_REQUIRED",
"LENGTH_REQUIRED" },
3662 { PJSIP_SC_CONDITIONAL_REQUEST_FAILED,
"PJSIP_SC_CONDITIONAL_REQUEST_FAILED",
"CONDITIONAL_REQUEST_FAILED" },
3663 { PJSIP_SC_REQUEST_ENTITY_TOO_LARGE,
"PJSIP_SC_REQUEST_ENTITY_TOO_LARGE",
"REQUEST_ENTITY_TOO_LARGE" },
3664 { PJSIP_SC_REQUEST_URI_TOO_LONG,
"PJSIP_SC_REQUEST_URI_TOO_LONG",
"REQUEST_URI_TOO_LONG" },
3665 { PJSIP_SC_UNSUPPORTED_MEDIA_TYPE,
"PJSIP_SC_UNSUPPORTED_MEDIA_TYPE",
"UNSUPPORTED_MEDIA_TYPE" },
3666 { PJSIP_SC_UNSUPPORTED_URI_SCHEME,
"PJSIP_SC_UNSUPPORTED_URI_SCHEME",
"UNSUPPORTED_URI_SCHEME" },
3667 { PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY,
"PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY",
"UNKNOWN_RESOURCE_PRIORITY" },
3668 { PJSIP_SC_BAD_EXTENSION,
"PJSIP_SC_BAD_EXTENSION",
"BAD_EXTENSION" },
3669 { PJSIP_SC_EXTENSION_REQUIRED,
"PJSIP_SC_EXTENSION_REQUIRED",
"EXTENSION_REQUIRED" },
3670 { PJSIP_SC_SESSION_TIMER_TOO_SMALL,
"PJSIP_SC_SESSION_TIMER_TOO_SMALL",
"SESSION_TIMER_TOO_SMALL" },
3671 { PJSIP_SC_INTERVAL_TOO_BRIEF,
"PJSIP_SC_INTERVAL_TOO_BRIEF",
"INTERVAL_TOO_BRIEF" },
3672 { PJSIP_SC_BAD_LOCATION_INFORMATION,
"PJSIP_SC_BAD_LOCATION_INFORMATION",
"BAD_LOCATION_INFORMATION" },
3673 { PJSIP_SC_USE_IDENTITY_HEADER,
"PJSIP_SC_USE_IDENTITY_HEADER",
"USE_IDENTITY_HEADER" },
3674 { PJSIP_SC_PROVIDE_REFERRER_HEADER,
"PJSIP_SC_PROVIDE_REFERRER_HEADER",
"PROVIDE_REFERRER_HEADER" },
3675 { PJSIP_SC_FLOW_FAILED,
"PJSIP_SC_FLOW_FAILED",
"FLOW_FAILED" },
3676 { PJSIP_SC_ANONIMITY_DISALLOWED,
"PJSIP_SC_ANONIMITY_DISALLOWED",
"ANONIMITY_DISALLOWED" },
3677 { PJSIP_SC_BAD_IDENTITY_INFO,
"PJSIP_SC_BAD_IDENTITY_INFO",
"BAD_IDENTITY_INFO" },
3678 { PJSIP_SC_UNSUPPORTED_CERTIFICATE,
"PJSIP_SC_UNSUPPORTED_CERTIFICATE",
"UNSUPPORTED_CERTIFICATE" },
3679 { PJSIP_SC_INVALID_IDENTITY_HEADER,
"PJSIP_SC_INVALID_IDENTITY_HEADER",
"INVALID_IDENTITY_HEADER" },
3680 { PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT,
"PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT",
"FIRST_HOP_LACKS_OUTBOUND_SUPPORT" },
3681 { PJSIP_SC_MAX_BREADTH_EXCEEDED,
"PJSIP_SC_MAX_BREADTH_EXCEEDED",
"MAX_BREADTH_EXCEEDED" },
3682 { PJSIP_SC_BAD_INFO_PACKAGE,
"PJSIP_SC_BAD_INFO_PACKAGE",
"BAD_INFO_PACKAGE" },
3683 { PJSIP_SC_CONSENT_NEEDED,
"PJSIP_SC_CONSENT_NEEDED",
"CONSENT_NEEDED" },
3684 { PJSIP_SC_TEMPORARILY_UNAVAILABLE,
"PJSIP_SC_TEMPORARILY_UNAVAILABLE",
"TEMPORARILY_UNAVAILABLE" },
3685 { PJSIP_SC_CALL_TSX_DOES_NOT_EXIST,
"PJSIP_SC_CALL_TSX_DOES_NOT_EXIST",
"CALL_TSX_DOES_NOT_EXIST" },
3686 { PJSIP_SC_LOOP_DETECTED,
"PJSIP_SC_LOOP_DETECTED",
"LOOP_DETECTED" },
3687 { PJSIP_SC_TOO_MANY_HOPS,
"PJSIP_SC_TOO_MANY_HOPS",
"TOO_MANY_HOPS" },
3688 { PJSIP_SC_ADDRESS_INCOMPLETE,
"PJSIP_SC_ADDRESS_INCOMPLETE",
"ADDRESS_INCOMPLETE" },
3689 { PJSIP_SC_BUSY_HERE,
"PJSIP_SC_BUSY_HERE",
"BUSY_HERE" },
3690 { PJSIP_SC_REQUEST_TERMINATED,
"PJSIP_SC_REQUEST_TERMINATED",
"REQUEST_TERMINATED" },
3691 { PJSIP_SC_NOT_ACCEPTABLE_HERE,
"PJSIP_SC_NOT_ACCEPTABLE_HERE",
"NOT_ACCEPTABLE_HERE" },
3692 { PJSIP_SC_BAD_EVENT,
"PJSIP_SC_BAD_EVENT",
"BAD_EVENT" },
3693 { PJSIP_SC_REQUEST_UPDATED,
"PJSIP_SC_REQUEST_UPDATED",
"REQUEST_UPDATED" },
3694 { PJSIP_SC_REQUEST_PENDING,
"PJSIP_SC_REQUEST_PENDING",
"REQUEST_PENDING" },
3695 { PJSIP_SC_UNDECIPHERABLE,
"PJSIP_SC_UNDECIPHERABLE",
"UNDECIPHERABLE" },
3696 { PJSIP_SC_SECURITY_AGREEMENT_NEEDED,
"PJSIP_SC_SECURITY_AGREEMENT_NEEDED",
"SECURITY_AGREEMENT_NEEDED" },
3697 { PJSIP_SC_INTERNAL_SERVER_ERROR,
"PJSIP_SC_INTERNAL_SERVER_ERROR",
"INTERNAL_SERVER_ERROR" },
3698 { PJSIP_SC_NOT_IMPLEMENTED,
"PJSIP_SC_NOT_IMPLEMENTED",
"NOT_IMPLEMENTED" },
3699 { PJSIP_SC_BAD_GATEWAY,
"PJSIP_SC_BAD_GATEWAY",
"BAD_GATEWAY" },
3700 { PJSIP_SC_SERVICE_UNAVAILABLE,
"PJSIP_SC_SERVICE_UNAVAILABLE",
"SERVICE_UNAVAILABLE" },
3701 { PJSIP_SC_SERVER_TIMEOUT,
"PJSIP_SC_SERVER_TIMEOUT",
"SERVER_TIMEOUT" },
3702 { PJSIP_SC_VERSION_NOT_SUPPORTED,
"PJSIP_SC_VERSION_NOT_SUPPORTED",
"VERSION_NOT_SUPPORTED" },
3703 { PJSIP_SC_MESSAGE_TOO_LARGE,
"PJSIP_SC_MESSAGE_TOO_LARGE",
"MESSAGE_TOO_LARGE" },
3704 { PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED,
"PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED",
"PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED" },
3705 { PJSIP_SC_PRECONDITION_FAILURE,
"PJSIP_SC_PRECONDITION_FAILURE",
"PRECONDITION_FAILURE" },
3706 { PJSIP_SC_BUSY_EVERYWHERE,
"PJSIP_SC_BUSY_EVERYWHERE",
"BUSY_EVERYWHERE" },
3707 { PJSIP_SC_DECLINE,
"PJSIP_SC_DECLINE",
"DECLINE" },
3708 { PJSIP_SC_DOES_NOT_EXIST_ANYWHERE,
"PJSIP_SC_DOES_NOT_EXIST_ANYWHERE",
"DOES_NOT_EXIST_ANYWHERE" },
3709 { PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE,
"PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE",
"NOT_ACCEPTABLE_ANYWHERE" },
3710 { PJSIP_SC_UNWANTED,
"PJSIP_SC_UNWANTED",
"UNWANTED" },
3711 { PJSIP_SC_REJECTED,
"PJSIP_SC_REJECTED",
"REJECTED" },
3714 int ast_sip_str2rc(
const char *name)
3718 if (ast_strlen_zero(name)) {
3722 for (i = 0; i < ARRAY_LEN(rc_map); i++) {
3723 if (strcasecmp(rc_map[i].short_name, name) == 0 ||
3724 strcasecmp(rc_map[i].long_name, name) == 0) {
3725 return rc_map[i].code;
3733 #ifdef TEST_FRAMEWORK
3740 info->name =
"xml_sanitization_end_null";
3741 info->category =
"/res/res_pjsip/";
3742 info->summary =
"Ensure XML sanitization works as expected with a long string";
3743 info->description =
"This test sanitizes a string which exceeds the output\n"
3744 "buffer size. Once done the string is confirmed to be NULL terminated.";
3745 return AST_TEST_NOT_RUN;
3750 ast_sip_sanitize_xml(
"aaaaaaaaaaaa", sanitized,
sizeof(sanitized));
3751 if (sanitized[7] !=
'\0') {
3752 ast_test_status_update(
test,
"Sanitized XML string is not null-terminated when it should be\n");
3753 return AST_TEST_FAIL;
3756 return AST_TEST_PASS;
3765 info->name =
"xml_sanitization_exceeds_buffer";
3766 info->category =
"/res/res_pjsip/";
3767 info->summary =
"Ensure XML sanitization does not exceed buffer when output won't fit";
3768 info->description =
"This test sanitizes a string which before sanitization would\n"
3769 "fit within the output buffer. After sanitization, however, the string would\n"
3770 "exceed the buffer. Once done the string is confirmed to be NULL terminated.";
3771 return AST_TEST_NOT_RUN;
3776 ast_sip_sanitize_xml(
"<><><>&", sanitized,
sizeof(sanitized));
3777 if (sanitized[7] !=
'\0') {
3778 ast_test_status_update(
test,
"Sanitized XML string is not null-terminated when it should be\n");
3779 return AST_TEST_FAIL;
3782 return AST_TEST_PASS;
3790 static int reload_configuration_task(
void *obj)
3792 ast_res_pjsip_reload_configuration();
3793 ast_res_pjsip_init_options_handling(1);
3794 ast_sip_initialize_dns();
3798 static int unload_pjsip(
void *data)
3804 if (ast_pjsip_endpoint && sip_serializer_pool) {
3805 ast_res_pjsip_cleanup_options_handling();
3806 ast_res_pjsip_cleanup_message_filter();
3807 ast_sip_destroy_distributor();
3808 ast_sip_destroy_transport_management();
3809 ast_res_pjsip_destroy_configuration();
3810 ast_sip_destroy_system();
3811 ast_sip_destroy_global_headers();
3812 ast_sip_unregister_service(&supplement_module);
3813 ast_sip_destroy_transport_events();
3816 if (monitor_thread) {
3817 stop_monitor_thread();
3818 monitor_thread = NULL;
3825 pj_pool_t *temp_pool = memory_pool;
3828 pj_pool_release(temp_pool);
3831 ast_pjsip_endpoint = NULL;
3833 if (caching_pool.lock) {
3842 static int load_pjsip(
void)
3844 const unsigned int flags = 0;
3852 if (pjsip_endpt_create(&caching_pool.factory,
"SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
3853 ast_log(LOG_ERROR,
"Failed to create PJSIP endpoint structure. Aborting load\n");
3860 remove_request_headers(ast_pjsip_endpoint);
3862 memory_pool = pj_pool_create(&caching_pool.factory,
"SIP", 1024, 1024, NULL);
3864 ast_log(LOG_ERROR,
"Failed to create memory pool for SIP. Aborting load\n");
3868 if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
3869 pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string,
sizeof(host_ip_ipv4_string), flags);
3870 ast_verb(3,
"Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
3873 if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
3874 pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string,
sizeof(host_ip_ipv6_string), flags);
3875 ast_verb(3,
"Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
3878 pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
3879 pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
3881 monitor_continue = 1;
3882 status = pj_thread_create(memory_pool,
"SIP", (pj_thread_proc *) &monitor_thread_exec,
3883 NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
3884 if (status != PJ_SUCCESS) {
3885 ast_log(LOG_ERROR,
"Failed to start SIP monitor thread. Aborting load\n");
3902 void never_called_res_pjsip(
void);
3903 void never_called_res_pjsip(
void)
3905 pjmedia_strerror(0, NULL, 0);
3909 pjsip_media_type pjsip_media_type_application_json;
3910 pjsip_media_type pjsip_media_type_application_media_control_xml;
3911 pjsip_media_type pjsip_media_type_application_pidf_xml;
3912 pjsip_media_type pjsip_media_type_application_xpidf_xml;
3913 pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml;
3914 pjsip_media_type pjsip_media_type_application_rlmi_xml;
3915 pjsip_media_type pjsip_media_type_application_simple_message_summary;
3916 pjsip_media_type pjsip_media_type_application_sdp;
3917 pjsip_media_type pjsip_media_type_multipart_alternative;
3918 pjsip_media_type pjsip_media_type_multipart_mixed;
3919 pjsip_media_type pjsip_media_type_multipart_related;
3920 pjsip_media_type pjsip_media_type_text_plain;
3922 static int load_module(
void)
3927 if (pj_init() != PJ_SUCCESS) {
3931 if (pjlib_util_init() != PJ_SUCCESS) {
3936 if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
3938 ast_log(LOG_WARNING,
"Failed to register pjmedia error codes. Codes will not be decoded.\n");
3942 pjsip_media_type_init2(&pjsip_media_type_application_json,
"application",
"json");
3943 pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml,
"application",
"media_control+xml");
3944 pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml,
"application",
"pidf+xml");
3945 pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml,
"application",
"xpidf+xml");
3946 pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml,
"application",
"cpim-xpidf+xml");
3947 pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml,
"application",
"rlmi+xml");
3948 pjsip_media_type_init2(&pjsip_media_type_application_sdp,
"application",
"sdp");
3949 pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary,
"application",
"simple-message-summary");
3950 pjsip_media_type_init2(&pjsip_media_type_multipart_alternative,
"multipart",
"alternative");
3951 pjsip_media_type_init2(&pjsip_media_type_multipart_mixed,
"multipart",
"mixed");
3952 pjsip_media_type_init2(&pjsip_media_type_multipart_related,
"multipart",
"related");
3953 pjsip_media_type_init2(&pjsip_media_type_text_plain,
"text",
"plain");
3956 if (ast_sip_initialize_system()) {
3957 ast_log(LOG_ERROR,
"Failed to initialize SIP 'system' configuration section. Aborting load\n");
3962 sip_get_threadpool_options(&options);
3963 options.thread_start = sip_thread_start;
3964 sip_threadpool = ast_threadpool_create(
"pjsip", NULL, &options);
3965 if (!sip_threadpool) {
3969 sip_serializer_pool = ast_serializer_pool_create(
3970 "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);
3971 if (!sip_serializer_pool) {
3972 ast_log(LOG_ERROR,
"Failed to create SIP serializer pool. Aborting load\n");
3977 ast_log(LOG_ERROR,
"Failed to start scheduler. Aborting load\n");
3986 if (ast_sip_initialize_transport_events()) {
3987 ast_log(LOG_ERROR,
"Failed to initialize SIP transport monitor. Aborting load\n");
3991 ast_sip_initialize_dns();
3992 ast_sip_initialize_global_headers();
3994 if (ast_res_pjsip_preinit_options_handling()) {
3995 ast_log(LOG_ERROR,
"Failed to pre-initialize OPTIONS handling. Aborting load\n");
3999 if (ast_res_pjsip_initialize_configuration()) {
4000 ast_log(LOG_ERROR,
"Failed to initialize SIP configuration. Aborting load\n");
4004 ast_sip_initialize_resolver();
4005 ast_sip_initialize_dns();
4007 if (ast_sip_initialize_transport_management()) {
4008 ast_log(LOG_ERROR,
"Failed to initialize SIP transport management. Aborting load\n");
4012 if (ast_sip_initialize_distributor()) {
4013 ast_log(LOG_ERROR,
"Failed to register distributor module. Aborting load\n");
4017 if (ast_sip_register_service(&supplement_module)) {
4018 ast_log(LOG_ERROR,
"Failed to initialize supplement hooks. Aborting load\n");
4022 if (ast_res_pjsip_init_options_handling(0)) {
4023 ast_log(LOG_ERROR,
"Failed to initialize OPTIONS handling. Aborting load\n");
4033 ast_sip_location_prune_boot_contacts();
4035 if (ast_res_pjsip_init_message_filter()) {
4036 ast_log(LOG_ERROR,
"Failed to initialize message IP updating. Aborting load\n");
4042 AST_TEST_REGISTER(xml_sanitization_end_null);
4043 AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
4051 ast_sip_destroy_scheduler();
4052 ast_serializer_pool_destroy(sip_serializer_pool);
4053 ast_threadpool_shutdown(sip_threadpool);
4058 static int reload_module(
void)
4065 ast_log(LOG_WARNING,
"Failed to reload PJSIP\n");
4072 static int unload_module(
void)
4074 AST_TEST_UNREGISTER(xml_sanitization_end_null);
4075 AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
4082 ast_sip_destroy_scheduler();
4083 ast_serializer_pool_destroy(sip_serializer_pool);
4084 ast_threadpool_shutdown(sip_threadpool);
4089 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Basic SIP resource",
4090 .support_level = AST_MODULE_SUPPORT_CORE,
4091 .load = load_module,
4092 .unload = unload_module,
4093 .reload = reload_module,
4095 .requires =
"dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb",
4096 .optional_modules =
"res_geolocation,res_statsd",
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Information needed to identify an endpoint in a call.
char * str
Subscriber phone number (Malloced)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field fromuser
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...
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
String manipulation functions.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
void(* callback)(void *token, pjsip_event *e)
const ast_string_field transport
struct ast_party_name name
Subscriber name.
struct ast_sip_endpoint_nat_configuration nat
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
pj_timer_entry * timeout_timer
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
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.
static pj_pool_t * pool
Global memory pool for configuration and timers.
struct ast_sip_auth_vector outbound_auths
Universally unique identifier support.
pjsip_tpfactory * factory
Potential pointer to the transport factory itself, if TCP/TLS.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
char * str
Subscriber name (Malloced)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
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.
Source contained fully valid UTF-8.
#define ast_strdup(str)
A wrapper for strdup()
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
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.
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...
CLI Formatter Context passed to all formatters.
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
UTF-8 information and validation functions.
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.
Socket address structure.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_pjproject_log_intercept_end(void)
End PJPROJECT log interception for CLI output.
int local_port
Local port for transport.
Structure for SIP transport information.
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
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...
struct pjsip_transport * transport
Transport itself.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void ast_pjproject_log_intercept_begin(int fd)
Begin PJPROJECT log interception for CLI output.
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...
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
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.
#define ast_debug(level,...)
Log a DEBUG message.
An entity with which Asterisk communicates.
pjsip_transport * transport
Potential pointer to the transport itself, if UDP.
enum ast_transport type
Type of transport.
const ast_string_field outbound_proxy
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_sip_endpoint_info_configuration info
int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
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...
Support for dynamic strings.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
void(* callback)(void *token, pjsip_event *e)
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
userdata associated with baseline taskprocessor test
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
unsigned int rewrite_contact
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor's current task.
struct pjsip_tpfactory * factory
Transport factory.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
An API for managing task processing threads that can be shared across modules.
pj_str_t local_address
Local address for transport.
An entity responsible for identifying the source of a SIP message.
structure to hold users read from users.conf
Structure used to handle boolean flags.
struct ast_sockaddr external_signaling_address
char * tag
User-set "tag".
An interchangeable way of handling digest authentication for SIP.
A ast_taskprocessor structure is a singleton by name.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
Standard Command Line Interface.
A supplement to SIP message processing.
An opaque threadpool structure.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Structure to hold information about an outbound request.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
unsigned int challenge_count
Internal Asterisk hangup causes.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
#define AST_TEST_DEFINE(hdr)
unsigned int allow_unauthenticated_options
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Structure which contains information about a transport.
unsigned char valid
TRUE if the name information is valid/present.
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.
an interchangeable way of responding to authentication challenges
const ast_string_field aors
#define ASTERISK_GPL_KEY
The text the key() function should return.
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...
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
unsigned int send_cb_called
unsigned char valid
TRUE if the number information is valid/present.
Structure for mutex and tracking information.
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...
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Sorcery Data Access Layer API.
const ast_string_field fromdomain
struct ast_sip_endpoint * endpoint
struct ast_party_number number
Subscriber phone number.
enum ast_sip_supplement_priority priority