23 #include "asterisk/res_pjsip.h"
25 #include "include/res_pjsip_private.h"
27 #include "asterisk/threadpool.h"
28 #include "asterisk/res_pjsip_cli.h"
30 static int distribute(
void *data);
31 static pj_bool_t distributor(pjsip_rx_data *rdata);
32 static pj_status_t record_serializer(pjsip_tx_data *tdata);
34 static pjsip_module distributor_mod = {
35 .name = {
"Request Distributor", 19},
36 .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 6,
37 .on_tx_request = record_serializer,
38 .on_rx_request = distributor,
39 .on_rx_response = distributor,
44 #define DEFAULT_SUSPECTS_BUCKETS 53
47 static unsigned int unidentified_count;
48 static unsigned int unidentified_period;
49 static unsigned int unidentified_prune_interval;
50 static int using_auth_username;
51 static enum ast_sip_taskprocessor_overload_trigger overload_trigger;
54 struct timeval first_seen;
60 #define DISTRIBUTOR_POOL_SIZE 31
74 static pj_status_t record_serializer(pjsip_tx_data *tdata)
78 serializer = ast_threadpool_serializer_get_current();
83 if (!ast_strlen_zero(name)
84 && (!tdata->mod_data[distributor_mod.id]
85 || strcmp(tdata->mod_data[distributor_mod.id], name))) {
89 tdata_name = pj_pool_alloc(tdata->pool, strlen(name) + 1);
90 strcpy(tdata_name, name);
92 tdata->mod_data[distributor_mod.id] = tdata_name;
113 pjsip_transaction *tsx;
115 pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAC,
116 &rdata->msg_info.cseq->method, rdata);
118 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
120 ast_debug(1,
"Could not find transaction for %s.\n",
121 pjsip_rx_data_get_info(rdata));
124 ast_debug(3,
"Found transaction %s for %s.\n",
125 tsx->obj_name, pjsip_rx_data_get_info(rdata));
128 const char *serializer_name;
130 serializer_name = tsx->last_tx->mod_data[distributor_mod.id];
131 if (!ast_strlen_zero(serializer_name)) {
134 ast_debug(3,
"Found serializer %s on transaction %s\n",
135 serializer_name, tsx->obj_name);
140 #ifdef HAVE_PJ_TRANSACTION_GRP_LOCK
141 pj_grp_lock_release(tsx->grp_lock);
143 pj_mutex_unlock(tsx->mutex);
159 #define DIALOG_ASSOCIATIONS_BUCKETS 251
181 static int buf_hash_add(
const char *pos,
size_t len,
int hash)
184 hash = hash * 33 ^ *pos++;
207 static int buf_hash(
const char *pos,
size_t len)
209 return buf_hash_add(pos, len, 5381);
212 static int dialog_associations_hash(
const void *obj,
int flags)
216 const pjsip_dialog *
dlg;
217 const char buf[
sizeof(pjsip_dialog *)];
226 key.dlg =
object->dlg;
236 static int dialog_associations_cmp(
void *obj,
void *arg,
int flags)
240 const pjsip_dialog *right_key = arg;
243 switch (flags & OBJ_SEARCH_MASK) {
245 right_key = object_right->
dlg;
248 if (object_left->
dlg == right_key) {
267 ao2_wrlock(dialog_associations);
271 dist = ao2_alloc(
sizeof(*dist), NULL);
288 ao2_unlock(dialog_associations);
295 ao2_wrlock(dialog_associations);
299 dist = ao2_alloc(
sizeof(*dist), NULL);
316 ao2_unlock(dialog_associations);
336 static pjsip_dialog *find_dialog(pjsip_rx_data *rdata)
339 pjsip_transaction *tsx;
342 pj_str_t *remote_tag;
344 if (!rdata->msg_info.msg) {
348 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
349 local_tag = &rdata->msg_info.to->tag;
350 remote_tag = &rdata->msg_info.from->tag;
352 local_tag = &rdata->msg_info.from->tag;
353 remote_tag = &rdata->msg_info.to->tag;
361 if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG ||
362 pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method) ||
363 rdata->msg_info.to->tag.slen != 0) {
364 dlg = pjsip_ua_find_dialog(&rdata->msg_info.cid->id, local_tag,
365 remote_tag, PJ_FALSE);
376 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
381 pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAS,
382 pjsip_get_invite_method(), rdata);
384 pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAC,
385 &rdata->msg_info.cseq->method, rdata);
388 tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE);
390 ast_debug(3,
"Could not find matching transaction for %s\n",
391 pjsip_rx_data_get_info(rdata));
395 dlg = pjsip_tsx_get_dlg(tsx);
397 #ifdef HAVE_PJ_TRANSACTION_GRP_LOCK
398 pj_grp_lock_release(tsx->grp_lock);
400 pj_mutex_unlock(tsx->mutex);
423 static int pjstr_hash_add(pj_str_t *str,
int hash)
425 return buf_hash_add(pj_strbuf(str), pj_strlen(str), hash);
440 static int pjstr_hash(pj_str_t *str)
442 return pjstr_hash_add(str, 5381);
448 pj_str_t *remote_tag;
451 if (!rdata->msg_info.msg) {
455 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
456 remote_tag = &rdata->msg_info.from->tag;
458 remote_tag = &rdata->msg_info.to->tag;
462 hash = pjstr_hash(&rdata->msg_info.cid->id);
463 hash = pjstr_hash_add(remote_tag, hash);
466 serializer =
ao2_bump(distributor_pool[hash % ARRAY_LEN(distributor_pool)]);
468 ast_debug(3,
"Calculated serializer %s to use for %s\n",
474 static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata);
476 static pjsip_module endpoint_mod = {
477 .name = {
"Endpoint Identifier", 19},
478 .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 3,
479 .on_rx_request = endpoint_lookup,
482 static pj_bool_t distributor(pjsip_rx_data *rdata)
487 pjsip_rx_data *clone;
497 dlg = find_dialog(rdata);
499 ast_debug(3,
"Searching for serializer associated with dialog %s for %s\n",
500 dlg->obj_name, pjsip_rx_data_get_info(rdata));
507 ast_debug(3,
"Found serializer %s associated with dialog %s\n",
515 }
else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
516 ast_debug(3,
"No dialog serializer for %s. Using request transaction as basis.\n",
517 pjsip_rx_data_get_info(rdata));
518 serializer = find_request_serializer(rdata);
527 }
else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method)
528 || !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_bye_method)) {
530 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata,
531 PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL);
535 if ((overload_trigger == TASKPROCESSOR_OVERLOAD_TRIGGER_GLOBAL &&
537 || (overload_trigger == TASKPROCESSOR_OVERLOAD_TRIGGER_PJSIP_ONLY &&
547 switch (rdata->tp_info.transport->key.type) {
548 case PJSIP_TRANSPORT_UDP6:
549 case PJSIP_TRANSPORT_UDP:
550 ast_debug(3,
"Taskprocessor overload alert: Ignoring '%s'.\n",
551 pjsip_rx_data_get_info(rdata));
554 ast_debug(3,
"Taskprocessor overload on non-udp transport. Received:'%s'. "
555 "Responding with a 503.\n", pjsip_rx_data_get_info(rdata));
556 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata,
557 PJSIP_SC_SERVICE_UNAVAILABLE, NULL, NULL, NULL);
568 if (pjsip_rx_data_clone(rdata, 0, &clone) != PJ_SUCCESS) {
582 ao2_cleanup(clone->endpt_info.mod_data[endpoint_mod.id]);
583 pjsip_rx_data_free_cloned(clone);
591 static struct ast_sip_auth *alloc_artificial_auth(
char *default_realm)
604 fake_auth->
type = AST_SIP_AUTH_TYPE_ARTIFICIAL;
611 static int create_artificial_auth(
void)
613 char default_realm[AST_SIP_AUTH_MAX_REALM_LENGTH + 1];
616 ast_sip_get_default_realm(default_realm,
sizeof(default_realm));
617 fake_auth = alloc_artificial_auth(default_realm);
619 ast_log(LOG_ERROR,
"Unable to create artificial auth\n");
635 static int create_artificial_endpoint(
void)
637 artificial_endpoint =
ast_sorcery_alloc(ast_sip_get_sorcery(),
"endpoint", NULL);
638 if (!artificial_endpoint) {
653 ao2_ref(artificial_endpoint, +1);
654 return artificial_endpoint;
657 static void log_failed_request(pjsip_rx_data *rdata,
char *msg,
unsigned int count,
unsigned int period)
659 char from_buf[PJSIP_MAX_URL_SIZE];
660 char callid_buf[PJSIP_MAX_URL_SIZE];
661 char method_buf[PJSIP_MAX_URL_SIZE];
662 char src_addr_buf[AST_SOCKADDR_BUFLEN];
663 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->msg_info.from->uri, from_buf, PJSIP_MAX_URL_SIZE);
664 ast_copy_pj_str(callid_buf, &rdata->msg_info.cid->id, PJSIP_MAX_URL_SIZE);
665 ast_copy_pj_str(method_buf, &rdata->msg_info.msg->line.req.method.name, PJSIP_MAX_URL_SIZE);
667 ast_log(LOG_NOTICE,
"Request '%s' from '%s' failed for '%s' (callid: %s) - %s"
668 " after %u tries in %.3f ms\n",
669 method_buf, from_buf,
670 pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buf,
sizeof(src_addr_buf), 3),
671 callid_buf, msg, count, period / 1000.0);
673 ast_log(LOG_NOTICE,
"Request '%s' from '%s' failed for '%s' (callid: %s) - %s\n",
674 method_buf, from_buf,
675 pj_sockaddr_print(&rdata->pkt_info.src_addr, src_addr_buf,
sizeof(src_addr_buf), 3),
688 if (ms < (unidentified_period * 1000) && unid->count >= unidentified_count) {
689 log_failed_request(rdata,
"No matching endpoint found", unid->count, ms);
695 static int apply_endpoint_acl(pjsip_rx_data *rdata,
struct ast_sip_endpoint *endpoint);
696 static int apply_endpoint_contact_acl(pjsip_rx_data *rdata,
struct ast_sip_endpoint *endpoint);
698 static void apply_acls(pjsip_rx_data *rdata)
703 endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
704 if (endpoint != artificial_endpoint
705 && (apply_endpoint_acl(rdata, endpoint)
706 || apply_endpoint_contact_acl(rdata, endpoint))) {
707 ast_debug(1,
"Endpoint '%s' not allowed by ACL\n",
711 ao2_replace(rdata->endpt_info.mod_data[endpoint_mod.id], artificial_endpoint);
715 static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata)
719 int is_ack = rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD;
721 endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
729 unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
OBJ_SEARCH_KEY);
738 endpoint = ast_sip_identify_endpoint(rdata);
740 unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
OBJ_SEARCH_KEY);
753 endpoint = ast_sip_get_artificial_endpoint();
757 rdata->endpt_info.mod_data[endpoint_mod.id] = endpoint;
759 if (endpoint == artificial_endpoint && !is_ack) {
760 char name[AST_UUID_STR_LEN] =
"";
761 pjsip_uri *from = rdata->msg_info.from->uri;
763 if (ast_sip_is_allowed_uri(from)) {
764 ast_copy_pj_str(name, ast_sip_pjsip_uri_get_username(from),
sizeof(name));
767 unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
OBJ_SEARCH_KEY);
769 check_endpoint(rdata, unid, name);
771 }
else if (using_auth_username) {
772 ao2_wrlock(unidentified_requests);
774 unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
777 check_endpoint(rdata, unid, name);
779 unid = ao2_alloc_options(
sizeof(*unid) + strlen(rdata->pkt_info.src_name) + 1,
782 ao2_unlock(unidentified_requests);
783 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
786 strcpy(unid->src_name, rdata->pkt_info.src_name);
792 ao2_unlock(unidentified_requests);
794 log_failed_request(rdata,
"No matching endpoint found", 0, 0);
803 static int apply_endpoint_acl(pjsip_rx_data *rdata,
struct ast_sip_endpoint *endpoint)
811 memset(&addr, 0,
sizeof(addr));
816 log_failed_request(rdata,
"Not match Endpoint ACL", 0, 0);
823 static int extract_contact_addr(pjsip_contact_hdr *contact,
struct ast_sockaddr **addrs)
825 pjsip_sip_uri *sip_uri;
828 if (!contact || contact->star) {
833 if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
837 sip_uri = pjsip_uri_get_uri(contact->uri);
838 ast_copy_pj_str(host, &sip_uri->host,
sizeof(host));
842 static int apply_endpoint_contact_acl(pjsip_rx_data *rdata,
struct ast_sip_endpoint *endpoint)
844 int num_contact_addrs;
848 pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
854 while ((contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
855 num_contact_addrs = extract_contact_addr(contact, &contact_addrs);
856 if (num_contact_addrs <= 0) {
859 for (i = 0; i < num_contact_addrs; ++i) {
861 log_failed_request(rdata,
"Not match Endpoint Contact ACL", 0, 0);
867 ast_free(contact_addrs);
877 static pj_bool_t authenticate(pjsip_rx_data *rdata)
880 int is_ack = rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD;
882 ast_assert(endpoint != NULL);
888 if (ast_sip_requires_authentication(endpoint, rdata)) {
889 pjsip_tx_data *tdata;
892 pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, 401, NULL, &tdata);
893 switch (ast_sip_check_authentication(endpoint, rdata, tdata)) {
894 case AST_SIP_AUTHENTICATION_CHALLENGE:
897 if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
898 pjsip_tx_data_dec_ref(tdata);
901 case AST_SIP_AUTHENTICATION_SUCCESS:
903 unid = ao2_find(unidentified_requests, rdata->pkt_info.src_name,
OBJ_SEARCH_KEY);
910 case AST_SIP_AUTHENTICATION_FAILED:
911 log_failed_request(rdata,
"Failed to authenticate", 0, 0);
913 if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
914 pjsip_tx_data_dec_ref(tdata);
917 case AST_SIP_AUTHENTICATION_ERROR:
918 log_failed_request(rdata,
"Error to authenticate", 0, 0);
920 pjsip_tx_data_dec_ref(tdata);
921 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
924 pjsip_tx_data_dec_ref(tdata);
925 }
else if (endpoint == artificial_endpoint) {
927 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
934 static pjsip_module auth_mod = {
935 .name = {
"Request Authenticator", 21},
936 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 2,
937 .on_rx_request = authenticate,
940 static int distribute(
void *data)
942 static pjsip_process_rdata_param param = {
943 .start_mod = &distributor_mod,
944 .idx_after_start = 1,
946 pj_bool_t handled = PJ_FALSE;
947 pjsip_rx_data *rdata = data;
948 int is_request = rdata->msg_info.msg->type == PJSIP_REQUEST_MSG;
949 int is_ack = is_request ? rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD : 0;
952 pjsip_endpt_process_rx_data(ast_sip_get_pjsip_endpoint(), rdata, ¶m, &handled);
953 if (!handled && is_request && !is_ack) {
954 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 501, NULL, NULL, NULL);
960 endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
961 ao2_cleanup(endpoint);
962 pjsip_rx_data_free_cloned(rdata);
968 struct ast_sip_endpoint *endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
975 static int suspects_sort(
const void *obj,
const void *arg,
int flags)
979 const char *right_key = arg;
982 switch (flags & OBJ_SEARCH_MASK) {
984 right_key = object_right->src_name;
987 cmp = strcmp(object_left->src_name, right_key);
990 cmp = strncmp(object_left->src_name, right_key, strlen(right_key));
999 static int suspects_compare(
void *obj,
void *arg,
int flags)
1003 const char *right_key = arg;
1006 switch (flags & OBJ_SEARCH_MASK) {
1008 right_key = object_right->src_name;
1011 if (strcmp(object_left->src_name, right_key) == 0) {
1016 if (strncmp(object_left->src_name, right_key, strlen(right_key)) == 0) {
1027 static int suspects_hash(
const void *obj,
int flags)
1032 switch (flags & OBJ_SEARCH_MASK) {
1038 key =
object->src_name;
1048 static struct ao2_container *cli_unid_get_container(
const char *regex)
1053 suspects_sort, suspects_compare);
1073 static void *cli_unid_retrieve_by_id(
const char *
id)
1078 static const char *cli_unid_get_id(
const void *obj)
1082 return unid->src_name;
1085 static int cli_unid_print_header(
void *obj,
void *arg,
int flags)
1090 int indent = CLI_INDENT_TO_SPACES(context->
indent_level);
1091 int filler = CLI_LAST_TABSTOP - indent - 7;
1096 "%*s: <IP Address%*.*s> <Count> <Age(sec)>\n",
1097 indent,
"Request", filler, filler, CLI_HEADER_FILLER);
1102 static int cli_unid_print_body(
void *obj,
void *arg,
int flags)
1113 flexwidth = CLI_LAST_TABSTOP - 4;
1118 flexwidth, flexwidth,
1119 unid->src_name, unid->count, ms / 1000.0);
1125 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Unidentified Requests",
1126 .
command =
"pjsip show unidentified_requests",
1127 .
usage =
"Usage: pjsip show unidentified_requests\n"
1128 " Show the PJSIP Unidentified Requests\n"),
1133 static int expire_requests(
void *
object,
void *arg,
int flags)
1139 if (ms > (*maxage) * 2 * 1000) {
1146 static int prune_task(
const void *data)
1148 unsigned int maxage;
1150 ast_sip_get_unidentified_request_thresholds(&unidentified_count, &unidentified_period, &unidentified_prune_interval);
1151 maxage = unidentified_period * 2;
1154 return unidentified_prune_interval * 1000;
1157 static int clean_task(
const void *data)
1162 static void global_loaded(
const char *object_type)
1164 char default_realm[AST_SIP_AUTH_MAX_REALM_LENGTH + 1];
1166 char *identifier_order;
1169 identifier_order = ast_sip_get_endpoint_identifier_order();
1170 if (identifier_order) {
1171 char *identify_method;
1175 ast_free(identifier_order);
1176 while ((identify_method =
ast_strip(strsep(&io_copy,
",")))) {
1177 if (!strcmp(identify_method,
"auth_username")) {
1182 using_auth_username = new_using;
1186 ast_sip_get_default_realm(default_realm,
sizeof(default_realm));
1187 fake_auth = ast_sip_get_artificial_auth();
1188 if (!fake_auth || strcmp(fake_auth->
realm, default_realm)) {
1189 ao2_cleanup(fake_auth);
1191 fake_auth = alloc_artificial_auth(default_realm);
1196 ao2_cleanup(fake_auth);
1198 ast_sip_get_unidentified_request_thresholds(&unidentified_count, &unidentified_period, &unidentified_prune_interval);
1200 overload_trigger = ast_sip_get_taskprocessor_overload_trigger();
1205 if (
ast_sched_add_variable(prune_context, unidentified_prune_interval * 1000, prune_task, NULL, 1) < 0) {
1220 static void distributor_pool_shutdown(
void)
1224 for (idx = 0; idx < ARRAY_LEN(distributor_pool); ++idx) {
1226 distributor_pool[idx] = NULL;
1238 static int distributor_pool_setup(
void)
1243 for (idx = 0; idx < ARRAY_LEN(distributor_pool); ++idx) {
1248 if (!distributor_pool[idx]) {
1255 int ast_sip_initialize_distributor(
void)
1258 DEFAULT_SUSPECTS_BUCKETS, suspects_hash, NULL, suspects_compare);
1259 if (!unidentified_requests) {
1264 DIALOG_ASSOCIATIONS_BUCKETS, dialog_associations_hash, NULL,
1265 dialog_associations_cmp);
1266 if (!dialog_associations) {
1267 ast_sip_destroy_distributor();
1271 if (distributor_pool_setup()) {
1272 ast_sip_destroy_distributor();
1277 if (!prune_context) {
1278 ast_sip_destroy_distributor();
1283 ast_sip_destroy_distributor();
1290 if (create_artificial_endpoint() || create_artificial_auth()) {
1291 ast_sip_destroy_distributor();
1295 if (ast_sip_register_service(&distributor_mod)) {
1296 ast_sip_destroy_distributor();
1299 if (ast_sip_register_service(&endpoint_mod)) {
1300 ast_sip_destroy_distributor();
1303 if (ast_sip_register_service(&auth_mod)) {
1304 ast_sip_destroy_distributor();
1310 if (!unid_formatter) {
1311 ast_sip_destroy_distributor();
1312 ast_log(LOG_ERROR,
"Unable to allocate memory for unid_formatter\n");
1315 unid_formatter->
name =
"unidentified_request";
1317 unid_formatter->
print_body = cli_unid_print_body;
1319 unid_formatter->
iterate = cli_unid_iterate;
1320 unid_formatter->
get_id = cli_unid_get_id;
1322 ast_sip_register_cli_formatter(unid_formatter);
1329 void ast_sip_destroy_distributor(
void)
1332 ast_sip_unregister_cli_formatter(unid_formatter);
1334 ast_sip_unregister_service(&auth_mod);
1335 ast_sip_unregister_service(&endpoint_mod);
1336 ast_sip_unregister_service(&distributor_mod);
1339 ao2_cleanup(artificial_endpoint);
1343 if (prune_context) {
1347 distributor_pool_shutdown();
1349 ao2_cleanup(dialog_associations);
1350 ao2_cleanup(unidentified_requests);
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
void ast_sip_report_auth_failed_challenge_response(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Send a security event notification for when a challenge response has failed.
struct ast_str * output_buffer
struct ao2_container *(* get_container)(const char *regex)
void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb)
Clean all scheduled events with matching callback.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
Asterisk main include file. File version handling, generic pbx functions.
char name[0]
Friendly name of the taskprocessor. Subsystem is appended after the name's NULL terminator.
CLI Formatter Registry Entry.
int( ao2_callback_fn)(void *obj, void *arg, int flags)
Type of a generic callback function.
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.
The arg parameter is a search key, but is not an object.
void ast_sip_report_auth_success(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Send a security event notification for when authentication succeeds.
void ast_sip_dialog_set_serializer(pjsip_dialog *dlg, struct ast_taskprocessor *serializer)
Set a serializer on a SIP dialog so requests and responses are automatically serialized.
descriptor for a cli entry.
#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.
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
void ast_sip_dialog_set_endpoint(pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint)
Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup.
Assume that the ao2_container is already locked.
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
CLI Formatter Context passed to all formatters.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Socket address structure.
void ast_sip_report_auth_challenge_sent(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Send a security event notification for when an authentication challenge is sent.
struct ast_acl_list * acl
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
struct ast_acl_list * contact_acl
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct ast_sip_endpoint * ast_sip_dialog_get_endpoint(pjsip_dialog *dlg)
Get the endpoint associated with this dialog.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void *(* retrieve_by_id)(const char *id)
struct ao2_container * container
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_sip_endpoint * endpoint
An entity with which Asterisk communicates.
enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
Apply a set of rules to a given IP address.
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
struct ast_sip_auth_vector inbound_auths
#define ao2_unlink(container, obj)
Remove an object from a container.
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
const ast_string_field realm
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Interface for a sorcery object type observer.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
unsigned int ast_taskprocessor_get_subsystem_alert(const char *subsystem)
Get the current taskprocessor high water alert count by subsystem.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
struct ast_taskprocessor * ast_sip_get_distributor_serializer(pjsip_rx_data *rdata)
Determine the distributor serializer for the SIP message.
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
void ast_sip_report_failed_acl(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
Send a security event notification for when an ACL check fails.
const ast_string_field auth_pass
struct ast_taskprocessor * serializer
enum ast_sip_auth_type type
An API for managing task processing threads that can be shared across modules.
const char *(* get_id)(const void *obj)
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
return a reference to a taskprocessor ONLY if it already exists
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
The arg parameter is an object of the same type.
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
A ast_taskprocessor structure is a singleton by name.
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
static force_inline int attribute_pure ast_str_hash_restrict(unsigned int hash)
Restrict hash value range.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
unsigned int ast_taskprocessor_alert_get(void)
Get the current taskprocessor high water alert count.
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
ao2_callback_fn * print_header
void ast_sip_report_invalid_endpoint(const char *name, pjsip_rx_data *rdata)
Send a security event notification for when an invalid endpoint is requested.
Search option field mask.
ao2_callback_fn * print_body
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
const ast_string_field auth_user
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.