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 182 unsigned int qualify_frequency;
184 int authenticate_qualify;
186 double qualify_timeout;
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));
252 status = pjsip_dlg_send_response(dlg, trans, tdata);
261 if (status != PJ_SUCCESS) {
272 pjsip_sip_uri *sip_ruri;
275 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
283 ruri = rdata->msg_info.msg->line.req.uri;
284 if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
289 sip_ruri = pjsip_uri_get_uri(ruri);
314 .name = {
"Options Module", 14},
316 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
359 size_t size =
sizeof(*contact_status) + strlen(name) + 1;
363 if (!contact_status) {
370 strcpy(contact_status->
name, name);
371 return contact_status;
411 ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
412 ast_sip_contact_status_cmp_fn);
424 endpoint_state_compositor =
AST_VECTOR_GET(&aor_options->compositors, i);
453 if (mgmt_serializer) {
475 if (!sip_options_contact_statuses) {
484 ao2_lock(sip_options_contact_statuses);
487 contact_status =
ao2_find(sip_options_contact_statuses,
489 if (contact_status) {
491 return contact_status;
496 if (!contact_status) {
501 contact_status->
rtt = 0;
520 return contact_status;
548 struct timeval rtt_start;
601 strcpy(aor_status->
name, name);
616 if (!endpoint_state_compositor->
active) {
622 ast_debug(3,
"Endpoint state compositor '%s' is online as AOR '%s' is available\n",
623 endpoint_state_compositor->
name, name);
644 endpoint_state_compositor =
AST_VECTOR_GET(&aor_options->compositors, i);
646 ao2_lock(endpoint_state_compositor);
648 aor_options->name, status);
675 if (!contact_callback_data->
aor_options->qualify_frequency) {
677 ao2_ref(contact_callback_data, -1);
685 ao2_ref(contact_callback_data, -1);
690 cs_old =
ao2_find(sip_options_contact_statuses,
694 ao2_ref(contact_callback_data, -1);
702 ao2_ref(contact_callback_data, -1);
711 ao2_link(sip_options_contact_statuses, cs_new);
721 if (contact_callback_data->
aor_options->available == 1) {
730 if (!contact_callback_data->
aor_options->available) {
736 ast_verb(3,
"Contact %s/%s is now %s. RTT: %.3f msec\n",
740 cs_new->
rtt / 1000.0);
755 ast_debug(3,
"Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
759 cs_new->
rtt / 1000.0);
775 ast_debug(3,
"AOR '%s' now has %d available contacts\n",
780 ao2_ref(contact_callback_data, -1);
791 switch(e->body.tsx_state.type) {
795 case PJSIP_EVENT_TRANSPORT_ERROR:
796 case PJSIP_EVENT_TIMER:
799 case PJSIP_EVENT_RX_MSG:
809 ast_log(
LOG_NOTICE,
"Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
812 ao2_ref(contact_callback_data, -1);
835 if (!contact_callback_data) {
843 return contact_callback_data;
852 pjsip_tx_data *tdata;
856 ast_debug(3,
"Qualifying contact '%s' on AOR '%s'\n",
866 endpoint_state_compositor =
AST_VECTOR_GET(&aor_options->compositors, 0);
868 endpoint_state_compositor->
name);
871 ast_debug(3,
"Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
877 ast_log(
LOG_ERROR,
"Unable to create request to qualify contact %s on AOR %s\n",
878 contact->
uri, aor_options->name);
885 ast_log(
LOG_ERROR,
"Unable to apply outbound proxy on request to qualify contact %s\n",
887 pjsip_tx_data_dec_ref(tdata);
892 if (!contact_status) {
893 ast_log(
LOG_ERROR,
"Unable to retrieve contact status information for contact %s on AOR %s\n",
894 contact->
uri, aor_options->name);
895 pjsip_tx_data_dec_ref(tdata);
901 if (!contact_callback_data) {
902 ast_log(
LOG_ERROR,
"Unable to create object to contain callback data for contact %s on AOR %s\n",
903 contact->
uri, aor_options->name);
904 pjsip_tx_data_dec_ref(tdata);
909 (
int)(aor_options->qualify_timeout * 1000), contact_callback_data,
911 ast_log(
LOG_ERROR,
"Unable to send request to qualify contact %s on AOR %s\n",
912 contact->
uri, aor_options->name);
913 ao2_ref(contact_callback_data, -1);
927 ast_debug(3,
"Qualifying all contacts on AOR '%s'\n", aor_options->name);
934 return aor_options->qualify_frequency * 1000;
1019 ast_debug(3,
"Attempted to remove contact status for '%s' but it does not exist\n",
1024 ast_verb(2,
"Contact %s/%s has been deleted\n", contact->
aor, contact->
uri);
1059 --aor_options->available;
1060 if (!aor_options->available) {
1064 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->name,
1065 aor_options->available);
1096 int initial_interval;
1099 if (max_time && max_time < qualify_frequency) {
1100 initial_interval = max_time;
1102 initial_interval = qualify_frequency;
1106 return 0 < initial_interval ? initial_interval : 1;
1130 ao2_link(sip_options_contact_statuses, cs_new);
1133 ast_verb(3,
"Contact %s/%s is now %s.\n",
1134 cs_new->
aor, cs_new->
uri,
1160 if (!contact_status) {
1164 switch (contact_status->
status) {
1187 if (!contact_status) {
1191 switch (contact_status->
status) {
1215 if (!contact_status) {
1220 switch (contact_status->
status) {
1247 ast_debug(3,
"Configuring AOR '%s' with current state of configuration and world\n",
1258 if (!existing_contacts) {
1259 ast_log(
LOG_WARNING,
"Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1286 char prefix[prefix_len + 1];
1291 prefix, prefix_len);
1310 ao2_ref(existing_contacts, -1);
1323 ast_debug(3,
"AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1324 aor_options->name, aor_options->available);
1325 }
else if (!aor_options->qualify_frequency) {
1328 aor_options->available = 0;
1329 ast_debug(3,
"AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1336 aor_options->available = 0;
1362 if (aor_options->qualify_frequency
1369 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
1375 ast_debug(3,
"AOR '%s' now has %d available contacts\n", aor_options->name,
1376 aor_options->available);
1388 ast_debug(3,
"Synchronizing AOR '%s' with current state of configuration and world\n",
1406 ao2_lock(endpoint_state_compositor);
1407 endpoint_state_compositor->
active = 0;
1436 task_data.
added = 1;
1476 ao2_lock(sip_options_endpoint_state_compositors);
1477 endpoint_state_compositor =
ao2_find(sip_options_endpoint_state_compositors,
1479 if (endpoint_state_compositor) {
1480 ao2_unlock(sip_options_endpoint_state_compositors);
1481 return endpoint_state_compositor;
1484 endpoint_state_compositor =
ao2_alloc(
sizeof(*endpoint_state_compositor)
1487 if (!endpoint_state_compositor) {
1488 ao2_unlock(sip_options_endpoint_state_compositors);
1498 sip_options_endpoint_aor_status_hash_fn,
NULL,
1499 sip_options_endpoint_aor_status_cmp_fn);
1501 ao2_unlock(sip_options_endpoint_state_compositors);
1502 ao2_ref(endpoint_state_compositor, -1);
1508 ao2_link_flags(sip_options_endpoint_state_compositors, endpoint_state_compositor,
1510 ao2_unlock(sip_options_endpoint_state_compositors);
1512 return endpoint_state_compositor;
1531 ast_debug(3,
"Adding endpoint compositor '%s' to AOR '%s'\n",
1560 ast_debug(3,
"Removing endpoint compositor '%s' from AOR '%s'\n",
1573 ao2_ref(endpoint_state_compositor, -1);
1594 ast_debug(3,
"Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
1599 ast_debug(3,
"Synchronizing endpoint '%s' with AORs '%s'\n",
1608 ast_debug(3,
"Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
1620 ast_debug(3,
"Endpoint '%s' referenced invalid AOR '%s'\n",
1634 "Could not create endpoint state compositor for '%s', endpoint state will be incorrect\n",
1675 ast_debug(3,
"Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
1711 ast_debug(3,
"AOR '%s' is no longer configured, removing it\n", aor_options->name);
1828 ao2_lock(endpoint_state_compositor);
1829 endpoint_state_compositor->
active = 0;
1840 ast_debug(3,
"Removing endpoint state compositor '%s' from AOR '%s'\n",
1845 ao2_lock(endpoint_state_compositor);
1868 endpoint_state_compositor =
ao2_find(sip_options_endpoint_state_compositors,
1870 if (!endpoint_state_compositor) {
1874 ast_debug(3,
"Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1877 ao2_ref(endpoint_state_compositor, -1);
1898 ast_debug(3,
"Endpoint '%s' has been created or modified, updating state\n",
1901 endpoint_state_compositor =
ao2_find(sip_options_endpoint_state_compositors,
1903 if (endpoint_state_compositor) {
1906 ao2_ref(endpoint_state_compositor, -1);
1937 ast_debug(3,
"Individually updating AOR '%s' with current state of configuration and world\n",
1943 if (!available && task_data->
aor_options->available) {
1944 ast_debug(3,
"After modifying AOR '%s' it has now become available\n",
1947 }
else if (available && !task_data->
aor_options->available) {
1948 ast_debug(3,
"After modifying AOR '%s' it has become unavailable\n",
1982 ao2_link(sip_options_aors, aor_options);
2036 ast_debug(3,
"AOR '%s' has been deleted, removing it\n", aor_options->name);
2083 || ((
int)(contact->
qualify_timeout * 1000)) != ((
int)(aor_options->qualify_timeout * 1000))) {
2110 ast_debug(3,
"Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2129 ast_log(
LOG_ERROR,
"Unable to schedule qualify for contacts of AOR '%s'\n",
2140 ast_debug(3,
"An unqualified contact has been added to AOR '%s' so it is now available\n",
2168 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2203 if (contact_status) {
2204 switch (contact_status->
status) {
2236 ast_debug(3,
"AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2287 ast_debug(3,
"Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2299 ast_debug(3,
"An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2349 const char *endpoint_name;
2357 "Usage: pjsip qualify <endpoint>\n" 2358 " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2368 endpoint_name = a->
argv[2];
2373 ast_cli(a->
fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2378 ast_cli(a->
fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2391 ast_cli(a->
fd,
"Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2470 astman_send_listack(s, m,
"A listing of Contacts follows, presented as ContactList events",
2486 const char *endpoint_name;
2492 e->
command =
"pjsip show qualify endpoint";
2494 "Usage: pjsip show qualify endpoint <id>\n" 2495 " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2505 endpoint_name = a->
argv[4];
2510 ast_cli(a->
fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2515 ast_cli(a->
fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2528 ast_cli(a->
fd,
" * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2529 ast_cli(a->
fd,
" Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2530 ast_cli(a->
fd,
" Qualify timeout : %d ms\n", (
int)(aor_options->qualify_timeout / 1000));
2531 ast_cli(a->
fd,
" Authenticate qualify : %s\n", aor_options->authenticate_qualify?
"yes":
"no");
2542 const char *aor_name;
2546 e->
command =
"pjsip show qualify aor";
2548 "Usage: pjsip show qualify aor <id>\n" 2549 " Show the PJSIP Aor current qualify options.\n";
2559 aor_name = a->
argv[4];
2563 ast_cli(a->
fd,
"Unable to retrieve aor '%s' qualify options\n", aor_name);
2567 ast_cli(a->
fd,
" * AOR '%s'\n", aor_name);
2568 ast_cli(a->
fd,
" Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2569 ast_cli(a->
fd,
" Qualify timeout : %d ms\n", (
int)(aor_options->qualify_timeout / 1000));
2570 ast_cli(a->
fd,
" Authenticate qualify : %s\n", aor_options->authenticate_qualify?
"yes":
"no");
2579 const char *endpoint_name;
2585 e->
command =
"pjsip reload qualify endpoint";
2587 "Usage: pjsip reload qualify endpoint <id>\n" 2588 " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2598 endpoint_name = a->
argv[4];
2603 ast_cli(a->
fd,
"Unable to retrieve endpoint %s\n", endpoint_name);
2608 ast_cli(a->
fd,
"No AORs configured for endpoint '%s'\n", endpoint_name);
2621 ast_cli(a->
fd,
"Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2633 const char *aor_name;
2637 e->
command =
"pjsip reload qualify aor";
2639 "Usage: pjsip reload qualify aor <id>\n" 2640 " Synchronize the PJSIP Aor qualify options.\n";
2650 aor_name = a->
argv[4];
2654 ast_cli(a->
fd,
"Unable to retrieve aor '%s'\n", aor_name);
2658 ast_cli(a->
fd,
"Synchronizing AOR '%s'\n", aor_name);
2782 ami->
arg = (
void *)endpoint;
2798 ast_debug(2,
"Cleaning up AOR '%s' for shutdown\n", aor_options->name);
2800 aor_options->qualify_frequency = 0;
2820 if (!sip_options_aors) {
2846 &contact_observer_callbacks);
2848 &aor_observer_callbacks);
2850 &endpoint_observer_callbacks);
2853 management_serializer =
NULL;
2854 if (mgmt_serializer) {
2865 shutdown_group =
NULL;
2867 if (mgmt_serializer) {
2872 sip_options_aors =
NULL;
2874 sip_options_contact_statuses =
NULL;
2875 ao2_cleanup(sip_options_endpoint_state_compositors);
2876 sip_options_endpoint_state_compositors =
NULL;
2887 management_serializer = mgmt_serializer;
2890 if (!shutdown_group) {
2895 &endpoint_observer_callbacks)) {
2899 &aor_observer_callbacks)) {
2903 &contact_observer_callbacks)) {
2915 return sip_options_contact_statuses ? 0 : -1;
2922 static const pj_str_t STR_OPTIONS = {
"OPTIONS", 7 };
2935 NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2941 sip_options_aor_hash_fn,
NULL, sip_options_aor_cmp_fn);
2942 if (!sip_options_aors) {
2946 sip_options_endpoint_state_compositors =
2949 sip_options_endpoint_state_compositor_hash_fn,
NULL,
2950 sip_options_endpoint_state_compositor_cmp_fn);
2951 if (!sip_options_endpoint_state_compositors) {
2957 if (!mgmt_serializer) {
2978 management_serializer = mgmt_serializer;
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
static int sip_options_update_aor_task(void *obj)
Task to synchronize an AOR with our local state.
static void contact_observer_updated(const void *obj)
Observer callback invoked on contact update.
enum sip_cc_notify_state state
static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
static char exten[AST_MAX_EXTENSION]
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
static struct sip_options_aor * sip_options_aor_alloc(struct ast_sip_aor *aor)
Allocator for AOR OPTIONS.
static int sip_options_contact_delete_management_task(void *obj)
Task to delete a contact from an AOR in its serializer.
#define AST_CLI_DEFINE(fn, txt,...)
static void sip_options_endpoint_state_compositor_dtor(void *obj)
Destructor for endpoint state compositors.
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.
static int sip_options_endpoint_compositor_add_task(void *obj)
Task which adds an AOR to an endpoint state compositor.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
static int ami_sip_qualify(struct mansession *s, const struct message *m)
static const char * short_status_map[]
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
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. ...
AO2_STRING_FIELD_HASH_FN(ast_sip_contact_status, name)
Hashing function for contact statuses.
static struct ao2_container * sip_options_contact_statuses
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 char * cli_show_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_cli_entry cli_options[]
int ast_res_pjsip_preinit_options_handling(void)
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
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.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static int sip_options_cleanup_task(void *obj)
Management task to clean up the environment.
The arg parameter is a search key, but is not an object.
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) ...
Structure which contains composites information for endpoint state.
Time-related functions and macros.
static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
Transition the contact status to qualified mode.
#define ao2_container_clone(orig, flags)
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
static const char * status_map[]
Task data for AOR creation or updating.
static void sip_options_aor_dtor(void *obj)
Destructor function for SIP OPTIONS AORs.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
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.
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
#define ao2_callback(c, flags, cb_fn, arg)
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
void(* created)(const void *object)
Callback for when an object is created.
Perform no matching, return all objects.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
char name[0]
The name of the endpoint.
Assume that the ao2_container is already locked.
static char * cli_reload_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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.
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.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static void sip_contact_status_dtor(void *obj)
Destructor for contact statuses.
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.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Return all matching objects.
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
static void endpoint_observer_modified(const void *obj)
Observer callback invoked on endpoint creation or modification.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_link_flags(container, obj, flags)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
static int sip_options_init_task(void *mgmt_serializer)
Management task to finish setting up the environment.
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.
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_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
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.
void ast_cli(int fd, const char *fmt,...)
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
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.
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE
The initial vector size for the endpoint state compositors on an AOR.
static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
static struct ast_sip_endpoint_formatter contact_status_formatter
ast_endpoint_state
Valid states for an endpoint.
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.
#define ast_verb(level,...)
const char * ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
int reload
Whether this is a reload or not.
struct ao2_container * existing
Optional container of existing AOR s.
AO2_STRING_FIELD_SORT_FN(ast_sip_contact_status, name)
Sort function for contact statuses.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
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 int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
Change state of a persistent endpoint.
ast_sip_contact_status_type
Status type for a contact.
Structure which contains status information for an AOR feeding an endpoint state compositor.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
#define ast_strlen_zero(foo)
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
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.
static struct ao2_container * sip_options_contact_statuses_alloc(void)
Helper function to allocate a contact statuses container.
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.
Structure which contains information required to synchronize.
int ast_res_pjsip_init_options_handling(int reload)
static char * cli_show_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
unsigned int qualify_frequency
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.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
#define EVENT_FLAG_SYSTEM
#define ast_debug(level,...)
Log a DEBUG message.
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_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int sip_contact_to_ami(const struct ast_sip_contact *contact, struct ast_str **buf)
#define CONTACT_STATUS_BUCKETS
These are the number of contact status buckets.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
General Asterisk PBX channel definitions.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
static int sip_options_aor_observer_deleted_task(void *obj)
Task to delete an AOR from the known universe.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
Transition the contact status to unqualified mode.
static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
Count AVAILABLE qualified contacts.
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
#define AST_MAX_EXTENSION
static int sip_options_contact_status_notify_task(void *obj)
Task to notify an AOR of a contact status change.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
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 struct ao2_container * endpoints
#define ao2_ref(o, delta)
In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
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.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
static pjsip_module options_module
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
static struct ao2_container * sip_options_endpoint_state_compositors
static void endpoint_observer_deleted(const void *obj)
Observer callback invoked on endpoint deletion.
#define ast_malloc(len)
A wrapper for malloc()
static void sip_options_contact_callback_data_dtor(void *obj)
Destructor for contact callback data.
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.
static struct ast_sip_contact_status * sip_contact_status_alloc(const char *name)
#define AST_VECTOR(name, type)
Define a vector structure.
An entity with which Asterisk communicates.
unsigned int ast_sip_get_max_initial_qualify_time(void)
Retrieve the system max initial qualify time.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
Retrieve the global setting 'send_contact_status_on_update_registration'.
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
Core PBX routines and definitions.
struct sip_options_aor * aor_options
The AOR options for this AOR.
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.
Structure which contains an AOR and contacts for qualifying purposes.
#define ast_test_suite_event_notify(s, f,...)
static int sip_options_aor_remove_task(void *obj)
Task which removes an AOR from all of the ESCs it is reporting to.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
static struct ast_sip_contact_status * sip_contact_status_copy(const struct ast_sip_contact_status *src)
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS
These are the number of buckets to store endpoint state compositors.
#define ast_string_fields_copy(copy, orig)
Copy all string fields from one instance to another of the same structure.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_unlink(container, obj)
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.
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
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.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
AO2_STRING_FIELD_CMP_FN(ast_sip_contact_status, name)
Comparator function for contact statuses.
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
Interface for a sorcery object type observer.
static int sip_options_synchronize_aor_task(void *obj)
Task to synchronize an AOR with our local state.
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.
int added
Whether this AOR is being added.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
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...
userdata associated with baseline taskprocessor test
static int format_contact_status_for_aor(void *obj, void *arg, int flags)
#define ao2_iterator_next(iter)
#define ao2_alloc(data_size, destructor_fn)
static struct ast_taskprocessor * management_serializer
static int contact_status_publish_update_task(void *obj)
Task to notify endpoints of a contact status change.
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
static void contact_observer_created(const void *obj)
Observer callback invoked on contact creation.
struct ao2_container * permanent_contacts
struct ast_sip_aor * aor
The AOR which contains the new configuraton.
#define ao2_find(container, arg, flags)
An API for managing task processing threads that can be shared across modules.
static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
Synchronize an endpoint with our local state.
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.
static int sip_options_synchronize_aor(void *obj, void *arg, int flags)
Synchronize an AOR with our local state.
char name[0]
The name of the AOR.
static int sip_options_unused_aor(void *obj, void *arg, int flags)
Callback which removes any unused AORs that remained after reloading.
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.
static int sip_options_contact_update_task(void *obj)
Task which updates a dynamic contact to an AOR.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
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.
#define EVENT_FLAG_REPORTING
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
The arg parameter is an object of the same type.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
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.
Replace objects with duplicate keys in container.
char * strsep(char **str, const char *delims)
char available
The last contributed available status of the named AOR (1 if available, 0 if not available) ...
A ast_taskprocessor structure is a singleton by name.
char active
Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
static int sip_options_cleanup_aor_task(void *obj)
Management task to clean up an AOR.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
static int sip_options_determine_initial_qualify_time(int qualify_frequency)
Determine an initial time for scheduling AOR qualifying.
static void aor_observer_deleted(const void *obj)
Observer callback invoked on AOR deletion.
static int sip_options_contact_delete_task(void *obj)
Task which deletes a dynamic contact from an AOR.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static int sip_options_endpoint_observer_modified_task(void *obj)
Task to synchronize the endpoint.
static struct ao2_container * sip_options_aors
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
struct ao2_container * contacts
All contacts associated with this AOR.
#define AOR_STATUS_BUCKETS
These are the number of buckets (per endpoint state compositor) to use to store AOR statuses...
static int sip_options_endpoint_compositor_remove_task(void *obj)
Task which adds removes an AOR from an endpoint state compositor.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
#define CONTACT_BUCKETS
These are the number of buckets (per AOR) to use to store contacts.
static void contact_observer_deleted(const void *obj)
Observer callback invoked on contact deletion.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
#define ast_random_double()
Returns a random number between 0.0 and 1.0, inclusive.
Reject objects with duplicate keys in container.
void ast_res_pjsip_cleanup_options_handling(void)
#define MAX_UNLOAD_TIMEOUT_TIME
Maximum wait time to join the below shutdown group.
static int ami_show_contacts(struct mansession *s, const struct message *m)
static void aor_observer_modified(const void *obj)
Observer callback invoked on AOR creation or modification.
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.
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.
const ast_string_field aors
static int sip_options_remove_contact(void *obj, void *arg, int flags)
Forward declaration of this helpful function.
static char * cli_reload_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int sip_options_contact_add_task(void *obj)
Task which adds a dynamic contact to an AOR.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
static int sip_options_qualify_contact(void *obj, void *arg, int flags)
Send a SIP OPTIONS request for a contact.
static int sip_options_contact_add_management_task(void *obj)
Task to add a dynamic contact to an AOR in its serializer.
static int sip_options_endpoint_observer_deleted_task(void *obj)
Task to delete an endpoint from the known universe.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a 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.
#define AOR_BUCKETS
These are the number of buckets to store AORs in.
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 struct ao2_container * get_all_contacts(void)
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.
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.
static char prefix[MAX_PREFIX]
Task details for adding an AOR to an endpoint state compositor.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
#define ao2_link(container, obj)
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.