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
218 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
219 pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
220 pjsip_tx_data *tdata;
221 const pjsip_hdr *hdr;
226 if (
status != PJ_SUCCESS) {
232 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ACCEPT,
NULL))) {
233 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
235 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ALLOW,
NULL))) {
236 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
238 if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_SUPPORTED,
NULL))) {
239 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
251 status = pjsip_dlg_send_response(dlg, trans, tdata);
260 if (
status != PJ_SUCCESS) {
273 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
281 ruri = rdata->msg_info.msg->line.req.uri;
311 .name = {
"Options Module", 14},
313 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
358 size_t size =
sizeof(*contact_status) + strlen(
name) + 1;
362 if (!contact_status) {
371 return contact_status;
413 ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
414 ast_sip_contact_status_cmp_fn);
455 if (mgmt_serializer) {
491 if (contact_status) {
493 return contact_status;
498 if (!contact_status) {
503 contact_status->
rtt = 0;
522 return contact_status;
618 if (!endpoint_state_compositor->
active) {
624 ast_debug(3,
"Endpoint state compositor '%s' is online as AOR '%s' is available\n",
625 endpoint_state_compositor->
name,
name);
648 ao2_lock(endpoint_state_compositor);
679 ao2_ref(contact_callback_data, -1);
687 ao2_ref(contact_callback_data, -1);
696 ao2_ref(contact_callback_data, -1);
704 ao2_ref(contact_callback_data, -1);
738 ast_verb(3,
"Contact %s/%s is now %s. RTT: %.3f msec\n",
742 cs_new->
rtt / 1000.0);
757 ast_debug(3,
"Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
761 cs_new->
rtt / 1000.0);
777 ast_debug(3,
"AOR '%s' now has %d available contacts\n",
782 ao2_ref(contact_callback_data, -1);
793 switch(e->body.tsx_state.type) {
797 case PJSIP_EVENT_TRANSPORT_ERROR:
798 case PJSIP_EVENT_TIMER:
801 case PJSIP_EVENT_RX_MSG:
811 ast_log(
LOG_WARNING,
"Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
814 ao2_ref(contact_callback_data, -1);
837 if (!contact_callback_data) {
845 return contact_callback_data;
854 pjsip_tx_data *tdata;
858 ast_debug(3,
"Qualifying contact '%s' on AOR '%s'\n",
870 endpoint_state_compositor->
name);
873 ast_debug(3,
"Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
879 ast_log(
LOG_ERROR,
"Unable to create request to qualify contact %s on AOR %s\n",
880 contact->
uri, aor_options->
name);
887 ast_log(
LOG_ERROR,
"Unable to apply outbound proxy on request to qualify contact %s\n",
889 pjsip_tx_data_dec_ref(tdata);
894 if (!contact_status) {
895 ast_log(
LOG_ERROR,
"Unable to retrieve contact status information for contact %s on AOR %s\n",
896 contact->
uri, aor_options->
name);
897 pjsip_tx_data_dec_ref(tdata);
903 if (!contact_callback_data) {
904 ast_log(
LOG_ERROR,
"Unable to create object to contain callback data for contact %s on AOR %s\n",
905 contact->
uri, aor_options->
name);
906 pjsip_tx_data_dec_ref(tdata);
913 ast_log(
LOG_ERROR,
"Unable to send request to qualify contact %s on AOR %s\n",
914 contact->
uri, aor_options->
name);
915 ao2_ref(contact_callback_data, -1);
929 ast_debug(3,
"Qualifying all contacts on AOR '%s'\n", aor_options->
name);
1021 ast_debug(3,
"Attempted to remove contact status for '%s' but it does not exist\n",
1026 ast_verb(2,
"Contact %s/%s has been deleted\n", contact->
aor, contact->
uri);
1066 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->
name,
1098 int initial_interval;
1102 initial_interval = max_time;
1108 return 0 < initial_interval ? initial_interval : 1;
1135 ast_verb(3,
"Contact %s/%s is now %s.\n",
1136 cs_new->
aor, cs_new->
uri,
1162 if (!contact_status) {
1166 switch (contact_status->
status) {
1189 if (!contact_status) {
1193 switch (contact_status->
status) {
1217 if (!contact_status) {
1222 switch (contact_status->
status) {
1249 ast_debug(3,
"Configuring AOR '%s' with current state of configuration and world\n",
1260 if (!existing_contacts) {
1261 ast_log(
LOG_WARNING,
"Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1288 char prefix[prefix_len + 1];
1312 ao2_ref(existing_contacts, -1);
1325 ast_debug(3,
"AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1331 ast_debug(3,
"AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1371 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
1377 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->
name,
1390 ast_debug(3,
"Synchronizing AOR '%s' with current state of configuration and world\n",
1408 ao2_lock(endpoint_state_compositor);
1409 endpoint_state_compositor->
active = 0;
1481 if (endpoint_state_compositor) {
1483 return endpoint_state_compositor;
1486 endpoint_state_compositor =
ao2_alloc(
sizeof(*endpoint_state_compositor)
1489 if (!endpoint_state_compositor) {
1500 sip_options_endpoint_aor_status_hash_fn,
NULL,
1501 sip_options_endpoint_aor_status_cmp_fn);
1504 ao2_ref(endpoint_state_compositor, -1);
1514 return endpoint_state_compositor;
1533 ast_debug(3,
"Adding endpoint compositor '%s' to AOR '%s'\n",
1538 task_data->endpoint_state_compositor)) {
1562 ast_debug(3,
"Removing endpoint compositor '%s' from AOR '%s'\n",
1563 task_data->endpoint_state_compositor->name,
1570 if (endpoint_state_compositor !=
task_data->endpoint_state_compositor) {
1575 ao2_ref(endpoint_state_compositor, -1);
1596 ast_debug(3,
"Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
1601 ast_debug(3,
"Synchronizing endpoint '%s' with AORs '%s'\n",
1610 ast_debug(3,
"Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
1622 ast_debug(3,
"Endpoint '%s' referenced invalid AOR '%s'\n",
1627 if (!
task_data.endpoint_state_compositor) {
1634 if (!
task_data.endpoint_state_compositor) {
1636 "Could not create endpoint state compositor for '%s', endpoint state will be incorrect\n",
1660 if (
task_data.endpoint_state_compositor) {
1666 task_data.endpoint_state_compositor->active = 1;
1677 ast_debug(3,
"Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
1713 ast_debug(3,
"AOR '%s' is no longer configured, removing it\n", aor_options->
name);
1842 ast_debug(3,
"Removing endpoint state compositor '%s' from AOR '%s'\n",
1872 if (!endpoint_state_compositor) {
1876 ast_debug(3,
"Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1879 ao2_ref(endpoint_state_compositor, -1);
1900 ast_debug(3,
"Endpoint '%s' has been created or modified, updating state\n",
1905 if (endpoint_state_compositor) {
1908 ao2_ref(endpoint_state_compositor, -1);
1939 ast_debug(3,
"Individually updating AOR '%s' with current state of configuration and world\n",
1946 ast_debug(3,
"After modifying AOR '%s' it has now become available\n",
1950 ast_debug(3,
"After modifying AOR '%s' it has become unavailable\n",
2038 ast_debug(3,
"AOR '%s' has been deleted, removing it\n", aor_options->
name);
2107 if (
task_data->aor_options->qualify_frequency) {
2112 ast_debug(3,
"Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2120 if (
task_data->aor_options->sched_task) {
2130 if (!
task_data->aor_options->sched_task) {
2131 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
2141 if (
task_data->aor_options->available == 1) {
2142 ast_debug(3,
"An unqualified contact has been added to AOR '%s' so it is now available\n",
2170 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2205 if (contact_status) {
2206 switch (contact_status->
status) {
2238 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2286 if (
task_data->aor_options->qualify_frequency) {
2289 ast_debug(3,
"Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2291 if (
task_data->aor_options->sched_task) {
2300 if (!
task_data->aor_options->available) {
2301 ast_debug(3,
"An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2351 const char *endpoint_name;
2359 "Usage: pjsip qualify <endpoint>\n"
2360 " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2370 endpoint_name =
a->argv[2];
2375 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2380 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2393 ast_cli(
a->fd,
"Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2472 astman_send_listack(s, m,
"A listing of Contacts follows, presented as ContactList events",
2488 const char *endpoint_name;
2494 e->
command =
"pjsip show qualify endpoint";
2496 "Usage: pjsip show qualify endpoint <id>\n"
2497 " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2507 endpoint_name =
a->argv[4];
2512 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2517 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2530 ast_cli(
a->fd,
" * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2544 const char *aor_name;
2548 e->
command =
"pjsip show qualify aor";
2550 "Usage: pjsip show qualify aor <id>\n"
2551 " Show the PJSIP Aor current qualify options.\n";
2561 aor_name =
a->argv[4];
2565 ast_cli(
a->fd,
"Unable to retrieve aor '%s' qualify options\n", aor_name);
2569 ast_cli(
a->fd,
" * AOR '%s'\n", aor_name);
2581 const char *endpoint_name;
2587 e->
command =
"pjsip reload qualify endpoint";
2589 "Usage: pjsip reload qualify endpoint <id>\n"
2590 " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2600 endpoint_name =
a->argv[4];
2605 ast_cli(
a->fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2610 ast_cli(
a->fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2623 ast_cli(
a->fd,
"Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2635 const char *aor_name;
2639 e->
command =
"pjsip reload qualify aor";
2641 "Usage: pjsip reload qualify aor <id>\n"
2642 " Synchronize the PJSIP Aor qualify options.\n";
2652 aor_name =
a->argv[4];
2656 ast_cli(
a->fd,
"Unable to retrieve aor '%s'\n", aor_name);
2660 ast_cli(
a->fd,
"Synchronizing AOR '%s'\n", aor_name);
2786 ami->
arg = (
void *)endpoint;
2802 ast_debug(2,
"Cleaning up AOR '%s' for shutdown\n", aor_options->
name);
2858 if (mgmt_serializer) {
2871 if (mgmt_serializer) {
2926 static const pj_str_t STR_OPTIONS = {
"OPTIONS", 7 };
2939 NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2945 sip_options_aor_hash_fn,
NULL, sip_options_aor_cmp_fn);
2953 sip_options_endpoint_state_compositor_hash_fn,
NULL,
2954 sip_options_endpoint_state_compositor_cmp_fn);
2961 if (!mgmt_serializer) {
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_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_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.
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 int available(struct dahdi_pvt **pvt, int is_specific_channel)
General Asterisk PBX channel definitions.
#define AST_MAX_EXTENSION
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#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.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
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.
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 thread pool.
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
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.
@ AST_SIP_SCHED_TASK_DATA_AO2
@ AST_SIP_SCHED_TASK_VARIABLE
static char prefix[MAX_PREFIX]
char * strsep(char **str, const char *delims)
#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 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 const char * status_map[]
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
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 when we get a result from a SIP OPTIONS request (a response or a timeout)
static struct sip_options_contact_callback_data * sip_options_contact_callback_data_alloc(struct ast_sip_contact *contact, struct sip_options_aor *aor_options)
Contact callback data allocator.
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.
#define MAX_UNLOAD_TIMEOUT_TIME
Maximum wait time to join the below shutdown group.
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 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 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 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 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 const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
AO2_STRING_FIELD_HASH_FN(ast_sip_contact_status, name)
Hashing function for contact statuses.
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.
AO2_STRING_FIELD_SORT_FN(ast_sip_contact_status, name)
Sort function for contact statuses.
AO2_STRING_FIELD_CMP_FN(ast_sip_contact_status, name)
Comparator function for contact statuses.
#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_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_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.
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.
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_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_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.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#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_strlen_zero(const char *s)
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.
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.
struct sip_options_aor::@454 compositors
The endpoint state compositors we are feeding, a reference is held to each.
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.
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.
userdata associated with baseline taskprocessor test
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.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
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_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
#define ast_test_suite_event_notify(s, f,...)
int ast_serializer_shutdown_group_join(struct ast_serializer_shutdown_group *shutdown_group, int timeout)
Wait for the serializers in the group to shutdown with timeout.
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
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.