Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Macros | Functions | Variables
pjsip_options.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjlib.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/astobj2.h"
#include "asterisk/cli.h"
#include "asterisk/time.h"
#include "asterisk/test.h"
#include "asterisk/statsd.h"
#include "include/res_pjsip_private.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/threadpool.h"
Include dependency graph for pjsip_options.c:

Go to the source code of this file.

Data Structures

struct  sip_options_aor
 Structure which contains an AOR and contacts for qualifying purposes. More...
 
struct  sip_options_contact_callback_data
 Structure used to contain information for an OPTIONS callback. More...
 
struct  sip_options_contact_observer_task_data
 Task details for adding an AOR to an endpoint state compositor. More...
 
struct  sip_options_endpoint_aor_status
 Structure which contains status information for an AOR feeding an endpoint state compositor. More...
 
struct  sip_options_endpoint_compositor_task_data
 Task details for adding an AOR to an endpoint state compositor. More...
 
struct  sip_options_endpoint_state_compositor
 Structure which contains composites information for endpoint state. More...
 
struct  sip_options_synchronize_aor_task_data
 Task data for AOR creation or updating. More...
 
struct  sip_options_synchronize_task_data
 Structure which contains information required to synchronize. More...
 

Macros

#define AOR_BUCKETS   1567
 These are the number of buckets to store AORs in. More...
 
#define AOR_STATUS_BUCKETS   3
 These are the number of buckets (per endpoint state compositor) to use to store AOR statuses. More...
 
#define CONTACT_BUCKETS   13
 These are the number of buckets (per AOR) to use to store contacts. More...
 
#define CONTACT_STATUS_BUCKETS   1567
 These are the number of contact status buckets. More...
 
#define DEFAULT_ENCODING   "identity"
 
#define DEFAULT_LANGUAGE   "en"
 
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS   13
 These are the number of buckets to store endpoint state compositors. More...
 
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE   1
 The initial vector size for the endpoint state compositors on an AOR. More...
 
#define MAX_UNLOAD_TIMEOUT_TIME   10 /* Seconds */
 Maximum wait time to join the below shutdown group. More...
 

Functions

static int ami_show_contacts (struct mansession *s, const struct message *m)
 
static int ami_sip_qualify (struct mansession *s, const struct message *m)
 
 AO2_STRING_FIELD_CMP_FN (ast_sip_contact_status, name)
 Comparator function for contact statuses. More...
 
 AO2_STRING_FIELD_CMP_FN (sip_options_aor, name)
 Comparator function for SIP OPTIONS AORs. More...
 
 AO2_STRING_FIELD_CMP_FN (sip_options_endpoint_aor_status, name)
 Comparator function for endpoint AOR status. More...
 
 AO2_STRING_FIELD_CMP_FN (sip_options_endpoint_state_compositor, name)
 Comparator function for endpoint state compositors. More...
 
 AO2_STRING_FIELD_HASH_FN (ast_sip_contact_status, name)
 Hashing function for contact statuses. More...
 
 AO2_STRING_FIELD_HASH_FN (sip_options_aor, name)
 Hashing function for OPTIONS AORs. More...
 
 AO2_STRING_FIELD_HASH_FN (sip_options_endpoint_aor_status, name)
 Hashing function for endpoint AOR status. More...
 
 AO2_STRING_FIELD_HASH_FN (sip_options_endpoint_state_compositor, name)
 Hashing function for endpoint state compositors. More...
 
 AO2_STRING_FIELD_SORT_FN (ast_sip_contact_status, name)
 Sort function for contact statuses. More...
 
static void aor_observer_deleted (const void *obj)
 Observer callback invoked on AOR deletion. More...
 
static void aor_observer_modified (const void *obj)
 Observer callback invoked on AOR creation or modification. More...
 
void ast_res_pjsip_cleanup_options_handling (void)
 
struct ast_sip_contact_statusast_res_pjsip_find_or_create_contact_status (const struct ast_sip_contact *contact)
 
int ast_res_pjsip_init_options_handling (int reload)
 
int ast_res_pjsip_preinit_options_handling (void)
 
int ast_sip_format_contact_ami (void *obj, void *arg, int flags)
 Formats the contact and sends over AMI. More...
 
const char * ast_sip_get_contact_short_status_label (const enum ast_sip_contact_status_type status)
 
struct ast_sip_contact_statusast_sip_get_contact_status (const struct ast_sip_contact *contact)
 Retrieve the current status for a contact. More...
 
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. More...
 
static char * cli_qualify (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_reload_qualify_aor (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_reload_qualify_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_show_qualify_aor (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_show_qualify_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void contact_observer_created (const void *obj)
 Observer callback invoked on contact creation. More...
 
static void contact_observer_deleted (const void *obj)
 Observer callback invoked on contact deletion. More...
 
static void contact_observer_updated (const void *obj)
 Observer callback invoked on contact update. More...
 
static int contact_status_publish_update_task (void *obj)
 Task to notify endpoints of a contact status change. More...
 
static void endpoint_observer_deleted (const void *obj)
 Observer callback invoked on endpoint deletion. More...
 
static void endpoint_observer_modified (const void *obj)
 Observer callback invoked on endpoint creation or modification. More...
 
static int format_ami_contact_status (const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
 
static int format_ami_contactlist_handler (void *obj, void *arg, int flags)
 
static int format_contact_status_for_aor (void *obj, void *arg, int flags)
 
static struct ao2_containerget_all_contacts (void)
 
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. More...
 
static pj_bool_t options_on_rx_request (pjsip_rx_data *rdata)
 
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) More...
 
static pj_status_t send_options_response (pjsip_rx_data *rdata, int code)
 
static struct ast_sip_contact_statussip_contact_status_alloc (const char *name)
 
static struct ast_sip_contact_statussip_contact_status_copy (const struct ast_sip_contact_status *src)
 
static void sip_contact_status_dtor (void *obj)
 Destructor for contact statuses. More...
 
static int sip_contact_to_ami (const struct ast_sip_contact *contact, struct ast_str **buf)
 
static struct sip_options_aorsip_options_aor_alloc (struct ast_sip_aor *aor)
 Allocator for AOR OPTIONS. More...
 
static void sip_options_aor_dtor (void *obj)
 Destructor function for SIP OPTIONS AORs. More...
 
static int sip_options_aor_observer_deleted_task (void *obj)
 Task to delete an AOR from the known universe. More...
 
static int sip_options_aor_observer_modified_task (void *obj)
 Task to synchronize the AOR. More...
 
static int sip_options_aor_remove_task (void *obj)
 Task which removes an AOR from all of the ESCs it is reporting to. More...
 
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. More...
 
static int sip_options_cleanup_aor_task (void *obj)
 Management task to clean up an AOR. More...
 
static int sip_options_cleanup_task (void *obj)
 Management task to clean up the environment. More...
 
static int sip_options_contact_add_management_task (void *obj)
 Task to add a dynamic contact to an AOR in its serializer. More...
 
static int sip_options_contact_add_task (void *obj)
 Task which adds a dynamic contact to an AOR. More...
 
static struct sip_options_contact_callback_datasip_options_contact_callback_data_alloc (struct ast_sip_contact *contact, struct sip_options_aor *aor_options)
 Contact callback data allocator. More...
 
static void sip_options_contact_callback_data_dtor (void *obj)
 Destructor for contact callback data. More...
 
static int sip_options_contact_delete_management_task (void *obj)
 Task to delete a contact from an AOR in its serializer. More...
 
static int sip_options_contact_delete_task (void *obj)
 Task which deletes a dynamic contact from an AOR. More...
 
static int sip_options_contact_status_available_count (void *obj, void *arg, int flags)
 Count AVAILABLE qualified contacts. More...
 
static int sip_options_contact_status_notify_task (void *obj)
 Task to notify an AOR of a contact status change. More...
 
static void sip_options_contact_status_update (struct ast_sip_contact_status *contact_status)
 
static struct ao2_containersip_options_contact_statuses_alloc (void)
 Helper function to allocate a contact statuses container. More...
 
static int sip_options_contact_update_task (void *obj)
 Task which updates a dynamic contact to an AOR. More...
 
static int sip_options_determine_initial_qualify_time (int qualify_frequency)
 Determine an initial time for scheduling AOR qualifying. More...
 
static int sip_options_endpoint_compositor_add_task (void *obj)
 Task which adds an AOR to an endpoint state compositor. More...
 
static int sip_options_endpoint_compositor_remove_task (void *obj)
 Task which adds removes an AOR from an endpoint state compositor. More...
 
static int sip_options_endpoint_observer_deleted_task (void *obj)
 Task to delete an endpoint from the known universe. More...
 
static int sip_options_endpoint_observer_modified_task (void *obj)
 Task to synchronize the endpoint. More...
 
static void sip_options_endpoint_state_compositor_dtor (void *obj)
 Destructor for endpoint state compositors. More...
 
static struct sip_options_endpoint_state_compositorsip_options_endpoint_state_compositor_find_or_alloc (const struct ast_sip_endpoint *endpoint)
 Find (or create) an endpoint state compositor. More...
 
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. More...
 
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. More...
 
static int sip_options_init_task (void *mgmt_serializer)
 Management task to finish setting up the environment. More...
 
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. More...
 
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. More...
 
static int sip_options_qualify_aor (void *obj)
 Task to qualify contacts of an AOR. More...
 
static int sip_options_qualify_contact (void *obj, void *arg, int flags)
 Send a SIP OPTIONS request for a contact. More...
 
static int sip_options_remove_contact (void *obj, void *arg, int flags)
 Forward declaration of this helpful function. More...
 
static void sip_options_remove_contact_status (struct sip_options_aor *aor_options, struct ast_sip_contact *contact)
 Remove contact status for a hint. More...
 
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. More...
 
static int sip_options_set_contact_status_qualified (void *obj, void *arg, int flags)
 Transition the contact status to qualified mode. More...
 
static int sip_options_set_contact_status_unqualified (void *obj, void *arg, int flags)
 Transition the contact status to unqualified mode. More...
 
static void sip_options_synchronize (int reload)
 Synchronize our local container of AORs and endpoint state compositors with the current configuration. More...
 
static int sip_options_synchronize_aor (void *obj, void *arg, int flags)
 Synchronize an AOR with our local state. More...
 
static int sip_options_synchronize_aor_task (void *obj)
 Task to synchronize an AOR with our local state. More...
 
static int sip_options_synchronize_endpoint (void *obj, void *arg, int flags)
 Synchronize an endpoint with our local state. More...
 
static int sip_options_synchronize_task (void *obj)
 Task to synchronize our local container of AORs and endpoint state compositors with the current configuration. More...
 
static int sip_options_unused_aor (void *obj, void *arg, int flags)
 Callback which removes any unused AORs that remained after reloading. More...
 
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. More...
 
static int sip_options_update_aor_task (void *obj)
 Task to synchronize an AOR with our local state. More...
 
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. More...
 

Variables

static const struct ast_sorcery_observer aor_observer_callbacks
 Observer callbacks for AORs. More...
 
static struct ast_cli_entry cli_options []
 
static const struct ast_sorcery_observer contact_observer_callbacks
 Observer callbacks for contacts. More...
 
static struct ast_sip_endpoint_formatter contact_status_formatter
 
static const struct ast_sorcery_observer endpoint_observer_callbacks
 Observer callbacks for endpoints. More...
 
static struct ast_taskprocessormanagement_serializer
 
static pjsip_module options_module
 
static const char * short_status_map []
 
static struct ast_serializer_shutdown_groupshutdown_group
 Shutdown group for options serializers. More...
 
static struct ao2_containersip_options_aors
 
static struct ao2_containersip_options_contact_statuses
 
static struct ao2_containersip_options_endpoint_state_compositors
 
static const char * status_map []
 

Macro Definition Documentation

◆ AOR_BUCKETS

#define AOR_BUCKETS   1567

These are the number of buckets to store AORs in.

Definition at line 103 of file pjsip_options.c.

◆ AOR_STATUS_BUCKETS

#define AOR_STATUS_BUCKETS   3

These are the number of buckets (per endpoint state compositor) to use to store AOR statuses.

Definition at line 123 of file pjsip_options.c.

◆ CONTACT_BUCKETS

#define CONTACT_BUCKETS   13

These are the number of buckets (per AOR) to use to store contacts.

Definition at line 114 of file pjsip_options.c.

◆ CONTACT_STATUS_BUCKETS

#define CONTACT_STATUS_BUCKETS   1567

These are the number of contact status buckets.

Definition at line 110 of file pjsip_options.c.

◆ DEFAULT_ENCODING

#define DEFAULT_ENCODING   "identity"

Definition at line 97 of file pjsip_options.c.

◆ DEFAULT_LANGUAGE

#define DEFAULT_LANGUAGE   "en"

Definition at line 96 of file pjsip_options.c.

◆ ENDPOINT_STATE_COMPOSITOR_BUCKETS

#define ENDPOINT_STATE_COMPOSITOR_BUCKETS   13

These are the number of buckets to store endpoint state compositors.

Definition at line 117 of file pjsip_options.c.

◆ ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE

#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE   1

The initial vector size for the endpoint state compositors on an AOR.

Definition at line 120 of file pjsip_options.c.

◆ MAX_UNLOAD_TIMEOUT_TIME

#define MAX_UNLOAD_TIMEOUT_TIME   10 /* Seconds */

Maximum wait time to join the below shutdown group.

Definition at line 126 of file pjsip_options.c.

Function Documentation

◆ ami_show_contacts()

static int ami_show_contacts ( struct mansession s,
const struct message m 
)
static

Definition at line 2455 of file pjsip_options.c.

2456{
2457 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2458 struct ao2_container *contacts;
2459
2460 contacts = get_all_contacts();
2461 if (!contacts) {
2462 astman_send_error(s, m, "Could not get Contacts\n");
2463 return 0;
2464 }
2465
2466 if (!ao2_container_count(contacts)) {
2467 astman_send_error(s, m, "No Contacts found\n");
2468 ao2_ref(contacts, -1);
2469 return 0;
2470 }
2471
2472 astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",
2473 "start");
2474
2476
2477 astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);
2479
2480 ao2_ref(contacts, -1);
2481
2482 return 0;
2483}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ OBJ_NODATA
Definition: astobj2.h:1044
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3396
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3354
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3432
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3015
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3440
static struct ao2_container * get_all_contacts(void)
static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
Generic container type.
AMI variable container.
Definition: res_pjsip.h:3035
struct mansession * s
Definition: res_pjsip.h:3037
const struct message * m
Definition: res_pjsip.h:3039

References ao2_callback, ao2_container_count(), ao2_ref, astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), ast_sip_ami::count, format_ami_contactlist_handler(), get_all_contacts(), ast_sip_ami::m, OBJ_NODATA, and ast_sip_ami::s.

Referenced by ast_res_pjsip_init_options_handling().

◆ ami_sip_qualify()

static int ami_sip_qualify ( struct mansession s,
const struct message m 
)
static

Definition at line 2668 of file pjsip_options.c.

2669{
2670 const char *endpoint_name = astman_get_header(m, "Endpoint");
2671 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2672 char *aors;
2673 char *aor_name;
2674
2675 if (ast_strlen_zero(endpoint_name)) {
2676 astman_send_error(s, m, "Endpoint parameter missing.");
2677 return 0;
2678 }
2679
2680 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2681 endpoint_name);
2682 if (!endpoint) {
2683 astman_send_error(s, m, "Unable to retrieve endpoint\n");
2684 return 0;
2685 }
2686
2687 /* send a qualify for all contacts registered with the endpoint */
2688 if (ast_strlen_zero(endpoint->aors)) {
2689 astman_send_error(s, m, "No AoRs configured for endpoint\n");
2690 return 0;
2691 }
2692
2693 aors = ast_strdupa(endpoint->aors);
2694 while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2695 struct sip_options_aor *aor_options;
2696
2697 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2698 if (!aor_options) {
2699 continue;
2700 }
2701
2703 aor_options);
2704 ao2_ref(aor_options, -1);
2705 }
2706
2707 astman_send_ack(s, m, "Endpoint found, will qualify");
2708 return 0;
2709}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3386
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.
Definition: res_pjsip.c:2179
char * strsep(char **str, const char *delims)
static struct ao2_container * sip_options_aors
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define NULL
Definition: resample.c:96
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
An entity with which Asterisk communicates.
Definition: res_pjsip.h:951
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ao2_find, ao2_ref, ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strip(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), NULL, OBJ_SEARCH_KEY, RAII_VAR, sip_options_aor::serializer, sip_options_aors, sip_options_qualify_aor(), and strsep().

Referenced by ast_res_pjsip_init_options_handling().

◆ AO2_STRING_FIELD_CMP_FN() [1/4]

AO2_STRING_FIELD_CMP_FN ( ast_sip_contact_status  ,
name   
)

Comparator function for contact statuses.

◆ AO2_STRING_FIELD_CMP_FN() [2/4]

AO2_STRING_FIELD_CMP_FN ( sip_options_aor  ,
name   
)

Comparator function for SIP OPTIONS AORs.

◆ AO2_STRING_FIELD_CMP_FN() [3/4]

AO2_STRING_FIELD_CMP_FN ( sip_options_endpoint_aor_status  ,
name   
)

Comparator function for endpoint AOR status.

◆ AO2_STRING_FIELD_CMP_FN() [4/4]

AO2_STRING_FIELD_CMP_FN ( sip_options_endpoint_state_compositor  ,
name   
)

Comparator function for endpoint state compositors.

◆ AO2_STRING_FIELD_HASH_FN() [1/4]

AO2_STRING_FIELD_HASH_FN ( ast_sip_contact_status  ,
name   
)

Hashing function for contact statuses.

◆ AO2_STRING_FIELD_HASH_FN() [2/4]

AO2_STRING_FIELD_HASH_FN ( sip_options_aor  ,
name   
)

Hashing function for OPTIONS AORs.

◆ AO2_STRING_FIELD_HASH_FN() [3/4]

AO2_STRING_FIELD_HASH_FN ( sip_options_endpoint_aor_status  ,
name   
)

Hashing function for endpoint AOR status.

◆ AO2_STRING_FIELD_HASH_FN() [4/4]

AO2_STRING_FIELD_HASH_FN ( sip_options_endpoint_state_compositor  ,
name   
)

Hashing function for endpoint state compositors.

◆ AO2_STRING_FIELD_SORT_FN()

AO2_STRING_FIELD_SORT_FN ( ast_sip_contact_status  ,
name   
)

Sort function for contact statuses.

◆ aor_observer_deleted()

static void aor_observer_deleted ( const void *  obj)
static

Observer callback invoked on AOR deletion.

Definition at line 2048 of file pjsip_options.c.

2049{
2052}
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

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_aor_observer_deleted_task().

◆ aor_observer_modified()

static void aor_observer_modified ( const void *  obj)
static

Observer callback invoked on AOR creation or modification.

Definition at line 2017 of file pjsip_options.c.

2018{
2021}
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_aor_observer_modified_task().

◆ ast_res_pjsip_cleanup_options_handling()

void ast_res_pjsip_cleanup_options_handling ( void  )

Definition at line 2839 of file pjsip_options.c.

2840{
2841 int remaining;
2842 struct ast_taskprocessor *mgmt_serializer;
2843
2845 ast_manager_unregister("PJSIPQualify");
2846 ast_manager_unregister("PJSIPShowContacts");
2848
2855
2856 mgmt_serializer = management_serializer;
2858 if (mgmt_serializer) {
2860 }
2861
2864 if (remaining) {
2865 ast_log(LOG_WARNING, "Cleanup incomplete. Could not stop %d AORs.\n",
2866 remaining);
2867 }
2870
2871 if (mgmt_serializer) {
2872 ast_taskprocessor_unreference(mgmt_serializer);
2873 }
2874
2881
2882 pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
2883}
#define ast_log
Definition: astobj2.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8014
#define LOG_WARNING
static pjsip_module options_module
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
#define MAX_UNLOAD_TIMEOUT_TIME
Maximum wait time to join the below shutdown group.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.
static struct ao2_container * sip_options_contact_statuses
static struct ao2_container * sip_options_endpoint_state_compositors
static struct ast_cli_entry cli_options[]
static int sip_options_cleanup_task(void *obj)
Management task to clean up the environment.
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
static struct ast_sip_endpoint_formatter contact_status_formatter
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:487
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.
Definition: sorcery.c:2418
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
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.
Definition: threadpool.c:1241
#define ARRAY_LEN(a)
Definition: utils.h:666

References ao2_cleanup, aor_observer_callbacks, ARRAY_LEN, ast_cli_unregister_multiple(), ast_log, ast_manager_unregister(), ast_serializer_shutdown_group_join(), ast_sip_get_pjsip_endpoint(), ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sip_unregister_endpoint_formatter(), ast_sorcery_observer_remove(), ast_taskprocessor_unreference(), cli_options, contact_observer_callbacks, contact_status_formatter, endpoint_observer_callbacks, LOG_WARNING, management_serializer, MAX_UNLOAD_TIMEOUT_TIME, NULL, options_module, shutdown_group, sip_options_aors, sip_options_cleanup_task(), sip_options_contact_statuses, and sip_options_endpoint_state_compositors.

Referenced by ast_res_pjsip_init_options_handling(), and unload_pjsip().

◆ ast_res_pjsip_find_or_create_contact_status()

struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status ( const struct ast_sip_contact contact)

Definition at line 464 of file pjsip_options.c.

465{
466 struct ast_sip_contact_status *contact_status;
467 int res;
468
469 /*
470 * At startup a contact status can be retrieved when static contacts
471 * are themselves being setup. This happens before we are fully setup.
472 * Since we don't actually trigger qualify or anything as a result it
473 * is safe to do so. They'll just get back a contact status that will
474 * be updated later. At this time they only care that the contact
475 * status gets created for the static contact anyway.
476 */
478 /*
479 * We haven't been pre-initialized or we are shutting down.
480 * Neither situation should happen.
481 */
482 ast_assert(0);
483 return NULL;
484 }
485
487
488 /* If contact status for this contact already exists just return it */
489 contact_status = ao2_find(sip_options_contact_statuses,
491 if (contact_status) {
493 return contact_status;
494 }
495
496 /* Otherwise we have to create and store a new contact status */
497 contact_status = sip_contact_status_alloc(ast_sorcery_object_get_id(contact));
498 if (!contact_status) {
500 return NULL;
501 }
502
503 contact_status->rtt = 0;
504 contact_status->status = CREATED;
505 contact_status->last_status = CREATED;
506 res = ast_string_field_set(contact_status, uri, contact->uri);
507 res |= ast_string_field_set(contact_status, aor, contact->aor);
508 if (res) {
510 ao2_ref(contact_status, -1);
511 return NULL;
512 }
513
516
517 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
518 "+1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
519
520 sip_options_contact_status_update(contact_status);
521
522 return contact_status;
523}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
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_contact_status * sip_contact_status_alloc(const char *name)
@ CREATED
Definition: res_pjsip.h:434
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
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.
Definition: res_statsd.c:186
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
A contact's status.
Definition: res_pjsip.h:443
const ast_string_field uri
Definition: res_pjsip.h:449
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:460
enum ast_sip_contact_status_type last_status
Definition: res_pjsip.h:462
const ast_string_field aor
Definition: res_pjsip.h:449
const ast_string_field uri
Definition: res_pjsip.h:406
const ast_string_field aor
Definition: res_pjsip.h:406
#define ast_assert(a)
Definition: utils.h:739

References ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_sip_contact::aor, ast_sip_contact_status::aor, ast_assert, ast_sip_get_contact_status_label(), ast_sorcery_object_get_id(), AST_STATSD_GAUGE, ast_statsd_log_string_va(), ast_string_field_set, CREATED, ast_sip_contact_status::last_status, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, ast_sip_contact_status::rtt, sip_contact_status_alloc(), sip_options_contact_status_update(), sip_options_contact_statuses, ast_sip_contact_status::status, ast_sip_contact::uri, and ast_sip_contact_status::uri.

Referenced by contact_apply_handler(), permanent_uri_handler(), sip_options_contact_add_task(), sip_options_contact_status_available_count(), sip_options_qualify_contact(), sip_options_set_contact_status_qualified(), and sip_options_set_contact_status_unqualified().

◆ ast_res_pjsip_init_options_handling()

int ast_res_pjsip_init_options_handling ( int  reload)

Definition at line 2922 of file pjsip_options.c.

2923{
2924 struct ast_taskprocessor *mgmt_serializer;
2925
2926 static const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
2927
2928 if (reload) {
2930 return 0;
2931 }
2932
2933 if (pjsip_endpt_register_module(ast_sip_get_pjsip_endpoint(), &options_module)
2934 != PJ_SUCCESS) {
2935 return -1;
2936 }
2937
2938 if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW,
2939 NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2941 return -1;
2942 }
2943
2945 sip_options_aor_hash_fn, NULL, sip_options_aor_cmp_fn);
2946 if (!sip_options_aors) {
2948 return -1;
2949 }
2953 sip_options_endpoint_state_compositor_hash_fn, NULL,
2954 sip_options_endpoint_state_compositor_cmp_fn);
2957 return -1;
2958 }
2959
2960 mgmt_serializer = ast_sip_create_serializer("pjsip/options/manage");
2961 if (!mgmt_serializer) {
2963 return -1;
2964 }
2965
2966 /*
2967 * Set the water mark levels high because we can get a flood of
2968 * contact status updates from sip_options_synchronize() that
2969 * quickly clears on initial load or reload.
2970 */
2971 ast_taskprocessor_alert_set_levels(mgmt_serializer, -1,
2973
2974 /*
2975 * We make sure that the environment is completely setup before we allow
2976 * any other threads to post contact_status updates to the
2977 * management_serializer.
2978 */
2980 mgmt_serializer)) {
2981 /* Set management_serializer in case pushing the task actually failed. */
2982 management_serializer = mgmt_serializer;
2984 return -1;
2985 }
2986
2992
2993 return 0;
2994}
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:365
#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.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:2094
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
static int ami_sip_qualify(struct mansession *s, const struct message *m)
void ast_res_pjsip_cleanup_options_handling(void)
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS
These are the number of buckets to store endpoint state compositors.
#define AOR_BUCKETS
These are the number of buckets to store AORs in.
static int ami_show_contacts(struct mansession *s, const struct message *m)
static int sip_options_init_task(void *mgmt_serializer)
Management task to finish setting up the environment.
static int reload(void)
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:481
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:64
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.

References ami_show_contacts(), ami_sip_qualify(), AO2_ALLOC_OPT_LOCK_RWLOCK, ao2_container_alloc_hash, AOR_BUCKETS, ARRAY_LEN, ast_cli_register_multiple, ast_manager_register_xml, ast_res_pjsip_cleanup_options_handling(), ast_sip_create_serializer(), ast_sip_get_pjsip_endpoint(), ast_sip_push_task_wait_serializer(), ast_sip_register_endpoint_formatter(), ast_taskprocessor_alert_set_levels(), AST_TASKPROCESSOR_HIGH_WATER_LEVEL, cli_options, contact_status_formatter, ENDPOINT_STATE_COMPOSITOR_BUCKETS, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, management_serializer, NULL, options_module, reload(), sip_options_aors, sip_options_endpoint_state_compositors, sip_options_init_task(), and sip_options_synchronize().

Referenced by load_module(), and reload_configuration_task().

◆ ast_res_pjsip_preinit_options_handling()

int ast_res_pjsip_preinit_options_handling ( void  )

Definition at line 2916 of file pjsip_options.c.

2917{
2919 return sip_options_contact_statuses ? 0 : -1;
2920}
static struct ao2_container * sip_options_contact_statuses_alloc(void)
Helper function to allocate a contact statuses container.

References sip_options_contact_statuses, and sip_options_contact_statuses_alloc().

Referenced by load_module().

◆ ast_sip_format_contact_ami()

int ast_sip_format_contact_ami ( void *  obj,
void *  arg,
int  flags 
)

Formats the contact and sends over AMI.

Parameters
obja pointer an ast_sip_contact_wrapper structure
arga pointer to an ast_sip_ami structure
flagsignored
Return values
0Success, otherwise non-zero on error

Definition at line 2719 of file pjsip_options.c.

2720{
2721 struct ast_sip_contact_wrapper *wrapper = obj;
2722 struct ast_sip_contact *contact = wrapper->contact;
2723 struct ast_sip_ami *ami = arg;
2725 struct ast_str *buf;
2726 const struct ast_sip_endpoint *endpoint = ami->arg;
2727 char secs[AST_TIME_T_LEN];
2728
2729 buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
2730 if (!buf) {
2731 return -1;
2732 }
2733
2735
2736 ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
2737 ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
2738 ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
2739 ast_time_t_to_string(contact->expiration_time.tv_sec, secs, sizeof(secs));
2740 ast_str_append(&buf, 0, "RegExpire: %s\r\n", secs);
2741 if (!ast_strlen_zero(contact->via_addr)) {
2742 ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
2743 if (contact->via_port) {
2744 ast_str_append(&buf, 0, ":%d", contact->via_port);
2745 }
2746 ast_str_append(&buf, 0, "\r\n");
2747 }
2748 if (!ast_strlen_zero(contact->call_id)) {
2749 ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id);
2750 }
2751 ast_str_append(&buf, 0, "Status: %s\r\n",
2753 if (!status || status->status != AVAILABLE) {
2754 ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2755 } else {
2756 ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2757 }
2758 ast_str_append(&buf, 0, "EndpointName: %s\r\n",
2759 endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, ""));
2760
2761 ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));
2762 ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify);
2763 ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy);
2764 ast_str_append(&buf, 0, "Path: %s\r\n", contact->path);
2765 ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency);
2766 ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout);
2767
2768 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2769 ami->count++;
2770
2771 ast_free(buf);
2773 return 0;
2774}
jack_status_t status
Definition: app_jack.c:146
#define ast_free(a)
Definition: astmm.h:180
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3275
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
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.
@ AVAILABLE
Definition: res_pjsip.h:430
@ UNKNOWN
Definition: res_pjsip.h:432
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
void * arg
Definition: res_pjsip.h:3043
A wrapper for contact that adds the aor_id and a consistent contact id. Used by ast_sip_for_each_cont...
Definition: res_pjsip.h:509
struct ast_sip_contact * contact
Definition: res_pjsip.h:515
Contact associated with an address of record.
Definition: res_pjsip.h:384
double qualify_timeout
Definition: res_pjsip.h:414
const ast_string_field via_addr
Definition: res_pjsip.h:406
const ast_string_field call_id
Definition: res_pjsip.h:406
const ast_string_field outbound_proxy
Definition: res_pjsip.h:406
struct timeval expiration_time
Definition: res_pjsip.h:408
const ast_string_field path
Definition: res_pjsip.h:406
const ast_string_field endpoint_name
Definition: res_pjsip.h:406
int authenticate_qualify
Definition: res_pjsip.h:412
const ast_string_field user_agent
Definition: res_pjsip.h:406
unsigned int qualify_frequency
Definition: res_pjsip.h:410
Support for dynamic strings.
Definition: strings.h:623
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....
Definition: time.c:152
#define AST_TIME_T_LEN
Definition: time.h:45

References ao2_cleanup, ast_sip_contact_wrapper::aor_id, ast_sip_ami::arg, ast_free, ast_sip_create_ami_event(), ast_sip_get_contact_status(), ast_sip_get_contact_status_label(), ast_sorcery_object_get_id(), ast_str_append(), ast_str_buffer(), ast_strlen_zero(), AST_TIME_T_LEN, ast_time_t_to_string(), astman_append(), ast_sip_contact::authenticate_qualify, AVAILABLE, buf, ast_sip_contact::call_id, ast_sip_contact_wrapper::contact, ast_sip_ami::count, ast_sip_contact::endpoint_name, ast_sip_contact::expiration_time, ast_sip_contact::outbound_proxy, ast_sip_contact::path, ast_sip_contact::qualify_frequency, ast_sip_contact::qualify_timeout, ast_sip_ami::s, S_OR, status, UNKNOWN, ast_sip_contact::uri, ast_sip_contact::user_agent, ast_sip_contact::via_addr, and ast_sip_contact::via_port.

Referenced by ami_show_registration_contact_statuses(), and format_contact_status_for_aor().

◆ ast_sip_get_contact_short_status_label()

const char * ast_sip_get_contact_short_status_label ( const enum ast_sip_contact_status_type  status)

Definition at line 339 of file pjsip_options.c.

340{
342 return short_status_map[status];
343}
static const char * short_status_map[]

References ARRAY_LEN, ast_assert, short_status_map, and status.

Referenced by cli_contact_print_body().

◆ ast_sip_get_contact_status()

struct ast_sip_contact_status * ast_sip_get_contact_status ( const struct ast_sip_contact contact)

◆ ast_sip_get_contact_status_label()

const char * ast_sip_get_contact_status_label ( const enum ast_sip_contact_status_type  status)

◆ cli_qualify()

static char * cli_qualify ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2348 of file pjsip_options.c.

2349{
2350 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2351 const char *endpoint_name;
2352 char *aors;
2353 char *aor_name;
2354
2355 switch (cmd) {
2356 case CLI_INIT:
2357 e->command = "pjsip qualify";
2358 e->usage =
2359 "Usage: pjsip qualify <endpoint>\n"
2360 " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2361 return NULL;
2362 case CLI_GENERATE:
2363 return NULL;
2364 }
2365
2366 if (a->argc != 3) {
2367 return CLI_SHOWUSAGE;
2368 }
2369
2370 endpoint_name = a->argv[2];
2371
2372 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2373 endpoint_name);
2374 if (!endpoint) {
2375 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2376 return CLI_FAILURE;
2377 }
2378
2379 if (ast_strlen_zero(endpoint->aors)) {
2380 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2381 return CLI_FAILURE;
2382 }
2383
2384 aors = ast_strdupa(endpoint->aors);
2385 while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2386 struct sip_options_aor *aor_options;
2387
2388 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2389 if (!aor_options) {
2390 continue;
2391 }
2392
2393 ast_cli(a->fd, "Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2395 aor_options);
2396 ao2_ref(aor_options, -1);
2397 }
2398
2399 return CLI_SUCCESS;
2400}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ao2_cleanup, ao2_find, ao2_ref, ast_cli(), ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strip(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, OBJ_SEARCH_KEY, RAII_VAR, sip_options_aor::serializer, sip_options_aors, sip_options_qualify_aor(), strsep(), and ast_cli_entry::usage.

◆ cli_reload_qualify_aor()

static char * cli_reload_qualify_aor ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2632 of file pjsip_options.c.

2633{
2634 struct ast_sip_aor *aor;
2635 const char *aor_name;
2636
2637 switch (cmd) {
2638 case CLI_INIT:
2639 e->command = "pjsip reload qualify aor";
2640 e->usage =
2641 "Usage: pjsip reload qualify aor <id>\n"
2642 " Synchronize the PJSIP Aor qualify options.\n";
2643 return NULL;
2644 case CLI_GENERATE:
2645 return NULL;
2646 }
2647
2648 if (a->argc != 5) {
2649 return CLI_SHOWUSAGE;
2650 }
2651
2652 aor_name = a->argv[4];
2653
2654 aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2655 if (!aor) {
2656 ast_cli(a->fd, "Unable to retrieve aor '%s'\n", aor_name);
2657 return CLI_FAILURE;
2658 }
2659
2660 ast_cli(a->fd, "Synchronizing AOR '%s'\n", aor_name);
2663 ao2_ref(aor, -1);
2664
2665 return CLI_SUCCESS;
2666}
A SIP address of record.
Definition: res_pjsip.h:470

References a, ao2_ref, ast_cli(), ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, management_serializer, NULL, sip_options_aor_observer_modified_task(), and ast_cli_entry::usage.

◆ cli_reload_qualify_endpoint()

static char * cli_reload_qualify_endpoint ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2578 of file pjsip_options.c.

2579{
2580 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2581 const char *endpoint_name;
2582 char *aors;
2583 char *aor_name;
2584
2585 switch (cmd) {
2586 case CLI_INIT:
2587 e->command = "pjsip reload qualify endpoint";
2588 e->usage =
2589 "Usage: pjsip reload qualify endpoint <id>\n"
2590 " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2591 return NULL;
2592 case CLI_GENERATE:
2593 return NULL;
2594 }
2595
2596 if (a->argc != 5) {
2597 return CLI_SHOWUSAGE;
2598 }
2599
2600 endpoint_name = a->argv[4];
2601
2602 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2603 endpoint_name);
2604 if (!endpoint) {
2605 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2606 return CLI_FAILURE;
2607 }
2608
2609 if (ast_strlen_zero(endpoint->aors)) {
2610 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2611 return CLI_FAILURE;
2612 }
2613
2614 aors = ast_strdupa(endpoint->aors);
2615 while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2616 struct ast_sip_aor *aor;
2617
2618 aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2619 if (!aor) {
2620 continue;
2621 }
2622
2623 ast_cli(a->fd, "Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2626 ao2_ref(aor, -1);
2627 }
2628
2629 return CLI_SUCCESS;
2630}

References a, ao2_cleanup, ao2_ref, ast_cli(), ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strip(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, management_serializer, NULL, RAII_VAR, sip_options_aor_observer_modified_task(), strsep(), and ast_cli_entry::usage.

◆ cli_show_qualify_aor()

static char * cli_show_qualify_aor ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2541 of file pjsip_options.c.

2542{
2543 struct sip_options_aor *aor_options;
2544 const char *aor_name;
2545
2546 switch (cmd) {
2547 case CLI_INIT:
2548 e->command = "pjsip show qualify aor";
2549 e->usage =
2550 "Usage: pjsip show qualify aor <id>\n"
2551 " Show the PJSIP Aor current qualify options.\n";
2552 return NULL;
2553 case CLI_GENERATE:
2554 return NULL;
2555 }
2556
2557 if (a->argc != 5) {
2558 return CLI_SHOWUSAGE;
2559 }
2560
2561 aor_name = a->argv[4];
2562
2563 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2564 if (!aor_options) {
2565 ast_cli(a->fd, "Unable to retrieve aor '%s' qualify options\n", aor_name);
2566 return CLI_FAILURE;
2567 }
2568
2569 ast_cli(a->fd, " * AOR '%s'\n", aor_name);
2570 ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2571 ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2572 ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2573 ao2_ref(aor_options, -1);
2574
2575 return CLI_SUCCESS;
2576}
double qualify_timeout
Qualify timeout. 0 is diabled.
unsigned int qualify_frequency
Frequency to send OPTIONS requests to AOR contacts. 0 is disabled.

References a, ao2_find, ao2_ref, ast_cli(), sip_options_aor::authenticate_qualify, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, OBJ_SEARCH_KEY, sip_options_aor::qualify_frequency, sip_options_aor::qualify_timeout, sip_options_aors, and ast_cli_entry::usage.

◆ cli_show_qualify_endpoint()

static char * cli_show_qualify_endpoint ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2485 of file pjsip_options.c.

2486{
2487 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2488 const char *endpoint_name;
2489 char *aors;
2490 char *aor_name;
2491
2492 switch (cmd) {
2493 case CLI_INIT:
2494 e->command = "pjsip show qualify endpoint";
2495 e->usage =
2496 "Usage: pjsip show qualify endpoint <id>\n"
2497 " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2498 return NULL;
2499 case CLI_GENERATE:
2500 return NULL;
2501 }
2502
2503 if (a->argc != 5) {
2504 return CLI_SHOWUSAGE;
2505 }
2506
2507 endpoint_name = a->argv[4];
2508
2509 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2510 endpoint_name);
2511 if (!endpoint) {
2512 ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2513 return CLI_FAILURE;
2514 }
2515
2516 if (ast_strlen_zero(endpoint->aors)) {
2517 ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2518 return CLI_FAILURE;
2519 }
2520
2521 aors = ast_strdupa(endpoint->aors);
2522 while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2523 struct sip_options_aor *aor_options;
2524
2525 aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2526 if (!aor_options) {
2527 continue;
2528 }
2529
2530 ast_cli(a->fd, " * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2531 ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2532 ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2533 ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2534 ast_cli(a->fd, "\n");
2535 ao2_ref(aor_options, -1);
2536 }
2537
2538 return CLI_SUCCESS;
2539}

References a, ao2_cleanup, ao2_find, ao2_ref, ast_cli(), ast_sip_get_sorcery(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strip(), ast_strlen_zero(), sip_options_aor::authenticate_qualify, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, OBJ_SEARCH_KEY, sip_options_aor::qualify_frequency, sip_options_aor::qualify_timeout, RAII_VAR, sip_options_aors, strsep(), and ast_cli_entry::usage.

◆ contact_observer_created()

static void contact_observer_created ( const void *  obj)
static

Observer callback invoked on contact creation.

Definition at line 2189 of file pjsip_options.c.

2190{
2193}
static int sip_options_contact_add_management_task(void *obj)
Task to add a dynamic contact to an AOR in its serializer.

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_contact_add_management_task().

◆ contact_observer_deleted()

static void contact_observer_deleted ( const void *  obj)
static

Observer callback invoked on contact deletion.

Definition at line 2335 of file pjsip_options.c.

2336{
2339}
static int sip_options_contact_delete_management_task(void *obj)
Task to delete a contact from an AOR in its serializer.

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_contact_delete_management_task().

◆ contact_observer_updated()

static void contact_observer_updated ( const void *  obj)
static

Observer callback invoked on contact update.

Definition at line 2227 of file pjsip_options.c.

2228{
2229 const struct ast_sip_contact *contact = obj;
2230 struct sip_options_aor *aor_options = ao2_find(sip_options_aors, contact->aor, OBJ_SEARCH_KEY);
2231
2232 if (has_qualify_changed(contact, aor_options)) {
2233 struct ast_sip_aor *aor;
2234
2236 contact->aor);
2237 if (aor) {
2238 ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2239 contact->aor);
2242 ao2_ref(aor, -1);
2243 }
2244 }
2245
2248
2249 task_data = ast_malloc(sizeof(*task_data));
2250 if (!task_data) {
2251 ao2_ref(aor_options, -1);
2252 return;
2253 }
2254
2255 task_data->contact = (struct ast_sip_contact *) contact;
2256 /* task_data takes ownership of aor_options and will take care of releasing the ref */
2257 task_data->aor_options = aor_options;
2258
2259 ao2_ref(task_data->contact, +1);
2260 if (ast_sip_push_task(task_data->aor_options->serializer,
2262 ao2_ref(task_data->contact, -1);
2263 ao2_ref(task_data->aor_options, -1);
2265 }
2266 } else {
2267 ao2_cleanup(aor_options);
2268 }
2269}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:2099
#define ast_debug(level,...)
Log a DEBUG message.
static int sip_options_contact_update_task(void *obj)
Task which updates a dynamic contact to an AOR.
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.
unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
Retrieve the global setting 'send_contact_status_on_update_registration'.
Task details for adding an AOR to an endpoint state compositor.
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
userdata associated with baseline taskprocessor test

References ao2_cleanup, ao2_find, ao2_ref, ast_sip_contact::aor, sip_options_contact_observer_task_data::aor_options, ast_debug, ast_free, ast_malloc, ast_sip_get_send_contact_status_on_update_registration(), ast_sip_get_sorcery(), ast_sip_push_task(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), has_qualify_changed(), management_serializer, OBJ_SEARCH_KEY, sip_options_aor_observer_modified_task(), sip_options_aors, and sip_options_contact_update_task().

◆ contact_status_publish_update_task()

static int contact_status_publish_update_task ( void *  obj)
static

Task to notify endpoints of a contact status change.

Note
Run by management_serializer

Definition at line 436 of file pjsip_options.c.

437{
438 struct ast_sip_contact_status *contact_status = obj;
439 struct sip_options_aor *aor_options;
440
441 aor_options = ao2_find(sip_options_aors, contact_status->aor, OBJ_SEARCH_KEY);
442 if (aor_options) {
443 sip_options_publish_contact_state(aor_options, contact_status);
444 ao2_ref(aor_options, -1);
445 }
446 ao2_ref(contact_status, -1);
447
448 return 0;
449}
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.

References ao2_find, ao2_ref, ast_sip_contact_status::aor, OBJ_SEARCH_KEY, sip_options_aors, and sip_options_publish_contact_state().

Referenced by sip_options_contact_status_update().

◆ endpoint_observer_deleted()

static void endpoint_observer_deleted ( const void *  obj)
static

Observer callback invoked on endpoint deletion.

Definition at line 1885 of file pjsip_options.c.

1886{
1889}
static int sip_options_endpoint_observer_deleted_task(void *obj)
Task to delete an endpoint from the known universe.

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_endpoint_observer_deleted_task().

◆ endpoint_observer_modified()

static void endpoint_observer_modified ( const void *  obj)
static

Observer callback invoked on endpoint creation or modification.

Definition at line 1917 of file pjsip_options.c.

1918{
1921}
static int sip_options_endpoint_observer_modified_task(void *obj)
Task to synchronize the endpoint.

References ast_sip_push_task_wait_serializer(), management_serializer, and sip_options_endpoint_observer_modified_task().

◆ format_ami_contact_status()

static int format_ami_contact_status ( const struct ast_sip_endpoint endpoint,
struct ast_sip_ami ami 
)
static

Definition at line 2783 of file pjsip_options.c.

2785{
2786 ami->arg = (void *)endpoint;
2788}
static int format_contact_status_for_aor(void *obj, void *arg, int flags)
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.
Definition: location.c:687
const ast_string_field aors
Definition: res_pjsip.h:980

References ast_sip_endpoint::aors, ast_sip_ami::arg, ast_sip_for_each_aor(), and format_contact_status_for_aor().

◆ format_ami_contactlist_handler()

static int format_ami_contactlist_handler ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2418 of file pjsip_options.c.

2419{
2420 struct ast_sip_contact *contact = obj;
2421 struct ast_sip_ami *ami = arg;
2422 struct ast_str *buf;
2424
2425 buf = ast_sip_create_ami_event("ContactList", ami);
2426 if (!buf) {
2427 return CMP_STOP;
2428 }
2429
2430 if (sip_contact_to_ami(contact, &buf)) {
2431 ast_free(buf);
2432 return CMP_STOP;
2433 }
2434
2435 /* Add extra info */
2437 ast_str_append(&buf, 0, "Status: %s\r\n",
2439 if (!status || status->status != AVAILABLE) {
2440 ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2441 } else {
2442 ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2443 }
2445
2446 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2447
2448 ami->count++;
2449
2450 ast_free(buf);
2451
2452 return 0;
2453}
@ CMP_STOP
Definition: astobj2.h:1028
static int sip_contact_to_ami(const struct ast_sip_contact *contact, struct ast_str **buf)

References ao2_cleanup, ast_sip_ami::arg, ast_free, ast_sip_create_ami_event(), ast_sip_get_contact_status(), ast_sip_get_contact_status_label(), ast_str_append(), ast_str_buffer(), astman_append(), AVAILABLE, buf, CMP_STOP, ast_sip_ami::count, ast_sip_ami::s, sip_contact_to_ami(), status, and UNKNOWN.

Referenced by ami_show_contacts().

◆ format_contact_status_for_aor()

static int format_contact_status_for_aor ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2776 of file pjsip_options.c.

2777{
2778 struct ast_sip_aor *aor = obj;
2779
2781}
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
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.
Definition: location.c:722

References ast_sip_for_each_contact(), and ast_sip_format_contact_ami().

Referenced by format_ami_contact_status().

◆ get_all_contacts()

static struct ao2_container * get_all_contacts ( void  )
static

Definition at line 2402 of file pjsip_options.c.

2403{
2404 struct ao2_container *contacts;
2405
2408
2409 return contacts;
2410}
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
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.
Definition: sorcery.c:1897

References AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), and NULL.

Referenced by ami_show_contacts().

◆ has_qualify_changed()

static int has_qualify_changed ( const struct ast_sip_contact contact,
const struct sip_options_aor aor_options 
)
static

Check if the contact qualify options are different than local aor qualify options.

Definition at line 2073 of file pjsip_options.c.

2074{
2075 if (!contact) {
2076 return 0;
2077 }
2078
2079 if (!aor_options) {
2080 if (contact->qualify_frequency) {
2081 return 1;
2082 }
2083 } else if (contact->qualify_frequency != aor_options->qualify_frequency
2084 || contact->authenticate_qualify != aor_options->authenticate_qualify
2085 || ((int)(contact->qualify_timeout * 1000)) != ((int)(aor_options->qualify_timeout * 1000))) {
2086 return 1;
2087 }
2088
2089 return 0;
2090}

References ast_sip_contact::authenticate_qualify, sip_options_aor::authenticate_qualify, ast_sip_contact::qualify_frequency, sip_options_aor::qualify_frequency, ast_sip_contact::qualify_timeout, and sip_options_aor::qualify_timeout.

Referenced by contact_observer_updated(), and sip_options_contact_add_management_task().

◆ options_on_rx_request()

static pj_bool_t options_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 267 of file pjsip_options.c.

268{
269 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
270 pjsip_uri *ruri;
271 char exten[AST_MAX_EXTENSION];
272
273 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
274 return PJ_FALSE;
275 }
276
277 if (!(endpoint = ast_pjsip_rdata_get_endpoint(rdata))) {
278 return PJ_FALSE;
279 }
280
281 ruri = rdata->msg_info.msg->line.req.uri;
282 if (!ast_sip_is_allowed_uri(ruri)) {
283 send_options_response(rdata, 416);
284 return PJ_TRUE;
285 }
286
287 ast_copy_pj_str(exten, ast_sip_pjsip_uri_get_username(ruri), sizeof(exten));
288
289 /*
290 * We may want to match in the dialplan without any user
291 * options getting in the way.
292 */
294
295 if (ast_shutting_down()) {
296 /*
297 * Not taking any new calls at this time.
298 * Likely a server availability OPTIONS poll.
299 */
300 send_options_response(rdata, 503);
301 } else if (!ast_strlen_zero(exten)
302 && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
303 send_options_response(rdata, 404);
304 } else {
305 send_options_response(rdata, 200);
306 }
307 return PJ_TRUE;
308}
int ast_shutting_down(void)
Definition: asterisk.c:1872
#define AST_MAX_EXTENSION
Definition: channel.h:134
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition: res_pjsip.c:3477
int ast_sip_is_allowed_uri(pjsip_uri *uri)
Check whether a pjsip_uri is allowed or not.
Definition: res_pjsip.c:3472
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3339
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.
Definition: res_pjsip.c:2201

References ao2_cleanup, ast_copy_pj_str(), ast_exists_extension(), AST_MAX_EXTENSION, ast_pjsip_rdata_get_endpoint(), ast_shutting_down(), ast_sip_is_allowed_uri(), ast_sip_pjsip_uri_get_username(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_strlen_zero(), NULL, RAII_VAR, and send_options_response().

◆ qualify_contact_cb()

static void qualify_contact_cb ( void *  token,
pjsip_event *  e 
)
static

Callback for when we get a result from a SIP OPTIONS request (a response or a timeout)

Definition at line 788 of file pjsip_options.c.

789{
790 struct sip_options_contact_callback_data *contact_callback_data = token;
792
793 switch(e->body.tsx_state.type) {
794 default:
795 ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
796 /* Fall through */
797 case PJSIP_EVENT_TRANSPORT_ERROR:
798 case PJSIP_EVENT_TIMER:
800 break;
801 case PJSIP_EVENT_RX_MSG:
803 break;
804 }
805
806 /* Update the callback data with the new status, this will get handled in the AOR serializer */
807 contact_callback_data->status = status;
808
809 if (ast_sip_push_task(contact_callback_data->aor_options->serializer,
810 sip_options_contact_status_notify_task, contact_callback_data)) {
811 ast_log(LOG_WARNING, "Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
812 ast_sorcery_object_get_id(contact_callback_data->contact),
813 contact_callback_data->aor_options->name);
814 ao2_ref(contact_callback_data, -1);
815 }
816
817 /* The task inherited our reference so we don't unreference here */
818}
#define LOG_ERROR
static int sip_options_contact_status_notify_task(void *obj)
Task to notify an AOR of a contact status change.
ast_sip_contact_status_type
Status type for a contact.
Definition: res_pjsip.h:426
@ UNAVAILABLE
Definition: res_pjsip.h:428
char name[0]
The name of the AOR.
Structure used to contain information for an OPTIONS callback.
struct ast_sip_contact * contact
The contact we qualified.
enum ast_sip_contact_status_type status
The new status of the contact.
struct sip_options_aor * aor_options
The AOR options.

References ao2_ref, sip_options_contact_callback_data::aor_options, ast_log, ast_sip_push_task(), ast_sorcery_object_get_id(), AVAILABLE, sip_options_contact_callback_data::contact, LOG_ERROR, LOG_WARNING, sip_options_aor::name, sip_options_aor::serializer, sip_options_contact_status_notify_task(), status, sip_options_contact_callback_data::status, and UNAVAILABLE.

Referenced by sip_options_qualify_contact().

◆ send_options_response()

static pj_status_t send_options_response ( pjsip_rx_data *  rdata,
int  code 
)
static

Definition at line 215 of file pjsip_options.c.

216{
217 pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
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;
222 pj_status_t status;
223
224 /* Make the response object */
225 status = ast_sip_create_response(rdata, code, NULL, &tdata);
226 if (status != PJ_SUCCESS) {
227 ast_log(LOG_ERROR, "Unable to create response (%d)\n", status);
228 return status;
229 }
230
231 /* Add appropriate headers */
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));
234 }
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));
237 }
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));
240 }
241
242 /*
243 * XXX TODO: pjsip doesn't care a lot about either of these headers -
244 * while it provides specific methods to create them, they are defined
245 * to be the standard string header creation. Hard coded here.
246 */
247 ast_sip_add_header(tdata, "Accept-Encoding", DEFAULT_ENCODING);
248 ast_sip_add_header(tdata, "Accept-Language", DEFAULT_LANGUAGE);
249
250 if (dlg && trans) {
251 status = pjsip_dlg_send_response(dlg, trans, tdata);
252 } else {
253 struct ast_sip_endpoint *endpoint;
254
255 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
256 status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
257 ao2_cleanup(endpoint);
258 }
259
260 if (status != PJ_SUCCESS) {
261 ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
262 }
263
264 return status;
265}
#define DEFAULT_ENCODING
Definition: pjsip_options.c:97
#define DEFAULT_LANGUAGE
Definition: pjsip_options.c:96
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.
Definition: res_pjsip.c:2468
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:2008
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.
Definition: res_pjsip.c:2424

References ao2_cleanup, ast_log, ast_pjsip_rdata_get_endpoint(), ast_sip_add_header(), ast_sip_create_response(), ast_sip_get_pjsip_endpoint(), ast_sip_send_stateful_response(), DEFAULT_ENCODING, DEFAULT_LANGUAGE, LOG_ERROR, NULL, and status.

Referenced by options_on_rx_request().

◆ sip_contact_status_alloc()

static struct ast_sip_contact_status * sip_contact_status_alloc ( const char *  name)
static

Definition at line 355 of file pjsip_options.c.

356{
357 struct ast_sip_contact_status *contact_status;
358 size_t size = sizeof(*contact_status) + strlen(name) + 1;
359
360 contact_status = ao2_alloc_options(size, sip_contact_status_dtor,
362 if (!contact_status) {
363 return NULL;
364 }
365 if (ast_string_field_init(contact_status, 256)) {
366 ao2_ref(contact_status, -1);
367 return NULL;
368 }
369 AST_VECTOR_INIT(&contact_status->security_mechanisms, 0);
370 strcpy(contact_status->name, name); /* SAFE */
371 return contact_status;
372}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static const char name[]
Definition: format_mp3.c:68
static void sip_contact_status_dtor(void *obj)
Destructor for contact statuses.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
struct ast_sip_security_mechanism_vector security_mechanisms
Definition: res_pjsip.h:458
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_string_field_init, AST_VECTOR_INIT, ast_sip_contact_status::name, name, NULL, ast_sip_contact_status::security_mechanisms, and sip_contact_status_dtor().

Referenced by ast_res_pjsip_find_or_create_contact_status(), and sip_contact_status_copy().

◆ sip_contact_status_copy()

static struct ast_sip_contact_status * sip_contact_status_copy ( const struct ast_sip_contact_status src)
static

Definition at line 374 of file pjsip_options.c.

375{
376 struct ast_sip_contact_status *dst;
377
378 dst = sip_contact_status_alloc(src->name);
379 if (!dst) {
380 return NULL;
381 }
382
383 if (ast_string_fields_copy(dst, src)) {
384 ao2_ref(dst, -1);
385 return NULL;
386 }
387 dst->rtt = src->rtt;
388 dst->status = src->status;
389 dst->last_status = src->last_status;
390
392 return dst;
393}
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.
#define ast_string_fields_copy(copy, orig)
Copy all string fields from one instance to another of the same structure.
Definition: stringfields.h:630

References ao2_ref, ast_sip_security_mechanisms_vector_copy(), ast_string_fields_copy, ast_sip_contact_status::last_status, ast_sip_contact_status::name, NULL, ast_sip_contact_status::rtt, ast_sip_contact_status::security_mechanisms, sip_contact_status_alloc(), and ast_sip_contact_status::status.

Referenced by sip_options_contact_status_notify_task(), sip_options_remove_contact_status(), and sip_options_set_contact_status().

◆ sip_contact_status_dtor()

static void sip_contact_status_dtor ( void *  obj)
static

Destructor for contact statuses.

Definition at line 346 of file pjsip_options.c.

347{
348 struct ast_sip_contact_status *contact_status = obj;
349
351
352 ast_string_field_free_memory(contact_status);
353}
void ast_sip_security_mechanisms_vector_destroy(struct ast_sip_security_mechanism_vector *security_mechanisms)
Free contents of a security mechanism vector.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ast_sip_security_mechanisms_vector_destroy(), ast_string_field_free_memory, and ast_sip_contact_status::security_mechanisms.

Referenced by sip_contact_status_alloc().

◆ sip_contact_to_ami()

static int sip_contact_to_ami ( const struct ast_sip_contact contact,
struct ast_str **  buf 
)
static

Definition at line 2412 of file pjsip_options.c.

2414{
2415 return ast_sip_sorcery_object_to_ami(contact, buf);
2416}
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.

References ast_sip_sorcery_object_to_ami(), and buf.

Referenced by format_ami_contactlist_handler().

◆ sip_options_aor_alloc()

static struct sip_options_aor * sip_options_aor_alloc ( struct ast_sip_aor aor)
static

Allocator for AOR OPTIONS.

Definition at line 965 of file pjsip_options.c.

966{
967 struct sip_options_aor *aor_options;
968 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
969
970 aor_options = ao2_alloc_options(sizeof(*aor_options) + strlen(ast_sorcery_object_get_id(aor)) + 1,
972 if (!aor_options) {
973 return NULL;
974 }
975
976 strcpy(aor_options->name, ast_sorcery_object_get_id(aor)); /* SAFE */
977
978 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/options/%s",
980 aor_options->serializer = ast_sip_create_serializer_group(tps_name,
982 if (!aor_options->serializer) {
983 ao2_ref(aor_options, -1);
984 return NULL;
985 }
986
988 ao2_ref(aor_options, -1);
989 return NULL;
990 }
991
995 if (!aor_options->contacts) {
996 ao2_ref(aor_options, -1);
997 return NULL;
998 }
999
1003 if (!aor_options->dynamic_contacts) {
1004 ao2_ref(aor_options, -1);
1005 return NULL;
1006 }
1007
1008 return aor_options;
1009}
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
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.
Definition: res_pjsip.c:2089
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE
The initial vector size for the endpoint state compositors on an AOR.
static void sip_options_aor_dtor(void *obj)
Destructor function for SIP OPTIONS AORs.
#define CONTACT_BUCKETS
These are the number of buckets (per AOR) to use to store contacts.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2470
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.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:61

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_container_alloc_hash, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, ao2_ref, ast_sip_create_serializer_group(), ast_sorcery_object_get_id(), ast_sorcery_object_id_compare(), ast_sorcery_object_id_hash(), ast_sorcery_object_id_sort(), ast_taskprocessor_build_name(), AST_TASKPROCESSOR_MAX_NAME, AST_VECTOR_INIT, sip_options_aor::compositors, CONTACT_BUCKETS, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE, sip_options_aor::name, NULL, sip_options_aor::serializer, shutdown_group, and sip_options_aor_dtor().

Referenced by sip_options_aor_observer_modified_task(), and sip_options_synchronize_aor().

◆ sip_options_aor_dtor()

static void sip_options_aor_dtor ( void *  obj)
static

Destructor function for SIP OPTIONS AORs.

Definition at line 943 of file pjsip_options.c.

944{
945 struct sip_options_aor *aor_options = obj;
946
947 /*
948 * Any contacts are unreachable since the AOR is being destroyed
949 * so remove their contact status
950 */
951 if (aor_options->contacts) {
953 sip_options_remove_contact, aor_options);
954 ao2_ref(aor_options->contacts, -1);
955 }
956 ao2_cleanup(aor_options->dynamic_contacts);
957
959
960 ast_assert(AST_VECTOR_SIZE(&aor_options->compositors) == 0);
961 AST_VECTOR_FREE(&aor_options->compositors);
962}
@ OBJ_UNLINK
Definition: astobj2.h:1039
static int sip_options_remove_contact(void *obj, void *arg, int flags)
Forward declaration of this helpful function.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174

References ao2_callback, ao2_cleanup, ao2_ref, ast_assert, ast_taskprocessor_unreference(), AST_VECTOR_FREE, AST_VECTOR_SIZE, sip_options_aor::compositors, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, OBJ_NODATA, OBJ_UNLINK, sip_options_aor::serializer, and sip_options_remove_contact().

Referenced by sip_options_aor_alloc().

◆ sip_options_aor_observer_deleted_task()

static int sip_options_aor_observer_deleted_task ( void *  obj)
static

Task to delete an AOR from the known universe.

Note
Run by management_serializer

Definition at line 2027 of file pjsip_options.c.

2028{
2029 struct ast_sip_aor *aor = obj;
2030 struct sip_options_aor *aor_options;
2031
2034 if (!aor_options) {
2035 return 0;
2036 }
2037
2038 ast_debug(3, "AOR '%s' has been deleted, removing it\n", aor_options->name);
2039
2041 aor_options);
2042 ao2_ref(aor_options, -1);
2043
2044 return 0;
2045}
static int sip_options_aor_remove_task(void *obj)
Task which removes an AOR from all of the ESCs it is reporting to.

References ao2_find, ao2_ref, ast_debug, ast_sip_push_task_wait_serializer(), ast_sorcery_object_get_id(), sip_options_aor::name, OBJ_SEARCH_KEY, OBJ_UNLINK, sip_options_aor::serializer, sip_options_aor_remove_task(), and sip_options_aors.

Referenced by aor_observer_deleted().

◆ sip_options_aor_observer_modified_task()

static int sip_options_aor_observer_modified_task ( void *  obj)
static

Task to synchronize the AOR.

Note
Run by management_serializer

Definition at line 1962 of file pjsip_options.c.

1963{
1964 struct ast_sip_aor *aor = obj;
1965 struct sip_options_aor *aor_options;
1966
1969 if (!aor_options) {
1970 struct ao2_container *endpoints;
1971
1972 aor_options = sip_options_aor_alloc(aor);
1973 if (!aor_options) {
1974 return 0;
1975 }
1976
1977 /*
1978 * This is a newly added AOR and we need to establish any
1979 * endpoint state compositors that may reference only the
1980 * AOR. If these need to be updated later then they'll
1981 * be done by modifying the endpoint or issuing a reload.
1982 */
1983 sip_options_apply_aor_configuration(aor_options, aor, 1);
1984 ao2_link(sip_options_aors, aor_options);
1985
1986 /*
1987 * Using LIKE doesn't seem to work very well with non-realtime so we
1988 * fetch everything right now and do a filter on our side.
1989 */
1992 if (endpoints) {
1994 ao2_ref(endpoints, -1);
1995 }
1996 } else {
1998 .aor_options = aor_options,
1999 .aor = aor,
2000 };
2001
2002 /*
2003 * If this AOR was modified we have to do our work in its serializer
2004 * instead of this thread to ensure that things aren't modified by
2005 * multiple threads.
2006 */
2009 }
2010
2011 ao2_ref(aor_options, -1);
2012
2013 return 0;
2014}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
static struct ao2_container * endpoints
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 struct sip_options_aor * sip_options_aor_alloc(struct ast_sip_aor *aor)
Allocator for AOR OPTIONS.
static int sip_options_update_aor_task(void *obj)
Task to synchronize an AOR with our local state.
Task data for AOR creation or updating.
struct sip_options_aor * aor_options
The AOR options for this AOR.
struct ast_sip_aor * aor
The AOR which contains the new configuraton.

References ao2_callback, ao2_find, ao2_link, ao2_ref, sip_options_synchronize_aor_task_data::aor, sip_options_synchronize_aor_task_data::aor_options, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_fields(), endpoints, NULL, OBJ_NODATA, OBJ_SEARCH_KEY, sip_options_aor::serializer, sip_options_aor_alloc(), sip_options_aors, sip_options_apply_aor_configuration(), sip_options_synchronize_endpoint(), and sip_options_update_aor_task().

Referenced by aor_observer_modified(), cli_reload_qualify_aor(), cli_reload_qualify_endpoint(), contact_observer_updated(), and sip_options_contact_add_management_task().

◆ sip_options_aor_remove_task()

static int sip_options_aor_remove_task ( void *  obj)
static

Task which removes an AOR from all of the ESCs it is reporting to.

Note
Run by aor_options->serializer

Definition at line 1690 of file pjsip_options.c.

1691{
1692 struct sip_options_aor *aor_options = obj;
1693
1695
1696 if (aor_options->sched_task) {
1698 ao2_ref(aor_options->sched_task, -1);
1699 aor_options->sched_task = NULL;
1700 }
1701
1702 return 0;
1703}
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
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.
@ REMOVED
Definition: res_pjsip.h:435
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.

References ao2_ref, ast_sip_sched_task_cancel(), NULL, REMOVED, sip_options_aor::sched_task, and sip_options_notify_endpoint_state_compositors().

Referenced by sip_options_aor_observer_deleted_task(), and sip_options_unused_aor().

◆ sip_options_apply_aor_configuration()

static void sip_options_apply_aor_configuration ( struct sip_options_aor aor_options,
struct ast_sip_aor aor,
int  is_new 
)
static

Function which applies configuration to an AOR options structure.

Note
Run by aor_options->serializer (or management_serializer on aor_options creation)

Definition at line 1242 of file pjsip_options.c.

1244{
1245 struct ao2_container *existing_contacts;
1246 struct ast_sip_contact *contact;
1247 struct ao2_iterator iter;
1248
1249 ast_debug(3, "Configuring AOR '%s' with current state of configuration and world\n",
1250 aor_options->name);
1251
1252 /*
1253 * Permanent contacts, since we receive no notification that they
1254 * are gone, follow the same approach as AORs. We create a copy
1255 * of the existing container and any reused contacts are removed
1256 * from it. Any contacts remaining in the container after
1257 * processing no longer exist so we need to remove their state.
1258 */
1259 existing_contacts = ao2_container_clone(aor_options->contacts, 0);
1260 if (!existing_contacts) {
1261 ast_log(LOG_WARNING, "Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1262 aor_options->name);
1263 return;
1264 }
1265
1267 NULL, NULL);
1268
1269 /* Process permanent contacts */
1270 if (aor->permanent_contacts) {
1271 iter = ao2_iterator_init(aor->permanent_contacts, 0);
1272 for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1273 ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1275 ao2_link(aor_options->contacts, contact);
1276 }
1277 ao2_iterator_destroy(&iter);
1278 }
1279
1280 /*
1281 * If this is newly added we need to see if there are any
1282 * existing dynamic contacts to add. Ones that are added
1283 * after creation will occur as a result of the contact
1284 * observer creation callback.
1285 */
1286 if (is_new) {
1287 size_t prefix_len = strlen(ast_sorcery_object_get_id(aor)) + sizeof(";@") - 1;
1288 char prefix[prefix_len + 1];
1289 struct ao2_container *contacts;
1290
1291 sprintf(prefix, "%s;@", ast_sorcery_object_get_id(aor)); /* Safe */
1293 prefix, prefix_len);
1294 if (contacts) {
1295 ao2_container_dup(aor_options->dynamic_contacts, contacts, 0);
1296 ao2_ref(contacts, -1);
1297 }
1298 }
1299
1300 /* Process dynamic contacts */
1301 iter = ao2_iterator_init(aor_options->dynamic_contacts, 0);
1302 for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1303 ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1305 ao2_link(aor_options->contacts, contact);
1306 }
1307 ao2_iterator_destroy(&iter);
1308
1309 /* Any contacts left no longer exist, so raise events and make them disappear */
1310 ao2_callback(existing_contacts, OBJ_NODATA | OBJ_UNLINK,
1311 sip_options_remove_contact, aor_options);
1312 ao2_ref(existing_contacts, -1);
1313
1314 /*
1315 * Update the available count if we transition between qualified
1316 * and unqualified. In the qualified case we need to start with
1317 * 0 available as the qualify process will take care of it. In
1318 * the unqualified case it is based on the number of contacts
1319 * present.
1320 */
1321 if (!aor->qualify_frequency) {
1322 ao2_callback(aor_options->contacts, OBJ_NODATA,
1324 aor_options->available = ao2_container_count(aor_options->contacts);
1325 ast_debug(3, "AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1326 aor_options->name, aor_options->available);
1327 } else if (!aor_options->qualify_frequency) {
1328 ao2_callback(aor_options->contacts, OBJ_NODATA,
1330 aor_options->available = 0;
1331 ast_debug(3, "AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1332 aor_options->name);
1333 } else {
1334 /*
1335 * Count the number of AVAILABLE qualified contacts to ensure
1336 * the count is in sync with reality.
1337 */
1338 aor_options->available = 0;
1339 ao2_callback(aor_options->contacts, OBJ_NODATA,
1341 }
1342
1343 aor_options->authenticate_qualify = aor->authenticate_qualify;
1344 aor_options->qualify_timeout = aor->qualify_timeout;
1345
1346 /*
1347 * If we need to stop or start the scheduled callback then do so.
1348 * This occurs due to the following:
1349 * 1. The qualify frequency has changed
1350 * 2. Contacts were added when previously there were none
1351 * 3. There are no contacts but previously there were some
1352 */
1353 if (aor_options->qualify_frequency != aor->qualify_frequency
1354 || (!aor_options->sched_task && ao2_container_count(aor_options->contacts))
1355 || (aor_options->sched_task && !ao2_container_count(aor_options->contacts))) {
1356 if (aor_options->sched_task) {
1358 ao2_ref(aor_options->sched_task, -1);
1359 aor_options->sched_task = NULL;
1360 }
1361
1362 /* If there is still a qualify frequency then schedule this */
1363 aor_options->qualify_frequency = aor->qualify_frequency;
1364 if (aor_options->qualify_frequency
1365 && ao2_container_count(aor_options->contacts)) {
1366 aor_options->sched_task = ast_sip_schedule_task(aor_options->serializer,
1370 if (!aor_options->sched_task) {
1371 ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
1372 aor_options->name);
1373 }
1374 }
1375 }
1376
1377 ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1378 aor_options->available);
1379}
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)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
#define ao2_container_clone(orig, flags)
Create a clone/copy of the given container.
Definition: astobj2.h:1419
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.
@ AST_SIP_SCHED_TASK_DATA_AO2
Definition: res_pjsip.h:2086
@ AST_SIP_SCHED_TASK_VARIABLE
Definition: res_pjsip.h:2069
static char prefix[MAX_PREFIX]
Definition: http.c:144
static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
Count AVAILABLE qualified contacts.
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_set_contact_status_qualified(void *obj, void *arg, int flags)
Transition the contact status to qualified mode.
static int sip_options_determine_initial_qualify_time(int qualify_frequency)
Determine an initial time for scheduling AOR qualifying.
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.
Definition: sorcery.c:1984
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
double qualify_timeout
Definition: res_pjsip.h:498
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:494
int authenticate_qualify
Definition: res_pjsip.h:488
unsigned int qualify_frequency
Definition: res_pjsip.h:486
unsigned int available
The number of available contacts on this AOR.
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.

References ao2_callback, ao2_container_clone, ao2_container_count(), ao2_container_dup(), ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_ref, ast_debug, ast_log, ast_sip_get_sorcery(), ast_sip_sched_task_cancel(), AST_SIP_SCHED_TASK_DATA_AO2, AST_SIP_SCHED_TASK_VARIABLE, ast_sip_schedule_task(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_prefix(), ast_taskprocessor_name(), ast_sip_aor::authenticate_qualify, sip_options_aor::authenticate_qualify, sip_options_aor::available, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, LOG_ERROR, LOG_WARNING, sip_options_aor::name, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, ast_sip_aor::permanent_contacts, prefix, ast_sip_aor::qualify_frequency, sip_options_aor::qualify_frequency, ast_sip_aor::qualify_timeout, sip_options_aor::qualify_timeout, sip_options_aor::sched_task, sip_options_aor::serializer, sip_options_contact_status_available_count(), sip_options_determine_initial_qualify_time(), sip_options_qualify_aor(), sip_options_remove_contact(), sip_options_set_contact_status_qualified(), and sip_options_set_contact_status_unqualified().

Referenced by sip_options_aor_observer_modified_task(), sip_options_synchronize_aor_task(), and sip_options_update_aor_task().

◆ sip_options_cleanup_aor_task()

static int sip_options_cleanup_aor_task ( void *  obj)
static

Management task to clean up an AOR.

Note
Run by aor_options->serializer

Definition at line 2798 of file pjsip_options.c.

2799{
2800 struct sip_options_aor *aor_options = obj;
2801
2802 ast_debug(2, "Cleaning up AOR '%s' for shutdown\n", aor_options->name);
2803
2804 aor_options->qualify_frequency = 0;
2805 if (aor_options->sched_task) {
2807 ao2_ref(aor_options->sched_task, -1);
2808 aor_options->sched_task = NULL;
2809 }
2811
2812 return 0;
2813}
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625

References ao2_cleanup, ao2_ref, ast_debug, ast_sip_sched_task_cancel(), AST_VECTOR_RESET, sip_options_aor::compositors, sip_options_aor::name, NULL, sip_options_aor::qualify_frequency, and sip_options_aor::sched_task.

Referenced by sip_options_cleanup_task().

◆ sip_options_cleanup_task()

static int sip_options_cleanup_task ( void *  obj)
static

Management task to clean up the environment.

Note
Run by management_serializer

Definition at line 2819 of file pjsip_options.c.

2820{
2821 struct ao2_iterator it_aor;
2822 struct sip_options_aor *aor_options;
2823
2824 if (!sip_options_aors) {
2825 /* Nothing to do */
2826 return 0;
2827 }
2828
2830 for (; (aor_options = ao2_iterator_next(&it_aor)); ao2_ref(aor_options, -1)) {
2832 sip_options_cleanup_aor_task, aor_options);
2833 }
2834 ao2_iterator_destroy(&it_aor);
2835
2836 return 0;
2837}
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
static int sip_options_cleanup_aor_task(void *obj)
Management task to clean up an AOR.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ao2_ref, ast_sip_push_task_wait_serializer(), sip_options_aor::serializer, sip_options_aors, and sip_options_cleanup_aor_task().

Referenced by ast_res_pjsip_cleanup_options_handling().

◆ sip_options_contact_add_management_task()

static int sip_options_contact_add_management_task ( void *  obj)
static

Task to add a dynamic contact to an AOR in its serializer.

Note
Run by management_serializer

Definition at line 2156 of file pjsip_options.c.

2157{
2159
2160 task_data.contact = obj;
2161 task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2163
2164 if (has_qualify_changed(task_data.contact, task_data.aor_options)) {
2165 struct ast_sip_aor *aor;
2166
2168 task_data.contact->aor);
2169 if (aor) {
2170 ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2171 task_data.contact->aor);
2173 ao2_ref(aor, -1);
2174 }
2175 }
2176
2177 if (!task_data.aor_options) {
2178 return 0;
2179 }
2180
2181 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2183 ao2_ref(task_data.aor_options, -1);
2184
2185 return 0;
2186}
static int sip_options_contact_add_task(void *obj)
Task which adds a dynamic contact to an AOR.

References ao2_find, ao2_ref, ast_debug, ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), has_qualify_changed(), OBJ_SEARCH_KEY, sip_options_aor_observer_modified_task(), sip_options_aors, and sip_options_contact_add_task().

Referenced by contact_observer_created().

◆ sip_options_contact_add_task()

static int sip_options_contact_add_task ( void *  obj)
static

Task which adds a dynamic contact to an AOR.

Note
Run by aor_options->serializer

Definition at line 2096 of file pjsip_options.c.

2097{
2099 struct ast_sip_contact_status *contact_status;
2100
2101 ao2_link(task_data->aor_options->dynamic_contacts, task_data->contact);
2102 ao2_link(task_data->aor_options->contacts, task_data->contact);
2103
2104 contact_status = ast_res_pjsip_find_or_create_contact_status(task_data->contact);
2105 ao2_cleanup(contact_status);
2106
2107 if (task_data->aor_options->qualify_frequency) {
2108 /* There will always be a contact here, and we need to immediately schedule
2109 * a qualify so that contacts are not waiting for the qualify_frequency
2110 * timer duration before qualifying.
2111 */
2112 ast_debug(3, "Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2113 task_data->aor_options->name);
2114 /*
2115 * We immediately schedule the initial qualify so that we get
2116 * reachable/unreachable as soon as possible. Realistically
2117 * since they pretty much just registered they should be
2118 * reachable.
2119 */
2120 if (task_data->aor_options->sched_task) {
2121 ast_sip_sched_task_cancel(task_data->aor_options->sched_task);
2122 ao2_ref(task_data->aor_options->sched_task, -1);
2123 task_data->aor_options->sched_task = NULL;
2124 }
2125 task_data->aor_options->sched_task = ast_sip_schedule_task(
2126 task_data->aor_options->serializer, 1, sip_options_qualify_aor,
2127 ast_taskprocessor_name(task_data->aor_options->serializer),
2128 task_data->aor_options,
2130 if (!task_data->aor_options->sched_task) {
2131 ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
2132 task_data->aor_options->name);
2133 }
2134 } else {
2135 /*
2136 * If this was the first contact added to a non-qualified AOR then
2137 * it should become available.
2138 */
2139 task_data->aor_options->available =
2140 ao2_container_count(task_data->aor_options->contacts);
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",
2143 task_data->aor_options->name);
2145 AVAILABLE);
2146 }
2147 }
2148
2149 return 0;
2150}
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)

References ao2_cleanup, ao2_container_count(), ao2_link, ao2_ref, ast_debug, ast_log, ast_res_pjsip_find_or_create_contact_status(), ast_sip_sched_task_cancel(), AST_SIP_SCHED_TASK_DATA_AO2, AST_SIP_SCHED_TASK_VARIABLE, ast_sip_schedule_task(), ast_taskprocessor_name(), AVAILABLE, LOG_ERROR, NULL, sip_options_notify_endpoint_state_compositors(), and sip_options_qualify_aor().

Referenced by sip_options_contact_add_management_task().

◆ sip_options_contact_callback_data_alloc()

static struct sip_options_contact_callback_data * sip_options_contact_callback_data_alloc ( struct ast_sip_contact contact,
struct sip_options_aor aor_options 
)
static

Contact callback data allocator.

Definition at line 830 of file pjsip_options.c.

832{
833 struct sip_options_contact_callback_data *contact_callback_data;
834
835 contact_callback_data = ao2_alloc_options(sizeof(*contact_callback_data),
837 if (!contact_callback_data) {
838 return NULL;
839 }
840
841 contact_callback_data->contact = ao2_bump(contact);
842 contact_callback_data->aor_options = ao2_bump(aor_options);
843 contact_callback_data->rtt_start = ast_tvnow();
844
845 return contact_callback_data;
846}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static void sip_options_contact_callback_data_dtor(void *obj)
Destructor for contact callback data.
struct timeval rtt_start
The time at which this OPTIONS attempt was started.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, sip_options_contact_callback_data::aor_options, ast_tvnow(), sip_options_contact_callback_data::contact, NULL, sip_options_contact_callback_data::rtt_start, and sip_options_contact_callback_data_dtor().

Referenced by sip_options_qualify_contact().

◆ sip_options_contact_callback_data_dtor()

static void sip_options_contact_callback_data_dtor ( void *  obj)
static

Destructor for contact callback data.

Definition at line 821 of file pjsip_options.c.

822{
823 struct sip_options_contact_callback_data *contact_callback_data = obj;
824
825 ao2_cleanup(contact_callback_data->contact);
826 ao2_cleanup(contact_callback_data->aor_options);
827}

References ao2_cleanup, sip_options_contact_callback_data::aor_options, and sip_options_contact_callback_data::contact.

Referenced by sip_options_contact_callback_data_alloc().

◆ sip_options_contact_delete_management_task()

static int sip_options_contact_delete_management_task ( void *  obj)
static

Task to delete a contact from an AOR in its serializer.

Note
Run by management_serializer

Definition at line 2315 of file pjsip_options.c.

2316{
2318
2319 task_data.contact = obj;
2320 task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2322 if (!task_data.aor_options) {
2323 /* For contacts that are deleted we don't really care if there is no AOR locally */
2324 return 0;
2325 }
2326
2327 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2329 ao2_ref(task_data.aor_options, -1);
2330
2331 return 0;
2332}
static int sip_options_contact_delete_task(void *obj)
Task which deletes a dynamic contact from an AOR.

References ao2_find, ao2_ref, ast_sip_push_task_wait_serializer(), OBJ_SEARCH_KEY, sip_options_aors, and sip_options_contact_delete_task().

Referenced by contact_observer_deleted().

◆ sip_options_contact_delete_task()

static int sip_options_contact_delete_task ( void *  obj)
static

Task which deletes a dynamic contact from an AOR.

Note
Run by aor_options->serializer

Definition at line 2275 of file pjsip_options.c.

2276{
2278
2279 ao2_find(task_data->aor_options->dynamic_contacts, task_data->contact,
2281 ao2_find(task_data->aor_options->contacts, task_data->contact,
2283
2285
2286 if (task_data->aor_options->qualify_frequency) {
2287 /* If this is the last contact then we need to stop the scheduled callback */
2288 if (!ao2_container_count(task_data->aor_options->contacts)) {
2289 ast_debug(3, "Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2290 task_data->aor_options->name);
2291 if (task_data->aor_options->sched_task) {
2292 ast_sip_sched_task_cancel(task_data->aor_options->sched_task);
2293 ao2_ref(task_data->aor_options->sched_task, -1);
2294 task_data->aor_options->sched_task = NULL;
2295 }
2296 }
2297 } else {
2298 task_data->aor_options->available =
2299 ao2_container_count(task_data->aor_options->contacts);
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",
2302 task_data->aor_options->name);
2304 UNAVAILABLE);
2305 }
2306 }
2307
2308 return 0;
2309}
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
static void sip_options_remove_contact_status(struct sip_options_aor *aor_options, struct ast_sip_contact *contact)
Remove contact status for a hint.

References ao2_container_count(), ao2_find, ao2_ref, ast_debug, ast_sip_sched_task_cancel(), NULL, OBJ_NODATA, OBJ_SEARCH_OBJECT, OBJ_UNLINK, sip_options_notify_endpoint_state_compositors(), sip_options_remove_contact_status(), and UNAVAILABLE.

Referenced by sip_options_contact_delete_management_task().

◆ sip_options_contact_status_available_count()

static int sip_options_contact_status_available_count ( void *  obj,
void *  arg,
int  flags 
)
static

Count AVAILABLE qualified contacts.

Definition at line 1210 of file pjsip_options.c.

1211{
1212 struct ast_sip_contact *contact = obj;
1213 unsigned int *available = arg;
1214 struct ast_sip_contact_status *contact_status;
1215
1216 contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1217 if (!contact_status) {
1218 return 0;
1219 }
1220
1221 /* Count qualified available contacts. */
1222 switch (contact_status->status) {
1223 case AVAILABLE:
1224 ++*available;
1225 break;
1226 case UNAVAILABLE:
1227 case UNKNOWN:
1228 case CREATED:
1229 case REMOVED:
1230 break;
1231 }
1232
1233 ao2_ref(contact_status, -1);
1234
1235 return 0;
1236}
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13451

References ao2_ref, ast_res_pjsip_find_or_create_contact_status(), available(), AVAILABLE, CREATED, REMOVED, ast_sip_contact_status::status, UNAVAILABLE, and UNKNOWN.

Referenced by sip_options_apply_aor_configuration().

◆ sip_options_contact_status_notify_task()

static int sip_options_contact_status_notify_task ( void *  obj)
static

Task to notify an AOR of a contact status change.

Note
Run by aor_options->serializer

Definition at line 663 of file pjsip_options.c.

664{
665 struct sip_options_contact_callback_data *contact_callback_data = obj;
666 struct ast_sip_contact *contact;
667 struct ast_sip_contact_status *cs_old;
668 struct ast_sip_contact_status *cs_new;
669
670 /*
671 * Determine if this is a late arriving notification, as it is
672 * possible that we get a callback from PJSIP giving us contact
673 * status but in the mean time said contact has been removed
674 * from the controlling AOR.
675 */
676
677 if (!contact_callback_data->aor_options->qualify_frequency) {
678 /* Contact qualify response is late */
679 ao2_ref(contact_callback_data, -1);
680 return 0;
681 }
682
683 contact = ao2_find(contact_callback_data->aor_options->contacts,
684 contact_callback_data->contact, OBJ_SEARCH_OBJECT);
685 if (!contact) {
686 /* Contact qualify response is late */
687 ao2_ref(contact_callback_data, -1);
688 return 0;
689 }
690 ao2_ref(contact, -1);
691
693 ast_sorcery_object_get_id(contact_callback_data->contact), OBJ_SEARCH_KEY);
694 if (!cs_old) {
695 /* Contact qualify response is late */
696 ao2_ref(contact_callback_data, -1);
697 return 0;
698 }
699
700 /* Update the contact specific status information */
701 cs_new = sip_contact_status_copy(cs_old);
702 ao2_ref(cs_old, -1);
703 if (!cs_new) {
704 ao2_ref(contact_callback_data, -1);
705 return 0;
706 }
707 cs_new->last_status = cs_new->status;
708 cs_new->status = contact_callback_data->status;
709 cs_new->rtt =
710 cs_new->status == AVAILABLE
711 ? ast_tvdiff_us(ast_tvnow(), contact_callback_data->rtt_start)
712 : 0;
714
715 /*
716 * If the status has changed then notify the endpoint state compositors
717 * and publish our events.
718 */
719 if (cs_new->last_status != cs_new->status) {
720 if (cs_new->status == AVAILABLE) {
721 /* If this is the first available contact then the AOR has become available */
722 ++contact_callback_data->aor_options->available;
723 if (contact_callback_data->aor_options->available == 1) {
725 contact_callback_data->aor_options, AVAILABLE);
726 }
727 } else if (cs_new->last_status == AVAILABLE) {
728 ast_assert(cs_new->status == UNAVAILABLE);
729
730 /* If there are no more available contacts then this AOR is unavailable */
731 --contact_callback_data->aor_options->available;
732 if (!contact_callback_data->aor_options->available) {
734 contact_callback_data->aor_options, UNAVAILABLE);
735 }
736 }
737
738 ast_verb(3, "Contact %s/%s is now %s. RTT: %.3f msec\n",
739 cs_new->aor,
740 cs_new->uri,
742 cs_new->rtt / 1000.0);
743
744 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
746 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
747 "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
748
750
751 ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
752 "Contact: %s\r\n"
753 "Status: %s",
754 cs_new->name,
756 } else {
757 ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
758 cs_new->aor,
759 cs_new->uri,
761 cs_new->rtt / 1000.0);
762 }
763
764 ast_statsd_log_full_va("PJSIP.contacts.%s.rtt", AST_STATSD_TIMER,
765 cs_new->status != AVAILABLE ? -1 : cs_new->rtt / 1000,
766 1.0,
767 cs_new->name);
768
769 ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
770 "Contact: %s\r\n"
771 "Status: %s\r\n"
772 "RTT: %" PRId64,
773 cs_new->name,
775 cs_new->rtt);
776
777 ast_debug(3, "AOR '%s' now has %d available contacts\n",
778 contact_callback_data->aor_options->name,
779 contact_callback_data->aor_options->available);
780
781 ao2_ref(cs_new, -1);
782 ao2_ref(contact_callback_data, -1);
783
784 return 0;
785}
#define ast_verb(level,...)
static struct ast_sip_contact_status * sip_contact_status_copy(const struct ast_sip_contact_status *src)
#define AST_STATSD_TIMER
Definition: statsd.h:41
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.
Definition: res_statsd.c:209
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87

References ao2_find, ao2_link, ao2_ref, ast_sip_contact_status::aor, sip_options_contact_callback_data::aor_options, ast_assert, ast_debug, ast_sip_get_contact_status_label(), ast_sorcery_object_get_id(), AST_STATSD_GAUGE, ast_statsd_log_full_va(), ast_statsd_log_string_va(), AST_STATSD_TIMER, ast_test_suite_event_notify, ast_tvdiff_us(), ast_tvnow(), ast_verb, AVAILABLE, sip_options_aor::available, sip_options_contact_callback_data::contact, sip_options_aor::contacts, ast_sip_contact_status::last_status, ast_sip_contact_status::name, sip_options_aor::name, OBJ_SEARCH_KEY, OBJ_SEARCH_OBJECT, sip_options_aor::qualify_frequency, ast_sip_contact_status::rtt, sip_options_contact_callback_data::rtt_start, sip_contact_status_copy(), sip_options_contact_status_update(), sip_options_contact_statuses, sip_options_notify_endpoint_state_compositors(), ast_sip_contact_status::status, sip_options_contact_callback_data::status, UNAVAILABLE, and ast_sip_contact_status::uri.

Referenced by qualify_contact_cb().

◆ sip_options_contact_status_update()

static void sip_options_contact_status_update ( struct ast_sip_contact_status contact_status)
static

Definition at line 451 of file pjsip_options.c.

452{
453 struct ast_taskprocessor *mgmt_serializer = management_serializer;
454
455 if (mgmt_serializer) {
456 ao2_ref(contact_status, +1);
458 contact_status)) {
459 ao2_ref(contact_status, -1);
460 }
461 }
462}
static int contact_status_publish_update_task(void *obj)
Task to notify endpoints of a contact status change.

References ao2_ref, ast_sip_push_task(), contact_status_publish_update_task(), and management_serializer.

Referenced by ast_res_pjsip_find_or_create_contact_status(), sip_options_contact_status_notify_task(), sip_options_contact_update_task(), sip_options_remove_contact_status(), and sip_options_set_contact_status().

◆ sip_options_contact_statuses_alloc()

static struct ao2_container * sip_options_contact_statuses_alloc ( void  )
static

Helper function to allocate a contact statuses container.

Definition at line 405 of file pjsip_options.c.

406{
407 /*
408 * Replace duplicate objects so we can update the immutable
409 * contact status objects by simply linking in a new object.
410 */
413 ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
414 ast_sip_contact_status_cmp_fn);
415}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
#define CONTACT_STATUS_BUCKETS
These are the number of contact status buckets.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, and CONTACT_STATUS_BUCKETS.

Referenced by ast_res_pjsip_preinit_options_handling().

◆ sip_options_contact_update_task()

static int sip_options_contact_update_task ( void *  obj)
static

Task which updates a dynamic contact to an AOR.

Note
Run by aor_options->serializer

Definition at line 2199 of file pjsip_options.c.

2200{
2202 struct ast_sip_contact_status *contact_status;
2203
2204 contact_status = ast_sip_get_contact_status(task_data->contact);
2205 if (contact_status) {
2206 switch (contact_status->status) {
2207 case CREATED:
2208 case UNAVAILABLE:
2209 case AVAILABLE:
2210 case UNKNOWN:
2211 /* Refresh the ContactStatus AMI events. */
2212 sip_options_contact_status_update(contact_status);
2213 break;
2214 case REMOVED:
2215 break;
2216 }
2217 ao2_ref(contact_status, -1);
2218 }
2219
2220 ao2_ref(task_data->contact, -1);
2221 ao2_ref(task_data->aor_options, -1);
2223 return 0;
2224}

References ao2_ref, ast_free, ast_sip_get_contact_status(), AVAILABLE, CREATED, REMOVED, sip_options_contact_status_update(), ast_sip_contact_status::status, UNAVAILABLE, and UNKNOWN.

Referenced by contact_observer_updated().

◆ sip_options_determine_initial_qualify_time()

static int sip_options_determine_initial_qualify_time ( int  qualify_frequency)
static

Determine an initial time for scheduling AOR qualifying.

Definition at line 1096 of file pjsip_options.c.

1097{
1098 int initial_interval;
1099 int max_time = ast_sip_get_max_initial_qualify_time();
1100
1101 if (max_time && max_time < qualify_frequency) {
1102 initial_interval = max_time;
1103 } else {
1104 initial_interval = qualify_frequency;
1105 }
1106
1107 initial_interval = (int)((initial_interval * 1000) * ast_random_double());
1108 return 0 < initial_interval ? initial_interval : 1;
1109}
unsigned int ast_sip_get_max_initial_qualify_time(void)
Retrieve the system max initial qualify time.
#define ast_random_double()
Returns a random number between 0.0 and 1.0, inclusive.
Definition: utils.h:624

References ast_random_double, ast_sip_get_max_initial_qualify_time(), and sip_options_aor::qualify_frequency.

Referenced by sip_options_apply_aor_configuration().

◆ sip_options_endpoint_compositor_add_task()

static int sip_options_endpoint_compositor_add_task ( void *  obj)
static

Task which adds an AOR to an endpoint state compositor.

Note
Run by aor_options->serializer

Definition at line 1529 of file pjsip_options.c.

1530{
1532
1533 ast_debug(3, "Adding endpoint compositor '%s' to AOR '%s'\n",
1534 task_data->endpoint_state_compositor->name, task_data->aor_options->name);
1535
1536 ao2_ref(task_data->endpoint_state_compositor, +1);
1537 if (AST_VECTOR_APPEND(&task_data->aor_options->compositors,
1538 task_data->endpoint_state_compositor)) {
1539 /* Failed to add so no need to update the endpoint status. Nothing changed. */
1540 ao2_ref(task_data->endpoint_state_compositor, -1);
1541 return 0;
1542 }
1543
1544 ao2_lock(task_data->endpoint_state_compositor);
1546 task_data->aor_options->name,
1547 task_data->aor_options->available ? AVAILABLE : UNAVAILABLE);
1548 ao2_unlock(task_data->endpoint_state_compositor);
1549
1550 return 0;
1551}
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.
Task details for adding an AOR to an endpoint state compositor.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_lock, ao2_ref, ao2_unlock, ast_debug, AST_VECTOR_APPEND, AVAILABLE, sip_options_update_endpoint_state_compositor_aor(), and UNAVAILABLE.

Referenced by sip_options_synchronize_endpoint().

◆ sip_options_endpoint_compositor_remove_task()

static int sip_options_endpoint_compositor_remove_task ( void *  obj)
static

Task which adds removes an AOR from an endpoint state compositor.

Note
Run by aor_options->serializer

Definition at line 1557 of file pjsip_options.c.

1558{
1560 int i;
1561
1562 ast_debug(3, "Removing endpoint compositor '%s' from AOR '%s'\n",
1563 task_data->endpoint_state_compositor->name,
1564 task_data->aor_options->name);
1565
1566 for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1567 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1568
1569 endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1570 if (endpoint_state_compositor != task_data->endpoint_state_compositor) {
1571 continue;
1572 }
1573
1574 AST_VECTOR_REMOVE(&task_data->aor_options->compositors, i, 0);
1575 ao2_ref(endpoint_state_compositor, -1);
1576 break;
1577 }
1578
1579 return 0;
1580}
Structure which contains composites information for endpoint state.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ao2_ref, ast_debug, AST_VECTOR_GET, AST_VECTOR_REMOVE, and AST_VECTOR_SIZE.

Referenced by sip_options_endpoint_unlink_aor_feeders().

◆ sip_options_endpoint_observer_deleted_task()

static int sip_options_endpoint_observer_deleted_task ( void *  obj)
static

Task to delete an endpoint from the known universe.

Note
Run by management_serializer

Definition at line 1865 of file pjsip_options.c.

1866{
1867 struct ast_sip_endpoint *endpoint = obj;
1868 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1869
1870 endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1872 if (!endpoint_state_compositor) {
1873 return 0;
1874 }
1875
1876 ast_debug(3, "Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1877 ast_sorcery_object_get_id(endpoint));
1878 sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1879 ao2_ref(endpoint_state_compositor, -1);
1880
1881 return 0;
1882}
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.

References ao2_find, ao2_ref, ast_debug, ast_sorcery_object_get_id(), OBJ_SEARCH_KEY, OBJ_UNLINK, sip_options_endpoint_state_compositors, and sip_options_endpoint_unlink_aor_feeders().

Referenced by endpoint_observer_deleted().

◆ sip_options_endpoint_observer_modified_task()

static int sip_options_endpoint_observer_modified_task ( void *  obj)
static

Task to synchronize the endpoint.

Note
Run by management_serializer

Definition at line 1895 of file pjsip_options.c.

1896{
1897 struct ast_sip_endpoint *endpoint = obj;
1898 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1899
1900 ast_debug(3, "Endpoint '%s' has been created or modified, updating state\n",
1901 ast_sorcery_object_get_id(endpoint));
1902
1903 endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1905 if (endpoint_state_compositor) {
1906 /* Unlink the AORs currently feeding the endpoint. */
1907 sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1908 ao2_ref(endpoint_state_compositor, -1);
1909 }
1910
1911 /* Connect the AORs that now feed the endpoint. */
1913 return 0;
1914}

References ao2_find, ao2_ref, ast_debug, ast_sorcery_object_get_id(), NULL, OBJ_SEARCH_KEY, OBJ_UNLINK, sip_options_endpoint_state_compositors, sip_options_endpoint_unlink_aor_feeders(), and sip_options_synchronize_endpoint().

Referenced by endpoint_observer_modified().

◆ sip_options_endpoint_state_compositor_dtor()

static void sip_options_endpoint_state_compositor_dtor ( void *  obj)
static

Destructor for endpoint state compositors.

Definition at line 1460 of file pjsip_options.c.

1461{
1462 struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1463
1464 ao2_cleanup(endpoint_state_compositor->aor_statuses);
1465}
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.

References ao2_cleanup, and sip_options_endpoint_state_compositor::aor_statuses.

Referenced by sip_options_endpoint_state_compositor_find_or_alloc().

◆ sip_options_endpoint_state_compositor_find_or_alloc()

static struct sip_options_endpoint_state_compositor * sip_options_endpoint_state_compositor_find_or_alloc ( const struct ast_sip_endpoint endpoint)
static

Find (or create) an endpoint state compositor.

Definition at line 1474 of file pjsip_options.c.

1475{
1476 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1477
1479 endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1481 if (endpoint_state_compositor) {
1483 return endpoint_state_compositor;
1484 }
1485
1486 endpoint_state_compositor = ao2_alloc(sizeof(*endpoint_state_compositor)
1487 + strlen(ast_sorcery_object_get_id(endpoint)) + 1,
1489 if (!endpoint_state_compositor) {
1491 return NULL;
1492 }
1493
1494 /*
1495 * NOTE: The endpoint_state_compositor->aor_statuses container is
1496 * externally protected by the endpoint_state_compositor lock.
1497 */
1498 endpoint_state_compositor->aor_statuses = ao2_container_alloc_hash(
1500 sip_options_endpoint_aor_status_hash_fn, NULL,
1501 sip_options_endpoint_aor_status_cmp_fn);
1502 if (!endpoint_state_compositor->aor_statuses) {
1504 ao2_ref(endpoint_state_compositor, -1);
1505 return NULL;
1506 }
1507
1508 strcpy(endpoint_state_compositor->name, ast_sorcery_object_get_id(endpoint)); /* SAFE */
1509
1510 ao2_link_flags(sip_options_endpoint_state_compositors, endpoint_state_compositor,
1511 OBJ_NOLOCK);
1513
1514 return endpoint_state_compositor;
1515}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void sip_options_endpoint_state_compositor_dtor(void *obj)
Destructor for endpoint state compositors.
#define AOR_STATUS_BUCKETS
These are the number of buckets (per endpoint state compositor) to use to store AOR statuses.
char name[0]
The name of the endpoint.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_hash, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, AOR_STATUS_BUCKETS, sip_options_endpoint_state_compositor::aor_statuses, ast_sorcery_object_get_id(), sip_options_endpoint_state_compositor::name, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, sip_options_endpoint_state_compositor_dtor(), and sip_options_endpoint_state_compositors.

Referenced by sip_options_synchronize_endpoint().

◆ sip_options_endpoint_unlink_aor_feeders()

static void sip_options_endpoint_unlink_aor_feeders ( struct ast_sip_endpoint endpoint,
struct sip_options_endpoint_state_compositor endpoint_state_compositor 
)
static

Unlink AORs feeding the endpoint status compositor.

Note
Run by management_serializer

Definition at line 1821 of file pjsip_options.c.

1823{
1824 struct ao2_iterator it_aor_statuses;
1825 struct sip_options_endpoint_aor_status *aor_status;
1827 .endpoint_state_compositor = endpoint_state_compositor,
1828 };
1829
1832
1833 /* Unlink AOR feeders pointing to endpoint */
1835 for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
1836 task_data.aor_options = ao2_find(sip_options_aors, aor_status->name,
1838 if (!task_data.aor_options) {
1839 continue;
1840 }
1841
1842 ast_debug(3, "Removing endpoint state compositor '%s' from AOR '%s'\n",
1843 ast_sorcery_object_get_id(endpoint), aor_status->name);
1845 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1848 ao2_ref(task_data.aor_options, -1);
1849 }
1850 ao2_iterator_destroy(&it_aor_statuses);
1851
1852 /*
1853 * We do not need to remove the AOR feeder status memory from the
1854 * aor_statuses container. The endpoint_state_compositor is about
1855 * to die and do it for us.
1856 */
1857
1859}
static int sip_options_endpoint_compositor_remove_task(void *obj)
Task which adds removes an AOR from an endpoint state compositor.
Structure which contains status information for an AOR feeding an endpoint state compositor.
char name[0]
The name of the AOR.
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
char active
Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.

References sip_options_endpoint_state_compositor::active, ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, sip_options_endpoint_state_compositor::aor_statuses, ast_debug, ast_sip_push_task_wait_serializer(), ast_sorcery_object_get_id(), sip_options_endpoint_compositor_task_data::endpoint_state_compositor, sip_options_endpoint_aor_status::name, OBJ_SEARCH_KEY, sip_options_aors, and sip_options_endpoint_compositor_remove_task().

Referenced by sip_options_endpoint_observer_deleted_task(), and sip_options_endpoint_observer_modified_task().

◆ sip_options_get_endpoint_state_compositor_state()

static enum ast_endpoint_state sip_options_get_endpoint_state_compositor_state ( const struct sip_options_endpoint_state_compositor endpoint_state_compositor)
static

Return the current state of an endpoint state compositor.

Precondition
The endpoint_state_compositor lock must be held.

Definition at line 559 of file pjsip_options.c.

561{
562 struct ao2_iterator it_aor_statuses;
563 struct sip_options_endpoint_aor_status *aor_status;
565
566 it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
567 for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
568 if (aor_status->available) {
570 ao2_ref(aor_status, -1);
571 break;
572 }
573 }
574 ao2_iterator_destroy(&it_aor_statuses);
575
576 return state;
577}
enum cc_state state
Definition: ccss.c:393
ast_endpoint_state
Valid states for an endpoint.
Definition: endpoints.h:51
@ AST_ENDPOINT_OFFLINE
Definition: endpoints.h:55
@ AST_ENDPOINT_ONLINE
Definition: endpoints.h:57
char available
The last contributed available status of the named AOR (1 if available, 0 if not available)

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, sip_options_endpoint_state_compositor::aor_statuses, AST_ENDPOINT_OFFLINE, AST_ENDPOINT_ONLINE, sip_options_endpoint_aor_status::available, and state.

Referenced by sip_options_synchronize_endpoint(), and sip_options_update_endpoint_state_compositor_aor().

◆ sip_options_init_task()

static int sip_options_init_task ( void *  mgmt_serializer)
static

Management task to finish setting up the environment.

Note
Run by management_serializer

Definition at line 2889 of file pjsip_options.c.

2890{
2891 management_serializer = mgmt_serializer;
2892
2894 if (!shutdown_group) {
2895 return -1;
2896 }
2897
2900 return -1;
2901 }
2904 return -1;
2905 }
2908 return -1;
2909 }
2910
2912
2913 return 0;
2914}
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.
Definition: sorcery.c:2386
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229

References aor_observer_callbacks, ast_serializer_shutdown_group_alloc(), ast_sip_get_sorcery(), ast_sorcery_observer_add(), contact_observer_callbacks, endpoint_observer_callbacks, management_serializer, shutdown_group, and sip_options_synchronize().

Referenced by ast_res_pjsip_init_options_handling().

◆ sip_options_notify_endpoint_state_compositors()

static void sip_options_notify_endpoint_state_compositors ( struct sip_options_aor aor_options,
enum ast_sip_contact_status_type  status 
)
static

Function which notifies endpoint state compositors of a state change of an AOR.

Definition at line 637 of file pjsip_options.c.

639{
640 int i;
641
642 /* Iterate through the associated endpoint state compositors updating them */
643 for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
644 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
645
646 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
647
648 ao2_lock(endpoint_state_compositor);
649 sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
650 aor_options->name, status);
651 ao2_unlock(endpoint_state_compositor);
652 }
653
654 if (status == REMOVED) {
656 }
657}

References ao2_cleanup, ao2_lock, ao2_unlock, AST_VECTOR_GET, AST_VECTOR_RESET, AST_VECTOR_SIZE, sip_options_aor::compositors, sip_options_aor::name, REMOVED, sip_options_update_endpoint_state_compositor_aor(), and status.

Referenced by sip_options_aor_remove_task(), sip_options_contact_add_task(), sip_options_contact_delete_task(), sip_options_contact_status_notify_task(), sip_options_remove_contact_status(), and sip_options_update_aor_task().

◆ sip_options_publish_contact_state()

static void sip_options_publish_contact_state ( const struct sip_options_aor aor_options,
const struct ast_sip_contact_status contact_status 
)
static

Function which publishes a contact status update to all interested endpoints.

Definition at line 418 of file pjsip_options.c.

420{
421 int i;
422
423 for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
424 const struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
425
426 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
428 contact_status);
429 }
430}
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.

References ast_sip_persistent_endpoint_publish_contact_state(), AST_VECTOR_GET, AST_VECTOR_SIZE, sip_options_aor::compositors, and sip_options_endpoint_state_compositor::name.

Referenced by contact_status_publish_update_task().

◆ sip_options_qualify_aor()

static int sip_options_qualify_aor ( void *  obj)
static

Task to qualify contacts of an AOR.

Note
Run by aor_options->serializer

Definition at line 925 of file pjsip_options.c.

926{
927 struct sip_options_aor *aor_options = obj;
928
929 ast_debug(3, "Qualifying all contacts on AOR '%s'\n", aor_options->name);
930
931 /* Attempt to send an OPTIONS request to every contact on this AOR */
933 (struct sip_options_aor *) aor_options);
934
935 /* Always reschedule to the frequency we should go */
936 return aor_options->qualify_frequency * 1000;
937}
static int sip_options_qualify_contact(void *obj, void *arg, int flags)
Send a SIP OPTIONS request for a contact.

References ao2_callback, ast_debug, sip_options_aor::contacts, sip_options_aor::name, OBJ_NODATA, sip_options_aor::qualify_frequency, and sip_options_qualify_contact().

Referenced by ami_sip_qualify(), cli_qualify(), sip_options_apply_aor_configuration(), and sip_options_contact_add_task().

◆ sip_options_qualify_contact()

static int sip_options_qualify_contact ( void *  obj,
void *  arg,
int  flags 
)
static

Send a SIP OPTIONS request for a contact.

Definition at line 849 of file pjsip_options.c.

850{
851 struct ast_sip_contact *contact = obj;
852 struct sip_options_aor *aor_options = arg;
853 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
854 pjsip_tx_data *tdata;
855 struct ast_sip_contact_status *contact_status;
856 struct sip_options_contact_callback_data *contact_callback_data;
857
858 ast_debug(3, "Qualifying contact '%s' on AOR '%s'\n",
860
862 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
864 }
865 if (!endpoint && AST_VECTOR_SIZE(&aor_options->compositors)) {
866 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
867
868 endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, 0);
869 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
870 endpoint_state_compositor->name);
871 }
872 if (!endpoint) {
873 ast_debug(3, "Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
874 ast_sorcery_object_get_id(contact), aor_options->name);
875 return 0;
876 }
877
878 if (ast_sip_create_request("OPTIONS", NULL, endpoint, NULL, contact, &tdata)) {
879 ast_log(LOG_ERROR, "Unable to create request to qualify contact %s on AOR %s\n",
880 contact->uri, aor_options->name);
881 return 0;
882 }
883
884 /* If an outbound proxy is specified set it on this request */
885 if (!ast_strlen_zero(contact->outbound_proxy) &&
887 ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
888 contact->uri);
889 pjsip_tx_data_dec_ref(tdata);
890 return 0;
891 }
892
893 contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
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);
898 return 0;
899 }
900 ao2_ref(contact_status, -1);
901
902 contact_callback_data = sip_options_contact_callback_data_alloc(contact, aor_options);
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);
907 return 0;
908 }
909
910 if (ast_sip_send_out_of_dialog_request(tdata, endpoint,
911 (int)(aor_options->qualify_timeout * 1000), contact_callback_data,
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);
916 }
917
918 return 0;
919}
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.
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.
Definition: res_pjsip.c:1938
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
Definition: res_pjsip.c:1992
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.
Definition: res_pjsip.c:1435

References ao2_cleanup, ao2_ref, sip_options_contact_callback_data::aor_options, ast_debug, ast_log, ast_res_pjsip_find_or_create_contact_status(), ast_sip_create_request(), ast_sip_get_sorcery(), ast_sip_send_out_of_dialog_request(), ast_sip_set_outbound_proxy(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strlen_zero(), AST_VECTOR_GET, AST_VECTOR_SIZE, sip_options_aor::compositors, sip_options_contact_callback_data::contact, ast_sip_contact::endpoint_name, LOG_ERROR, sip_options_endpoint_state_compositor::name, sip_options_aor::name, NULL, ast_sip_contact::outbound_proxy, qualify_contact_cb(), sip_options_aor::qualify_timeout, RAII_VAR, sip_options_contact_callback_data_alloc(), and ast_sip_contact::uri.

Referenced by sip_options_qualify_aor().

◆ sip_options_remove_contact()

static int sip_options_remove_contact ( void *  obj,
void *  arg,
int  flags 
)
static

Forward declaration of this helpful function.

Callback function to remove a contact and its contact status from an AOR.

Definition at line 1085 of file pjsip_options.c.

1086{
1087 struct ast_sip_contact *contact = obj;
1088 struct sip_options_aor *aor_options = arg;
1089
1090 sip_options_remove_contact_status(aor_options, contact);
1091
1092 return CMP_MATCH;
1093}
@ CMP_MATCH
Definition: astobj2.h:1027

References CMP_MATCH, and sip_options_remove_contact_status().

Referenced by sip_options_aor_dtor(), and sip_options_apply_aor_configuration().

◆ sip_options_remove_contact_status()

static void sip_options_remove_contact_status ( struct sip_options_aor aor_options,
struct ast_sip_contact contact 
)
static

Remove contact status for a hint.

Definition at line 1012 of file pjsip_options.c.

1014{
1015 struct ast_sip_contact_status *cs_new;
1016 struct ast_sip_contact_status *cs_old;
1017
1020 if (!cs_old) {
1021 ast_debug(3, "Attempted to remove contact status for '%s' but it does not exist\n",
1022 ast_sorcery_object_get_id(contact));
1023 return;
1024 }
1025
1026 ast_verb(2, "Contact %s/%s has been deleted\n", contact->aor, contact->uri);
1027
1028 /* Update the contact status to reflect its new state */
1029 cs_new = sip_contact_status_copy(cs_old);
1030 if (!cs_new) {
1031 /*
1032 * We'll have to violate the immutable property because we
1033 * couldn't create a new one to modify and we are deleting
1034 * the contact status anyway.
1035 */
1036 cs_new = cs_old;
1037 } else {
1038 ao2_ref(cs_old, -1);
1039 }
1040 cs_new->last_status = cs_new->status;
1041 cs_new->status = REMOVED;
1042 cs_new->rtt = 0;
1043
1044 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1045 "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1046 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1047 "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1048
1050
1051 /*
1052 * The only time we need to update the AOR is if this contact was
1053 * available and qualify is in use, otherwise we can just stop
1054 * early.
1055 */
1056 if (!aor_options->qualify_frequency || cs_new->last_status != AVAILABLE) {
1057 ao2_ref(cs_new, -1);
1058 return;
1059 }
1060
1061 --aor_options->available;
1062 if (!aor_options->available) {
1064 }
1065
1066 ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1067 aor_options->available);
1068
1069 ao2_ref(cs_new, -1);
1070}

References ao2_find, ao2_ref, ast_sip_contact::aor, ast_debug, ast_sip_get_contact_status_label(), ast_sorcery_object_get_id(), AST_STATSD_GAUGE, ast_statsd_log_string_va(), ast_verb, AVAILABLE, sip_options_aor::available, ast_sip_contact_status::last_status, sip_options_aor::name, OBJ_SEARCH_KEY, OBJ_UNLINK, sip_options_aor::qualify_frequency, REMOVED, ast_sip_contact_status::rtt, sip_contact_status_copy(), sip_options_contact_status_update(), sip_options_contact_statuses, sip_options_notify_endpoint_state_compositors(), ast_sip_contact_status::status, UNAVAILABLE, and ast_sip_contact::uri.

Referenced by sip_options_contact_delete_task(), and sip_options_remove_contact().

◆ sip_options_set_contact_status()

static void sip_options_set_contact_status ( struct ast_sip_contact_status contact_status,
enum ast_sip_contact_status_type  status 
)
static

Set the contact status for a contact.

Definition at line 1112 of file pjsip_options.c.

1114{
1115 struct ast_sip_contact_status *cs_new;
1116
1117 /* Update the contact specific status information */
1118 cs_new = sip_contact_status_copy(contact_status);
1119 if (!cs_new) {
1120 return;
1121 }
1122 cs_new->last_status = cs_new->status;
1123 cs_new->status = status;
1124
1125 /*
1126 * We need to always set the RTT to zero because we haven't completed
1127 * an OPTIONS ping so RTT is unknown. If the OPTIONS ping were still
1128 * running it will be refreshed on the next go round anyway.
1129 */
1130 cs_new->rtt = 0;
1131
1133
1134 if (cs_new->status != cs_new->last_status) {
1135 ast_verb(3, "Contact %s/%s is now %s.\n",
1136 cs_new->aor, cs_new->uri,
1138
1139 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1140 "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1141 ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1142 "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1143
1145
1146 ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
1147 "Contact: %s\r\n"
1148 "Status: %s",
1149 cs_new->name,
1151 }
1152 ao2_ref(cs_new, -1);
1153}

References ao2_link, ao2_ref, ast_sip_contact_status::aor, ast_sip_get_contact_status_label(), AST_STATSD_GAUGE, ast_statsd_log_string_va(), ast_test_suite_event_notify, ast_verb, ast_sip_contact_status::last_status, ast_sip_contact_status::name, ast_sip_contact_status::rtt, sip_contact_status_copy(), sip_options_contact_status_update(), sip_options_contact_statuses, status, ast_sip_contact_status::status, and ast_sip_contact_status::uri.

Referenced by sip_options_set_contact_status_qualified(), and sip_options_set_contact_status_unqualified().

◆ sip_options_set_contact_status_qualified()

static int sip_options_set_contact_status_qualified ( void *  obj,
void *  arg,
int  flags 
)
static

Transition the contact status to qualified mode.

Definition at line 1183 of file pjsip_options.c.

1184{
1185 struct ast_sip_contact *contact = obj;
1186 struct ast_sip_contact_status *contact_status;
1187
1188 contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1189 if (!contact_status) {
1190 return 0;
1191 }
1192
1193 switch (contact_status->status) {
1194 case AVAILABLE:
1196 break;
1197 case UNAVAILABLE:
1198 case UNKNOWN:
1199 case CREATED:
1200 case REMOVED:
1201 break;
1202 }
1203
1204 ao2_ref(contact_status, -1);
1205
1206 return 0;
1207}
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.

References ao2_ref, ast_res_pjsip_find_or_create_contact_status(), AVAILABLE, CREATED, REMOVED, sip_options_set_contact_status(), ast_sip_contact_status::status, UNAVAILABLE, and UNKNOWN.

Referenced by sip_options_apply_aor_configuration().

◆ sip_options_set_contact_status_unqualified()

static int sip_options_set_contact_status_unqualified ( void *  obj,
void *  arg,
int  flags 
)
static

Transition the contact status to unqualified mode.

Definition at line 1156 of file pjsip_options.c.

1157{
1158 struct ast_sip_contact *contact = obj;
1159 struct ast_sip_contact_status *contact_status;
1160
1161 contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1162 if (!contact_status) {
1163 return 0;
1164 }
1165
1166 switch (contact_status->status) {
1167 case AVAILABLE:
1168 case UNAVAILABLE:
1169 case UNKNOWN:
1170 sip_options_set_contact_status(contact_status, CREATED);
1171 break;
1172 case CREATED:
1173 case REMOVED:
1174 break;
1175 }
1176
1177 ao2_ref(contact_status, -1);
1178
1179 return 0;
1180}

References ao2_ref, ast_res_pjsip_find_or_create_contact_status(), AVAILABLE, CREATED, REMOVED, sip_options_set_contact_status(), ast_sip_contact_status::status, UNAVAILABLE, and UNKNOWN.

Referenced by sip_options_apply_aor_configuration().

◆ sip_options_synchronize()

static void sip_options_synchronize ( int  reload)
static

Synchronize our local container of AORs and endpoint state compositors with the current configuration.

Definition at line 1807 of file pjsip_options.c.

1808{
1810 .reload = reload,
1811 };
1812
1814 &task_data);
1815}
static int sip_options_synchronize_task(void *obj)
Task to synchronize our local container of AORs and endpoint state compositors with the current confi...
Structure which contains information required to synchronize.

References ast_sip_push_task_wait_serializer(), management_serializer, reload(), and sip_options_synchronize_task().

Referenced by ast_res_pjsip_init_options_handling(), and sip_options_init_task().

◆ sip_options_synchronize_aor()

static int sip_options_synchronize_aor ( void *  obj,
void *  arg,
int  flags 
)
static

Synchronize an AOR with our local state.

Note
Run by management_serializer

Definition at line 1423 of file pjsip_options.c.

1424{
1426 .aor = obj,
1427 .existing = arg,
1428 };
1429
1430 task_data.aor_options = ao2_find(sip_options_aors,
1432 if (!task_data.aor_options) {
1433 task_data.aor_options = sip_options_aor_alloc(task_data.aor);
1434 if (!task_data.aor_options) {
1435 return 0;
1436 }
1437
1438 task_data.added = 1;
1439
1440 /* Nothing is aware of this AOR yet so we can just update it in this thread */
1442 ao2_link(sip_options_aors, task_data.aor_options);
1443 } else {
1444 /* This AOR already exists so we have to do manipulation in its serializer */
1445 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1447 }
1448
1449 ao2_ref(task_data.aor_options, -1);
1450
1451 if (task_data.existing) {
1454 }
1455
1456 return 0;
1457}
static int sip_options_synchronize_aor_task(void *obj)
Task to synchronize an AOR with our local state.

References ao2_find, ao2_link, ao2_ref, ast_sip_push_task_wait_serializer(), ast_sorcery_object_get_id(), OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, sip_options_aor_alloc(), sip_options_aors, and sip_options_synchronize_aor_task().

Referenced by sip_options_synchronize_task().

◆ sip_options_synchronize_aor_task()

static int sip_options_synchronize_aor_task ( void *  obj)
static

Task to synchronize an AOR with our local state.

Note
Run by aor_options->serializer (or management_serializer on aor_options creation)

Definition at line 1385 of file pjsip_options.c.

1386{
1388 int i;
1389
1390 ast_debug(3, "Synchronizing AOR '%s' with current state of configuration and world\n",
1391 task_data->aor_options->name);
1392
1394 task_data->added);
1395
1396 /*
1397 * Endpoint state compositors are removed in this operation but not
1398 * added. To reduce the amount of work done they are done later. In
1399 * the mean time things can still qualify and once an endpoint state
1400 * compositor is added to the AOR it will be updated with the current
1401 * state.
1402 */
1403 for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1404 struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1405
1406 endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1407
1408 ao2_lock(endpoint_state_compositor);
1409 endpoint_state_compositor->active = 0;
1410 sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
1411 task_data->aor_options->name, REMOVED);
1412 ao2_unlock(endpoint_state_compositor);
1413 }
1414 AST_VECTOR_RESET(&task_data->aor_options->compositors, ao2_cleanup);
1415
1416 return 0;
1417}

References sip_options_endpoint_state_compositor::active, ao2_cleanup, ao2_lock, ao2_unlock, ast_debug, AST_VECTOR_GET, AST_VECTOR_RESET, AST_VECTOR_SIZE, REMOVED, sip_options_apply_aor_configuration(), and sip_options_update_endpoint_state_compositor_aor().

Referenced by sip_options_synchronize_aor().

◆ sip_options_synchronize_endpoint()

static int sip_options_synchronize_endpoint ( void *  obj,
void *  arg,
int  flags 
)
static

Synchronize an endpoint with our local state.

Note
Run by management_serializer

Definition at line 1586 of file pjsip_options.c.

1587{
1588 struct ast_sip_endpoint *endpoint = obj;
1589 struct ast_sip_aor *aor = arg;
1590 char *aors;
1591 char *aor_name;
1593
1594 if (ast_strlen_zero(endpoint->aors)) {
1595 /* There are no AORs, so really... who the heck knows */
1596 ast_debug(3, "Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
1597 ast_sorcery_object_get_id(endpoint));
1598 return 0;
1599 }
1600
1601 ast_debug(3, "Synchronizing endpoint '%s' with AORs '%s'\n",
1602 ast_sorcery_object_get_id(endpoint), endpoint->aors);
1603
1604 aors = ast_strdupa(endpoint->aors);
1605 while ((aor_name = ast_strip(strsep(&aors, ",")))) {
1606 if (ast_strlen_zero(aor_name)) {
1607 continue;
1608 }
1609 if (aor && strcasecmp(ast_sorcery_object_get_id(aor), aor_name)) {
1610 ast_debug(3, "Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
1611 aor_name, ast_sorcery_object_get_id(endpoint),
1613 continue;
1614 }
1615
1616 task_data.aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
1617 if (!task_data.aor_options) {
1618 /*
1619 * They have referenced an invalid AOR. If that's all they've
1620 * done we will set them to offline at the end.
1621 */
1622 ast_debug(3, "Endpoint '%s' referenced invalid AOR '%s'\n",
1623 ast_sorcery_object_get_id(endpoint), aor_name);
1624 continue;
1625 }
1626
1627 if (!task_data.endpoint_state_compositor) {
1628 /*
1629 * We create an endpoint state compositor only after we know
1630 * for sure we need it.
1631 */
1632 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",
1637 ast_sorcery_object_get_id(endpoint));
1638 ao2_ref(task_data.aor_options, -1);
1641 return 0;
1642 }
1643 }
1644
1645 /* We use a synchronous task so that we don't flood the system */
1646 ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
1648
1649 ao2_ref(task_data.aor_options, -1);
1650
1651 /*
1652 * If we filtered on a specific AOR name then the endpoint can
1653 * only reference it once so break early.
1654 */
1655 if (aor) {
1656 break;
1657 }
1658 }
1659
1660 if (task_data.endpoint_state_compositor) {
1661 /*
1662 * If an endpoint state compositor is present determine the current state
1663 * of the endpoint and update it.
1664 */
1665 ao2_lock(task_data.endpoint_state_compositor);
1666 task_data.endpoint_state_compositor->active = 1;
1669 ao2_unlock(task_data.endpoint_state_compositor);
1670
1671 ao2_ref(task_data.endpoint_state_compositor, -1);
1672 } else if (!aor) {
1673 /* If no explicit AOR is specified we are updating the endpoint itself, so then set
1674 * it to offline if no endpoint compositor exists as they referenced an invalid AOR
1675 * or none at all
1676 */
1677 ast_debug(3, "Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
1678 ast_sorcery_object_get_id(endpoint));
1681 }
1682
1683 return 0;
1684}
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.
static int sip_options_endpoint_compositor_add_task(void *obj)
Task which adds an AOR to an endpoint state compositor.
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.
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
Change state of a persistent endpoint.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_sip_endpoint::aors, ast_debug, AST_ENDPOINT_OFFLINE, ast_log, ast_sip_persistent_endpoint_update_state(), ast_sip_push_task_wait_serializer(), ast_sorcery_object_get_id(), ast_strdupa, ast_strip(), ast_strlen_zero(), LOG_WARNING, NULL, OBJ_SEARCH_KEY, sip_options_aors, sip_options_endpoint_compositor_add_task(), sip_options_endpoint_state_compositor_find_or_alloc(), sip_options_get_endpoint_state_compositor_state(), and strsep().

Referenced by sip_options_aor_observer_modified_task(), sip_options_endpoint_observer_modified_task(), and sip_options_synchronize_task().

◆ sip_options_synchronize_task()

static int sip_options_synchronize_task ( void *  obj)
static

Task to synchronize our local container of AORs and endpoint state compositors with the current configuration.

Note
Run by management_serializer

Definition at line 1751 of file pjsip_options.c.

1752{
1754 struct ao2_container *existing = NULL;
1755 struct ao2_container *objects;
1756
1757 /*
1758 * When reloading we keep track of the existing AORs so we can
1759 * terminate old ones that are no longer referenced or used.
1760 */
1761 if (task_data->reload) {
1763 if (!existing) {
1764 return 0;
1765 }
1766 }
1767
1770 if (objects) {
1771 /* Go through the returned AORs and synchronize with our local state */
1773 ao2_ref(objects, -1);
1774 }
1775
1776 /*
1777 * Any AORs remaining in existing are no longer referenced by
1778 * the current container of AORs we retrieved, so remove them.
1779 */
1780 if (existing) {
1783 ao2_ref(existing, -1);
1784 }
1785
1788 if (objects) {
1789 /* Go through the provided endpoints and update AORs */
1791 ao2_ref(objects, -1);
1792 }
1793
1794 /*
1795 * All endpoint state compositors that don't have any AORs
1796 * feeding them information can be removed. If they end
1797 * up getting needed later they'll just be recreated.
1798 */
1802
1803 return 0;
1804}
static int sip_options_unused_aor(void *obj, void *arg, int flags)
Callback which removes any unused AORs that remained after reloading.
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_synchronize_aor(void *obj, void *arg, int flags)
Synchronize an AOR with our local state.

References ao2_callback, ao2_container_clone, ao2_ref, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sip_options_aors, sip_options_endpoint_state_compositors, sip_options_synchronize_aor(), sip_options_synchronize_endpoint(), sip_options_unused_aor(), and sip_options_unused_endpoint_state_compositor().

Referenced by sip_options_synchronize().

◆ sip_options_unused_aor()

static int sip_options_unused_aor ( void *  obj,
void *  arg,
int  flags 
)
static

Callback which removes any unused AORs that remained after reloading.

Note
Run by management_serializer

Definition at line 1709 of file pjsip_options.c.

1710{
1711 struct sip_options_aor *aor_options = obj;
1712
1713 ast_debug(3, "AOR '%s' is no longer configured, removing it\n", aor_options->name);
1714
1716 aor_options);
1717 ao2_unlink(sip_options_aors, aor_options);
1718
1719 return CMP_MATCH;
1720}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578

References ao2_unlink, ast_debug, ast_sip_push_task_wait_serializer(), CMP_MATCH, sip_options_aor::name, sip_options_aor::serializer, sip_options_aor_remove_task(), and sip_options_aors.

Referenced by sip_options_synchronize_task().

◆ sip_options_unused_endpoint_state_compositor()

static int sip_options_unused_endpoint_state_compositor ( void *  obj,
void *  arg,
int  flags 
)
static

Callback function used to unlink and remove event state compositors that have no AORs feeding them.

Note
Run by management_serializer

Definition at line 1726 of file pjsip_options.c.

1727{
1728 struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1729
1730 if (ao2_container_count(endpoint_state_compositor->aor_statuses)) {
1731 return 0;
1732 }
1733
1734 /* No AORs are feeding this endpoint state compositor */
1735 ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
1737
1738 return CMP_MATCH;
1739}

References ao2_container_count(), sip_options_endpoint_state_compositor::aor_statuses, AST_ENDPOINT_OFFLINE, ast_sip_persistent_endpoint_update_state(), CMP_MATCH, and sip_options_endpoint_state_compositor::name.

Referenced by sip_options_synchronize_task().

◆ sip_options_update_aor_task()

static int sip_options_update_aor_task ( void *  obj)
static

Task to synchronize an AOR with our local state.

Note
Run by aor_options->serializer

Definition at line 1934 of file pjsip_options.c.

1935{
1937 int available = task_data->aor_options->available;
1938
1939 ast_debug(3, "Individually updating AOR '%s' with current state of configuration and world\n",
1940 task_data->aor_options->name);
1941
1943 task_data->added);
1944
1945 if (!available && task_data->aor_options->available) {
1946 ast_debug(3, "After modifying AOR '%s' it has now become available\n",
1947 task_data->aor_options->name);
1949 } else if (available && !task_data->aor_options->available) {
1950 ast_debug(3, "After modifying AOR '%s' it has become unavailable\n",
1951 task_data->aor_options->name);
1953 }
1954
1955 return 0;
1956}

References ast_debug, available(), AVAILABLE, sip_options_apply_aor_configuration(), sip_options_notify_endpoint_state_compositors(), and UNAVAILABLE.

Referenced by sip_options_aor_observer_modified_task().

◆ sip_options_update_endpoint_state_compositor_aor()

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 
)
static

Update the AOR status on an endpoint state compositor.

Precondition
The endpoint_state_compositor lock must be held.

Definition at line 583 of file pjsip_options.c.

585{
586 struct sip_options_endpoint_aor_status *aor_status;
587 enum ast_endpoint_state endpoint_state;
588
589 aor_status = ao2_find(endpoint_state_compositor->aor_statuses, name,
591 if (!aor_status) {
592 /* The AOR status doesn't exist already so we don't need to go any further */
593 if (status == REMOVED) {
594 return;
595 }
596
597 aor_status = ao2_alloc_options(sizeof(*aor_status) + strlen(name) + 1, NULL,
599 if (!aor_status) {
600 return;
601 }
602
603 strcpy(aor_status->name, name); /* SAFE */
604 ao2_link(endpoint_state_compositor->aor_statuses, aor_status);
605 }
606
607 if (status == REMOVED) {
608 /*
609 * If the AOR is being removed then remove its AOR status
610 * from the endpoint compositor.
611 */
612 ao2_unlink(endpoint_state_compositor->aor_statuses, aor_status);
613 } else {
614 aor_status->available = (status == AVAILABLE ? 1 : 0);
615 }
616 ao2_ref(aor_status, -1);
617
618 if (!endpoint_state_compositor->active) {
619 return;
620 }
621
622 /* If this AOR is available then the endpoint itself has to be online */
623 if (status == AVAILABLE) {
624 ast_debug(3, "Endpoint state compositor '%s' is online as AOR '%s' is available\n",
625 endpoint_state_compositor->name, name);
626 endpoint_state = AST_ENDPOINT_ONLINE;
627 } else {
628 endpoint_state =
629 sip_options_get_endpoint_state_compositor_state(endpoint_state_compositor);
630 }
631
632 ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
633 endpoint_state);
634}

References sip_options_endpoint_state_compositor::active, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_find, ao2_link, ao2_ref, ao2_unlink, sip_options_endpoint_state_compositor::aor_statuses, ast_debug, AST_ENDPOINT_ONLINE, ast_sip_persistent_endpoint_update_state(), AVAILABLE, sip_options_endpoint_aor_status::available, sip_options_endpoint_aor_status::name, sip_options_endpoint_state_compositor::name, name, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, REMOVED, sip_options_get_endpoint_state_compositor_state(), and status.

Referenced by sip_options_endpoint_compositor_add_task(), sip_options_notify_endpoint_state_compositors(), and sip_options_synchronize_aor_task().

Variable Documentation

◆ aor_observer_callbacks

const struct ast_sorcery_observer aor_observer_callbacks
static
Initial value:
= {
}
static void aor_observer_deleted(const void *obj)
Observer callback invoked on AOR deletion.
static void aor_observer_modified(const void *obj)
Observer callback invoked on AOR creation or modification.

Observer callbacks for AORs.

Definition at line 2055 of file pjsip_options.c.

Referenced by ast_res_pjsip_cleanup_options_handling(), and sip_options_init_task().

◆ cli_options

struct ast_cli_entry cli_options[]
static

◆ contact_observer_callbacks

const struct ast_sorcery_observer contact_observer_callbacks
static
Initial value:
= {
}
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 contact_observer_updated(const void *obj)
Observer callback invoked on contact update.

Observer callbacks for contacts.

Definition at line 2342 of file pjsip_options.c.

Referenced by ast_res_pjsip_cleanup_options_handling(), and sip_options_init_task().

◆ contact_status_formatter

struct ast_sip_endpoint_formatter contact_status_formatter
static
Initial value:
= {
}
static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)

Definition at line 2790 of file pjsip_options.c.

Referenced by ast_res_pjsip_cleanup_options_handling(), and ast_res_pjsip_init_options_handling().

◆ endpoint_observer_callbacks

const struct ast_sorcery_observer endpoint_observer_callbacks
static
Initial value:
= {
}
static void endpoint_observer_modified(const void *obj)
Observer callback invoked on endpoint creation or modification.
static void endpoint_observer_deleted(const void *obj)
Observer callback invoked on endpoint deletion.

Observer callbacks for endpoints.

Definition at line 1924 of file pjsip_options.c.

Referenced by ast_res_pjsip_cleanup_options_handling(), and sip_options_init_task().

◆ management_serializer

struct ast_taskprocessor* management_serializer
static

◆ options_module

pjsip_module options_module
static

◆ short_status_map

const char* short_status_map[]
static

Definition at line 325 of file pjsip_options.c.

Referenced by ast_sip_get_contact_short_status_label().

◆ shutdown_group

struct ast_serializer_shutdown_group* shutdown_group
static

◆ sip_options_aors

struct ao2_container* sip_options_aors
static

◆ sip_options_contact_statuses

struct ao2_container* sip_options_contact_statuses
static

◆ sip_options_endpoint_state_compositors

struct ao2_container* sip_options_endpoint_state_compositors
static

◆ status_map

const char* status_map[]
static

Definition at line 317 of file pjsip_options.c.

Referenced by ast_sip_get_contact_status_label().