Asterisk - The Open Source Telephony Project  GIT-master-a1fa8df
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"

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_state_compositor, name)
 Comparator function for endpoint state compositors. More...
 
 AO2_STRING_FIELD_CMP_FN (sip_options_endpoint_aor_status, name)
 Comparator function for endpoint AOR status. 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_state_compositor, name)
 Hashing function for endpoint state compositors. More...
 
 AO2_STRING_FIELD_HASH_FN (sip_options_endpoint_aor_status, name)
 Hashing function for endpoint AOR status. 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.

Referenced by ast_res_pjsip_init_options_handling().

◆ 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.

Referenced by sip_options_endpoint_state_compositor_find_or_alloc().

◆ 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.

Referenced by sip_options_aor_alloc().

◆ 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.

Referenced by sip_options_contact_statuses_alloc().

◆ DEFAULT_ENCODING

#define DEFAULT_ENCODING   "identity"

Definition at line 97 of file pjsip_options.c.

Referenced by send_options_response().

◆ DEFAULT_LANGUAGE

#define DEFAULT_LANGUAGE   "en"

Definition at line 96 of file pjsip_options.c.

Referenced by send_options_response().

◆ 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.

Referenced by ast_res_pjsip_init_options_handling().

◆ 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.

Referenced by sip_options_aor_alloc().

◆ 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.

Referenced by ast_res_pjsip_cleanup_options_handling().

Function Documentation

◆ ami_show_contacts()

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

Definition at line 2453 of file pjsip_options.c.

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().

2454 {
2455  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2456  struct ao2_container *contacts;
2457 
2458  contacts = get_all_contacts();
2459  if (!contacts) {
2460  astman_send_error(s, m, "Could not get Contacts\n");
2461  return 0;
2462  }
2463 
2464  if (!ao2_container_count(contacts)) {
2465  astman_send_error(s, m, "No Contacts found\n");
2466  ao2_ref(contacts, -1);
2467  return 0;
2468  }
2469 
2470  astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",
2471  "start");
2472 
2474 
2475  astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);
2477 
2478  ao2_ref(contacts, -1);
2479 
2480  return 0;
2481 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
const struct message * m
Definition: res_pjsip.h:2741
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:3237
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
AMI variable container.
Definition: res_pjsip.h:2737
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct mansession * s
Definition: res_pjsip.h:2739
Generic container type.
static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
static struct ao2_container * get_all_contacts(void)
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:3201

◆ ami_sip_qualify()

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

Definition at line 2666 of file pjsip_options.c.

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_qualify_aor(), and strsep().

Referenced by ast_res_pjsip_init_options_handling().

2667 {
2668  const char *endpoint_name = astman_get_header(m, "Endpoint");
2669  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2670  char *aors;
2671  char *aor_name;
2672 
2673  if (ast_strlen_zero(endpoint_name)) {
2674  astman_send_error(s, m, "Endpoint parameter missing.");
2675  return 0;
2676  }
2677 
2678  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2679  endpoint_name);
2680  if (!endpoint) {
2681  astman_send_error(s, m, "Unable to retrieve endpoint\n");
2682  return 0;
2683  }
2684 
2685  /* send a qualify for all contacts registered with the endpoint */
2686  if (ast_strlen_zero(endpoint->aors)) {
2687  astman_send_error(s, m, "No AoRs configured for endpoint\n");
2688  return 0;
2689  }
2690 
2691  aors = ast_strdupa(endpoint->aors);
2692  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2693  struct sip_options_aor *aor_options;
2694 
2695  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2696  if (!aor_options) {
2697  continue;
2698  }
2699 
2701  aor_options);
2702  ao2_ref(aor_options, -1);
2703  }
2704 
2705  astman_send_ack(s, m, "Endpoint found, will qualify");
2706  return 0;
2707 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
#define NULL
Definition: resample.c:96
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
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
#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:911
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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:5218
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
char * strsep(char **str, const char *delims)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * sip_options_aors
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ AO2_STRING_FIELD_CMP_FN() [1/4]

AO2_STRING_FIELD_CMP_FN ( ast_sip_contact_status  ,
name   
)

Comparator function for contact statuses.

Referenced by ast_sip_get_contact_status(), sip_contact_status_copy(), and sip_options_endpoint_state_compositor_dtor().

◆ 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_state_compositor  ,
name   
)

Comparator function for endpoint state compositors.

◆ AO2_STRING_FIELD_CMP_FN() [4/4]

AO2_STRING_FIELD_CMP_FN ( sip_options_endpoint_aor_status  ,
name   
)

Comparator function for endpoint AOR status.

◆ AO2_STRING_FIELD_HASH_FN() [1/4]

AO2_STRING_FIELD_HASH_FN ( ast_sip_contact_status  ,
name   
)

◆ 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_state_compositor  ,
name   
)

Hashing function for endpoint state compositors.

◆ AO2_STRING_FIELD_HASH_FN() [4/4]

AO2_STRING_FIELD_HASH_FN ( sip_options_endpoint_aor_status  ,
name   
)

Hashing function for endpoint AOR status.

◆ AO2_STRING_FIELD_SORT_FN()

AO2_STRING_FIELD_SORT_FN ( ast_sip_contact_status  ,
name   
)

Sort function for contact statuses.

Referenced by sip_contact_status_copy().

◆ aor_observer_deleted()

static void aor_observer_deleted ( const void *  obj)
static

Observer callback invoked on AOR deletion.

Definition at line 2046 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_aor_observer_deleted_task().

2047 {
2050 }
static int sip_options_aor_observer_deleted_task(void *obj)
Task to delete an AOR from the known universe.
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:5218
static struct ast_taskprocessor * management_serializer

◆ aor_observer_modified()

static void aor_observer_modified ( const void *  obj)
static

Observer callback invoked on AOR creation or modification.

Definition at line 2015 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_aor_observer_modified_task().

2016 {
2019 }
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:5218
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
static struct ast_taskprocessor * management_serializer

◆ ast_res_pjsip_cleanup_options_handling()

void ast_res_pjsip_cleanup_options_handling ( void  )

Definition at line 2835 of file pjsip_options.c.

References ao2_cleanup, 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(), LOG_WARNING, management_serializer, MAX_UNLOAD_TIMEOUT_TIME, NULL, options_module, and sip_options_cleanup_task().

Referenced by ast_res_pjsip_init_options_handling(), and unload_pjsip().

2836 {
2837  int remaining;
2838  struct ast_taskprocessor *mgmt_serializer;
2839 
2841  ast_manager_unregister("PJSIPQualify");
2842  ast_manager_unregister("PJSIPShowContacts");
2844 
2851 
2852  mgmt_serializer = management_serializer;
2854  if (mgmt_serializer) {
2856  }
2857 
2860  if (remaining) {
2861  ast_log(LOG_WARNING, "Cleanup incomplete. Could not stop %d AORs.\n",
2862  remaining);
2863  }
2865  shutdown_group = NULL;
2866 
2867  if (mgmt_serializer) {
2868  ast_taskprocessor_unreference(mgmt_serializer);
2869  }
2870 
2877 
2878  pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
2879 }
static struct ao2_container * sip_options_contact_statuses
static struct ast_cli_entry cli_options[]
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static int sip_options_cleanup_task(void *obj)
Management task to clean up the environment.
#define LOG_WARNING
Definition: logger.h:274
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:3685
#define NULL
Definition: resample.c:96
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
static struct ast_sip_endpoint_formatter contact_status_formatter
#define ast_log
Definition: astobj2.c:42
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:5218
static pjsip_module options_module
static struct ao2_container * sip_options_endpoint_state_compositors
#define ARRAY_LEN(a)
Definition: utils.h:639
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
static struct ast_taskprocessor * management_serializer
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static struct ao2_container * sip_options_aors
#define MAX_UNLOAD_TIMEOUT_TIME
Maximum wait time to join the below shutdown group.
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.

◆ 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 462 of file pjsip_options.c.

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(), 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().

463 {
464  struct ast_sip_contact_status *contact_status;
465  int res;
466 
467  /*
468  * At startup a contact status can be retrieved when static contacts
469  * are themselves being setup. This happens before we are fully setup.
470  * Since we don't actually trigger qualify or anything as a result it
471  * is safe to do so. They'll just get back a contact status that will
472  * be updated later. At this time they only care that the contact
473  * status gets created for the static contact anyway.
474  */
476  /*
477  * We haven't been pre-initialized or we are shutting down.
478  * Neither situation should happen.
479  */
480  ast_assert(0);
481  return NULL;
482  }
483 
485 
486  /* If contact status for this contact already exists just return it */
487  contact_status = ao2_find(sip_options_contact_statuses,
489  if (contact_status) {
491  return contact_status;
492  }
493 
494  /* Otherwise we have to create and store a new contact status */
495  contact_status = sip_contact_status_alloc(ast_sorcery_object_get_id(contact));
496  if (!contact_status) {
498  return NULL;
499  }
500 
501  contact_status->rtt = 0;
502  contact_status->status = CREATED;
503  contact_status->last_status = CREATED;
504  res = ast_string_field_set(contact_status, uri, contact->uri);
505  res |= ast_string_field_set(contact_status, aor, contact->aor);
506  if (res) {
508  ao2_ref(contact_status, -1);
509  return NULL;
510  }
511 
514 
515  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
516  "+1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
517 
518  sip_options_contact_status_update(contact_status);
519 
520  return contact_status;
521 }
enum ast_sip_contact_status_type last_status
Definition: res_pjsip.h:353
A contact&#39;s status.
Definition: res_pjsip.h:341
static struct ao2_container * sip_options_contact_statuses
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ast_assert(a)
Definition: utils.h:710
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const ast_string_field uri
Definition: res_pjsip.h:347
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static struct ast_sip_contact_status * sip_contact_status_alloc(const char *name)
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
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.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
const ast_string_field aor
Definition: res_pjsip.h:303
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
const ast_string_field uri
Definition: res_pjsip.h:303
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
const ast_string_field aor
Definition: res_pjsip.h:347
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ ast_res_pjsip_init_options_handling()

int ast_res_pjsip_init_options_handling ( int  reload)

Definition at line 2918 of file pjsip_options.c.

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, ENDPOINT_STATE_COMPOSITOR_BUCKETS, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, NULL, options_module, sip_options_init_task(), and sip_options_synchronize().

Referenced by load_module(), and reload_configuration_task().

2919 {
2920  struct ast_taskprocessor *mgmt_serializer;
2921 
2922  static const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
2923 
2924  if (reload) {
2926  return 0;
2927  }
2928 
2929  if (pjsip_endpt_register_module(ast_sip_get_pjsip_endpoint(), &options_module)
2930  != PJ_SUCCESS) {
2931  return -1;
2932  }
2933 
2934  if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW,
2935  NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2937  return -1;
2938  }
2939 
2941  sip_options_aor_hash_fn, NULL, sip_options_aor_cmp_fn);
2942  if (!sip_options_aors) {
2944  return -1;
2945  }
2949  sip_options_endpoint_state_compositor_hash_fn, NULL,
2950  sip_options_endpoint_state_compositor_cmp_fn);
2953  return -1;
2954  }
2955 
2956  mgmt_serializer = ast_sip_create_serializer("pjsip/options/manage");
2957  if (!mgmt_serializer) {
2959  return -1;
2960  }
2961 
2962  /*
2963  * Set the water mark levels high because we can get a flood of
2964  * contact status updates from sip_options_synchronize() that
2965  * quickly clears on initial load or reload.
2966  */
2967  ast_taskprocessor_alert_set_levels(mgmt_serializer, -1,
2969 
2970  /*
2971  * We make sure that the environment is completely setup before we allow
2972  * any other threads to post contact_status updates to the
2973  * management_serializer.
2974  */
2976  mgmt_serializer)) {
2977  /* Set management_serializer in case pushing the task actually failed. */
2978  management_serializer = mgmt_serializer;
2980  return -1;
2981  }
2982 
2985  ami_sip_qualify);
2988 
2989  return 0;
2990 }
static int ami_sip_qualify(struct mansession *s, const struct message *m)
static struct ast_cli_entry cli_options[]
static int reload(void)
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int sip_options_init_task(void *mgmt_serializer)
Management task to finish setting up the environment.
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
#define NULL
Definition: resample.c:96
static struct ast_sip_endpoint_formatter contact_status_formatter
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:3679
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
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:5218
static pjsip_module options_module
static struct ao2_container * sip_options_endpoint_state_compositors
#define ARRAY_LEN(a)
Definition: utils.h:639
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS
These are the number of buckets to store endpoint state compositors.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
static struct ast_taskprocessor * management_serializer
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
static struct ao2_container * sip_options_aors
void ast_res_pjsip_cleanup_options_handling(void)
static int ami_show_contacts(struct mansession *s, const struct message *m)
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define AOR_BUCKETS
These are the number of buckets to store AORs in.

◆ ast_res_pjsip_preinit_options_handling()

int ast_res_pjsip_preinit_options_handling ( void  )

Definition at line 2912 of file pjsip_options.c.

References sip_options_contact_statuses_alloc().

Referenced by load_module().

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

◆ 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 2717 of file pjsip_options.c.

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(), 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_contact_status::rtt, ast_sip_ami::s, S_OR, status, ast_sip_contact_status::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().

2718 {
2719  struct ast_sip_contact_wrapper *wrapper = obj;
2720  struct ast_sip_contact *contact = wrapper->contact;
2721  struct ast_sip_ami *ami = arg;
2723  struct ast_str *buf;
2724  const struct ast_sip_endpoint *endpoint = ami->arg;
2725 
2726  buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
2727  if (!buf) {
2728  return -1;
2729  }
2730 
2731  status = ast_sip_get_contact_status(contact);
2732 
2733  ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
2734  ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
2735  ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
2736  ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
2737  if (!ast_strlen_zero(contact->via_addr)) {
2738  ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
2739  if (contact->via_port) {
2740  ast_str_append(&buf, 0, ":%d", contact->via_port);
2741  }
2742  ast_str_append(&buf, 0, "\r\n");
2743  }
2744  if (!ast_strlen_zero(contact->call_id)) {
2745  ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id);
2746  }
2747  ast_str_append(&buf, 0, "Status: %s\r\n",
2748  ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2749  if (!status || status->status != AVAILABLE) {
2750  ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2751  } else {
2752  ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2753  }
2754  ast_str_append(&buf, 0, "EndpointName: %s\r\n",
2755  endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, ""));
2756 
2757  ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));
2758  ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify);
2759  ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy);
2760  ast_str_append(&buf, 0, "Path: %s\r\n", contact->path);
2761  ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency);
2762  ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout);
2763 
2764  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2765  ami->count++;
2766 
2767  ast_free(buf);
2768  ao2_cleanup(status);
2769  return 0;
2770 }
int authenticate_qualify
Definition: res_pjsip.h:309
A contact&#39;s status.
Definition: res_pjsip.h:341
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
const ast_string_field outbound_proxy
Definition: res_pjsip.h:303
const ast_string_field call_id
Definition: res_pjsip.h:303
const ast_string_field user_agent
Definition: res_pjsip.h:303
const ast_string_field path
Definition: res_pjsip.h:303
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const ast_string_field via_addr
Definition: res_pjsip.h:303
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
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:1091
unsigned int qualify_frequency
Definition: res_pjsip.h:307
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
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:396
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct mansession * s
Definition: res_pjsip.h:2739
double qualify_timeout
Definition: res_pjsip.h:311
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
struct ast_sip_contact * contact
Definition: res_pjsip.h:402
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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.
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
struct timeval expiration_time
Definition: res_pjsip.h:305
#define ast_free(a)
Definition: astmm.h:182
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.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const ast_string_field uri
Definition: res_pjsip.h:303
jack_status_t status
Definition: app_jack.c:146

◆ 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 342 of file pjsip_options.c.

References ARRAY_LEN, ast_assert, short_status_map, and status.

Referenced by cli_contact_print_body().

343 {
345  return short_status_map[status];
346 }
static const char * short_status_map[]
#define ast_assert(a)
Definition: utils.h:710
#define ARRAY_LEN(a)
Definition: utils.h:639
jack_status_t status
Definition: app_jack.c:146

◆ ast_sip_get_contact_status()

struct ast_sip_contact_status* ast_sip_get_contact_status ( const struct ast_sip_contact contact)

Retrieve the current status for a contact.

Parameters
contactThe contact.
Return values
non-NULLSuccess
NULLStatus information not found
Note
The returned contact status object is immutable.

Definition at line 523 of file pjsip_options.c.

References ao2_find, AO2_STRING_FIELD_CMP_FN(), AO2_STRING_FIELD_HASH_FN(), ast_sorcery_object_get_id(), sip_options_endpoint_aor_status::name, and OBJ_SEARCH_KEY.

Referenced by ast_sip_format_contact_ami(), cli_contact_print_body(), contact_remove_unreachable(), format_ami_contactlist_handler(), pjsip_contact_function_read(), and sip_options_contact_update_task().

524 {
527 }
static struct ao2_container * sip_options_contact_statuses
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ ast_sip_get_contact_status_label()

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.

Return values
thecharacter string equivalent.

Definition at line 336 of file pjsip_options.c.

References ARRAY_LEN, ast_assert, status, and status_map.

Referenced by ast_res_pjsip_find_or_create_contact_status(), ast_sip_format_contact_ami(), ast_sip_initialize_sorcery_location(), ast_sip_persistent_endpoint_publish_contact_state(), format_ami_contactlist_handler(), pjsip_contact_function_read(), sip_options_contact_status_notify_task(), sip_options_remove_contact_status(), and sip_options_set_contact_status().

337 {
339  return status_map[status];
340 }
static const char * status_map[]
#define ast_assert(a)
Definition: utils.h:710
#define ARRAY_LEN(a)
Definition: utils.h:639
jack_status_t status
Definition: app_jack.c:146

◆ cli_qualify()

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

Definition at line 2346 of file pjsip_options.c.

References ao2_cleanup, ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::fd, NULL, OBJ_SEARCH_KEY, RAII_VAR, sip_options_aor::serializer, sip_options_qualify_aor(), strsep(), and ast_cli_entry::usage.

2347 {
2348  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2349  const char *endpoint_name;
2350  char *aors;
2351  char *aor_name;
2352 
2353  switch (cmd) {
2354  case CLI_INIT:
2355  e->command = "pjsip qualify";
2356  e->usage =
2357  "Usage: pjsip qualify <endpoint>\n"
2358  " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2359  return NULL;
2360  case CLI_GENERATE:
2361  return NULL;
2362  }
2363 
2364  if (a->argc != 3) {
2365  return CLI_SHOWUSAGE;
2366  }
2367 
2368  endpoint_name = a->argv[2];
2369 
2370  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2371  endpoint_name);
2372  if (!endpoint) {
2373  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2374  return CLI_FAILURE;
2375  }
2376 
2377  if (ast_strlen_zero(endpoint->aors)) {
2378  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2379  return CLI_FAILURE;
2380  }
2381 
2382  aors = ast_strdupa(endpoint->aors);
2383  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2384  struct sip_options_aor *aor_options;
2385 
2386  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2387  if (!aor_options) {
2388  continue;
2389  }
2390 
2391  ast_cli(a->fd, "Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2393  aor_options);
2394  ao2_ref(aor_options, -1);
2395  }
2396 
2397  return CLI_SUCCESS;
2398 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
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
#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:911
const int fd
Definition: cli.h:159
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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:5218
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
Structure which contains an AOR and contacts for qualifying purposes.
const char *const * argv
Definition: cli.h:161
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char * strsep(char **str, const char *delims)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * sip_options_aors
const ast_string_field aors
Definition: res_pjsip.h:821

◆ 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 2630 of file pjsip_options.c.

References ao2_ref, ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::fd, NULL, sip_options_aor_observer_modified_task(), and ast_cli_entry::usage.

2631 {
2632  struct ast_sip_aor *aor;
2633  const char *aor_name;
2634 
2635  switch (cmd) {
2636  case CLI_INIT:
2637  e->command = "pjsip reload qualify aor";
2638  e->usage =
2639  "Usage: pjsip reload qualify aor <id>\n"
2640  " Synchronize the PJSIP Aor qualify options.\n";
2641  return NULL;
2642  case CLI_GENERATE:
2643  return NULL;
2644  }
2645 
2646  if (a->argc != 5) {
2647  return CLI_SHOWUSAGE;
2648  }
2649 
2650  aor_name = a->argv[4];
2651 
2652  aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2653  if (!aor) {
2654  ast_cli(a->fd, "Unable to retrieve aor '%s'\n", aor_name);
2655  return CLI_FAILURE;
2656  }
2657 
2658  ast_cli(a->fd, "Synchronizing AOR '%s'\n", aor_name);
2661  ao2_ref(aor, -1);
2662 
2663  return CLI_SUCCESS;
2664 }
A SIP address of record.
Definition: res_pjsip.h:361
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
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
const int fd
Definition: cli.h:159
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
static struct ast_taskprocessor * management_serializer
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ 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 2576 of file pjsip_options.c.

References ao2_cleanup, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::fd, NULL, RAII_VAR, sip_options_aor_observer_modified_task(), strsep(), and ast_cli_entry::usage.

2577 {
2578  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2579  const char *endpoint_name;
2580  char *aors;
2581  char *aor_name;
2582 
2583  switch (cmd) {
2584  case CLI_INIT:
2585  e->command = "pjsip reload qualify endpoint";
2586  e->usage =
2587  "Usage: pjsip reload qualify endpoint <id>\n"
2588  " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2589  return NULL;
2590  case CLI_GENERATE:
2591  return NULL;
2592  }
2593 
2594  if (a->argc != 5) {
2595  return CLI_SHOWUSAGE;
2596  }
2597 
2598  endpoint_name = a->argv[4];
2599 
2600  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2601  endpoint_name);
2602  if (!endpoint) {
2603  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2604  return CLI_FAILURE;
2605  }
2606 
2607  if (ast_strlen_zero(endpoint->aors)) {
2608  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2609  return CLI_FAILURE;
2610  }
2611 
2612  aors = ast_strdupa(endpoint->aors);
2613  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2614  struct ast_sip_aor *aor;
2615 
2616  aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2617  if (!aor) {
2618  continue;
2619  }
2620 
2621  ast_cli(a->fd, "Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2624  ao2_ref(aor, -1);
2625  }
2626 
2627  return CLI_SUCCESS;
2628 }
A SIP address of record.
Definition: res_pjsip.h:361
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
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
#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:911
const int fd
Definition: cli.h:159
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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:5218
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
static struct ast_taskprocessor * management_serializer
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char * strsep(char **str, const char *delims)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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 2539 of file pjsip_options.c.

References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, OBJ_SEARCH_KEY, and ast_cli_entry::usage.

2540 {
2541  struct sip_options_aor *aor_options;
2542  const char *aor_name;
2543 
2544  switch (cmd) {
2545  case CLI_INIT:
2546  e->command = "pjsip show qualify aor";
2547  e->usage =
2548  "Usage: pjsip show qualify aor <id>\n"
2549  " Show the PJSIP Aor current qualify options.\n";
2550  return NULL;
2551  case CLI_GENERATE:
2552  return NULL;
2553  }
2554 
2555  if (a->argc != 5) {
2556  return CLI_SHOWUSAGE;
2557  }
2558 
2559  aor_name = a->argv[4];
2560 
2561  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2562  if (!aor_options) {
2563  ast_cli(a->fd, "Unable to retrieve aor '%s' qualify options\n", aor_name);
2564  return CLI_FAILURE;
2565  }
2566 
2567  ast_cli(a->fd, " * AOR '%s'\n", aor_name);
2568  ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2569  ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2570  ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2571  ao2_ref(aor_options, -1);
2572 
2573  return CLI_SUCCESS;
2574 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static struct ao2_container * sip_options_aors

◆ 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 2483 of file pjsip_options.c.

References ao2_cleanup, ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_sip_get_sorcery(), 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, ast_cli_args::fd, NULL, OBJ_SEARCH_KEY, RAII_VAR, strsep(), and ast_cli_entry::usage.

2484 {
2485  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2486  const char *endpoint_name;
2487  char *aors;
2488  char *aor_name;
2489 
2490  switch (cmd) {
2491  case CLI_INIT:
2492  e->command = "pjsip show qualify endpoint";
2493  e->usage =
2494  "Usage: pjsip show qualify endpoint <id>\n"
2495  " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2496  return NULL;
2497  case CLI_GENERATE:
2498  return NULL;
2499  }
2500 
2501  if (a->argc != 5) {
2502  return CLI_SHOWUSAGE;
2503  }
2504 
2505  endpoint_name = a->argv[4];
2506 
2507  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2508  endpoint_name);
2509  if (!endpoint) {
2510  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2511  return CLI_FAILURE;
2512  }
2513 
2514  if (ast_strlen_zero(endpoint->aors)) {
2515  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2516  return CLI_FAILURE;
2517  }
2518 
2519  aors = ast_strdupa(endpoint->aors);
2520  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2521  struct sip_options_aor *aor_options;
2522 
2523  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2524  if (!aor_options) {
2525  continue;
2526  }
2527 
2528  ast_cli(a->fd, " * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2529  ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2530  ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2531  ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2532  ast_cli(a->fd, "\n");
2533  ao2_ref(aor_options, -1);
2534  }
2535 
2536  return CLI_SUCCESS;
2537 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
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
#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:911
const int fd
Definition: cli.h:159
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:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
Structure which contains an AOR and contacts for qualifying purposes.
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char * strsep(char **str, const char *delims)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * sip_options_aors

◆ contact_observer_created()

static void contact_observer_created ( const void *  obj)
static

Observer callback invoked on contact creation.

Definition at line 2187 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_contact_add_management_task().

2188 {
2191 }
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:5218
static struct ast_taskprocessor * management_serializer
static int sip_options_contact_add_management_task(void *obj)
Task to add a dynamic contact to an AOR in its serializer.

◆ contact_observer_deleted()

static void contact_observer_deleted ( const void *  obj)
static

Observer callback invoked on contact deletion.

Definition at line 2333 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_contact_delete_management_task().

2334 {
2337 }
static int sip_options_contact_delete_management_task(void *obj)
Task to delete a contact from an AOR in its serializer.
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:5218
static struct ast_taskprocessor * management_serializer

◆ contact_observer_updated()

static void contact_observer_updated ( const void *  obj)
static

Observer callback invoked on contact update.

Definition at line 2225 of file pjsip_options.c.

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(), sip_options_contact_observer_task_data::contact, has_qualify_changed(), OBJ_SEARCH_KEY, sip_options_aor::serializer, sip_options_aor_observer_modified_task(), and sip_options_contact_update_task().

2226 {
2227  const struct ast_sip_contact *contact = obj;
2228  struct sip_options_aor *aor_options = ao2_find(sip_options_aors, contact->aor, OBJ_SEARCH_KEY);
2229 
2230  if (has_qualify_changed(contact, aor_options)) {
2231  struct ast_sip_aor *aor;
2232 
2234  contact->aor);
2235  if (aor) {
2236  ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2237  contact->aor);
2240  ao2_ref(aor, -1);
2241  }
2242  }
2243 
2246 
2247  task_data = ast_malloc(sizeof(*task_data));
2248  if (!task_data) {
2249  ao2_ref(aor_options, -1);
2250  return;
2251  }
2252 
2253  task_data->contact = (struct ast_sip_contact *) contact;
2254  /* task_data takes ownership of aor_options and will take care of releasing the ref */
2255  task_data->aor_options = aor_options;
2256 
2257  ao2_ref(task_data->contact, +1);
2258  if (ast_sip_push_task(task_data->aor_options->serializer,
2259  sip_options_contact_update_task, task_data)) {
2260  ao2_ref(task_data->contact, -1);
2261  ao2_ref(task_data->aor_options, -1);
2262  ast_free(task_data);
2263  }
2264  } else {
2265  ao2_cleanup(aor_options);
2266  }
2267 }
A SIP address of record.
Definition: res_pjsip.h:361
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
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.
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
Retrieve the global setting &#39;send_contact_status_on_update_registration&#39;.
Task details for adding an AOR to an endpoint state compositor.
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_sip_contact * contact
The contact itself.
struct ast_taskprocessor * serializer
The serializer for this AOR.
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
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:5138
Contact associated with an address of record.
Definition: res_pjsip.h:281
userdata associated with baseline taskprocessor test
static struct ast_taskprocessor * management_serializer
#define ast_free(a)
Definition: astmm.h:182
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int sip_options_contact_update_task(void *obj)
Task which updates a dynamic contact to an AOR.
const ast_string_field aor
Definition: res_pjsip.h:303
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * sip_options_aors

◆ 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 434 of file pjsip_options.c.

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

Referenced by sip_options_contact_status_update().

435 {
436  struct ast_sip_contact_status *contact_status = obj;
437  struct sip_options_aor *aor_options;
438 
439  aor_options = ao2_find(sip_options_aors, contact_status->aor, OBJ_SEARCH_KEY);
440  if (aor_options) {
441  sip_options_publish_contact_state(aor_options, contact_status);
442  ao2_ref(aor_options, -1);
443  }
444  ao2_ref(contact_status, -1);
445 
446  return 0;
447 }
A contact&#39;s status.
Definition: res_pjsip.h:341
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
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.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * sip_options_aors
const ast_string_field aor
Definition: res_pjsip.h:347

◆ endpoint_observer_deleted()

static void endpoint_observer_deleted ( const void *  obj)
static

Observer callback invoked on endpoint deletion.

Definition at line 1883 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_endpoint_observer_deleted_task().

1884 {
1887 }
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:5218
static struct ast_taskprocessor * management_serializer
static int sip_options_endpoint_observer_deleted_task(void *obj)
Task to delete an endpoint from the known universe.

◆ endpoint_observer_modified()

static void endpoint_observer_modified ( const void *  obj)
static

Observer callback invoked on endpoint creation or modification.

Definition at line 1915 of file pjsip_options.c.

References ast_sip_push_task_wait_serializer(), and sip_options_endpoint_observer_modified_task().

1916 {
1919 }
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:5218
static struct ast_taskprocessor * management_serializer
static int sip_options_endpoint_observer_modified_task(void *obj)
Task to synchronize the endpoint.

◆ 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 2779 of file pjsip_options.c.

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

2781 {
2782  ami->arg = (void *)endpoint;
2784 }
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 &#39;on_aor&#39; handler. ...
Definition: location.c:684
void * arg
Definition: res_pjsip.h:2745
static int format_contact_status_for_aor(void *obj, void *arg, int flags)
const ast_string_field aors
Definition: res_pjsip.h:821

◆ format_ami_contactlist_handler()

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

Definition at line 2416 of file pjsip_options.c.

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_contact_status::rtt, ast_sip_ami::s, sip_contact_to_ami(), status, ast_sip_contact_status::status, and UNKNOWN.

Referenced by ami_show_contacts().

2417 {
2418  struct ast_sip_contact *contact = obj;
2419  struct ast_sip_ami *ami = arg;
2420  struct ast_str *buf;
2422 
2423  buf = ast_sip_create_ami_event("ContactList", ami);
2424  if (!buf) {
2425  return CMP_STOP;
2426  }
2427 
2428  if (sip_contact_to_ami(contact, &buf)) {
2429  ast_free(buf);
2430  return CMP_STOP;
2431  }
2432 
2433  /* Add extra info */
2434  status = ast_sip_get_contact_status(contact);
2435  ast_str_append(&buf, 0, "Status: %s\r\n",
2436  ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2437  if (!status || status->status != AVAILABLE) {
2438  ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2439  } else {
2440  ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2441  }
2442  ao2_cleanup(status);
2443 
2444  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2445 
2446  ami->count++;
2447 
2448  ast_free(buf);
2449 
2450  return 0;
2451 }
A contact&#39;s status.
Definition: res_pjsip.h:341
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
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:1091
static int sip_contact_to_ami(const struct ast_sip_contact *contact, struct ast_str **buf)
struct mansession * s
Definition: res_pjsip.h:2739
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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.
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
#define ast_free(a)
Definition: astmm.h:182
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.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
jack_status_t status
Definition: app_jack.c:146

◆ format_contact_status_for_aor()

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

Definition at line 2772 of file pjsip_options.c.

References ast_sip_for_each_contact(), and ast_sip_format_contact_ami().

Referenced by format_ami_contact_status().

2773 {
2774  struct ast_sip_aor *aor = obj;
2775 
2777 }
A SIP address of record.
Definition: res_pjsip.h:361
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 &#39;on_contact&#39; handler.
Definition: location.c:719

◆ get_all_contacts()

static struct ao2_container* get_all_contacts ( void  )
static

Definition at line 2400 of file pjsip_options.c.

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().

2401 {
2402  struct ao2_container *contacts;
2403 
2404  contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
2406 
2407  return contacts;
2408 }
Perform no matching, return all objects.
Definition: sorcery.h:123
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
Generic container type.

◆ 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 2071 of file pjsip_options.c.

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

Referenced by contact_observer_updated(), and sip_options_contact_add_management_task().

2072 {
2073  if (!contact) {
2074  return 0;
2075  }
2076 
2077  if (!aor_options) {
2078  if (contact->qualify_frequency) {
2079  return 1;
2080  }
2081  } else if (contact->qualify_frequency != aor_options->qualify_frequency
2082  || contact->authenticate_qualify != aor_options->authenticate_qualify
2083  || ((int)(contact->qualify_timeout * 1000)) != ((int)(aor_options->qualify_timeout * 1000))) {
2084  return 1;
2085  }
2086 
2087  return 0;
2088 }
int authenticate_qualify
Definition: res_pjsip.h:309
unsigned int qualify_frequency
Definition: res_pjsip.h:307
double qualify_timeout
Definition: res_pjsip.h:311

◆ options_on_rx_request()

static pj_bool_t options_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 268 of file pjsip_options.c.

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

269 {
270  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
271  pjsip_uri *ruri;
272  pjsip_sip_uri *sip_ruri;
273  char exten[AST_MAX_EXTENSION];
274 
275  if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
276  return PJ_FALSE;
277  }
278 
279  if (!(endpoint = ast_pjsip_rdata_get_endpoint(rdata))) {
280  return PJ_FALSE;
281  }
282 
283  ruri = rdata->msg_info.msg->line.req.uri;
284  if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
285  send_options_response(rdata, 416);
286  return PJ_TRUE;
287  }
288 
289  sip_ruri = pjsip_uri_get_uri(ruri);
290  ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
291 
292  /*
293  * We may want to match in the dialplan without any user
294  * options getting in the way.
295  */
297 
298  if (ast_shutting_down()) {
299  /*
300  * Not taking any new calls at this time.
301  * Likely a server availability OPTIONS poll.
302  */
303  send_options_response(rdata, 503);
304  } else if (!ast_strlen_zero(exten)
305  && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
306  send_options_response(rdata, 404);
307  } else {
308  send_options_response(rdata, 200);
309  }
310  return PJ_TRUE;
311 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3036
int ast_shutting_down(void)
Definition: asterisk.c:1834
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:5240
#define NULL
Definition: resample.c:96
static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
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.
#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:911
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define AST_MAX_EXTENSION
Definition: channel.h:135
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
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:4179
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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 786 of file pjsip_options.c.

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_NOTICE, 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().

787 {
788  struct sip_options_contact_callback_data *contact_callback_data = token;
790 
791  switch(e->body.tsx_state.type) {
792  default:
793  ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
794  /* Fall through */
795  case PJSIP_EVENT_TRANSPORT_ERROR:
796  case PJSIP_EVENT_TIMER:
797  status = UNAVAILABLE;
798  break;
799  case PJSIP_EVENT_RX_MSG:
800  status = AVAILABLE;
801  break;
802  }
803 
804  /* Update the callback data with the new status, this will get handled in the AOR serializer */
805  contact_callback_data->status = status;
806 
807  if (ast_sip_push_task(contact_callback_data->aor_options->serializer,
808  sip_options_contact_status_notify_task, contact_callback_data)) {
809  ast_log(LOG_NOTICE, "Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
810  ast_sorcery_object_get_id(contact_callback_data->contact),
811  contact_callback_data->aor_options->name);
812  ao2_ref(contact_callback_data, -1);
813  }
814 
815  /* The task inherited our reference so we don't unreference here */
816 }
struct ast_sip_contact * contact
The contact we qualified.
ast_sip_contact_status_type
Status type for a contact.
Definition: res_pjsip.h:323
enum ast_sip_contact_status_type status
The new status of the contact.
#define ast_log
Definition: astobj2.c:42
static int sip_options_contact_status_notify_task(void *obj)
Task to notify an AOR of a contact status change.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Structure used to contain information for an OPTIONS callback.
#define LOG_ERROR
Definition: logger.h:285
struct ast_taskprocessor * serializer
The serializer for this AOR.
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:5138
struct sip_options_aor * aor_options
The AOR options.
#define LOG_NOTICE
Definition: logger.h:263
jack_status_t status
Definition: app_jack.c:146

◆ 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.

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().

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. We never did add them
246  * in chan_sip, although RFC 3261 says they SHOULD. Hard coded here.
247  */
248  ast_sip_add_header(tdata, "Accept-Encoding", DEFAULT_ENCODING);
249  ast_sip_add_header(tdata, "Accept-Language", DEFAULT_LANGUAGE);
250 
251  if (dlg && trans) {
252  status = pjsip_dlg_send_response(dlg, trans, tdata);
253  } else {
254  struct ast_sip_endpoint *endpoint;
255 
256  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
257  status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
258  ao2_cleanup(endpoint);
259  }
260 
261  if (status != PJ_SUCCESS) {
262  ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
263  }
264 
265  return status;
266 }
#define NULL
Definition: resample.c:96
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:5063
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.
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:5448
#define ast_log
Definition: astobj2.c:42
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:5420
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define LOG_ERROR
Definition: logger.h:285
#define DEFAULT_LANGUAGE
Definition: pjsip_options.c:96
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define DEFAULT_ENCODING
Definition: pjsip_options.c:97
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
jack_status_t status
Definition: app_jack.c:146

◆ sip_contact_status_alloc()

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

Definition at line 356 of file pjsip_options.c.

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

Referenced by ast_res_pjsip_find_or_create_contact_status(), and sip_contact_status_copy().

357 {
358  struct ast_sip_contact_status *contact_status;
359  size_t size = sizeof(*contact_status) + strlen(name) + 1;
360 
361  contact_status = ao2_alloc_options(size, sip_contact_status_dtor,
363  if (!contact_status) {
364  return NULL;
365  }
366  if (ast_string_field_init(contact_status, 256)) {
367  ao2_ref(contact_status, -1);
368  return NULL;
369  }
370  strcpy(contact_status->name, name); /* SAFE */
371  return contact_status;
372 }
A contact&#39;s status.
Definition: res_pjsip.h:341
static const char name[]
Definition: format_mp3.c:68
static void sip_contact_status_dtor(void *obj)
Destructor for contact statuses.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464

◆ 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.

References ao2_ref, AO2_STRING_FIELD_CMP_FN(), AO2_STRING_FIELD_HASH_FN(), AO2_STRING_FIELD_SORT_FN(), ast_string_fields_copy, ast_sip_contact_status::last_status, sip_options_endpoint_aor_status::name, ast_sip_contact_status::name, NULL, ast_sip_contact_status::rtt, 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().

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  return dst;
391 }
enum ast_sip_contact_status_type last_status
Definition: res_pjsip.h:353
A contact&#39;s status.
Definition: res_pjsip.h:341
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_sip_contact_status * sip_contact_status_alloc(const char *name)
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
#define ast_string_fields_copy(copy, orig)
Copy all string fields from one instance to another of the same structure.
Definition: stringfields.h:627

◆ sip_contact_status_dtor()

static void sip_contact_status_dtor ( void *  obj)
static

Destructor for contact statuses.

Definition at line 349 of file pjsip_options.c.

References ast_string_field_free_memory.

Referenced by sip_contact_status_alloc().

350 {
351  struct ast_sip_contact_status *contact_status = obj;
352 
353  ast_string_field_free_memory(contact_status);
354 }
A contact&#39;s status.
Definition: res_pjsip.h:341
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ sip_contact_to_ami()

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

Definition at line 2410 of file pjsip_options.c.

References ast_sip_sorcery_object_to_ami().

Referenced by format_ami_contactlist_handler().

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

◆ 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 963 of file pjsip_options.c.

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, CONTACT_BUCKETS, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE, NULL, sip_options_aor::serializer, and sip_options_aor_dtor().

Referenced by sip_options_aor_observer_modified_task(), and sip_options_synchronize_aor().

964 {
965  struct sip_options_aor *aor_options;
966  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
967 
968  aor_options = ao2_alloc_options(sizeof(*aor_options) + strlen(ast_sorcery_object_get_id(aor)) + 1,
970  if (!aor_options) {
971  return NULL;
972  }
973 
974  strcpy(aor_options->name, ast_sorcery_object_get_id(aor)); /* SAFE */
975 
976  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/options/%s",
978  aor_options->serializer = ast_sip_create_serializer_group(tps_name,
980  if (!aor_options->serializer) {
981  ao2_ref(aor_options, -1);
982  return NULL;
983  }
984 
985  if (AST_VECTOR_INIT(&aor_options->compositors, ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE)) {
986  ao2_ref(aor_options, -1);
987  return NULL;
988  }
989 
993  if (!aor_options->contacts) {
994  ao2_ref(aor_options, -1);
995  return NULL;
996  }
997 
1001  if (!aor_options->dynamic_contacts) {
1002  ao2_ref(aor_options, -1);
1003  return NULL;
1004  }
1005 
1006  return aor_options;
1007 }
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
static void sip_options_aor_dtor(void *obj)
Destructor function for SIP OPTIONS AORs.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:60
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE
The initial vector size for the endpoint state compositors on an AOR.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
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:5128
Structure which contains an AOR and contacts for qualifying purposes.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ast_taskprocessor * serializer
The serializer for this AOR.
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.
#define CONTACT_BUCKETS
These are the number of buckets (per AOR) to use to store contacts.
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.

◆ sip_options_aor_dtor()

static void sip_options_aor_dtor ( void *  obj)
static

Destructor function for SIP OPTIONS AORs.

Definition at line 941 of file pjsip_options.c.

References ao2_callback, ao2_cleanup, ao2_ref, ast_assert, ast_taskprocessor_unreference(), AST_VECTOR_FREE, AST_VECTOR_SIZE, 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().

942 {
943  struct sip_options_aor *aor_options = obj;
944 
945  /*
946  * Any contacts are unreachable since the AOR is being destroyed
947  * so remove their contact status
948  */
949  if (aor_options->contacts) {
950  ao2_callback(aor_options->contacts, OBJ_NODATA | OBJ_UNLINK,
951  sip_options_remove_contact, aor_options);
952  ao2_ref(aor_options->contacts, -1);
953  }
954  ao2_cleanup(aor_options->dynamic_contacts);
955 
957 
958  ast_assert(AST_VECTOR_SIZE(&aor_options->compositors) == 0);
959  AST_VECTOR_FREE(&aor_options->compositors);
960 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ast_assert(a)
Definition: utils.h:710
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct ao2_container * contacts
All contacts associated with this AOR.
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:611
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.

◆ 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 2025 of file pjsip_options.c.

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

Referenced by aor_observer_deleted().

2026 {
2027  struct ast_sip_aor *aor = obj;
2028  struct sip_options_aor *aor_options;
2029 
2032  if (!aor_options) {
2033  return 0;
2034  }
2035 
2036  ast_debug(3, "AOR '%s' has been deleted, removing it\n", aor_options->name);
2037 
2039  aor_options);
2040  ao2_ref(aor_options, -1);
2041 
2042  return 0;
2043 }
A SIP address of record.
Definition: res_pjsip.h:361
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Structure which contains an AOR and contacts for qualifying purposes.
static int sip_options_aor_remove_task(void *obj)
Task which removes an AOR from all of the ESCs it is reporting to.
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * sip_options_aors

◆ 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 1960 of file pjsip_options.c.

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_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().

1961 {
1962  struct ast_sip_aor *aor = obj;
1963  struct sip_options_aor *aor_options;
1964 
1966  OBJ_SEARCH_KEY);
1967  if (!aor_options) {
1968  struct ao2_container *endpoints;
1969 
1970  aor_options = sip_options_aor_alloc(aor);
1971  if (!aor_options) {
1972  return 0;
1973  }
1974 
1975  /*
1976  * This is a newly added AOR and we need to establish any
1977  * endpoint state compositors that may reference only the
1978  * AOR. If these need to be updated later then they'll
1979  * be done by modifying the endpoint or issuing a reload.
1980  */
1981  sip_options_apply_aor_configuration(aor_options, aor, 1);
1982  ao2_link(sip_options_aors, aor_options);
1983 
1984  /*
1985  * Using LIKE doesn't seem to work very well with non-realtime so we
1986  * fetch everything right now and do a filter on our side.
1987  */
1990  if (endpoints) {
1992  ao2_ref(endpoints, -1);
1993  }
1994  } else {
1996  .aor_options = aor_options,
1997  .aor = aor,
1998  };
1999 
2000  /*
2001  * If this AOR was modified we have to do our work in its serializer
2002  * instead of this thread to ensure that things aren't modified by
2003  * multiple threads.
2004  */
2006  sip_options_update_aor_task, &task_data);
2007  }
2008 
2009  ao2_ref(aor_options, -1);
2010 
2011  return 0;
2012 }
static int sip_options_update_aor_task(void *obj)
Task to synchronize an AOR with our local state.
static struct sip_options_aor * sip_options_aor_alloc(struct ast_sip_aor *aor)
Allocator for AOR OPTIONS.
A SIP address of record.
Definition: res_pjsip.h:361
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.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Task data for AOR creation or updating.
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Perform no matching, return all objects.
Definition: sorcery.h:123
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
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:5218
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct sip_options_aor * aor_options
The AOR options for this AOR.
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_taskprocessor * serializer
The serializer for this AOR.
userdata associated with baseline taskprocessor test
struct ast_sip_aor * aor
The AOR which contains the new configuraton.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
Synchronize an endpoint with our local state.
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ao2_container * sip_options_aors
Generic container type.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ 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 1688 of file pjsip_options.c.

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().

1689 {
1690  struct sip_options_aor *aor_options = obj;
1691 
1693 
1694  if (aor_options->sched_task) {
1695  ast_sip_sched_task_cancel(aor_options->sched_task);
1696  ao2_ref(aor_options->sched_task, -1);
1697  aor_options->sched_task = NULL;
1698  }
1699 
1700  return 0;
1701 }
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
#define NULL
Definition: resample.c:96
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_sip_sched_task * sched_task
The scheduler task for this 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 1240 of file pjsip_options.c.

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::contacts, sip_options_aor::dynamic_contacts, LOG_ERROR, LOG_WARNING, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, ast_sip_aor::permanent_contacts, prefix, ast_sip_aor::qualify_frequency, ast_sip_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().

1242 {
1243  struct ao2_container *existing_contacts;
1244  struct ast_sip_contact *contact;
1245  struct ao2_iterator iter;
1246 
1247  ast_debug(3, "Configuring AOR '%s' with current state of configuration and world\n",
1248  aor_options->name);
1249 
1250  /*
1251  * Permanent contacts, since we receive no notification that they
1252  * are gone, follow the same approach as AORs. We create a copy
1253  * of the existing container and any reused contacts are removed
1254  * from it. Any contacts remaining in the container after
1255  * processing no longer exist so we need to remove their state.
1256  */
1257  existing_contacts = ao2_container_clone(aor_options->contacts, 0);
1258  if (!existing_contacts) {
1259  ast_log(LOG_WARNING, "Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1260  aor_options->name);
1261  return;
1262  }
1263 
1265  NULL, NULL);
1266 
1267  /* Process permanent contacts */
1268  if (aor->permanent_contacts) {
1269  iter = ao2_iterator_init(aor->permanent_contacts, 0);
1270  for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1271  ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1273  ao2_link(aor_options->contacts, contact);
1274  }
1275  ao2_iterator_destroy(&iter);
1276  }
1277 
1278  /*
1279  * If this is newly added we need to see if there are any
1280  * existing dynamic contacts to add. Ones that are added
1281  * after creation will occur as a result of the contact
1282  * observer creation callback.
1283  */
1284  if (is_new) {
1285  size_t prefix_len = strlen(ast_sorcery_object_get_id(aor)) + sizeof(";@") - 1;
1286  char prefix[prefix_len + 1];
1287  struct ao2_container *contacts;
1288 
1289  sprintf(prefix, "%s;@", ast_sorcery_object_get_id(aor)); /* Safe */
1290  contacts = ast_sorcery_retrieve_by_prefix(ast_sip_get_sorcery(), "contact",
1291  prefix, prefix_len);
1292  if (contacts) {
1293  ao2_container_dup(aor_options->dynamic_contacts, contacts, 0);
1294  ao2_ref(contacts, -1);
1295  }
1296  }
1297 
1298  /* Process dynamic contacts */
1299  iter = ao2_iterator_init(aor_options->dynamic_contacts, 0);
1300  for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1301  ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1303  ao2_link(aor_options->contacts, contact);
1304  }
1305  ao2_iterator_destroy(&iter);
1306 
1307  /* Any contacts left no longer exist, so raise events and make them disappear */
1308  ao2_callback(existing_contacts, OBJ_NODATA | OBJ_UNLINK,
1309  sip_options_remove_contact, aor_options);
1310  ao2_ref(existing_contacts, -1);
1311 
1312  /*
1313  * Update the available count if we transition between qualified
1314  * and unqualified. In the qualified case we need to start with
1315  * 0 available as the qualify process will take care of it. In
1316  * the unqualified case it is based on the number of contacts
1317  * present.
1318  */
1319  if (!aor->qualify_frequency) {
1320  ao2_callback(aor_options->contacts, OBJ_NODATA,
1322  aor_options->available = ao2_container_count(aor_options->contacts);
1323  ast_debug(3, "AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1324  aor_options->name, aor_options->available);
1325  } else if (!aor_options->qualify_frequency) {
1326  ao2_callback(aor_options->contacts, OBJ_NODATA,
1328  aor_options->available = 0;
1329  ast_debug(3, "AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1330  aor_options->name);
1331  } else {
1332  /*
1333  * Count the number of AVAILABLE qualified contacts to ensure
1334  * the count is in sync with reality.
1335  */
1336  aor_options->available = 0;
1337  ao2_callback(aor_options->contacts, OBJ_NODATA,
1338  sip_options_contact_status_available_count, &aor_options->available);
1339  }
1340 
1341  aor_options->authenticate_qualify = aor->authenticate_qualify;
1342  aor_options->qualify_timeout = aor->qualify_timeout;
1343 
1344  /*
1345  * If we need to stop or start the scheduled callback then do so.
1346  * This occurs due to the following:
1347  * 1. The qualify frequency has changed
1348  * 2. Contacts were added when previously there were none
1349  * 3. There are no contacts but previously there were some
1350  */
1351  if (aor_options->qualify_frequency != aor->qualify_frequency
1352  || (!aor_options->sched_task && ao2_container_count(aor_options->contacts))
1353  || (aor_options->sched_task && !ao2_container_count(aor_options->contacts))) {
1354  if (aor_options->sched_task) {
1355  ast_sip_sched_task_cancel(aor_options->sched_task);
1356  ao2_ref(aor_options->sched_task, -1);
1357  aor_options->sched_task = NULL;
1358  }
1359 
1360  /* If there is still a qualify frequency then schedule this */
1361  aor_options->qualify_frequency = aor->qualify_frequency;
1362  if (aor_options->qualify_frequency
1363  && ao2_container_count(aor_options->contacts)) {
1364  aor_options->sched_task = ast_sip_schedule_task(aor_options->serializer,
1365  sip_options_determine_initial_qualify_time(aor_options->qualify_frequency),
1368  if (!aor_options->sched_task) {
1369  ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
1370  aor_options->name);
1371  }
1372  }
1373  }
1374 
1375  ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1376  aor_options->available);
1377 }
double qualify_timeout
Definition: res_pjsip.h:387
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
Transition the contact status to qualified mode.
#define ao2_container_clone(orig, flags)
Definition: astobj2.h:1430
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
#define LOG_WARNING
Definition: logger.h:274
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
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
#define NULL
Definition: resample.c:96
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
unsigned int qualify_frequency
Definition: res_pjsip.h:375
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.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
Transition the contact status to unqualified mode.
static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
Count AVAILABLE qualified contacts.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define LOG_ERROR
Definition: logger.h:285
struct ast_taskprocessor * serializer
The serializer for this AOR.
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.
Contact associated with an address of record.
Definition: res_pjsip.h:281
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:383
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static int sip_options_determine_initial_qualify_time(int qualify_frequency)
Determine an initial time for scheduling AOR qualifying.
struct ao2_container * contacts
All contacts associated with this AOR.
int authenticate_qualify
Definition: res_pjsip.h:377
Generic container type.
static int sip_options_remove_contact(void *obj, void *arg, int flags)
Forward declaration of this helpful function.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
static char prefix[MAX_PREFIX]
Definition: http.c:141
#define ao2_link(container, obj)
Definition: astobj2.h:1549
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.

◆ 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 2794 of file pjsip_options.c.

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

Referenced by sip_options_cleanup_task().

2795 {
2796  struct sip_options_aor *aor_options = obj;
2797 
2798  ast_debug(2, "Cleaning up AOR '%s' for shutdown\n", aor_options->name);
2799 
2800  aor_options->qualify_frequency = 0;
2801  if (aor_options->sched_task) {
2802  ast_sip_sched_task_cancel(aor_options->sched_task);
2803  ao2_ref(aor_options->sched_task, -1);
2804  aor_options->sched_task = NULL;
2805  }
2806  AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
2807 
2808  return 0;
2809 }
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.

◆ 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 2815 of file pjsip_options.c.

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, and sip_options_cleanup_aor_task().

Referenced by ast_res_pjsip_cleanup_options_handling().

2816 {
2817  struct ao2_iterator it_aor;
2818  struct sip_options_aor *aor_options;
2819 
2820  if (!sip_options_aors) {
2821  /* Nothing to do */
2822  return 0;
2823  }
2824 
2826  for (; (aor_options = ao2_iterator_next(&it_aor)); ao2_ref(aor_options, -1)) {
2828  sip_options_cleanup_aor_task, aor_options);
2829  }
2830  ao2_iterator_destroy(&it_aor);
2831 
2832  return 0;
2833 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure which contains an AOR and contacts for qualifying purposes.
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static int sip_options_cleanup_aor_task(void *obj)
Management task to clean up an AOR.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static struct ao2_container * sip_options_aors
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ 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 2154 of file pjsip_options.c.

References ao2_find, ao2_ref, ast_sip_contact::aor, sip_options_contact_observer_task_data::aor_options, ast_debug, ast_sip_get_sorcery(), ast_sip_push_task_wait_serializer(), ast_sorcery_retrieve_by_id(), sip_options_contact_observer_task_data::contact, has_qualify_changed(), OBJ_SEARCH_KEY, sip_options_aor::serializer, sip_options_aor_observer_modified_task(), and sip_options_contact_add_task().

Referenced by contact_observer_created().

2155 {
2157 
2158  task_data.contact = obj;
2159  task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2160  OBJ_SEARCH_KEY);
2161 
2162  if (has_qualify_changed(task_data.contact, task_data.aor_options)) {
2163  struct ast_sip_aor *aor;
2164 
2166  task_data.contact->aor);
2167  if (aor) {
2168  ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2169  task_data.contact->aor);
2171  ao2_ref(aor, -1);
2172  }
2173  }
2174 
2175  if (!task_data.aor_options) {
2176  return 0;
2177  }
2178 
2179  ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2181  ao2_ref(task_data.aor_options, -1);
2182 
2183  return 0;
2184 }
A SIP address of record.
Definition: res_pjsip.h:361
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
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.
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Task details for adding an AOR to an endpoint state compositor.
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
userdata associated with baseline taskprocessor test
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ao2_container * sip_options_aors
static int sip_options_contact_add_task(void *obj)
Task which adds a dynamic contact to an AOR.

◆ 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 2094 of file pjsip_options.c.

References ao2_cleanup, ao2_container_count(), ao2_link, ao2_ref, sip_options_contact_observer_task_data::aor_options, 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, sip_options_contact_observer_task_data::contact, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, LOG_ERROR, NULL, sip_options_aor::sched_task, sip_options_aor::serializer, sip_options_notify_endpoint_state_compositors(), and sip_options_qualify_aor().

Referenced by sip_options_contact_add_management_task().

2095 {
2097  struct ast_sip_contact_status *contact_status;
2098 
2099  ao2_link(task_data->aor_options->dynamic_contacts, task_data->contact);
2100  ao2_link(task_data->aor_options->contacts, task_data->contact);
2101 
2102  contact_status = ast_res_pjsip_find_or_create_contact_status(task_data->contact);
2103  ao2_cleanup(contact_status);
2104 
2105  if (task_data->aor_options->qualify_frequency) {
2106  /* There will always be a contact here, and we need to immediately schedule
2107  * a qualify so that contacts are not waiting for the qualify_frequency
2108  * timer duration before qualifying.
2109  */
2110  ast_debug(3, "Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2111  task_data->aor_options->name);
2112  /*
2113  * We immediately schedule the initial qualify so that we get
2114  * reachable/unreachable as soon as possible. Realistically
2115  * since they pretty much just registered they should be
2116  * reachable.
2117  */
2118  if (task_data->aor_options->sched_task) {
2120  ao2_ref(task_data->aor_options->sched_task, -1);
2121  task_data->aor_options->sched_task = NULL;
2122  }
2126  task_data->aor_options,
2128  if (!task_data->aor_options->sched_task) {
2129  ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
2130  task_data->aor_options->name);
2131  }
2132  } else {
2133  /*
2134  * If this was the first contact added to a non-qualified AOR then
2135  * it should become available.
2136  */
2137  task_data->aor_options->available =
2139  if (task_data->aor_options->available == 1) {
2140  ast_debug(3, "An unqualified contact has been added to AOR '%s' so it is now available\n",
2141  task_data->aor_options->name);
2143  AVAILABLE);
2144  }
2145  }
2146 
2147  return 0;
2148 }
A contact&#39;s status.
Definition: res_pjsip.h:341
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
#define NULL
Definition: resample.c:96
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
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.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Task details for adding an AOR to an endpoint state compositor.
struct ast_sip_contact * contact
The contact itself.
#define LOG_ERROR
Definition: logger.h:285
struct ast_taskprocessor * serializer
The serializer for this AOR.
userdata associated with baseline taskprocessor test
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ao2_container * contacts
All contacts associated with this AOR.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
#define ao2_link(container, obj)
Definition: astobj2.h:1549
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.

◆ 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 828 of file pjsip_options.c.

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().

830 {
831  struct sip_options_contact_callback_data *contact_callback_data;
832 
833  contact_callback_data = ao2_alloc_options(sizeof(*contact_callback_data),
835  if (!contact_callback_data) {
836  return NULL;
837  }
838 
839  contact_callback_data->contact = ao2_bump(contact);
840  contact_callback_data->aor_options = ao2_bump(aor_options);
841  contact_callback_data->rtt_start = ast_tvnow();
842 
843  return contact_callback_data;
844 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
struct ast_sip_contact * contact
The contact we qualified.
#define ao2_bump(obj)
Definition: astobj2.h:491
static void sip_options_contact_callback_data_dtor(void *obj)
Destructor for contact callback data.
Structure used to contain information for an OPTIONS callback.
struct timeval rtt_start
The time at which this OPTIONS attempt was started.
struct sip_options_aor * aor_options
The AOR options.

◆ 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 819 of file pjsip_options.c.

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().

820 {
821  struct sip_options_contact_callback_data *contact_callback_data = obj;
822 
823  ao2_cleanup(contact_callback_data->contact);
824  ao2_cleanup(contact_callback_data->aor_options);
825 }
struct ast_sip_contact * contact
The contact we qualified.
Structure used to contain information for an OPTIONS callback.
struct sip_options_aor * aor_options
The AOR options.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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 2313 of file pjsip_options.c.

References ao2_find, ao2_ref, ast_sip_contact::aor, sip_options_contact_observer_task_data::aor_options, ast_sip_push_task_wait_serializer(), sip_options_contact_observer_task_data::contact, OBJ_SEARCH_KEY, sip_options_aor::serializer, and sip_options_contact_delete_task().

Referenced by contact_observer_deleted().

2314 {
2316 
2317  task_data.contact = obj;
2318  task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2319  OBJ_SEARCH_KEY);
2320  if (!task_data.aor_options) {
2321  /* For contacts that are deleted we don't really care if there is no AOR locally */
2322  return 0;
2323  }
2324 
2325  ast_sip_push_task_wait_serializer(task_data.aor_options->serializer,
2327  ao2_ref(task_data.aor_options, -1);
2328 
2329  return 0;
2330 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Task details for adding an AOR to an endpoint state compositor.
userdata associated with baseline taskprocessor test
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int sip_options_contact_delete_task(void *obj)
Task which deletes a dynamic contact from an AOR.
static struct ao2_container * sip_options_aors

◆ 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 2273 of file pjsip_options.c.

References ao2_container_count(), ao2_find, ao2_ref, sip_options_contact_observer_task_data::aor_options, ast_debug, ast_sip_sched_task_cancel(), sip_options_contact_observer_task_data::contact, sip_options_aor::contacts, sip_options_aor::dynamic_contacts, NULL, OBJ_NODATA, OBJ_SEARCH_OBJECT, OBJ_UNLINK, sip_options_aor::sched_task, sip_options_notify_endpoint_state_compositors(), sip_options_remove_contact_status(), and UNAVAILABLE.

Referenced by sip_options_contact_delete_management_task().

2274 {
2276 
2277  ao2_find(task_data->aor_options->dynamic_contacts, task_data->contact,
2279  ao2_find(task_data->aor_options->contacts, task_data->contact,
2281 
2282  sip_options_remove_contact_status(task_data->aor_options, task_data->contact);
2283 
2284  if (task_data->aor_options->qualify_frequency) {
2285  /* If this is the last contact then we need to stop the scheduled callback */
2286  if (!ao2_container_count(task_data->aor_options->contacts)) {
2287  ast_debug(3, "Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2288  task_data->aor_options->name);
2289  if (task_data->aor_options->sched_task) {
2291  ao2_ref(task_data->aor_options->sched_task, -1);
2292  task_data->aor_options->sched_task = NULL;
2293  }
2294  }
2295  } else {
2296  task_data->aor_options->available =
2298  if (!task_data->aor_options->available) {
2299  ast_debug(3, "An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2300  task_data->aor_options->name);
2302  UNAVAILABLE);
2303  }
2304  }
2305 
2306  return 0;
2307 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
#define NULL
Definition: resample.c:96
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static void sip_options_remove_contact_status(struct sip_options_aor *aor_options, struct ast_sip_contact *contact)
Remove contact status for a hint.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Task details for adding an AOR to an endpoint state compositor.
struct ast_sip_contact * contact
The contact itself.
userdata associated with baseline taskprocessor test
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
struct ao2_container * contacts
All contacts associated with this AOR.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.

◆ 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 1208 of file pjsip_options.c.

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

Referenced by sip_options_apply_aor_configuration().

1209 {
1210  struct ast_sip_contact *contact = obj;
1211  unsigned int *available = arg;
1212  struct ast_sip_contact_status *contact_status;
1213 
1214  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1215  if (!contact_status) {
1216  return 0;
1217  }
1218 
1219  /* Count qualified available contacts. */
1220  switch (contact_status->status) {
1221  case AVAILABLE:
1222  ++*available;
1223  break;
1224  case UNAVAILABLE:
1225  case UNKNOWN:
1226  case CREATED:
1227  case REMOVED:
1228  break;
1229  }
1230 
1231  ao2_ref(contact_status, -1);
1232 
1233  return 0;
1234 }
A contact&#39;s status.
Definition: res_pjsip.h:341
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
Contact associated with an address of record.
Definition: res_pjsip.h:281
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13068

◆ 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 661 of file pjsip_options.c.

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_contact_callback_data::contact, sip_options_aor::contacts, ast_sip_contact_status::last_status, ast_sip_contact_status::name, OBJ_SEARCH_KEY, OBJ_SEARCH_OBJECT, ast_sip_contact_status::rtt, sip_options_contact_callback_data::rtt_start, sip_contact_status_copy(), sip_options_contact_status_update(), 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().

662 {
663  struct sip_options_contact_callback_data *contact_callback_data = obj;
664  struct ast_sip_contact *contact;
665  struct ast_sip_contact_status *cs_old;
666  struct ast_sip_contact_status *cs_new;
667 
668  /*
669  * Determine if this is a late arriving notification, as it is
670  * possible that we get a callback from PJSIP giving us contact
671  * status but in the mean time said contact has been removed
672  * from the controlling AOR.
673  */
674 
675  if (!contact_callback_data->aor_options->qualify_frequency) {
676  /* Contact qualify response is late */
677  ao2_ref(contact_callback_data, -1);
678  return 0;
679  }
680 
681  contact = ao2_find(contact_callback_data->aor_options->contacts,
682  contact_callback_data->contact, OBJ_SEARCH_OBJECT);
683  if (!contact) {
684  /* Contact qualify response is late */
685  ao2_ref(contact_callback_data, -1);
686  return 0;
687  }
688  ao2_ref(contact, -1);
689 
691  ast_sorcery_object_get_id(contact_callback_data->contact), OBJ_SEARCH_KEY);
692  if (!cs_old) {
693  /* Contact qualify response is late */
694  ao2_ref(contact_callback_data, -1);
695  return 0;
696  }
697 
698  /* Update the contact specific status information */
699  cs_new = sip_contact_status_copy(cs_old);
700  ao2_ref(cs_old, -1);
701  if (!cs_new) {
702  ao2_ref(contact_callback_data, -1);
703  return 0;
704  }
705  cs_new->last_status = cs_new->status;
706  cs_new->status = contact_callback_data->status;
707  cs_new->rtt =
708  cs_new->status == AVAILABLE
709  ? ast_tvdiff_us(ast_tvnow(), contact_callback_data->rtt_start)
710  : 0;
712 
713  /*
714  * If the status has changed then notify the endpoint state compositors
715  * and publish our events.
716  */
717  if (cs_new->last_status != cs_new->status) {
718  if (cs_new->status == AVAILABLE) {
719  /* If this is the first available contact then the AOR has become available */
720  ++contact_callback_data->aor_options->available;
721  if (contact_callback_data->aor_options->available == 1) {
723  contact_callback_data->aor_options, AVAILABLE);
724  }
725  } else if (cs_new->last_status == AVAILABLE) {
726  ast_assert(cs_new->status == UNAVAILABLE);
727 
728  /* If there are no more available contacts then this AOR is unavailable */
729  --contact_callback_data->aor_options->available;
730  if (!contact_callback_data->aor_options->available) {
732  contact_callback_data->aor_options, UNAVAILABLE);
733  }
734  }
735 
736  ast_verb(3, "Contact %s/%s is now %s. RTT: %.3f msec\n",
737  cs_new->aor,
738  cs_new->uri,
740  cs_new->rtt / 1000.0);
741 
742  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
743  "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
744  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
745  "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
746 
748 
749  ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
750  "Contact: %s\r\n"
751  "Status: %s",
752  cs_new->name,
754  } else {
755  ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
756  cs_new->aor,
757  cs_new->uri,
759  cs_new->rtt / 1000.0);
760  }
761 
762  ast_statsd_log_full_va("PJSIP.contacts.%s.rtt", AST_STATSD_TIMER,
763  cs_new->status != AVAILABLE ? -1 : cs_new->rtt / 1000,
764  1.0,
765  cs_new->name);
766 
767  ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
768  "Contact: %s\r\n"
769  "Status: %s\r\n"
770  "RTT: %" PRId64,
771  cs_new->name,
773  cs_new->rtt);
774 
775  ast_debug(3, "AOR '%s' now has %d available contacts\n",
776  contact_callback_data->aor_options->name,
777  contact_callback_data->aor_options->available);
778 
779  ao2_ref(cs_new, -1);
780  ao2_ref(contact_callback_data, -1);
781 
782  return 0;
783 }
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
enum ast_sip_contact_status_type last_status
Definition: res_pjsip.h:353
A contact&#39;s status.
Definition: res_pjsip.h:341
static struct ao2_container * sip_options_contact_statuses
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:710
const ast_string_field uri
Definition: res_pjsip.h:347
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_sip_contact * contact
The contact we qualified.
enum ast_sip_contact_status_type status
The new status of the contact.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
Structure used to contain information for an OPTIONS callback.
static struct ast_sip_contact_status * sip_contact_status_copy(const struct ast_sip_contact_status *src)
struct timeval rtt_start
The time at which this OPTIONS attempt was started.
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.
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct sip_options_aor * aor_options
The AOR options.
#define AST_STATSD_TIMER
Definition: statsd.h:41
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
struct ao2_container * contacts
All contacts associated with this AOR.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
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
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
const ast_string_field aor
Definition: res_pjsip.h:347
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ sip_options_contact_status_update()

static void sip_options_contact_status_update ( struct ast_sip_contact_status contact_status)
static

Definition at line 449 of file pjsip_options.c.

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().

450 {
451  struct ast_taskprocessor *mgmt_serializer = management_serializer;
452 
453  if (mgmt_serializer) {
454  ao2_ref(contact_status, +1);
456  contact_status)) {
457  ao2_ref(contact_status, -1);
458  }
459  }
460 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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:5138
static struct ast_taskprocessor * management_serializer
static int contact_status_publish_update_task(void *obj)
Task to notify endpoints of a contact status change.
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69

◆ 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 403 of file pjsip_options.c.

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().

404 {
405  /*
406  * Replace duplicate objects so we can update the immutable
407  * contact status objects by simply linking in a new object.
408  */
411  ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
412  ast_sip_contact_status_cmp_fn);
413 }
#define CONTACT_STATUS_BUCKETS
These are the number of contact status buckets.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
Replace objects with duplicate keys in container.
Definition: astobj2.h:1215

◆ 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 2197 of file pjsip_options.c.

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

Referenced by contact_observer_updated().

2198 {
2200  struct ast_sip_contact_status *contact_status;
2201 
2202  contact_status = ast_sip_get_contact_status(task_data->contact);
2203  if (contact_status) {
2204  switch (contact_status->status) {
2205  case CREATED:
2206  case UNAVAILABLE:
2207  case AVAILABLE:
2208  case UNKNOWN:
2209  /* Refresh the ContactStatus AMI events. */
2210  sip_options_contact_status_update(contact_status);
2211  break;
2212  case REMOVED:
2213  break;
2214  }
2215  ao2_ref(contact_status, -1);
2216  }
2217 
2218  ao2_ref(task_data->contact, -1);
2219  ao2_ref(task_data->aor_options, -1);
2220  ast_free(task_data);
2221  return 0;
2222 }
A contact&#39;s status.
Definition: res_pjsip.h:341
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Task details for adding an AOR to an endpoint state compositor.
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
struct ast_sip_contact * contact
The contact itself.
userdata associated with baseline taskprocessor test
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
#define ast_free(a)
Definition: astmm.h:182
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)

◆ 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 1094 of file pjsip_options.c.

References ast_random_double, and ast_sip_get_max_initial_qualify_time().

Referenced by sip_options_apply_aor_configuration().

1095 {
1096  int initial_interval;
1097  int max_time = ast_sip_get_max_initial_qualify_time();
1098 
1099  if (max_time && max_time < qualify_frequency) {
1100  initial_interval = max_time;
1101  } else {
1102  initial_interval = qualify_frequency;
1103  }
1104 
1105  initial_interval = (int)((initial_interval * 1000) * ast_random_double());
1106  return 0 < initial_interval ? initial_interval : 1;
1107 }
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:599

◆ 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 1527 of file pjsip_options.c.

References ao2_lock, ao2_ref, ao2_unlock, sip_options_endpoint_compositor_task_data::aor_options, ast_debug, AST_VECTOR_APPEND, AVAILABLE, sip_options_endpoint_compositor_task_data::endpoint_state_compositor, sip_options_endpoint_state_compositor::name, sip_options_update_endpoint_state_compositor_aor(), and UNAVAILABLE.

Referenced by sip_options_synchronize_endpoint().

1528 {
1530 
1531  ast_debug(3, "Adding endpoint compositor '%s' to AOR '%s'\n",
1532  task_data->endpoint_state_compositor->name, task_data->aor_options->name);
1533 
1534  ao2_ref(task_data->endpoint_state_compositor, +1);
1535  if (AST_VECTOR_APPEND(&task_data->aor_options->compositors,
1536  task_data->endpoint_state_compositor)) {
1537  /* Failed to add so no need to update the endpoint status. Nothing changed. */
1538  ao2_ref(task_data->endpoint_state_compositor, -1);
1539  return 0;
1540  }
1541 
1542  ao2_lock(task_data->endpoint_state_compositor);
1544  task_data->aor_options->name,
1545  task_data->aor_options->available ? AVAILABLE : UNAVAILABLE);
1547 
1548  return 0;
1549 }
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
char name[0]
The name of the endpoint.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
userdata associated with baseline taskprocessor test
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.

◆ 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 1555 of file pjsip_options.c.

References ao2_ref, sip_options_endpoint_compositor_task_data::aor_options, ast_debug, AST_VECTOR_GET, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, sip_options_endpoint_compositor_task_data::endpoint_state_compositor, and sip_options_endpoint_state_compositor::name.

Referenced by sip_options_endpoint_unlink_aor_feeders().

1556 {
1558  int i;
1559 
1560  ast_debug(3, "Removing endpoint compositor '%s' from AOR '%s'\n",
1561  task_data->endpoint_state_compositor->name,
1562  task_data->aor_options->name);
1563 
1564  for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1565  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1566 
1567  endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1568  if (endpoint_state_compositor != task_data->endpoint_state_compositor) {
1569  continue;
1570  }
1571 
1572  AST_VECTOR_REMOVE(&task_data->aor_options->compositors, i, 0);
1573  ao2_ref(endpoint_state_compositor, -1);
1574  break;
1575  }
1576 
1577  return 0;
1578 }
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
Structure which contains composites information for endpoint state.
char name[0]
The name of the endpoint.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
userdata associated with baseline taskprocessor test
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
Task details for adding an AOR to an endpoint state compositor.

◆ 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 1863 of file pjsip_options.c.

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

Referenced by endpoint_observer_deleted().

1864 {
1865  struct ast_sip_endpoint *endpoint = obj;
1866  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1867 
1868  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1870  if (!endpoint_state_compositor) {
1871  return 0;
1872  }
1873 
1874  ast_debug(3, "Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1875  ast_sorcery_object_get_id(endpoint));
1876  sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1877  ao2_ref(endpoint_state_compositor, -1);
1878 
1879  return 0;
1880 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Structure which contains composites information for endpoint state.
static void sip_options_endpoint_unlink_aor_feeders(struct ast_sip_endpoint *endpoint, struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Unlink AORs feeding the endpoint status compositor.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static struct ao2_container * sip_options_endpoint_state_compositors
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ 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 1893 of file pjsip_options.c.

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

Referenced by endpoint_observer_modified().

1894 {
1895  struct ast_sip_endpoint *endpoint = obj;
1896  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1897 
1898  ast_debug(3, "Endpoint '%s' has been created or modified, updating state\n",
1899  ast_sorcery_object_get_id(endpoint));
1900 
1901  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1903  if (endpoint_state_compositor) {
1904  /* Unlink the AORs currently feeding the endpoint. */
1905  sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1906  ao2_ref(endpoint_state_compositor, -1);
1907  }
1908 
1909  /* Connect the AORs that now feed the endpoint. */
1910  sip_options_synchronize_endpoint(endpoint, NULL, 0);
1911  return 0;
1912 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Structure which contains composites information for endpoint state.
static void sip_options_endpoint_unlink_aor_feeders(struct ast_sip_endpoint *endpoint, struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Unlink AORs feeding the endpoint status compositor.
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ao2_container * sip_options_endpoint_state_compositors
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
Synchronize an endpoint with our local state.

◆ 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 1458 of file pjsip_options.c.

References ao2_cleanup, AO2_STRING_FIELD_CMP_FN(), AO2_STRING_FIELD_HASH_FN(), sip_options_endpoint_state_compositor::aor_statuses, and sip_options_endpoint_aor_status::name.

Referenced by sip_options_endpoint_state_compositor_find_or_alloc().

1459 {
1460  struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1461 
1462  ao2_cleanup(endpoint_state_compositor->aor_statuses);
1463 }
Structure which contains composites information for endpoint state.
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ 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 1472 of file pjsip_options.c.

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, and sip_options_endpoint_state_compositor_dtor().

Referenced by sip_options_synchronize_endpoint().

1473 {
1474  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1475 
1477  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1479  if (endpoint_state_compositor) {
1481  return endpoint_state_compositor;
1482  }
1483 
1484  endpoint_state_compositor = ao2_alloc(sizeof(*endpoint_state_compositor)
1485  + strlen(ast_sorcery_object_get_id(endpoint)) + 1,
1487  if (!endpoint_state_compositor) {
1489  return NULL;
1490  }
1491 
1492  /*
1493  * NOTE: The endpoint_state_compositor->aor_statuses container is
1494  * externally protected by the endpoint_state_compositor lock.
1495  */
1496  endpoint_state_compositor->aor_statuses = ao2_container_alloc_hash(
1498  sip_options_endpoint_aor_status_hash_fn, NULL,
1499  sip_options_endpoint_aor_status_cmp_fn);
1500  if (!endpoint_state_compositor->aor_statuses) {
1502  ao2_ref(endpoint_state_compositor, -1);
1503  return NULL;
1504  }
1505 
1506  strcpy(endpoint_state_compositor->name, ast_sorcery_object_get_id(endpoint)); /* SAFE */
1507 
1508  ao2_link_flags(sip_options_endpoint_state_compositors, endpoint_state_compositor,
1509  OBJ_NOLOCK);
1511 
1512  return endpoint_state_compositor;
1513 }
static void sip_options_endpoint_state_compositor_dtor(void *obj)
Destructor for endpoint state compositors.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Structure which contains composites information for endpoint state.
char name[0]
The name of the endpoint.
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static struct ao2_container * sip_options_endpoint_state_compositors
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define AOR_STATUS_BUCKETS
These are the number of buckets (per endpoint state compositor) to use to store AOR statuses...

◆ 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 1819 of file pjsip_options.c.

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_compositor_task_data::aor_options, 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_aor::serializer, and sip_options_endpoint_compositor_remove_task().

Referenced by sip_options_endpoint_observer_deleted_task(), and sip_options_endpoint_observer_modified_task().

1821 {
1822  struct ao2_iterator it_aor_statuses;
1823  struct sip_options_endpoint_aor_status *aor_status;
1825  .endpoint_state_compositor = endpoint_state_compositor,
1826  };
1827 
1828  ao2_lock(endpoint_state_compositor);
1829  endpoint_state_compositor->active = 0;
1830 
1831  /* Unlink AOR feeders pointing to endpoint */
1832  it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
1833  for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
1834  task_data.aor_options = ao2_find(sip_options_aors, aor_status->name,
1835  OBJ_SEARCH_KEY);
1836  if (!task_data.aor_options) {
1837  continue;
1838  }
1839 
1840  ast_debug(3, "Removing endpoint state compositor '%s' from AOR '%s'\n",
1841  ast_sorcery_object_get_id(endpoint), aor_status->name);
1842  ao2_unlock(endpoint_state_compositor);
1845  ao2_lock(endpoint_state_compositor);
1846  ao2_ref(task_data.aor_options, -1);
1847  }
1848  ao2_iterator_destroy(&it_aor_statuses);
1849 
1850  /*
1851  * We do not need to remove the AOR feeder status memory from the
1852  * aor_statuses container. The endpoint_state_compositor is about
1853  * to die and do it for us.
1854  */
1855 
1856  ao2_unlock(endpoint_state_compositor);
1857 }
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
Structure which contains status information for an AOR feeding an endpoint state compositor.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
struct ast_taskprocessor * serializer
The serializer for this AOR.
userdata associated with baseline taskprocessor test
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
char name[0]
The name of the AOR.
char active
Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static struct ao2_container * sip_options_aors
static int sip_options_endpoint_compositor_remove_task(void *obj)
Task which adds removes an AOR from an endpoint state compositor.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
Task details for adding an AOR to an endpoint state compositor.

◆ 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 557 of file pjsip_options.c.

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().

559 {
560  struct ao2_iterator it_aor_statuses;
561  struct sip_options_endpoint_aor_status *aor_status;
563 
564  it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
565  for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
566  if (aor_status->available) {
567  state = AST_ENDPOINT_ONLINE;
568  ao2_ref(aor_status, -1);
569  break;
570  }
571  }
572  ao2_iterator_destroy(&it_aor_statuses);
573 
574  return state;
575 }
enum sip_cc_notify_state state
Definition: chan_sip.c:963
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
ast_endpoint_state
Valid states for an endpoint.
Definition: endpoints.h:51
Structure which contains status information for an AOR feeding an endpoint state compositor.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char available
The last contributed available status of the named AOR (1 if available, 0 if not available) ...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ 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 2885 of file pjsip_options.c.

References ast_serializer_shutdown_group_alloc(), ast_sip_get_sorcery(), ast_sorcery_observer_add(), and sip_options_synchronize().

Referenced by ast_res_pjsip_init_options_handling().

2886 {
2887  management_serializer = mgmt_serializer;
2888 
2890  if (!shutdown_group) {
2891  return -1;
2892  }
2893 
2896  return -1;
2897  }
2900  return -1;
2901  }
2904  return -1;
2905  }
2906 
2908 
2909  return 0;
2910 }
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229
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
static struct ast_taskprocessor * management_serializer
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.

◆ 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 635 of file pjsip_options.c.

References ao2_cleanup, ao2_lock, ao2_unlock, AST_VECTOR_GET, AST_VECTOR_RESET, AST_VECTOR_SIZE, REMOVED, and sip_options_update_endpoint_state_compositor_aor().

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().

637 {
638  int i;
639 
640  /* Iterate through the associated endpoint state compositors updating them */
641  for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
642  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
643 
644  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
645 
646  ao2_lock(endpoint_state_compositor);
647  sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
648  aor_options->name, status);
649  ao2_unlock(endpoint_state_compositor);
650  }
651 
652  if (status == REMOVED) {
653  AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
654  }
655 }
Structure which contains composites information for endpoint state.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_lock(a)
Definition: astobj2.h:718
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
jack_status_t status
Definition: app_jack.c:146
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.

◆ 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 416 of file pjsip_options.c.

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

Referenced by contact_status_publish_update_task().

418 {
419  int i;
420 
421  for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
422  const struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
423 
424  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
425  ast_sip_persistent_endpoint_publish_contact_state(endpoint_state_compositor->name,
426  contact_status);
427  }
428 }
Structure which contains composites information for endpoint state.
char name[0]
The name of the endpoint.
void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
Publish the change of state for a contact.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ 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 923 of file pjsip_options.c.

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

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

924 {
925  struct sip_options_aor *aor_options = obj;
926 
927  ast_debug(3, "Qualifying all contacts on AOR '%s'\n", aor_options->name);
928 
929  /* Attempt to send an OPTIONS request to every contact on this AOR */
931  (struct sip_options_aor *) aor_options);
932 
933  /* Always reschedule to the frequency we should go */
934  return aor_options->qualify_frequency * 1000;
935 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
Structure which contains an AOR and contacts for qualifying purposes.
struct ao2_container * contacts
All contacts associated with this AOR.
static int sip_options_qualify_contact(void *obj, void *arg, int flags)
Send a SIP OPTIONS request for a contact.

◆ 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 847 of file pjsip_options.c.

References ao2_cleanup, ao2_ref, 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, ast_sip_contact::endpoint_name, LOG_ERROR, sip_options_endpoint_state_compositor::name, NULL, ast_sip_contact::outbound_proxy, qualify_contact_cb(), RAII_VAR, sip_options_contact_callback_data_alloc(), and ast_sip_contact::uri.

Referenced by sip_options_qualify_aor().

848 {
849  struct ast_sip_contact *contact = obj;
850  struct sip_options_aor *aor_options = arg;
851  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
852  pjsip_tx_data *tdata;
853  struct ast_sip_contact_status *contact_status;
854  struct sip_options_contact_callback_data *contact_callback_data;
855 
856  ast_debug(3, "Qualifying contact '%s' on AOR '%s'\n",
857  ast_sorcery_object_get_id(contact), aor_options->name);
858 
859  if (!ast_strlen_zero(contact->endpoint_name)) {
860  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
861  contact->endpoint_name);
862  }
863  if (!endpoint && AST_VECTOR_SIZE(&aor_options->compositors)) {
864  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
865 
866  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, 0);
867  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
868  endpoint_state_compositor->name);
869  }
870  if (!endpoint) {
871  ast_debug(3, "Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
872  ast_sorcery_object_get_id(contact), aor_options->name);
873  return 0;
874  }
875 
876  if (ast_sip_create_request("OPTIONS", NULL, endpoint, NULL, contact, &tdata)) {
877  ast_log(LOG_ERROR, "Unable to create request to qualify contact %s on AOR %s\n",
878  contact->uri, aor_options->name);
879  return 0;
880  }
881 
882  /* If an outbound proxy is specified set it on this request */
883  if (!ast_strlen_zero(contact->outbound_proxy) &&
884  ast_sip_set_outbound_proxy(tdata, contact->outbound_proxy)) {
885  ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
886  contact->uri);
887  pjsip_tx_data_dec_ref(tdata);
888  return 0;
889  }
890 
891  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
892  if (!contact_status) {
893  ast_log(LOG_ERROR, "Unable to retrieve contact status information for contact %s on AOR %s\n",
894  contact->uri, aor_options->name);
895  pjsip_tx_data_dec_ref(tdata);
896  return 0;
897  }
898  ao2_ref(contact_status, -1);
899 
900  contact_callback_data = sip_options_contact_callback_data_alloc(contact, aor_options);
901  if (!contact_callback_data) {
902  ast_log(LOG_ERROR, "Unable to create object to contain callback data for contact %s on AOR %s\n",
903  contact->uri, aor_options->name);
904  pjsip_tx_data_dec_ref(tdata);
905  return 0;
906  }
907 
908  if (ast_sip_send_out_of_dialog_request(tdata, endpoint,
909  (int)(aor_options->qualify_timeout * 1000), contact_callback_data,
911  ast_log(LOG_ERROR, "Unable to send request to qualify contact %s on AOR %s\n",
912  contact->uri, aor_options->name);
913  ao2_ref(contact_callback_data, -1);
914  }
915 
916  return 0;
917 }
A contact&#39;s status.
Definition: res_pjsip.h:341
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.
const ast_string_field outbound_proxy
Definition: res_pjsip.h:303
static void qualify_contact_cb(void *token, pjsip_event *e)
Callback for when we get a result from a SIP OPTIONS request (a response or a timeout) ...
Structure which contains composites information for endpoint state.
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
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:5047
char name[0]
The name of the endpoint.
#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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: