96#define DEFAULT_LANGUAGE "en"
97#define DEFAULT_ENCODING "identity"
101#define AOR_BUCKETS 61
103#define AOR_BUCKETS 1567
108#define CONTACT_STATUS_BUCKETS 61
110#define CONTACT_STATUS_BUCKETS 1567
114#define CONTACT_BUCKETS 13
117#define ENDPOINT_STATE_COMPOSITOR_BUCKETS 13
120#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE 1
123#define AOR_STATUS_BUCKETS 3
126#define MAX_UNLOAD_TIMEOUT_TIME 10
217 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
218 pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
219 pjsip_tx_data *tdata;
220 const pjsip_hdr *hdr;
225 if (
status != PJ_SUCCESS) {
231 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ACCEPT,
NULL))) {
232 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
234 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ALLOW,
NULL))) {
235 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
237 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_SUPPORTED,
NULL))) {
238 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
250 status = pjsip_dlg_send_response(dlg, trans, tdata);
259 if (
status != PJ_SUCCESS) {
272 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
280 ruri = rdata->msg_info.msg->line.req.uri;
310 .name = {
"Options Module", 14},
312 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
357 size_t size =
sizeof(*contact_status) + strlen(
name) + 1;
361 if (!contact_status) {
370 return contact_status;
412 ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
413 ast_sip_contact_status_cmp_fn);
454 if (mgmt_serializer) {
490 if (contact_status) {
492 return contact_status;
497 if (!contact_status) {
502 contact_status->
rtt = 0;
521 return contact_status;
569 char *
names[PJSIP_MAX_RESOLVED_ADDRESSES];
582 for (idx = 0; idx <
task_data->count; ++idx) {
607 for (idx = 0; idx <
task_data->count; ++idx) {
608 pjsip_tx_data *tdata;
610 pjsip_transaction *tsx =
NULL;
613 batch->contact, &tdata)) {
620 pjsip_tx_data_dec_ref(tdata);
631 tdata->dest_info.addr.count = 1;
632 tdata->dest_info.cur_addr = 0;
633 tdata->dest_info.addr.entry[0].type =
task_data->addresses.entry[idx].type;
634 tdata->dest_info.addr.entry[0].priority =
task_data->addresses.entry[idx].priority;
635 tdata->dest_info.addr.entry[0].weight =
task_data->addresses.entry[idx].weight;
636 tdata->dest_info.addr.entry[0].addr_len =
task_data->addresses.entry[idx].addr_len;
637 pj_sockaddr_cp(&tdata->dest_info.addr.entry[0].addr,
639 pj_strdup(tdata->pool, &tdata->dest_info.addr.entry[0].name,
641 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA,
NULL);
643 via->branch_param.slen = 0;
648 (
int)(
batch->aor_options->qualify_timeout * 1000),
677 pj_grp_lock_dec_ref(tsx->grp_lock);
698 pjsip_tsx_terminate_async(tsx, PJSIP_SC_REQUEST_TERMINATED);
766 if (!endpoint_state_compositor->
active) {
772 ast_debug(3,
"Endpoint state compositor '%s' is online as AOR '%s' is available\n",
773 endpoint_state_compositor->
name,
name);
796 ao2_lock(endpoint_state_compositor);
827 ao2_ref(contact_callback_data, -1);
835 ao2_ref(contact_callback_data, -1);
844 ao2_ref(contact_callback_data, -1);
852 ao2_ref(contact_callback_data, -1);
886 ast_verb(3,
"Contact %s/%s is now %s. RTT: %.3f msec\n",
890 cs_new->
rtt / 1000.0);
905 ast_debug(3,
"Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
909 cs_new->
rtt / 1000.0);
925 ast_debug(3,
"AOR '%s' now has %d available contacts\n",
930 ao2_ref(contact_callback_data, -1);
951 if (!
batch->completed) {
959 batch->completed = 1;
964 }
else if (!
batch->pending) {
966 batch->completed = 1;
1023 switch(e->body.tsx_state.type) {
1027 case PJSIP_EVENT_TRANSPORT_ERROR:
1028 case PJSIP_EVENT_TIMER:
1031 case PJSIP_EVENT_RX_MSG:
1033 (e->body.tsx_state.tsx->status_code < 200 || e->body.tsx_state.tsx->status_code >= 300)) {
1039 case PJSIP_EVENT_USER:
1045 ast_debug(3,
"Received user event for contact '%s', ignoring\n",
1048 ao2_ref(contact_callback_data, -1);
1053 ao2_ref(contact_callback_data, -1);
1069 pjsip_tx_data_dec_ref(contact_callback_data->
resolve_tdata);
1086 if (!contact_callback_data) {
1091 ao2_ref(contact_callback_data, -1);
1101 return contact_callback_data;
1114 const pjsip_tx_data *tdata, pjsip_host_info *destination)
1116 pjsip_transport_type_e transport_type = PJSIP_TRANSPORT_UNSPECIFIED;
1118 if ((tdata->tp_sel.type != PJSIP_TPSELECTOR_TRANSPORT
1119 && tdata->tp_sel.type != PJSIP_TPSELECTOR_LISTENER)
1120 || !tdata->tp_sel.u.ptr) {
1124 if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
1125 transport_type = tdata->tp_sel.u.transport->key.type;
1127 transport_type = tdata->tp_sel.u.listener->type;
1130 if (destination->type != PJSIP_TRANSPORT_UNSPECIFIED
1131 && ((destination->type | PJSIP_TRANSPORT_IPV6)
1132 != (transport_type | PJSIP_TRANSPORT_IPV6))) {
1133 return PJSIP_ETPNOTSUITABLE;
1136 destination->type = transport_type;
1142 const pjsip_server_addresses *addresses)
1157 "Unable to allocate qualify resolve task for '%s'\n",
1168 if (
batch->resolve_tdata) {
1169 pjsip_tx_data_dec_ref(
batch->resolve_tdata);
1176 "Unable to queue qualify resolve task for '%s'\n",
1186 if (
task_data->count > PJSIP_MAX_RESOLVED_ADDRESSES) {
1187 task_data->count = PJSIP_MAX_RESOLVED_ADDRESSES;
1190 for (idx = 0; idx <
task_data->count; ++idx) {
1204 task_data->addresses.entry[idx].name.ptr = name_copy;
1212 if (
batch->resolve_tdata) {
1213 pjsip_tx_data_dec_ref(
batch->resolve_tdata);
1224 "Unable to queue qualify resolve task for '%s'\n",
1241 pjsip_tx_data *tdata;
1242 pjsip_host_info destination;
1246 ast_debug(3,
"Qualifying contact '%s' on AOR '%s'\n",
1258 endpoint_state_compositor->
name);
1261 ast_debug(3,
"Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
1273 ast_log(
LOG_ERROR,
"Unable to create request to qualify contact %s on AOR %s\n",
1274 contact->
uri, aor_options->
name);
1281 ast_log(
LOG_ERROR,
"Unable to apply outbound proxy on request to qualify contact %s\n",
1283 pjsip_tx_data_dec_ref(tdata);
1288 if (!contact_status) {
1289 ast_log(
LOG_ERROR,
"Unable to retrieve contact status information for contact %s on AOR %s\n",
1290 contact->
uri, aor_options->
name);
1291 pjsip_tx_data_dec_ref(tdata);
1297 aor_options, endpoint, tdata);
1298 if (!contact_callback_data) {
1299 ast_log(
LOG_ERROR,
"Unable to create object to contain callback data for contact %s on AOR %s\n",
1300 contact->
uri, aor_options->
name);
1301 pjsip_tx_data_dec_ref(tdata);
1312 if (pjsip_get_request_dest(tdata, &destination) != PJ_SUCCESS
1315 ast_log(
LOG_ERROR,
"Unable to resolve destination to qualify contact %s on AOR %s\n",
1316 contact->
uri, aor_options->
name);
1317 ao2_ref(contact_callback_data, -1);
1335 ast_debug(3,
"Qualifying all contacts on AOR '%s'\n", aor_options->
name);
1423 ast_debug(3,
"Attempted to remove contact status for '%s' but it does not exist\n",
1428 ast_verb(2,
"Contact %s/%s has been deleted\n", contact->
aor, contact->
uri);
1468 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->
name,
1500 int initial_interval;
1504 initial_interval = max_time;
1510 return 0 < initial_interval ? initial_interval : 1;
1537 ast_verb(3,
"Contact %s/%s is now %s.\n",
1538 cs_new->
aor, cs_new->
uri,
1564 if (!contact_status) {
1568 switch (contact_status->
status) {
1591 if (!contact_status) {
1595 switch (contact_status->
status) {
1619 if (!contact_status) {
1624 switch (contact_status->
status) {
1651 ast_debug(3,
"Configuring AOR '%s' with current state of configuration and world\n",
1662 if (!existing_contacts) {
1663 ast_log(
LOG_WARNING,
"Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1690 char prefix[prefix_len + 1];
1714 ao2_ref(existing_contacts, -1);
1727 ast_debug(3,
"AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1733 ast_debug(3,
"AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1774 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
1780 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->
name,
1793 ast_debug(3,
"Synchronizing AOR '%s' with current state of configuration and world\n",
1811 ao2_lock(endpoint_state_compositor);
1812 endpoint_state_compositor->
active = 0;
1884 if (endpoint_state_compositor) {
1886 return endpoint_state_compositor;
1889 endpoint_state_compositor =
ao2_alloc(
sizeof(*endpoint_state_compositor)
1892 if (!endpoint_state_compositor) {
1903 sip_options_endpoint_aor_status_hash_fn,
NULL,
1904 sip_options_endpoint_aor_status_cmp_fn);
1907 ao2_ref(endpoint_state_compositor, -1);
1917 return endpoint_state_compositor;
1936 ast_debug(3,
"Adding endpoint compositor '%s' to AOR '%s'\n",
1941 task_data->endpoint_state_compositor)) {
1965 ast_debug(3,
"Removing endpoint compositor '%s' from AOR '%s'\n",
1966 task_data->endpoint_state_compositor->name,
1973 if (endpoint_state_compositor !=
task_data->endpoint_state_compositor) {
1978 ao2_ref(endpoint_state_compositor, -1);
1999 ast_debug(3,
"Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
2004 ast_debug(3,
"Synchronizing endpoint '%s' with AORs '%s'\n",
2013 ast_debug(3,
"Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
2025 ast_debug(3,
"Endpoint '%s' referenced invalid AOR '%s'\n",
2030 if (!
task_data.endpoint_state_compositor) {
2037 if (!
task_data.endpoint_state_compositor) {
2039 "Could not create endpoint state compositor for '%s', endpoint state will be incorrect\n",
2063 if (
task_data.endpoint_state_compositor) {
2069 task_data.endpoint_state_compositor->active = 1;
2080 ast_debug(3,
"Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
2116 ast_debug(3,
"AOR '%s' is no longer configured, removing it\n", aor_options->
name);
2245 ast_debug(3,
"Removing endpoint state compositor '%s' from AOR '%s'\n",
2275 if (!endpoint_state_compositor) {
2279 ast_debug(3,
"Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
2282 ao2_ref(endpoint_state_compositor, -1);
2303 ast_debug(3,
"Endpoint '%s' has been created or modified, updating state\n",
2308 if (endpoint_state_compositor) {
2311 ao2_ref(endpoint_state_compositor, -1);
2342 ast_debug(3,
"Individually updating AOR '%s' with current state of configuration and world\n",
2349 ast_debug(3,
"After modifying AOR '%s' it has now become available\n",
2353 ast_debug(3,
"After modifying AOR '%s' it has become unavailable\n",
2441 ast_debug(3,
"AOR '%s' has been deleted, removing it\n", aor_options->
name);
2511 if (
task_data->aor_options->qualify_frequency) {
2516 ast_debug(3,
"Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2524 if (
task_data->aor_options->sched_task) {
2534 if (!
task_data->aor_options->sched_task) {
2535 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
2545 if (
task_data->aor_options->available == 1) {
2546 ast_debug(3,
"An unqualified contact has been added to AOR '%s' so it is now available\n",
2574 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2609 if (contact_status) {
2610 switch (contact_status->
status) {
2642 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2690 if (
task_data->aor_options->qualify_frequency) {
2693 ast_debug(3,
"Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2695 if (
task_data->aor_options->sched_task) {
2704 if (!
task_data->aor_options->available) {
2705 ast_debug(3,
"An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2755 const char *endpoint_name;
2763 "Usage: pjsip qualify <endpoint>\n"
2764 " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2774 endpoint_name =
a->argv[2];
2779 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2784 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2797 ast_cli(
a->fd,
"Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2876 astman_send_listack(s, m,
"A listing of Contacts follows, presented as ContactList events",
2892 const char *endpoint_name;
2898 e->
command =
"pjsip show qualify endpoint";
2900 "Usage: pjsip show qualify endpoint <id>\n"
2901 " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2911 endpoint_name =
a->argv[4];
2916 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2921 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2934 ast_cli(
a->fd,
" * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2949 const char *aor_name;
2953 e->
command =
"pjsip show qualify aor";
2955 "Usage: pjsip show qualify aor <id>\n"
2956 " Show the PJSIP Aor current qualify options.\n";
2966 aor_name =
a->argv[4];
2970 ast_cli(
a->fd,
"Unable to retrieve aor '%s' qualify options\n", aor_name);
2974 ast_cli(
a->fd,
" * AOR '%s'\n", aor_name);
2987 const char *endpoint_name;
2993 e->
command =
"pjsip reload qualify endpoint";
2995 "Usage: pjsip reload qualify endpoint <id>\n"
2996 " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
3006 endpoint_name =
a->argv[4];
3011 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
3016 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
3029 ast_cli(
a->fd,
"Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
3041 const char *aor_name;
3045 e->
command =
"pjsip reload qualify aor";
3047 "Usage: pjsip reload qualify aor <id>\n"
3048 " Synchronize the PJSIP Aor qualify options.\n";
3058 aor_name =
a->argv[4];
3062 ast_cli(
a->fd,
"Unable to retrieve aor '%s'\n", aor_name);
3066 ast_cli(
a->fd,
"Synchronizing AOR '%s'\n", aor_name);
3193 ami->
arg = (
void *)endpoint;
3209 ast_debug(2,
"Cleaning up AOR '%s' for shutdown\n", aor_options->
name);
3264 if (mgmt_serializer) {
3315 static const pj_str_t STR_OPTIONS = {
"OPTIONS", 7 };
3328 NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
3334 sip_options_aor_hash_fn,
NULL, sip_options_aor_cmp_fn);
3342 sip_options_endpoint_state_compositor_hash_fn,
NULL,
3343 sip_options_endpoint_state_compositor_cmp_fn);
3350 if (!mgmt_serializer) {
void ast_cli_unregister_multiple(void)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
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.
#define ao2_iterator_next(iter)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_RWLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
#define ao2_unlink(container, obj)
Remove an object from a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AO2_STRING_FIELD_SORT_FN(stype, field)
Creates a sort function for a structure string field.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#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.
#define ao2_container_clone(orig, flags)
Create a clone/copy of the given container.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
static struct cdr_batch * batch
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
General Asterisk PBX channel definitions.
#define AST_MAX_EXTENSION
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
ast_endpoint_state
Valid states for an endpoint.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
struct ast_taskprocessor * ast_sip_get_distributor_serializer_hash(int hash)
Determine the distributor serializer for a given hash.
#define ast_sip_push_task(serializer, sip_task, task_data)
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
struct ast_sip_sched_task * ast_sip_schedule_task(struct ast_taskprocessor *serializer, int interval, ast_sip_task sip_task, const char *name, void *task_data, enum ast_sip_scheduler_task_flags flags)
Schedule a task to run in the res_pjsip taskpool.
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
@ AST_SIP_SCHED_TASK_DATA_AO2
@ AST_SIP_SCHED_TASK_VARIABLE
static char prefix[MAX_PREFIX]
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
static struct ao2_container * endpoints
#define EVENT_FLAG_REPORTING
#define EVENT_FLAG_SYSTEM
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Core PBX routines and definitions.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static pjsip_module options_module
static void aor_observer_deleted(const void *obj)
Observer callback invoked on AOR deletion.
static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
int ast_res_pjsip_preinit_options_handling(void)
static struct ao2_container * sip_options_aors
static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
Count AVAILABLE qualified contacts.
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE
The initial vector size for the endpoint state compositors on an AOR.
static int sip_options_target_result_task(void *obj)
Combine the result of one resolved target with the other targets.
static void sip_contact_status_dtor(void *obj)
Destructor for contact statuses.
static int sip_options_synchronize_aor_task(void *obj)
Task to synchronize an AOR with our local state.
static void sip_options_endpoint_unlink_aor_feeders(struct ast_sip_endpoint *endpoint, struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Unlink AORs feeding the endpoint status compositor.
static char * cli_reload_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void sip_options_aor_dtor(void *obj)
Destructor function for SIP OPTIONS AORs.
static char * cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int sip_options_endpoint_observer_modified_task(void *obj)
Task to synchronize the endpoint.
static int sip_options_aor_observer_deleted_task(void *obj)
Task to delete an AOR from the known universe.
static struct ast_taskprocessor * management_serializer
static int sip_options_contact_update_task(void *obj)
Task which updates a dynamic contact to an AOR.
static void endpoint_observer_modified(const void *obj)
Observer callback invoked on endpoint creation or modification.
static void aor_observer_modified(const void *obj)
Observer callback invoked on AOR creation or modification.
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
static struct ao2_container * get_all_contacts(void)
static void contact_observer_created(const void *obj)
Observer callback invoked on contact creation.
static void contact_observer_deleted(const void *obj)
Observer callback invoked on contact deletion.
static void sip_options_endpoint_state_compositor_dtor(void *obj)
Destructor for endpoint state compositors.
static struct sip_options_endpoint_state_compositor * sip_options_endpoint_state_compositor_find_or_alloc(const struct ast_sip_endpoint *endpoint)
Find (or create) an endpoint state compositor.
#define AOR_STATUS_BUCKETS
These are the number of buckets (per endpoint state compositor) to use to store AOR statuses.
static void qualify_contact_cb(void *token, pjsip_event *e)
Callback for an OPTIONS response, timeout, or transport error.
static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
Transition the contact status to unqualified mode.
int ast_res_pjsip_init_options_handling(int reload)
static void contact_observer_updated(const void *obj)
Observer callback invoked on contact update.
static int sip_options_endpoint_observer_deleted_task(void *obj)
Task to delete an endpoint from the known universe.
static int sip_contact_to_ami(const struct ast_sip_contact *contact, struct ast_str **buf)
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.
static int sip_options_contact_add_management_task(void *obj)
Task to add a dynamic contact to an AOR in its serializer.
static const char * short_status_map[]
static int sip_options_aor_remove_task(void *obj)
Task which removes an AOR from all of the ESCs it is reporting to.
static struct ao2_container * sip_options_contact_statuses
static int sip_options_cleanup_aor_task(void *obj)
Management task to clean up an AOR.
#define CONTACT_STATUS_BUCKETS
These are the number of contact status buckets.
static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
static int sip_options_unused_aor(void *obj, void *arg, int flags)
Callback which removes any unused AORs that remained after reloading.
static void sip_options_transaction_free(pjsip_transaction *tsx)
static char * cli_reload_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int ami_sip_qualify(struct mansession *s, const struct message *m)
static struct sip_options_contact_callback_data * sip_options_contact_callback_data_alloc(struct ast_sip_contact *contact, struct sip_options_aor *aor_options, struct ast_sip_endpoint *endpoint, pjsip_tx_data *resolve_tdata)
Contact callback data allocator.
static char * cli_show_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ao2_container * sip_options_contact_statuses_alloc(void)
Helper function to allocate a contact statuses container.
const char * ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
static int sip_options_unused_endpoint_state_compositor(void *obj, void *arg, int flags)
Callback function used to unlink and remove event state compositors that have no AORs feeding them.
static void sip_options_queue_target_result(struct sip_options_contact_callback_data *batch, enum ast_sip_contact_status_type status)
Queue a resolved target's qualification result to be combined with the other targets.
static int sip_options_endpoint_compositor_remove_task(void *obj)
Task which adds removes an AOR from an endpoint state compositor.
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
static int sip_options_endpoint_compositor_add_task(void *obj)
Task which adds an AOR to an endpoint state compositor.
void ast_res_pjsip_cleanup_options_handling(void)
static int sip_options_contact_delete_management_task(void *obj)
Task to delete a contact from an AOR in its serializer.
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS
These are the number of buckets to store endpoint state compositors.
static struct ao2_container * sip_options_endpoint_state_compositors
static void sip_options_apply_aor_configuration(struct sip_options_aor *aor_options, struct ast_sip_aor *aor, int is_new)
Function which applies configuration to an AOR options structure.
static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
Synchronize an endpoint with our local state.
static int sip_options_contact_status_notify_task(void *obj)
Task to notify an AOR of a contact status change.
static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
#define AOR_BUCKETS
These are the number of buckets to store AORs in.
static int format_contact_status_for_aor(void *obj, void *arg, int flags)
static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
Transition the contact status to qualified mode.
static int sip_options_qualify_contact(void *obj, void *arg, int flags)
Send a SIP OPTIONS request for a contact.
static void sip_options_remove_contact_status(struct sip_options_aor *aor_options, struct ast_sip_contact *contact)
Remove contact status for a hint.
static char * cli_show_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct sip_options_aor * sip_options_aor_alloc(struct ast_sip_aor *aor)
Allocator for AOR OPTIONS.
static void endpoint_observer_deleted(const void *obj)
Observer callback invoked on endpoint deletion.
static struct ast_cli_entry cli_options[]
static int sip_options_cleanup_task(void *obj)
Management task to clean up the environment.
static void sip_options_qualify_resolve_cb(pj_status_t status, void *token, const pjsip_server_addresses *addresses)
DNS callback used to fan out a qualify to every resolved target.
static void sip_options_target_result_dtor(void *obj)
Destructor for a resolved target's qualification result.
static int sip_options_remove_contact(void *obj, void *arg, int flags)
Forward declaration of this helpful function.
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
static int sip_options_synchronize_task(void *obj)
Task to synchronize our local container of AORs and endpoint state compositors with the current confi...
static void sip_options_contact_callback_data_dtor(void *obj)
Destructor for contact callback data.
static void sip_options_publish_contact_state(const struct sip_options_aor *aor_options, const struct ast_sip_contact_status *contact_status)
Function which publishes a contact status update to all interested endpoints.
static void sip_options_qualify_resolve_task_dtor(void *obj)
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
static enum ast_endpoint_state sip_options_get_endpoint_state_compositor_state(const struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Return the current state of an endpoint state compositor.
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
static void sip_options_set_contact_status(struct ast_sip_contact_status *contact_status, enum ast_sip_contact_status_type status)
Set the contact status for a contact.
static int sip_options_synchronize_aor(void *obj, void *arg, int flags)
Synchronize an AOR with our local state.
static int sip_options_contact_delete_task(void *obj)
Task which deletes a dynamic contact from an AOR.
static int ami_show_contacts(struct mansession *s, const struct message *m)
static void sip_options_update_endpoint_state_compositor_aor(struct sip_options_endpoint_state_compositor *endpoint_state_compositor, const char *name, enum ast_sip_contact_status_type status)
Update the AOR status on an endpoint state compositor.
static int sip_options_determine_initial_qualify_time(int qualify_frequency)
Determine an initial time for scheduling AOR qualifying.
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
static int contact_status_publish_update_task(void *obj)
Task to notify endpoints of a contact status change.
static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
static int sip_options_contact_add_task(void *obj)
Task which adds a dynamic contact to an AOR.
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
const char * ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
translate ast_sip_contact_status_type to character string.
static struct ast_sip_endpoint_formatter contact_status_formatter
static int has_qualify_changed(const struct ast_sip_contact *contact, const struct sip_options_aor *aor_options)
Check if the contact qualify options are different than local aor qualify options.
static int sip_options_update_aor_task(void *obj)
Task to synchronize an AOR with our local state.
static void sip_options_cancel_target_transactions(struct sip_options_contact_callback_data *batch)
Terminate all in-flight target transactions for a batch.
static pj_status_t sip_options_apply_transport_to_destination(const pjsip_tx_data *tdata, pjsip_host_info *destination)
Apply a request's transport selector to its DNS destination.
#define CONTACT_BUCKETS
These are the number of buckets (per AOR) to use to store contacts.
static struct ast_sip_contact_status * sip_contact_status_copy(const struct ast_sip_contact_status *src)
static int sip_options_qualify_resolve_task(void *obj)
Process a DNS resolution result on the AOR serializer.
static int sip_options_init_task(void *mgmt_serializer)
Management task to finish setting up the environment.
static struct ast_sip_contact_status * sip_contact_status_alloc(const char *name)
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
unsigned int ast_sip_get_max_initial_qualify_time(void)
Retrieve the system max initial qualify time.
void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
Publish the change of state for a contact.
void ast_sip_security_mechanisms_vector_copy(struct ast_sip_security_mechanism_vector *dst, const struct ast_sip_security_mechanism_vector *src)
Duplicate a security mechanism.
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **p_tdata)
General purpose method for creating a SIP response.
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg)
For every contact on an AOR call the given 'on_contact' handler.
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given 'on_aor' handler.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
Retrieve the global setting 'send_contact_status_on_update_registration'.
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
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.
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.
void ast_sip_security_mechanisms_vector_destroy(struct ast_sip_security_mechanism_vector *security_mechanisms)
Free contents of a security mechanism vector.
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
Change state of a persistent endpoint.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
int ast_sip_send_out_of_dialog_request_with_tsx(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e), pjsip_transaction **tsx)
Send an Out-Of-Dialog SIP request and return its transaction.
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
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_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.
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
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.
ast_sip_contact_status_type
Status type for a contact.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
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.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
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.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
struct ao2_container * ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
Retrieve multiple objects whose id begins with the specified prefix.
void AST_OPTIONAL_API_NAME() ast_statsd_log_string_va(const char *metric_name, const char *metric_type, const char *value, double sample_rate,...)
Send a stat to the configured statsd server.
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
void AST_OPTIONAL_API_NAME() ast_statsd_log_full_va(const char *metric_name, const char *metric_type, intmax_t value, double sample_rate,...)
Send a stat to the configured statsd server.
#define ast_string_fields_copy(copy, orig)
Copy all string fields from one instance to another of the same structure.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
descriptor for a cli entry.
struct ao2_container * permanent_contacts
unsigned int qualify_frequency
An entity with which Asterisk communicates.
const ast_string_field aors
Interface for a sorcery object type observer.
void(* created)(const void *object)
Callback for when an object is created.
Support for dynamic strings.
A ast_taskprocessor structure is a singleton by name.
In case you didn't read that giant block of text above the mansession_session struct,...
Structure which contains an AOR and contacts for qualifying purposes.
double qualify_timeout
Qualify timeout. 0 is diabled.
struct ao2_container * contacts
All contacts associated with this AOR.
int qualify_2xx_only
If true only authenticate if OPTIONS response is 2XX.
struct sip_options_aor::@491 compositors
The endpoint state compositors we are feeding, a reference is held to each.
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.
struct ast_taskprocessor * serializer
The serializer for this AOR.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
unsigned int available
The number of available contacts on this AOR.
unsigned int qualify_frequency
Frequency to send OPTIONS requests to AOR contacts. 0 is disabled.
char name[0]
The name of the AOR.
Structure which contains status information for an AOR feeding an endpoint state compositor.
char available
The last contributed available status of the named AOR (1 if available, 0 if not available)
char name[0]
The name of the AOR.
Task details for adding an AOR to an endpoint state compositor.
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
Structure which contains composites information for endpoint state.
char active
Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
char name[0]
The name of the endpoint.
char * names[PJSIP_MAX_RESOLVED_ADDRESSES]
pjsip_server_addresses addresses
struct sip_options_contact_callback_data * batch
Task data for AOR creation or updating.
struct sip_options_aor * aor_options
The AOR options for this AOR.
int added
Whether this AOR is being added.
struct ast_sip_aor * aor
The AOR which contains the new configuraton.
struct ao2_container * existing
Optional container of existing AOR s.
Structure which contains information required to synchronize.
int reload
Whether this is a reload or not.
Result of qualifying an individual address belonging to a contact resolved from an A,...
enum ast_sip_contact_status_type status
struct sip_options_contact_callback_data * batch
userdata associated with baseline taskprocessor test
struct ast_taskprocessor * ast_taskpool_serializer_get_current(void)
Get the taskpool serializer currently associated with this thread.
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
#define ast_test_suite_event_notify(s, f,...)
Time-related functions and macros.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
int ast_time_t_to_string(time_t time, char *buf, size_t length)
Converts to a string representation of a time_t as decimal seconds since the epoch....
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_random_double()
Returns a random number between 0.0 and 1.0, inclusive.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.