23 #include <pjsip_simple.h> 24 #include <pjsip/sip_transaction.h> 27 #include <pjmedia/errno.h> 3264 #define MOD_DATA_CONTACT "contact" 3267 #define SERIALIZER_POOL_SIZE 8 3292 time_t t = time(
NULL);
3295 strftime(date,
sizeof(date),
"%a, %d %b %Y %T GMT", &tm);
3302 pjsip_module **module = data;
3304 ast_log(
LOG_ERROR,
"There is no PJSIP endpoint. Unable to register services\n");
3308 ast_log(
LOG_ERROR,
"Unable to register module %.*s\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
3311 ast_debug(1,
"Registered SIP service %.*s (%p)\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
3322 pjsip_module **module = data;
3327 ast_debug(1,
"Unregistered SIP service %.*s\n", (
int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
3340 if (registered_authenticator) {
3341 ast_log(
LOG_WARNING,
"Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
3344 registered_authenticator = auth;
3345 ast_debug(1,
"Registered SIP authenticator module %p\n", auth);
3352 if (registered_authenticator != auth) {
3353 ast_log(
LOG_WARNING,
"Trying to unregister authenticator %p but authenticator %p registered\n",
3354 auth, registered_authenticator);
3357 registered_authenticator =
NULL;
3358 ast_debug(1,
"Unregistered SIP authenticator %p\n", auth);
3364 && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
3365 ast_debug(3,
"Skipping OPTIONS authentication due to endpoint configuration\n");
3369 if (!registered_authenticator) {
3370 ast_log(
LOG_WARNING,
"No SIP authenticator registered. Assuming authentication is not required\n");
3378 pjsip_rx_data *rdata, pjsip_tx_data *tdata)
3380 if (!registered_authenticator) {
3381 ast_log(
LOG_WARNING,
"No SIP authenticator registered. Assuming authentication is successful\n");
3391 if (registered_outbound_authenticator) {
3392 ast_log(
LOG_WARNING,
"Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
3395 registered_outbound_authenticator = auth;
3396 ast_debug(1,
"Registered SIP outbound authenticator module %p\n", auth);
3403 if (registered_outbound_authenticator != auth) {
3404 ast_log(
LOG_WARNING,
"Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
3405 auth, registered_outbound_authenticator);
3408 registered_outbound_authenticator =
NULL;
3409 ast_debug(1,
"Unregistered SIP outbound authenticator %p\n", auth);
3413 pjsip_tx_data *old_request, pjsip_tx_data **new_request)
3415 if (!registered_outbound_authenticator) {
3416 ast_log(
LOG_WARNING,
"No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
3434 char *prev, *current, *identifier_order;
3438 id_list_item =
ast_calloc(1,
sizeof(*id_list_item));
3439 if (!id_list_item) {
3446 ast_debug(1,
"Register endpoint identifier %s(%p)\n", name ?:
"", identifier);
3465 while ((current = strchr(current,
','))) {
3467 if (!strncmp(prev, name, current - prev)
3468 && strlen(name) == current - prev) {
3476 if (!strcmp(prev, name)) {
3521 ast_debug(1,
"Unregistered endpoint identifier %p\n", identifier);
3545 pjsip_generic_string_hdr *hdr;
3548 hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str,
NULL);
3553 pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
3574 e->
command =
"pjsip dump endpt [details]";
3576 "Usage: pjsip dump endpt [details]\n" 3577 " Dump the res_pjsip endpt internals.\n" 3579 "Warning: PJPROJECT documents that the function used by this\n" 3580 "CLI command may cause a crash when asking for details because\n" 3581 "it tries to access all active memory pools.\n";
3589 e->
command =
"pjsip dump endpt";
3591 "Usage: pjsip dump endpt\n" 3592 " Dump the res_pjsip endpt internals.\n";
3600 || (a->
argc == 4 && strcasecmp(a->
argv[3],
"details"))) {
3611 #define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n" 3616 e->
command =
"pjsip show identifiers";
3617 e->
usage =
"Usage: pjsip show identifiers\n" 3618 " List all registered endpoint identifiers\n";
3633 iter->
name ? iter->
name :
"name not specified");
3637 #undef ENDPOINT_IDENTIFIER_FORMAT 3646 e->
command =
"pjsip show settings";
3647 e->
usage =
"Usage: pjsip show settings\n" 3648 " Show global and system configuration options\n";
3656 ast_cli(a->
fd,
"Could not allocate output buffer.\n");
3662 ast_cli(a->
fd,
"Error retrieving settings.\n");
3724 pjsip_rx_data *rdata)
3730 if (uri->port == rdata->pkt_info.src_port
3731 && !pj_strcmp(&uri->host,
3732 pj_cstr(&host_name, rdata->pkt_info.src_name))
3734 && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
3738 if (!strcasecmp(
"WSS", rdata->tp_info.transport->type_name)) {
3740 pj_cstr(&type_name,
"ws");
3742 pj_cstr(&type_name, rdata->tp_info.transport->type_name);
3745 if (!pj_stricmp(&uri->transport_param, &type_name)
3748 || !pj_stricmp(&uri->transport_param,
3749 pj_cstr(&type_name,
"ws")))) {
3763 pjsip_sip_uri *sip_uri,
char *
buf,
size_t buf_len)
3767 pjsip_param *x_transport;
3774 x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
3792 pjsip_tpselector *selector)
3795 pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
3797 uri = pjsip_uri_get_uri(dlg->target);
3804 pjsip_dlg_set_transport(dlg, selector);
3806 if (selector == &sel) {
3814 const char *
domain,
const pj_str_t *target, pjsip_tpselector *selector)
3816 pj_str_t
tmp, local_addr;
3818 pjsip_sip_uri *sip_uri;
3819 pjsip_transport_type_e
type;
3821 char default_user[PJSIP_MAX_URL_SIZE];
3825 user = default_user;
3829 pj_strdup_with_null(pool, &tmp, target);
3831 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
3832 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
3836 sip_uri = pjsip_uri_get_uri(uri);
3839 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
3840 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
3841 if (type == PJSIP_TRANSPORT_UNSPECIFIED
3842 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
3843 type = PJSIP_TRANSPORT_TLS;
3845 }
else if (!sip_uri->transport_param.slen) {
3846 type = PJSIP_TRANSPORT_UDP;
3847 }
else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
3852 if (pj_strchr(&sip_uri->host,
':')) {
3853 type |= PJSIP_TRANSPORT_IPV6;
3858 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3859 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3862 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
3863 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
3868 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3869 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3873 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
3874 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
3880 &local_addr, &local_port) != PJ_SUCCESS) {
3883 pj_strdup(pool, &local_addr, pj_gethostname());
3884 local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
3888 if (pj_strchr(&local_addr,
':')) {
3889 type |= PJSIP_TRANSPORT_IPV6;
3892 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3893 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3894 "<sip:%s@%s%.*s%s:%d%s%s>",
3896 (type & PJSIP_TRANSPORT_IPV6) ?
"[" :
"",
3897 (
int)local_addr.slen,
3899 (type & PJSIP_TRANSPORT_IPV6) ?
"]" :
"",
3901 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
3902 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
3913 if (!transport_state) {
3920 if (transport_state->
flow) {
3925 selector->type = PJSIP_TPSELECTOR_TRANSPORT;
3926 selector->u.transport = transport_state->
transport;
3927 pjsip_transport_add_ref(selector->u.transport);
3928 }
else if (transport_state->
factory) {
3929 selector->type = PJSIP_TPSELECTOR_LISTENER;
3930 selector->u.listener = transport_state->
factory;
3936 }
else if (transport->
flow) {
3938 #ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE 3939 selector->disable_connection_reuse = PJ_TRUE;
3941 ast_log(
LOG_WARNING,
"Connection reuse could not be disabled on transport '%s' as support is not available\n",
3948 if (transport_state->
flow) {
3976 pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
3978 char transport_name[128];
3989 if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
3990 pjsip_transport_dec_ref(selector->u.transport);
3996 pjsip_sip_uri *sip_uri;
3998 static const pj_str_t STR_PHONE = {
"phone", 5 };
4000 if (!endpoint || !endpoint->
usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
4004 sip_uri = pjsip_uri_get_uri(uri);
4006 if (!pj_strlen(&sip_uri->user)) {
4010 if (pj_strbuf(&sip_uri->user)[0] ==
'+') {
4015 for (; i < pj_strlen(&sip_uri->user); i++) {
4021 if (i < pj_strlen(&sip_uri->user)) {
4025 sip_uri->user_param = STR_PHONE;
4029 const char *uri,
const char *request_user)
4031 char enclosed_uri[PJSIP_MAX_URL_SIZE];
4032 pj_str_t local_uri = {
"sip:temp@temp", 13 }, remote_uri, target_uri;
4034 pjsip_dialog *dlg =
NULL;
4036 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4037 static const pj_str_t HCONTACT = {
"Contact", 7 };
4039 snprintf(enclosed_uri,
sizeof(enclosed_uri),
"<%s>", uri);
4040 pj_cstr(&remote_uri, enclosed_uri);
4042 pj_cstr(&target_uri, uri);
4044 res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri,
NULL, &remote_uri, &target_uri, &dlg);
4045 if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
4048 res = PJSIP_EINVALIDURI;
4049 pjsip_dlg_terminate(dlg);
4051 if (res != PJ_SUCCESS) {
4052 if (res == PJSIP_EINVALIDURI) {
4054 "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
4067 pjsip_dlg_terminate(dlg);
4075 pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
4076 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
4077 if (!dlg->local.info->uri) {
4079 "Could not parse URI '%s' for endpoint '%s'\n",
4082 pjsip_dlg_terminate(dlg);
4086 dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen,
NULL);
4089 pjsip_sip_uri *sip_uri;
4091 sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
4092 pj_strdup2(dlg->pool, &sip_uri->user, endpoint->
contact_user);
4097 pjsip_sip_uri *sip_uri;
4099 if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
4100 sip_uri = pjsip_uri_get_uri(dlg->target);
4101 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
4103 if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
4104 sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
4105 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
4114 pjsip_route_hdr route_set, *route;
4115 static const pj_str_t ROUTE_HNAME = {
"Route", 5 };
4118 pj_list_init(&route_set);
4120 pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
4121 if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen,
NULL))) {
4122 ast_log(
LOG_ERROR,
"Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
4125 pjsip_dlg_terminate(dlg);
4128 pj_list_insert_nodes_before(&route_set, route);
4130 pjsip_dlg_set_route_set(dlg, &route_set);
4150 pjsip_rr_hdr *record_route;
4152 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
4156 record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE,
NULL);
4158 if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
4164 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
NULL);
4166 if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
4175 const pj_str_t *
contact, pjsip_dialog **p_dlg);
4182 pjsip_transport_type_e
type = rdata->tp_info.transport->key.type;
4183 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4185 pjsip_contact_hdr *contact_hdr;
4189 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
NULL);
4195 transport = rdata->tp_info.transport;
4196 if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
4197 transport = selector.u.transport;
4199 type = transport->key.type;
4201 contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
4202 contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
4203 "<%s:%s%.*s%s:%d%s%s>",
4205 (type & PJSIP_TRANSPORT_IPV6) ?
"[" :
"",
4206 (
int)transport->local_name.host.slen,
4207 transport->local_name.host.ptr,
4208 (type & PJSIP_TRANSPORT_IPV6) ?
"]" :
"",
4209 transport->local_name.port,
4210 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ?
";transport=" :
"",
4211 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) :
"");
4213 *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
4214 if (*status != PJ_SUCCESS) {
4215 char err[PJ_ERR_MSG_SIZE];
4217 pj_strerror(*status, err,
sizeof(err));
4225 pjsip_dlg_set_transport(dlg, &selector);
4235 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK 4238 dlg =
create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
4240 pjsip_dlg_dec_lock(dlg);
4250 pjsip_rx_data *rdata, pj_status_t *
status)
4252 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK 4253 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
4264 pjsip_dlg_inc_lock(dlg);
4272 char *transport_type,
const char *local_name,
int local_port,
const char *
contact)
4280 pj_list_init(&rdata->msg_info.parse_err);
4282 rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
4283 if (!rdata->tp_info.transport) {
4287 ast_copy_string(rdata->pkt_info.packet, packet,
sizeof(rdata->pkt_info.packet));
4288 ast_copy_string(rdata->pkt_info.src_name, src_name,
sizeof(rdata->pkt_info.src_name));
4289 rdata->pkt_info.src_port = src_port;
4290 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
4291 pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
4293 pjsip_parse_rdata(packet, strlen(packet), rdata);
4294 if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
4299 pjsip_contact_hdr *contact_hdr;
4301 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
NULL);
4303 contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (
char *)contact,
4304 strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
4305 if (!contact_hdr->uri) {
4312 pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
4313 rdata->msg_info.via->rport_param = -1;
4315 rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
4316 rdata->tp_info.transport->type_name = transport_type;
4317 pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
4318 rdata->tp_info.transport->local_name.port = local_port;
4324 char *transport_type,
const char *local_name,
int local_port)
4327 local_name, local_port,
NULL);
4331 static const pjsip_method
info_method = {PJSIP_OTHER_METHOD, {
"INFO", 4} };
4338 {
"INVITE", &pjsip_invite_method },
4339 {
"CANCEL", &pjsip_cancel_method },
4340 {
"ACK", &pjsip_ack_method },
4341 {
"BYE", &pjsip_bye_method },
4342 {
"REGISTER", &pjsip_register_method },
4343 {
"OPTIONS", &pjsip_options_method },
4344 {
"SUBSCRIBE", &pjsip_subscribe_method },
4345 {
"NOTIFY", &pjsip_notify_method },
4355 if (!strcmp(method,
methods[i].method)) {
4364 if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
4374 .name = {
"Out of dialog supplement hook", 29 },
4376 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 1,
4381 const char *uri,
struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
4384 pj_str_t remote_uri;
4387 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4389 const char *fromuser;
4406 pj_cstr(&remote_uri,
contact->uri);
4408 pj_cstr(&remote_uri, uri);
4418 sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
4419 if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
4420 ast_log(
LOG_ERROR,
"Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
4421 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
4423 pj_strbuf(&remote_uri));
4432 endpoint ? endpoint->
fromdomain :
NULL, &remote_uri, &selector)) {
4433 ast_log(
LOG_ERROR,
"Unable to create From header for %.*s request to endpoint %s\n",
4434 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
4442 &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
4443 ast_log(
LOG_ERROR,
"Unable to create outbound %.*s request to endpoint %s\n",
4444 (
int) pj_strlen(&method->name), pj_strbuf(&method->name),
4451 pjsip_tx_data_set_transport(*tdata, &selector);
4456 pjsip_contact_hdr *contact_hdr;
4457 pjsip_sip_uri *contact_uri;
4458 static const pj_str_t HCONTACT = {
"Contact", 7 };
4459 static const pj_str_t HCONTACTSHORT = {
"m", 1 };
4461 contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
4463 contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
4464 pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->
contact_user);
4474 ast_log(
LOG_ERROR,
"Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
4537 if (supplement == iter) {
4547 if (pjsip_dlg_send_request(dlg, tdata, -1,
NULL) != PJ_SUCCESS) {
4562 pj_cstr(&method, supplement_method);
4564 return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
4567 #define TIMER_INACTIVE 0 4568 #define TIMEOUT_TIMER2 5 4577 void (*callback)(
void *token, pjsip_event *e);
4611 void (*callback)(
void *token, pjsip_event *e);
4639 if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
4640 ast_debug(2,
"%p: PJSIP tsx timer expired\n", req_wrapper);
4644 ast_debug(3,
"%p: Timeout already handled\n", req_wrapper);
4649 ast_debug(2,
"%p: PJSIP tsx response received\n", req_wrapper);
4660 int timers_cancelled = 0;
4662 ast_debug(3,
"%p: Cancelling timer\n", req_wrapper);
4664 timers_cancelled = pj_timer_heap_cancel_if_active(
4667 if (timers_cancelled > 0) {
4671 ast_debug(3,
"%p: Timer cancelled\n", req_wrapper);
4679 ast_debug(3,
"%p: Timer already expired\n", req_wrapper);
4690 if (!cb_called && req_wrapper->
callback) {
4692 ast_debug(2,
"%p: Callbacks executed\n", req_wrapper);
4708 ast_debug(2,
"%p: Internal tsx timer expired after %d msec\n",
4709 req_wrapper, req_wrapper->
timeout);
4718 ast_debug(3,
"%p: Timeout already handled\n", req_wrapper);
4724 ast_debug(3,
"%p: Timer handled here\n", req_wrapper);
4730 if (!cb_called && req_wrapper->
callback) {
4733 PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->
tdata);
4734 event.body.tsx_state.type = PJSIP_EVENT_TIMER;
4737 ast_debug(2,
"%p: Callbacks executed\n", req_wrapper);
4747 pjsip_tx_data_dec_ref(req_wrapper->
tdata);
4748 ast_debug(2,
"%p: wrapper destroyed\n", req_wrapper);
4752 pjsip_tx_data *
tdata, pj_int32_t
timeout,
void *token, pjsip_endpt_send_callback cb)
4755 pj_status_t ret_val;
4760 pjsip_tx_data_dec_ref(tdata);
4767 pjsip_tx_data_dec_ref(tdata);
4771 ast_debug(2,
"%p: Wrapper created\n", req_wrapper);
4779 pjsip_tx_data_add_ref(tdata);
4782 pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
4784 req_wrapper->
timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
4786 ast_debug(2,
"%p: Set timer to %d msec\n", req_wrapper, timeout);
4795 ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
4797 if (ret_val != PJ_SUCCESS) {
4799 "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
4800 (
int) pj_strlen(&tdata->msg->line.req.method.name),
4801 pj_strbuf(&tdata->msg->line.req.method.name),
4803 ao2_t_ref(req_wrapper, -2,
"Drop timer and routine ref");
4804 pjsip_tx_data_dec_ref(tdata);
4814 if (ret_val != PJ_SUCCESS) {
4815 char errmsg[PJ_ERR_MSG_SIZE];
4823 pj_strerror(ret_val, errmsg,
sizeof(errmsg));
4825 (
int) ret_val, errmsg, (
int) pj_strlen(&tdata->msg->line.req.method.name),
4826 pj_strbuf(&tdata->msg->line.req.method.name),
4830 int timers_cancelled;
4833 timers_cancelled = pj_timer_heap_cancel_if_active(
4834 pjsip_endpt_get_timer_heap(endpt),
4836 if (timers_cancelled > 0) {
4847 ret_val = PJ_SUCCESS;
4863 ret_val = PJ_SUCCESS;
4875 if (!tdata || !tdata->dest_info.addr.count
4876 || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
4882 ++tdata->dest_info.cur_addr;
4884 via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL);
4885 via->branch_param.slen = 0;
4887 pjsip_tx_data_invalidate_msg(tdata);
4897 pjsip_transaction *tsx;
4898 pjsip_tx_data *tdata;
4905 tsx = e->body.tsx_state.tsx;
4907 switch (tsx->status_code) {
4913 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
4918 tdata = tsx->last_tx;
4923 pjsip_tx_data_add_ref(tdata);
4930 req_data, send_request_cb) == PJ_SUCCESS;
4943 if (e->type == PJSIP_EVENT_TSX_STATE) {
4944 switch(e->body.tsx_state.type) {
4945 case PJSIP_EVENT_TRANSPORT_ERROR:
4946 case PJSIP_EVENT_TIMER:
4956 case PJSIP_EVENT_RX_MSG:
4957 challenge = e->body.tsx_state.src.rdata;
4995 void (*callback)(
void *token, pjsip_event *e))
5003 pjsip_tx_data_dec_ref(tdata);
5036 void (*callback)(
void *token, pjsip_event *e))
5038 ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
5049 pjsip_route_hdr *route;
5050 static const pj_str_t ROUTE_HNAME = {
"Route", 5 };
5053 pj_strdup2_with_null(tdata->pool, &tmp, proxy);
5054 if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen,
NULL))) {
5058 pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
5067 pjsip_generic_string_hdr *hdr;
5069 pj_cstr(&hdr_name, name);
5070 pj_cstr(&hdr_value, value);
5072 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
5074 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
5084 pj_cstr(&type, body->
type);
5085 pj_cstr(&subtype, body->
subtype);
5088 return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
5094 tdata->msg->body = pjsip_body;
5102 pjsip_msg_body *body = pjsip_multipart_create(tdata->pool,
NULL,
NULL);
5104 for (i = 0; i < num_bodies; ++i) {
5105 pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
5107 pjsip_multipart_add_part(tdata->pool, body, part);
5110 tdata->msg->body = body;
5116 size_t combined_size = strlen(body_text) + tdata->msg->body->len;
5119 ast_str_set(&body_buffer, 0,
"%.*s%s", (
int) tdata->msg->body->len, (
char *) tdata->msg->body->data, body_text);
5121 tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
5122 pj_memcpy(tdata->msg->body->data,
ast_str_buffer(body_buffer), combined_size);
5123 tdata->msg->body->len = combined_size;
5181 memset(&std, 0,
sizeof(std));
5184 std.
task = sip_task;
5207 return sip_task(task_data);
5234 return sip_task(task_data);
5242 size_t chars_to_copy =
MIN(size - 1, pj_strlen(src));
5243 memcpy(dest, pj_strbuf(src), chars_to_copy);
5244 dest[chars_to_copy] =
'\0';
5249 int res =
ast_asprintf(dest,
"%.*s", (
int)pj_strlen(src), pj_strbuf(src));
5263 if (!content_type) {
5267 pjsip_media_type_init2(&compare, type, subtype);
5269 return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
5279 while (monitor_continue) {
5280 const pj_time_val delay = {0, 10};
5288 monitor_continue = 0;
5289 pj_thread_join(monitor_thread);
5294 #define SIP_SERVANT_ID 0x5E2F1D 5298 pj_thread_desc *
desc;
5300 uint32_t *servant_id;
5304 ast_log(
LOG_ERROR,
"Could not set SIP servant ID in thread-local storage.\n");
5311 ast_log(
LOG_ERROR,
"Could not get thread desc from thread-local storage. Expect awful things to occur\n");
5314 pj_bzero(*desc,
sizeof(*desc));
5316 if (pj_thread_register(
"Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
5323 uint32_t *servant_id;
5325 if (monitor_thread &&
5326 pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
5340 unsigned int hval = 0;
5346 return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
5350 const char *key,
void *
val)
5353 ht = pj_hash_create(pool, 11);
5356 pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
5365 if (pjsip_rdata_get_dlg(rdata)) {
5388 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ,
NULL);
5413 if (status != PJ_SUCCESS) {
5414 pjsip_tx_data_dec_ref(tdata);
5417 return status == PJ_SUCCESS ? 0 : -1;
5422 pjsip_transaction *tsx;
5424 if (pjsip_tsx_create_uas(
NULL, rdata, &tsx) != PJ_SUCCESS) {
5433 pjsip_tx_data_dec_ref(tdata);
5436 pjsip_tsx_recv_msg(tsx, rdata);
5440 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
5441 pjsip_tx_data_dec_ref(tdata);
5475 if (af == pj_AF_INET()) {
5477 }
else if (af == pj_AF_INET6()) {
5485 char *
buf,
size_t buf_len)
5517 if (!strcasecmp(dtmf_mode,
"info")) {
5519 }
else if (!strcasecmp(dtmf_mode,
"rfc4733")) {
5521 }
else if (!strcasecmp(dtmf_mode,
"inband")) {
5523 }
else if (!strcasecmp(dtmf_mode,
"none")) {
5525 }
else if (!strcasecmp(dtmf_mode,
"auto")) {
5527 }
else if (!strcasecmp(dtmf_mode,
"auto_info")) {
5538 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)) {
5540 }
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)) {
5541 value =
"local_merge";
5542 }
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)) {
5543 value =
"local_first";
5544 }
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)) {
5546 }
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)) {
5547 value =
"remote_merge";
5548 }
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)) {
5549 value =
"remote_first";
5561 if (strcmp(pref_str,
"local") == 0) {
5563 }
else if (is_outgoing && strcmp(pref_str,
"local_merge") == 0) {
5565 }
else if (strcmp(pref_str,
"local_first") == 0) {
5567 }
else if (strcmp(pref_str,
"remote") == 0) {
5569 }
else if (is_outgoing && strcmp(pref_str,
"remote_merge") == 0) {
5571 }
else if (strcmp(pref_str,
"remote_first") == 0) {
5589 pjsip_name_addr *id_name_addr;
5590 pjsip_sip_uri *id_uri;
5592 id_name_addr = (pjsip_name_addr *) id_hdr->uri;
5593 id_uri = pjsip_uri_get_uri(id_name_addr->uri);
5597 int name_buf_len = strlen(id->
name.
str) * 2 + 1;
5601 pj_strdup2(pool, &id_name_addr->display, name_buf);
5603 pj_strdup2(pool, &id_name_addr->display,
NULL);
5608 pj_strdup2(pool, &id_uri->user, id->
number.
str);
5615 const pjsip_hdr *
request_headers = pjsip_endpt_get_request_headers(endpt);
5616 pjsip_hdr *iter = request_headers->next;
5618 while (iter != request_headers) {
5619 pjsip_hdr *to_erase = iter;
5621 pj_list_erase(to_erase);
5635 #ifdef TEST_FRAMEWORK 5642 info->name =
"xml_sanitization_end_null";
5643 info->category =
"/res/res_pjsip/";
5644 info->summary =
"Ensure XML sanitization works as expected with a long string";
5645 info->description =
"This test sanitizes a string which exceeds the output\n" 5646 "buffer size. Once done the string is confirmed to be NULL terminated.";
5653 if (sanitized[7] !=
'\0') {
5667 info->name =
"xml_sanitization_exceeds_buffer";
5668 info->category =
"/res/res_pjsip/";
5669 info->summary =
"Ensure XML sanitization does not exceed buffer when output won't fit";
5670 info->description =
"This test sanitizes a string which before sanitization would\n" 5671 "fit within the output buffer. After sanitization, however, the string would\n" 5672 "exceed the buffer. Once done the string is confirmed to be NULL terminated.";
5679 if (sanitized[7] !=
'\0') {
5718 if (monitor_thread) {
5720 monitor_thread =
NULL;
5730 pj_pool_release(temp_pool);
5735 if (caching_pool.lock) {
5746 const unsigned int flags = 0;
5754 if (pjsip_endpt_create(&caching_pool.factory,
"SIP", &
ast_pjsip_endpoint) != PJ_SUCCESS) {
5755 ast_log(
LOG_ERROR,
"Failed to create PJSIP endpoint structure. Aborting load\n");
5764 memory_pool = pj_pool_create(&caching_pool.factory,
"SIP", 1024, 1024,
NULL);
5766 ast_log(
LOG_ERROR,
"Failed to create memory pool for SIP. Aborting load\n");
5783 monitor_continue = 1;
5785 NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
5786 if (status != PJ_SUCCESS) {
5807 pjmedia_strerror(0,
NULL, 0);
5815 if (pj_init() != PJ_SUCCESS) {
5819 if (pjlib_util_init() != PJ_SUCCESS) {
5824 if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
5826 ast_log(
LOG_WARNING,
"Failed to register pjmedia error codes. Codes will not be decoded.\n");
5830 ast_log(
LOG_ERROR,
"Failed to initialize SIP 'system' configuration section. Aborting load\n");
5838 if (!sip_threadpool) {
5844 if (!sip_serializer_pool) {
5845 ast_log(
LOG_ERROR,
"Failed to create SIP serializer pool. Aborting load\n");
5860 ast_log(
LOG_ERROR,
"Failed to initialize SIP transport monitor. Aborting load\n");
5868 ast_log(
LOG_ERROR,
"Failed to pre-initialize OPTIONS handling. Aborting load\n");
5873 ast_log(
LOG_ERROR,
"Failed to initialize SIP configuration. Aborting load\n");
5881 ast_log(
LOG_ERROR,
"Failed to initialize SIP transport management. Aborting load\n");
5886 ast_log(
LOG_ERROR,
"Failed to register distributor module. Aborting load\n");
5891 ast_log(
LOG_ERROR,
"Failed to initialize supplement hooks. Aborting load\n");
5896 ast_log(
LOG_ERROR,
"Failed to initialize OPTIONS handling. Aborting load\n");
5901 ast_log(
LOG_ERROR,
"Failed to initialize message IP updating. Aborting load\n");
5960 .requires =
"dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb",
5961 .optional_modules =
"res_statsd",
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
long ast_sip_threadpool_queue_size(void)
Return the size of the SIP threadpool's task queue.
static pj_sockaddr host_ip_ipv6
void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
Add 'user=phone' parameter to URI if enabled and user is a phone number.
int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Register an outbound SIP authenticator.
struct ast_str * output_buffer
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
int sip_cli_print_global(struct ast_sip_cli_context *context)
Information needed to identify an endpoint in a call.
int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
Register a SIP authenticator.
#define AST_CLI_DEFINE(fn, txt,...)
pj_status_t(* create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
char * str
Subscriber phone number (Malloced)
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a response to an out of dialog request.
int ast_res_pjsip_preinit_options_handling(void)
int sip_cli_print_system(struct ast_sip_cli_context *context)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field fromuser
static struct ast_cli_entry cli_commands[]
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
struct ast_threadpool * ast_sip_threadpool(void)
Retrieve the SIP threadpool object.
struct ast_sip_endpoint * ast_sip_identify_endpoint(pjsip_rx_data *rdata)
Determine the endpoint that has sent a SIP message.
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...
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a stateful response to an out of dialog request.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static const pjsip_method * get_pjsip_method(const char *method)
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
Convert the DTMF mode enum value into a string.
static struct ast_threadstorage pj_thread_storage
static struct ast_sip_authenticator * registered_authenticator
void ast_sip_initialize_global_headers(void)
int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text)
Append body data to a SIP message.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
#define AST_RWLIST_INSERT_AFTER
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
void ast_sip_destroy_global_headers(void)
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
static const pjsip_method message_method
void(* callback)(void *token, pjsip_event *e)
const ast_string_field transport
const pjsip_method pjsip_publish_method
Defined method for PUBLISH.
struct ast_party_name name
Subscriber name.
int ast_sip_initialize_distributor(void)
int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Determine if an incoming request requires authentication.
struct ast_sip_endpoint_nat_configuration nat
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
ast_sip_check_auth_result
Possible returns from ast_sip_check_authentication.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
Unregister a SIP authenticator.
#define ast_set_flag(p, flag)
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
const pjsip_method * pmethod
pj_timer_entry * timeout_timer
int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
Get the transport name from an endpoint or request uri.
static struct send_request_data * send_request_data_alloc(struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static struct ast_threadpool * sip_threadpool
pj_thread_t * monitor_thread
static pj_pool_t * pool
Global memory pool for configuration and timers.
struct ast_sip_auth_vector outbound_auths
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP response.
Universally unique identifier support.
int ast_sip_destroy_scheduler(void)
static void sip_thread_start(void)
struct ast_taskprocessor * ast_threadpool_serializer_group(const char *name, struct ast_threadpool *pool, struct ast_serializer_shutdown_group *shutdown_group)
Serialized execution of tasks within a ast_threadpool.
#define AST_TEST_REGISTER(cb)
int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port)
General purpose method for creating an rdata structure using specific information.
pj_caching_pool caching_pool
char * str
Subscriber name (Malloced)
#define ast_cond_wait(cond, mutex)
int ast_copy_pj_str2(char **dest, const pj_str_t *src)
Create and copy a pj_str_t into a standard character buffer.
#define ast_cond_init(cond, attr)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
int ast_sip_initialize_transport_management(void)
static struct @481 methods[]
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.
#define ao2_alloc_options(data_size, destructor_fn, options)
pjsip_dialog * ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
General purpose method for creating a UAS dialog with an endpoint.
#define ast_mutex_lock(a)
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
static const pjsip_method info_method
#define ast_str_alloca(init_len)
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.
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
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...
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth)
Unregister an outbound SIP authenticator.
const char * ast_sip_call_codec_pref_to_str(struct ast_flags pref)
Convert the call codec preference flags to a string.
static int register_service(void *data)
void ast_cli(int fd, const char *fmt,...)
void ast_sip_initialize_dns(void)
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.
void ast_res_pjsip_cleanup_options_handling(void)
#define ast_cond_signal(cond)
#define ast_verb(level,...)
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
static int create_out_of_dialog_request(const pjsip_method *method, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
static int task(void *data)
Queued task for baseline test.
void ast_sip_destroy_transport_events(void)
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
void ast_sip_initialize_resolver(void)
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
pjsip_dialog * ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user)
General purpose method for creating a UAC dialog with an endpoint.
static void * monitor_thread_exec(void *endpt)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define ENDPOINT_IDENTIFIER_FORMAT
#define AST_RWLIST_INSERT_HEAD
#define ast_debug(level,...)
Log a DEBUG message.
void ast_sip_unregister_service(pjsip_module *module)
int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
Checks if the given content type matches type/subtype.
int ast_sip_call_codec_str_to_pref(struct ast_flags *pref, const char *pref_str, int is_outgoing)
Convert a call codec preference string to preference flags.
void ast_sip_destroy_transport_management(void)
void * ast_sip_dict_get(void *ht, const char *key)
Retrieves the value associated with the given key.
static pjsip_module supplement_module
Structure for SIP transport information.
void never_called_res_pjsip(void)
static char * cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
static char * cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 ast_cli_entry * next
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_test_status_update(a, b, c...)
int ast_sip_add_body_multipart(pjsip_tx_data *tdata, const struct ast_sip_body *bodies[], int num_bodies)
Add a multipart body to an outbound SIP message.
struct pjsip_transport * transport
Transport itself.
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
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.
#define AST_RWLIST_TRAVERSE
static int load_pjsip(void)
static int unregister_service(void *data)
#define ao2_ref(o, delta)
static int reload_configuration_task(void *obj)
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
#define AST_RWLIST_REMOVE_CURRENT
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void(* thread_start)(void)
Function to call when a thread starts.
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...
struct ast_sip_supplement * next
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
A set of macros to manage forward-linked lists.
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_RWLIST_INSERT_BEFORE_CURRENT
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting 'disable multi domain'.
An entity with which Asterisk communicates.
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define ast_sip_mod_data_get(mod_data, id, key)
Using the dictionary stored in mod_data array at a given id, retrieve the value associated with the g...
const ast_string_field outbound_proxy
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
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.
int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port, const char *contact)
General purpose method for creating an rdata structure using specific information.
long ast_threadpool_queue_size(struct ast_threadpool *pool)
Return the size of the threadpool's task queue.
#define AST_SIP_X_AST_TXP_LEN
static int unload_module(void)
int ast_sip_initialize_system(void)
struct ast_sip_endpoint_info_configuration info
static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint, pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options)
int ast_res_pjsip_init_options_handling(int reload)
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
Sets pjsip_tpselector from an endpoint or uri.
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...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
static void send_request_data_destroy(void *obj)
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
int ast_sip_initialize_transport_events(void)
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)
#define AST_TEST_UNREGISTER(cb)
static pjsip_endpoint * ast_pjsip_endpoint
enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Method to determine authentication status of an incoming request.
AST_TEST_DEFINE(xml_sanitization_end_null)
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
char * ast_sip_get_endpoint_identifier_order(void)
Retrieve the global endpoint_identifier_order setting.
ast_sip_dtmf_mode
DTMF modes for SIP endpoints.
userdata associated with baseline taskprocessor test
#define ast_cond_destroy(cond)
#define ao2_alloc(data_size, destructor_fn)
#define MAX_RX_CHALLENGES
char * ast_sip_rdata_get_header_value(pjsip_rx_data *rdata, const pj_str_t str)
Get a specific header value from rdata.
static struct ast_serializer_pool * sip_serializer_pool
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_identifier *identifier, const char *name)
Register a SIP endpoint identifier with a name.
unsigned int rewrite_contact
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor's current task.
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
static int reload_module(void)
struct pjsip_tpfactory * factory
Transport factory.
int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
#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.
void ast_sip_message_apply_transport(const char *transport_name, pjsip_tx_data *tdata)
Apply the configuration for a transport to an outgoing message.
struct ast_threadpool * ast_threadpool_create(const char *name, struct ast_threadpool_listener *listener, const struct ast_threadpool_options *options)
Create a new threadpool.
int ast_res_pjsip_reload_configuration(void)
static void endpt_send_request_cb(void *token, pjsip_event *e)
#define SERIALIZER_POOL_SIZE
void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id)
Set name and number information on an identity header.
int ast_res_pjsip_initialize_configuration(void)
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Module has failed to load, may be in an inconsistent state.
static struct ast_threadstorage servant_id_storage
void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
Replace offensive XML characters with XML entities.
struct ast_sip_endpoint_identifier * identifier
An API for managing task processing threads that can be shared across modules.
static pjsip_dialog * create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
An entity responsible for identifying the source of a SIP message.
structure to hold users read from users.conf
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Structure used to handle boolean flags.
static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
pjsip_dialog * ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
General purpose method for creating a UAS dialog with an endpoint.
static int load_module(void)
static int unload_pjsip(void *data)
static int monitor_continue
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct ast_serializer_pool * ast_serializer_pool_create(const char *name, unsigned int size, struct ast_threadpool *threadpool, int timeout)
Create a serializer pool.
void ast_res_pjsip_destroy_configuration(void)
void ast_res_pjsip_cleanup_message_filter(void)
void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
Unregister a an supplement to SIP out of dialog processing.
void * ast_sip_dict_set(pj_pool_t *pool, void *ht, const char *key, void *val)
Set the value for the given key.
#define AST_RWLIST_INSERT_TAIL
static int sync_task(void *data)
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
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.
int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, pjsip_tpselector *selector)
Set the transport on a dialog.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static pj_sockaddr host_ip_ipv4
Standard Command Line Interface.
A supplement to SIP message processing.
void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
Register a supplement to SIP out of dialog processing.
static int do_cli_dump_endpt(void *v_a)
An opaque threadpool structure.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int compare(const char *text, const char *template)
Structure to hold information about an outbound request.
#define AST_SIP_X_AST_TXP
int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending an Out-Of-Dialog SIP request.
void ast_pjproject_log_intercept_end(void)
End PJPROJECT log interception for CLI output.
unsigned int challenge_count
unsigned int allow_unauthenticated_options
int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami, int *count)
Formats the endpoint and sends over AMI.
static void remove_request_headers(pjsip_endpoint *endpt)
int error(const char *format,...)
void ast_sip_add_date_header(pjsip_tx_data *tdata)
Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.
#define ast_mutex_init(pmutex)
int ast_res_pjsip_init_message_filter(void)
unsigned char valid
TRUE if the name information is valid/present.
#define ast_mutex_destroy(a)
int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
Retrieve the local host address in IP form.
an interchangeable way of responding to authentication challenges
void ast_sip_destroy_system(void)
void ast_pjproject_log_intercept_begin(int fd)
Begin PJPROJECT log interception for CLI output.
const ast_string_field aors
static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user, const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
static void stop_monitor_thread(void)
#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...
static void send_request_cb(void *token, pjsip_event *e)
Asterisk module definitions.
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
unsigned int send_cb_called
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
unsigned char valid
TRUE if the number information is valid/present.
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
#define AST_RWLIST_TRAVERSE_SAFE_END
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Structure for mutex and tracking information.
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Sorcery Data Access Layer API.
#define ast_mutex_unlock(a)
const ast_string_field fromdomain
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
struct ast_sip_endpoint * endpoint
struct ast_party_number number
Subscriber phone number.
enum ast_sip_supplement_priority priority
static void send_request_wrapper_destructor(void *obj)
void ast_sip_destroy_distributor(void)