Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
res_pjsip_outbound_registration.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_cli.h"
#include "asterisk/module.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/cli.h"
#include "asterisk/stasis_system.h"
#include "asterisk/threadstorage.h"
#include "asterisk/threadpool.h"
#include "asterisk/statsd.h"
#include "res_pjsip/include/res_pjsip_private.h"
#include "asterisk/vector.h"
#include "asterisk/pbx.h"
Include dependency graph for res_pjsip_outbound_registration.c:

Go to the source code of this file.

Data Structures

struct  pjsip_generic_string_hdr_vector
 
struct  registration_response
 Structure for registration response. More...
 
struct  sip_ami_outbound
 
struct  sip_outbound_registration
 Outbound registration information. More...
 
struct  sip_outbound_registration_client_state
 Outbound registration client state information (persists for lifetime of regc) More...
 
struct  sip_outbound_registration_state
 Outbound registration state information (persists for lifetime that registration should exist) More...
 

Macros

#define DEFAULT_STATE_BUCKETS   53
 Default number of state container buckets.
 
#define LINE_PARAMETER_SIZE   8
 Size of the buffer for creating a unique string for the line.
 
#define MAX_UNLOAD_TIMEOUT_TIME   35 /* Seconds */
 
#define REGISTRATION_URI_FIELD_LEN   53
 
#define REREGISTER_BUFFER_TIME   10
 Amount of buffer time (in seconds) before expiration that we re-register at.
 

Enumerations

enum  sip_outbound_registration_status {
  SIP_REGISTRATION_UNREGISTERED = 0 , SIP_REGISTRATION_REGISTERED , SIP_REGISTRATION_REJECTED_TEMPORARY , SIP_REGISTRATION_REJECTED_PERMANENT ,
  SIP_REGISTRATION_STOPPING , SIP_REGISTRATION_STOPPED
}
 Various states that an outbound registration may be in. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_configured_supported_headers (struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
 Helper function to add configured supported headers.
 
static void add_security_headers (struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
 Adds security negotiation mechanisms of outbound registration client state as Security headers to tdata.
 
static int add_to_supported_header (pjsip_tx_data *tdata, pj_str_t *name)
 Helper function to add string to Supported header.
 
static int ami_outbound_registration_detail (void *obj, void *arg, int flags)
 
static int ami_outbound_registration_task (void *obj)
 
static int ami_register (struct mansession *s, const struct message *m)
 
static int ami_show_outbound_registrations (struct mansession *s, const struct message *m)
 
static int ami_unregister (struct mansession *s, const struct message *m)
 
static AO2_GLOBAL_OBJ_STATIC (current_states)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (register_callback_invoked, NULL, ast_free_ptr, static)
 Some thread local storage used to determine if the running thread invoked the callback.
 
static void auth_observer (const char *type)
 
static int can_reuse_registration (struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
 
static void cancel_registration (struct sip_outbound_registration_client_state *client_state)
 Helper function which cancels the timer on a client.
 
static int check_state (void *obj, void *arg, int flags)
 
static char * cli_complete_registration (const char *line, const char *word, int pos, int state)
 
static struct ao2_containercli_get_container (const char *regex)
 
static int cli_iterator (void *container, ao2_callback_fn callback, void *args)
 
static int cli_print_body (void *obj, void *arg, int flags)
 
static int cli_print_header (void *obj, void *arg, int flags)
 
static char * cli_register (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void * cli_retrieve_by_id (const char *id)
 
static char * cli_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int contact_add_security_headers_to_status (void *obj, void *arg, int flags)
 
static int contact_has_security_mechanisms (void *obj, void *arg, int flags)
 
static const char * fetch_google_access_token (const struct ast_sip_auth *auth)
 Get google oauth2 access token using refresh token.
 
static struct ao2_containerget_registrations (void)
 
static struct sip_outbound_registration_stateget_state (const char *id)
 
static struct pjsip_param * get_uri_option_line (const void *uri)
 
static int handle_client_registration (void *data)
 Callback function for registering.
 
static int handle_client_state_destruction (void *data)
 Callback function for unregistering (potentially) and destroying state.
 
static int handle_registration_response (void *data)
 Callback function for handling a response to a registration attempt.
 
static struct ast_sip_endpointline_identify (pjsip_rx_data *rdata)
 Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration.
 
static int line_identify_relationship (void *obj, void *arg, int flags)
 Callback function for matching an outbound registration based on line.
 
static int load_module (void)
 
static int monitor_matcher (void *a, void *b)
 
static char * my_cli_traverse_objects (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void network_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int outbound_auth_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int outbound_auths_to_str (const void *obj, const intptr_t *args, char **buf)
 
static int outbound_auths_to_var_list (const void *obj, struct ast_variable **fields)
 
static int queue_register (struct sip_outbound_registration_state *state)
 
static int queue_unregister (struct sip_outbound_registration_state *state)
 
static pj_status_t registration_client_send (struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
 Helper function which sends a message and cleans up, if needed, on failure.
 
static void registration_deleted_observer (const void *obj)
 
static void registration_loaded_observer (const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
 
static void registration_response_destroy (void *obj)
 Registration response structure destructor.
 
static int registration_state_cmp (void *obj, void *arg, int flags)
 comparator function for state objects
 
static int registration_state_hash (const void *obj, const int flags)
 hashing function for state objects
 
static void registration_transport_monitor_setup (const char *transport_key, const char *registration_name)
 
static void registration_transport_shutdown_cb (void *obj)
 
static int reload_module (void)
 
static void reregister_all (void)
 
static int reregister_immediately_cb (void *obj)
 
static void save_response_fields_to_transport (struct registration_response *response)
 
static void schedule_registration (struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
 Helper function which sets up the timer to re-register in a specific amount of time.
 
static void schedule_retry (struct registration_response *response, unsigned int interval, const char *server_uri, const char *client_uri)
 
static int security_mechanism_to_str (const void *obj, const intptr_t *args, char **buf)
 
static int security_mechanisms_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int security_negotiation_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int security_negotiation_to_str (const void *obj, const intptr_t *args, char **buf)
 
static int set_outbound_initial_authentication_credentials (pjsip_regc *regc, const struct ast_sip_auth_vector *auth_vector)
 
static int sip_dialog_create_contact (pj_pool_t *pool, pj_str_t *contact, const char *user, const pj_str_t *target, pjsip_tpselector *selector, const char *line, const char *header_params)
 Helper function which populates a pj_str_t with a contact header.
 
static void * sip_outbound_registration_alloc (const char *name)
 Allocator function for registration information.
 
static int sip_outbound_registration_apply (const struct ast_sorcery *sorcery, void *obj)
 Apply function which finds or allocates a state structure.
 
static void sip_outbound_registration_client_state_destroy (void *obj)
 Destructor function for client registration state.
 
static void sip_outbound_registration_destroy (void *obj)
 Destructor function for registration information.
 
static int sip_outbound_registration_is_temporal (unsigned int code, struct sip_outbound_registration_client_state *client_state)
 Helper function which determines if a response code is temporal or not.
 
static int sip_outbound_registration_perform (void *data)
 Helper function which performs a single registration.
 
static int sip_outbound_registration_regc_alloc (void *data)
 Helper function that allocates a pjsip registration client and configures it.
 
static void sip_outbound_registration_response_cb (struct pjsip_regc_cbparam *param)
 Callback function for outbound registration client.
 
static struct sip_outbound_registration_statesip_outbound_registration_state_alloc (struct sip_outbound_registration *registration)
 Allocator function for registration state.
 
static void sip_outbound_registration_state_destroy (void *obj)
 Destructor function for registration state.
 
static const char * sip_outbound_registration_status_str (enum sip_outbound_registration_status state)
 
static void sip_outbound_registration_timer_cb (pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
 Timer callback function, used just for registrations.
 
static int unload_module (void)
 
static void unregister_all (void)
 
static int unregister_task (void *obj)
 
static void update_client_state_status (struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Outbound Registration Support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .reload = reload_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", .optional_modules = "res_statsd", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_sip_cli_formatter_entrycli_formatter
 
static struct ast_cli_entry cli_outbound_registration []
 
static struct ast_sip_endpoint_identifier line_identifier
 
static struct stasis_subscriptionnetwork_change_sub
 
static const struct ast_sorcery_observer observer_callbacks_auth
 
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
 
static pj_str_t OUTBOUND_NAME = { "outbound", 8 }
 
static pj_str_t PATH_NAME = { "path", 4 }
 
static const struct ast_sorcery_observer registration_observer
 
static const char * security_negotiation_map []
 
static struct ast_serializer_shutdown_groupshutdown_group
 

Macro Definition Documentation

◆ DEFAULT_STATE_BUCKETS

#define DEFAULT_STATE_BUCKETS   53

Default number of state container buckets.

Definition at line 630 of file res_pjsip_outbound_registration.c.

◆ LINE_PARAMETER_SIZE

#define LINE_PARAMETER_SIZE   8

Size of the buffer for creating a unique string for the line.

Definition at line 449 of file res_pjsip_outbound_registration.c.

◆ MAX_UNLOAD_TIMEOUT_TIME

#define MAX_UNLOAD_TIMEOUT_TIME   35 /* Seconds */

Time needs to be long enough for a transaction to timeout if nothing replies.

Definition at line 624 of file res_pjsip_outbound_registration.c.

◆ REGISTRATION_URI_FIELD_LEN

#define REGISTRATION_URI_FIELD_LEN   53

◆ REREGISTER_BUFFER_TIME

#define REREGISTER_BUFFER_TIME   10

Amount of buffer time (in seconds) before expiration that we re-register at.

Definition at line 446 of file res_pjsip_outbound_registration.c.

Enumeration Type Documentation

◆ sip_outbound_registration_status

Various states that an outbound registration may be in.

Enumerator
SIP_REGISTRATION_UNREGISTERED 

Currently unregistered.

SIP_REGISTRATION_REGISTERED 

Registered, yay!

SIP_REGISTRATION_REJECTED_TEMPORARY 

Registration was rejected, but response was temporal.

SIP_REGISTRATION_REJECTED_PERMANENT 

Registration was rejected, permanently.

SIP_REGISTRATION_STOPPING 

Registration is stopping.

SIP_REGISTRATION_STOPPED 

Registration has been stopped.

Definition at line 452 of file res_pjsip_outbound_registration.c.

452 {
453 /*! \brief Currently unregistered */
455 /*! \brief Registered, yay! */
457 /*! \brief Registration was rejected, but response was temporal */
459 /*! \brief Registration was rejected, permanently */
461 /*! \brief Registration is stopping. */
463 /*! \brief Registration has been stopped */
465};
@ SIP_REGISTRATION_REGISTERED
Registered, yay!
@ SIP_REGISTRATION_REJECTED_PERMANENT
Registration was rejected, permanently.
@ SIP_REGISTRATION_STOPPED
Registration has been stopped.
@ SIP_REGISTRATION_STOPPING
Registration is stopping.
@ SIP_REGISTRATION_UNREGISTERED
Currently unregistered.
@ SIP_REGISTRATION_REJECTED_TEMPORARY
Registration was rejected, but response was temporal.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3069 of file res_pjsip_outbound_registration.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3069 of file res_pjsip_outbound_registration.c.

◆ add_configured_supported_headers()

static int add_configured_supported_headers ( struct sip_outbound_registration_client_state client_state,
pjsip_tx_data *  tdata 
)
static

Helper function to add configured supported headers.

Definition at line 1000 of file res_pjsip_outbound_registration.c.

1001{
1002 if (client_state->support_path) {
1003 if (!add_to_supported_header(tdata, &PATH_NAME)) {
1004 return 0;
1005 }
1006 }
1007
1008 if (client_state->support_outbound) {
1009 if (!add_to_supported_header(tdata, &OUTBOUND_NAME)) {
1010 return 0;
1011 }
1012 }
1013
1014 return 1;
1015}
static pj_str_t PATH_NAME
static int add_to_supported_header(pjsip_tx_data *tdata, pj_str_t *name)
Helper function to add string to Supported header.
static pj_str_t OUTBOUND_NAME
unsigned int support_outbound
Determines whether SIP Outbound support should be advertised.
unsigned int support_path
Determines whether SIP Path support should be advertised.

References add_to_supported_header(), OUTBOUND_NAME, PATH_NAME, sip_outbound_registration_client_state::support_outbound, and sip_outbound_registration_client_state::support_path.

Referenced by handle_client_registration(), handle_client_state_destruction(), and unregister_task().

◆ add_security_headers()

static void add_security_headers ( struct sip_outbound_registration_client_state client_state,
pjsip_tx_data *  tdata 
)
static

Adds security negotiation mechanisms of outbound registration client state as Security headers to tdata.

Definition at line 821 of file res_pjsip_outbound_registration.c.

823{
824 int add_sec_client_header = 0;
825 struct sip_outbound_registration *reg = NULL;
826 struct ast_sip_endpoint *endpt = NULL;
827 struct ao2_container *contact_container;
828 struct ast_sip_contact_status *contact_status = NULL;
829 struct ast_sip_security_mechanism_vector *sec_mechs = NULL;
830 static const pj_str_t security_verify = { "Security-Verify", 15 };
831 static const pj_str_t security_client = { "Security-Client", 15 };
832
834 return;
835 }
836
837 /* Get contact status through registration -> endpoint name -> aor -> contact (if set) */
838 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", client_state->registration_name))
839 && !ast_strlen_zero(reg->endpoint) && (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))
840 && (contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors))) {
841 /* Retrieve all contacts associated with aors from this endpoint
842 * and find the first one that has security mechanisms.
843 */
844 ao2_callback(contact_container, OBJ_NODATA, contact_has_security_mechanisms, &contact_status);
845 if (contact_status) {
846 ao2_lock(contact_status);
847 sec_mechs = &contact_status->security_mechanisms;
848 }
849 ao2_cleanup(contact_container);
850 }
851 /* Use client_state->server_security_mechanisms if contact_status does not exist. */
852 if (!contact_status && AST_VECTOR_SIZE(&client_state->server_security_mechanisms)) {
853 sec_mechs = &client_state->server_security_mechanisms;
854 }
855 if (client_state->status == SIP_REGISTRATION_REJECTED_TEMPORARY || client_state->auth_attempted) {
856 if (sec_mechs != NULL && pjsip_msg_find_hdr_by_name(tdata->msg, &security_verify, NULL) == NULL) {
857 ast_sip_add_security_headers(sec_mechs, "Security-Verify", 0, tdata);
858 }
859 if (client_state->last_status_code == 494) {
860 ast_sip_remove_headers_by_name_and_value(tdata->msg, &security_client, NULL);
861 } else {
862 /* necessary if a retry occures */
863 add_sec_client_header = (pjsip_msg_find_hdr_by_name(tdata->msg, &security_client, NULL) == NULL) ? 1 : 0;
864 }
865 } else {
866 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
867 }
868
869 if (add_sec_client_header) {
870 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
871 }
872
873 /* Cleanup */
874 if (contact_status) {
875 ao2_unlock(contact_status);
876 ao2_cleanup(contact_status);
877 }
878 ao2_cleanup(endpt);
879 ao2_cleanup(reg);
880}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
@ OBJ_NODATA
Definition astobj2.h:1044
struct ao2_container * ast_sip_location_retrieve_contacts_from_aor_list(const char *aor_list)
Retrieve all contacts from a list of AORs.
Definition location.c:335
void ast_sip_remove_headers_by_name_and_value(pjsip_msg *msg, const pj_str_t *hdr_name, const char *value)
Removes all headers of a specific name and value from a pjsip_msg.
@ AST_SIP_SECURITY_NEG_MEDIASEC
Definition res_pjsip.h:355
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
int ast_sip_add_security_headers(struct ast_sip_security_mechanism_vector *security_mechanisms, const char *header_name, int add_qval, pjsip_tx_data *tdata)
Add security headers to transmission data.
static int contact_has_security_mechanisms(void *obj, void *arg, int flags)
#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:1917
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Generic container type.
A contact's status.
Definition res_pjsip.h:451
struct ast_sip_security_mechanism_vector security_mechanisms
Definition res_pjsip.h:466
An entity with which Asterisk communicates.
Definition res_pjsip.h:1051
const ast_string_field aors
Definition res_pjsip.h:1080
unsigned int auth_attempted
Non-zero if we have attempted sending a REGISTER with authentication.
enum ast_sip_security_negotiation security_negotiation
Type of security negotiation to use (RFC 3329).
int last_status_code
Status code of last response if we have tried to register before.
struct ast_sip_security_mechanism_vector server_security_mechanisms
Security mechanisms of the peer (RFC 3329).
char * registration_name
The name of the registration sorcery object.
enum sip_outbound_registration_status status
Current state of this registration.
struct ast_sip_security_mechanism_vector security_mechanisms
Client security mechanisms (RFC 3329).
Outbound registration information.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620

References ao2_callback, ao2_cleanup, ao2_lock, ao2_unlock, ast_sip_endpoint::aors, ast_sip_add_security_headers(), ast_sip_get_sorcery(), ast_sip_location_retrieve_contacts_from_aor_list(), ast_sip_remove_headers_by_name_and_value(), AST_SIP_SECURITY_NEG_MEDIASEC, ast_sorcery_retrieve_by_id(), ast_strlen_zero(), AST_VECTOR_SIZE, sip_outbound_registration_client_state::auth_attempted, contact_has_security_mechanisms(), sip_outbound_registration::endpoint, sip_outbound_registration_client_state::last_status_code, NULL, OBJ_NODATA, sip_outbound_registration_client_state::registration_name, ast_sip_contact_status::security_mechanisms, sip_outbound_registration_client_state::security_mechanisms, sip_outbound_registration_client_state::security_negotiation, sip_outbound_registration_client_state::server_security_mechanisms, SIP_REGISTRATION_REJECTED_TEMPORARY, and sip_outbound_registration_client_state::status.

Referenced by registration_client_send().

◆ add_to_supported_header()

static int add_to_supported_header ( pjsip_tx_data *  tdata,
pj_str_t *  name 
)
static

Helper function to add string to Supported header.

Definition at line 965 of file res_pjsip_outbound_registration.c.

966{
967 pjsip_supported_hdr *hdr;
968 int i;
969
970 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
971 if (!hdr) {
972 /* insert a new Supported header */
973 hdr = pjsip_supported_hdr_create(tdata->pool);
974 if (!hdr) {
975 pjsip_tx_data_dec_ref(tdata);
976 return 0;
977 }
978
979 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
980 }
981
982 /* Don't add the value if it's already there */
983 for (i = 0; i < hdr->count; ++i) {
984 if (pj_stricmp(&hdr->values[i], name) == 0) {
985 return 1;
986 }
987 }
988
989 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
990 return 0;
991 }
992
993 /* add on to the existing Supported header */
994 pj_strassign(&hdr->values[hdr->count++], name);
995
996 return 1;
997}
static const char name[]
Definition format_mp3.c:68

References name, and NULL.

Referenced by add_configured_supported_headers().

◆ ami_outbound_registration_detail()

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

Definition at line 2607 of file res_pjsip_outbound_registration.c.

2608{
2609 struct sip_ami_outbound *ami = arg;
2610
2611 ami->registration = obj;
2613}
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c:2165
static int ami_outbound_registration_task(void *obj)

References sip_ami_outbound::ami, ami_outbound_registration_task(), ast_sip_push_task_wait_servant(), and NULL.

Referenced by ami_show_outbound_registrations().

◆ ami_outbound_registration_task()

static int ami_outbound_registration_task ( void *  obj)
static

Definition at line 2571 of file res_pjsip_outbound_registration.c.

2572{
2573 struct sip_ami_outbound *ami = obj;
2574 struct ast_str *buf;
2576
2577 buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
2578 if (!buf) {
2579 return -1;
2580 }
2581
2583
2585 pjsip_regc_info info;
2586
2587 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
2588 ++ami->registered;
2589 } else {
2590 ++ami->not_registered;
2591 }
2592
2593 ast_str_append(&buf, 0, "Status: %s\r\n",
2594 sip_outbound_registration_status_str(state->client_state->status));
2595
2596 pjsip_regc_get_info(state->client_state->client, &info);
2597 ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
2598 ao2_ref(state, -1);
2599 }
2600
2601 astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
2602 ast_free(buf);
2603
2605}
#define ast_free(a)
Definition astmm.h:180
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
char buf[BUFSIZE]
Definition eagi_proxy.c:66
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1903
int ast_sip_format_auths_ami(const struct ast_sip_auth_vector *auths, struct ast_sip_ami *ami)
Format auth details for AMI.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
static struct sip_outbound_registration_state * get_state(const char *id)
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
struct mansession * s
Definition res_pjsip.h:3202
Support for dynamic strings.
Definition strings.h:623
struct sip_outbound_registration * registration
Outbound registration state information (persists for lifetime that registration should exist)
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.

References sip_ami_outbound::ami, ao2_ref, ast_free, ast_sip_create_ami_event(), ast_sip_format_auths_ami(), ast_sip_sorcery_object_to_ami(), ast_sorcery_object_get_id(), ast_str_append(), ast_str_buffer(), astman_append(), buf, get_state(), sip_ami_outbound::not_registered, sip_outbound_registration::outbound_auths, sip_ami_outbound::registered, sip_ami_outbound::registration, ast_sip_ami::s, sip_outbound_registration_status_str(), and SIP_REGISTRATION_REGISTERED.

Referenced by ami_outbound_registration_detail().

◆ ami_register()

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

Definition at line 2527 of file res_pjsip_outbound_registration.c.

2528{
2529 const char *registration_name = astman_get_header(m, "Registration");
2531
2532 if (ast_strlen_zero(registration_name)) {
2533 astman_send_error(s, m, "Registration parameter missing.");
2534 return 0;
2535 }
2536
2537 if (strcmp(registration_name, "*all") == 0) {
2539 astman_send_ack(s, m, "Reregistrations queued.");
2540 return 0;
2541 }
2542
2543 state = get_state(registration_name);
2544 if (!state) {
2545 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2546 return 0;
2547 }
2548
2549 /* We need to serialize the unregister and register so they need
2550 * to be queued as separate tasks.
2551 */
2552 if (queue_unregister(state)) {
2553 astman_send_ack(s, m, "Failed to queue unregistration");
2554 } else if (queue_register(state)) {
2555 astman_send_ack(s, m, "Failed to queue unregistration");
2556 } else {
2557 astman_send_ack(s, m, "Reregistration sent");
2558 }
2559
2560 ao2_ref(state, -1);
2561 return 0;
2562}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1982
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:2014
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1643
static int queue_unregister(struct sip_outbound_registration_state *state)
static int queue_register(struct sip_outbound_registration_state *state)
static void reregister_all(void)

References ao2_ref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), get_state(), queue_register(), queue_unregister(), and reregister_all().

Referenced by load_module().

◆ ami_show_outbound_registrations()

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

Definition at line 2615 of file res_pjsip_outbound_registration.c.

2617{
2618 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2619 struct sip_ami_outbound ami_outbound = { .ami = &ami };
2620 struct ao2_container *regs;
2621
2622 regs = get_registrations();
2623 if (!regs) {
2624 astman_send_error(s, m, "Unable to retrieve "
2625 "outbound registrations\n");
2626 return -1;
2627 }
2628
2629 astman_send_listack(s, m, "Following are Events for each Outbound registration",
2630 "start");
2631
2633
2634 astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
2635 ami_outbound.registered + ami_outbound.not_registered);
2636 astman_append(s,
2637 "Registered: %d\r\n"
2638 "NotRegistered: %d\r\n",
2639 ami_outbound.registered,
2640 ami_outbound.not_registered);
2642
2643 ao2_ref(regs, -1);
2644 return 0;
2645}
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:2024
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:2060
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2068
static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
static struct ao2_container * get_registrations(void)
AMI variable container.
Definition res_pjsip.h:3200
const struct message * m
Definition res_pjsip.h:3204

References sip_ami_outbound::ami, ami_outbound_registration_detail(), ao2_callback, ao2_ref, astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), get_registrations(), ast_sip_ami::m, sip_ami_outbound::not_registered, OBJ_NODATA, sip_ami_outbound::registered, and ast_sip_ami::s.

Referenced by load_module().

◆ ami_unregister()

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

Definition at line 2495 of file res_pjsip_outbound_registration.c.

2496{
2497 const char *registration_name = astman_get_header(m, "Registration");
2499
2500 if (ast_strlen_zero(registration_name)) {
2501 astman_send_error(s, m, "Registration parameter missing.");
2502 return 0;
2503 }
2504
2505 if (strcmp(registration_name, "*all") == 0) {
2507 astman_send_ack(s, m, "Unregistrations queued.");
2508 return 0;
2509 }
2510
2511 state = get_state(registration_name);
2512 if (!state) {
2513 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2514 return 0;
2515 }
2516
2517 if (queue_unregister(state)) {
2518 astman_send_ack(s, m, "Failed to queue unregistration");
2519 } else {
2520 astman_send_ack(s, m, "Unregistration sent");
2521 }
2522
2523 ao2_ref(state, -1);
2524 return 0;
2525}
static void unregister_all(void)

References ao2_ref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), get_state(), queue_unregister(), and unregister_all().

Referenced by load_module().

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( current_states  )
static

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 3069 of file res_pjsip_outbound_registration.c.

◆ AST_THREADSTORAGE_CUSTOM_SCOPE()

AST_THREADSTORAGE_CUSTOM_SCOPE ( register_callback_invoked  ,
NULL  ,
ast_free_ptr  ,
static   
)

Some thread local storage used to determine if the running thread invoked the callback.

◆ auth_observer()

static void auth_observer ( const char *  type)
static

Definition at line 2771 of file res_pjsip_outbound_registration.c.

2772{
2773 struct sip_outbound_registration *registration;
2775 struct ao2_container *regs;
2776 const char *registration_id;
2777 struct ao2_iterator i;
2778
2779 ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
2780
2781 regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
2783 if (!regs || ao2_container_count(regs) == 0) {
2784 ao2_cleanup(regs);
2785 return;
2786 }
2787
2788 i = ao2_iterator_init(regs, 0);
2789 for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
2790 registration_id = ast_sorcery_object_get_id(registration);
2791 state = get_state(registration_id);
2792 if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
2793 ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
2794
2795 if (ast_sip_push_task(state->client_state->serializer,
2797 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
2798 ao2_ref(state, -1);
2799 }
2800 }
2802 }
2804 ao2_cleanup(regs);
2805}
#define ast_log
Definition astobj2.c:42
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition res_pjsip.c:2099
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
static int sip_outbound_registration_perform(void *data)
Helper function which performs a single registration.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition sorcery.h:123
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition sorcery.c:1961
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821

References ao2_bump, ao2_cleanup, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_debug, ast_log, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sip_push_task(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_fields(), get_state(), LOG_ERROR, NULL, sip_outbound_registration_perform(), and SIP_REGISTRATION_REJECTED_PERMANENT.

◆ can_reuse_registration()

static int can_reuse_registration ( struct sip_outbound_registration existing,
struct sip_outbound_registration applied 
)
static

Definition at line 1866 of file res_pjsip_outbound_registration.c.

1868{
1869 int rc = 1;
1871 struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
1872 struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
1873 struct ast_variable *vc = NULL;
1874
1875 if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
1876 rc = 0;
1877 ast_debug(4, "Registration '%s' changed. Can't re-use.\n", ast_sorcery_object_get_id(existing));
1878 } else {
1879 ast_debug(4, "Registration '%s' didn't change. Can re-use\n", ast_sorcery_object_get_id(existing));
1880 }
1881
1885
1886 return rc;
1887}
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260
static struct ast_sorcery * sorcery
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition sorcery.h:1137
int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
Create a changeset given two object sets.
Definition sorcery.c:1727
Full structure for sorcery.
Definition sorcery.c:231
Structure for variables, used for configurations and for channel variables.

References ast_debug, ast_sip_get_sorcery(), ast_sorcery_changeset_create(), ast_sorcery_object_get_id(), ast_sorcery_objectset_create, ast_variables_destroy(), NULL, and sorcery.

Referenced by sip_outbound_registration_apply().

◆ cancel_registration()

static void cancel_registration ( struct sip_outbound_registration_client_state client_state)
static

Helper function which cancels the timer on a client.

Definition at line 757 of file res_pjsip_outbound_registration.c.

758{
759 if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
760 &client_state->timer, client_state->timer.id)) {
761 /* The timer was successfully cancelled, drop the refcount of client_state */
762 ao2_ref(client_state, -1);
763 }
764}
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:520
pj_timer_entry timer
Timer entry for retrying on temporal responses.

References ao2_ref, ast_sip_get_pjsip_endpoint(), and sip_outbound_registration_client_state::timer.

Referenced by handle_client_state_destruction(), reregister_immediately_cb(), schedule_registration(), and unregister_task().

◆ check_state()

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

Definition at line 2811 of file res_pjsip_outbound_registration.c.

2812{
2814 struct sip_outbound_registration *registration;
2815
2816 registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
2817 ast_sorcery_object_get_id(state->registration));
2818 if (!registration) {
2819 /* This is a dead registration */
2820 return CMP_MATCH;
2821 }
2822
2823 ao2_ref(registration, -1);
2824 return 0;
2825}
@ CMP_MATCH
Definition astobj2.h:1027

References ao2_ref, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), and CMP_MATCH.

Referenced by registration_loaded_observer().

◆ cli_complete_registration()

static char * cli_complete_registration ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 2360 of file res_pjsip_outbound_registration.c.

2362{
2363 char *result = NULL;
2364 int wordlen;
2365 int which = 0;
2366 struct sip_outbound_registration *registration;
2368 struct ao2_iterator i;
2369
2370 if (pos != 3) {
2371 return NULL;
2372 }
2373
2374 wordlen = strlen(word);
2375 if (wordlen == 0 && ++which > state) {
2376 return ast_strdup("*all");
2377 }
2378
2381 if (!registrations) {
2382 return NULL;
2383 }
2384
2386 while ((registration = ao2_iterator_next(&i))) {
2387 const char *name = ast_sorcery_object_get_id(registration);
2388
2389 if (!strncasecmp(word, name, wordlen) && ++which > state) {
2391 }
2392
2393 ao2_ref(registration, -1);
2394 if (result) {
2395 break;
2396 }
2397 }
2399
2401 return result;
2402}
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
static PGresult * result
Definition cel_pgsql.c:84
short word

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_fields(), ast_strdup, name, NULL, and result.

Referenced by cli_register(), and cli_unregister().

◆ cli_get_container()

static struct ao2_container * cli_get_container ( const char *  regex)
static

Definition at line 2647 of file res_pjsip_outbound_registration.c.

2648{
2650 struct ao2_container *s_container;
2651
2653 if (!container) {
2654 return NULL;
2655 }
2656
2659 if (!s_container) {
2660 return NULL;
2661 }
2662
2663 if (ao2_container_dup(s_container, container, 0)) {
2664 ao2_ref(s_container, -1);
2665 return NULL;
2666 }
2667
2668 return s_container;
2669}
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.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition astobj2.h:1327
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
struct ao2_container * container
Definition res_fax.c:603
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Definition sorcery.c:2018
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition sorcery.c:2528
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition sorcery.c:2504
#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:978

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_cleanup, ao2_container_alloc_list, ao2_container_dup(), ao2_ref, ast_sip_get_sorcery(), ast_sorcery_object_id_compare(), ast_sorcery_object_id_sort(), ast_sorcery_retrieve_by_regex(), container, NULL, RAII_VAR, and regex().

Referenced by load_module().

◆ cli_iterator()

static int cli_iterator ( void *  container,
ao2_callback_fn  callback,
void *  args 
)
static

Definition at line 2671 of file res_pjsip_outbound_registration.c.

2672{
2674
2675 return 0;
2676}
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
static struct @519 args

References ao2_callback, args, callback(), container, and OBJ_NODATA.

Referenced by load_module().

◆ cli_print_body()

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

Definition at line 2707 of file res_pjsip_outbound_registration.c.

2708{
2709 struct sip_outbound_registration *registration = obj;
2710 struct ast_sip_cli_context *context = arg;
2711 const char *id = ast_sorcery_object_get_id(registration);
2713 int expsecs;
2714#define REGISTRATION_URI_FIELD_LEN 53
2715
2716 ast_assert(context->output_buffer != NULL);
2717 expsecs = state ? state->client_state->registration_expires - ((int) time(NULL)) : 0;
2718
2719 ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s %-26s %-16s %s%d%s\n",
2720 id,
2721 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2722 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2726 : "n/a",
2728 state ? " (exp. " : "", abs(expsecs), state ? (expsecs < 0 ? "s ago)" : "s)") : "");
2730
2731 if (context->show_details
2732 || (context->show_details_only_level_0 && context->indent_level == 0)) {
2733 ast_str_append(&context->output_buffer, 0, "\n");
2735 }
2736
2737 return 0;
2738}
jack_status_t status
Definition app_jack.c:149
#define abs(x)
Definition f2c.h:195
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object's ast_variable list.
Definition pjsip_cli.c:36
#define REGISTRATION_URI_FIELD_LEN
CLI Formatter Context passed to all formatters.
struct sip_outbound_registration_client_state * client_state
Client state information.
struct sip_outbound_registration * registration
Outbound registration configuration object.
#define ast_assert(a)
Definition utils.h:776
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

References abs, ao2_cleanup, ast_assert, ast_sip_cli_print_sorcery_objectset(), ast_sorcery_object_get_id(), ast_str_append(), AST_VECTOR_GET, AST_VECTOR_SIZE, get_state(), NULL, sip_outbound_registration::outbound_auths, sip_outbound_registration_state::registration, REGISTRATION_URI_FIELD_LEN, sip_outbound_registration::server_uri, and sip_outbound_registration_status_str().

Referenced by load_module().

◆ cli_print_header()

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

Definition at line 2695 of file res_pjsip_outbound_registration.c.

2696{
2697 struct ast_sip_cli_context *context = arg;
2698
2699 ast_assert(context->output_buffer != NULL);
2700
2701 ast_str_append(&context->output_buffer, 0,
2702 " <Registration/ServerURI..............................> <Auth....................> <Status.......>\n");
2703
2704 return 0;
2705}

References ast_assert, ast_str_append(), and NULL.

Referenced by load_module().

◆ cli_register()

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

Definition at line 2447 of file res_pjsip_outbound_registration.c.

2448{
2450 const char *registration_name;
2451
2452 switch (cmd) {
2453 case CLI_INIT:
2454 e->command = "pjsip send register";
2455 e->usage =
2456 "Usage: pjsip send register <registration> | *all \n"
2457 " Unregisters the specified (or all) outbound "
2458 "registration(s) then starts registration(s) and schedules re-registrations.\n";
2459 return NULL;
2460 case CLI_GENERATE:
2461 return cli_complete_registration(a->line, a->word, a->pos, a->n);
2462 }
2463
2464 if (a->argc != 4) {
2465 return CLI_SHOWUSAGE;
2466 }
2467
2468 registration_name = a->argv[3];
2469
2470 if (strcmp(registration_name, "*all") == 0) {
2472 ast_cli(a->fd, "Re-register all queued\n");
2473 return CLI_SUCCESS;
2474 }
2475
2476 state = get_state(registration_name);
2477 if (!state) {
2478 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2479 return CLI_FAILURE;
2480 }
2481
2482 /* We need to serialize the unregister and register so they need
2483 * to be queued as separate tasks.
2484 */
2485 if (queue_unregister(state)) {
2486 ast_cli(a->fd, "Failed to queue unregistration\n");
2487 } else if (queue_register(state)) {
2488 ast_cli(a->fd, "Failed to queue registration\n");
2489 }
2490
2491 ao2_ref(state, -1);
2492 return CLI_SUCCESS;
2493}
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
static char * cli_complete_registration(const char *line, const char *word, int pos, int state)
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
static struct test_val a

References a, ao2_ref, ast_cli(), cli_complete_registration(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, get_state(), NULL, queue_register(), queue_unregister(), reregister_all(), and ast_cli_entry::usage.

◆ cli_retrieve_by_id()

static void * cli_retrieve_by_id ( const char *  id)
static

Definition at line 2678 of file res_pjsip_outbound_registration.c.

2679{
2680 struct ao2_container *states;
2681 void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
2682
2683 if (!obj) {
2684 /* if the object no longer exists then remove its state */
2685 states = ao2_global_obj_ref(current_states);
2686 if (states) {
2688 ao2_ref(states, -1);
2689 }
2690 }
2691
2692 return obj;
2693}
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition astobj2.h:918
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
@ OBJ_UNLINK
Definition astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition astobj2.h:1101

References ao2_find, ao2_global_obj_ref, ao2_ref, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_id(), OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by load_module().

◆ cli_unregister()

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

Definition at line 2404 of file res_pjsip_outbound_registration.c.

2405{
2407 const char *registration_name;
2408
2409 switch (cmd) {
2410 case CLI_INIT:
2411 e->command = "pjsip send unregister";
2412 e->usage =
2413 "Usage: pjsip send unregister <registration> | *all\n"
2414 " Unregisters the specified (or all) outbound registration(s) "
2415 "and stops future registration attempts.\n";
2416 return NULL;
2417 case CLI_GENERATE:
2418 return cli_complete_registration(a->line, a->word, a->pos, a->n);
2419 }
2420
2421 if (a->argc != 4) {
2422 return CLI_SHOWUSAGE;
2423 }
2424
2425 registration_name = a->argv[3];
2426
2427 if (strcmp(registration_name, "*all") == 0) {
2429 ast_cli(a->fd, "Unregister all queued\n");
2430 return CLI_SUCCESS;
2431 }
2432
2433 state = get_state(registration_name);
2434 if (!state) {
2435 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2436 return CLI_FAILURE;
2437 }
2438
2439 if (queue_unregister(state)) {
2440 ast_cli(a->fd, "Failed to queue unregistration\n");
2441 }
2442
2443 ao2_ref(state, -1);
2444 return CLI_SUCCESS;
2445}

References a, ao2_ref, ast_cli(), cli_complete_registration(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, get_state(), NULL, queue_unregister(), unregister_all(), and ast_cli_entry::usage.

◆ contact_add_security_headers_to_status()

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

Definition at line 798 of file res_pjsip_outbound_registration.c.

799{
800 struct ast_sip_contact *contact = obj;
801 struct pjsip_generic_string_hdr_vector *header_vector = arg;
802 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
803
804 if (!contact_status) {
805 return 0;
806 }
807 if (AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
808 goto out;
809 }
810
811 ao2_lock(contact_status);
813 ao2_unlock(contact_status);
814
815out:
816 ao2_cleanup(contact_status);
817 return 0;
818}
void ast_sip_header_to_security_mechanism(const pjsip_generic_string_hdr *hdr, struct ast_sip_security_mechanism_vector *security_mechanisms)
Append to security mechanism vector from SIP header.
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
Contact associated with an address of record.
Definition res_pjsip.h:390
FILE * out
Definition utils/frame.c:33
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition vector.h:873

References ao2_cleanup, ao2_lock, ao2_unlock, ast_sip_get_contact_status(), ast_sip_header_to_security_mechanism(), AST_VECTOR_CALLBACK_VOID, AST_VECTOR_SIZE, out, and ast_sip_contact_status::security_mechanisms.

Referenced by handle_registration_response().

◆ contact_has_security_mechanisms()

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

Definition at line 781 of file res_pjsip_outbound_registration.c.

782{
783 struct ast_sip_contact *contact = obj;
784 struct ast_sip_contact_status **ret = arg;
785 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
786
787 if (!contact_status) {
788 return 0;
789 }
790 if (!AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
791 ao2_cleanup(contact_status);
792 return 0;
793 }
794 *ret = contact_status;
795 return CMP_MATCH | CMP_STOP;
796}
@ CMP_STOP
Definition astobj2.h:1028

References ao2_cleanup, ast_sip_get_contact_status(), AST_VECTOR_SIZE, CMP_MATCH, CMP_STOP, and ast_sip_contact_status::security_mechanisms.

Referenced by add_security_headers().

◆ fetch_google_access_token()

static const char * fetch_google_access_token ( const struct ast_sip_auth auth)
static

Get google oauth2 access token using refresh token.

Definition at line 1890 of file res_pjsip_outbound_registration.c.

1891{
1892 char *cmd = NULL;
1893 const char *token;
1894 const char *url = "https://www.googleapis.com/oauth2/v3/token";
1895 char buf[4096];
1896 int res;
1897 struct ast_json_error error;
1898 struct ast_json *json;
1899
1900 /* set timeout to be shorter than default 180s (also checks func_curl is available) */
1901 if (ast_func_write(NULL, "CURLOPT(conntimeout)", "10")) {
1902 ast_log(LOG_ERROR, "CURL is unavailable. This is required for Google OAuth 2.0 authentication. Please ensure it is loaded.\n");
1903 return NULL;
1904 }
1905
1906 res = ast_asprintf(&cmd,
1907 "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
1908 url, auth->oauth_clientid, auth->oauth_secret, auth->refresh_token);
1909 if (res < 0) {
1910 return NULL;
1911 }
1912
1913 ast_debug(2, "Performing Google OAuth 2.0 authentication using command: %s\n", cmd);
1914
1915 buf[0] = '\0';
1916 res = ast_func_read(NULL, cmd, buf, sizeof(buf));
1917 ast_free(cmd);
1918 if (res) {
1919 ast_log(LOG_ERROR, "Could not retrieve Google OAuth 2.0 authentication\n");
1920 return NULL;
1921 }
1922
1923 ast_debug(2, "Google OAuth 2.0 authentication returned: %s\n", buf);
1924
1925 json = ast_json_load_string(buf, &error);
1926 if (!json) {
1927 ast_log(LOG_ERROR, "Could not parse Google OAuth 2.0 authentication: %d(%d) %s: '%s'\n",
1928 error.line, error.column, error.text, buf);
1929 return NULL;
1930 }
1931
1932 token = ast_json_string_get(ast_json_object_get(json, "access_token"));
1933 if (!token) {
1934 ast_log(LOG_ERROR, "Could not find Google OAuth 2.0 access_token in: '%s'\n",
1935 buf);
1936 }
1937 token = ast_strdup(token);
1938 ast_json_unref(json);
1939 return token;
1940}
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_load_string(const char *input, struct ast_json_error *error)
Parse null terminated string into a JSON object or array.
Definition json.c:567
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition json.c:407
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
static char url[512]
JSON parsing error information.
Definition json.h:887
Abstract JSON element (object, array, string, int, ...).
const ast_string_field oauth_clientid
Definition res_pjsip.h:681
const ast_string_field oauth_secret
Definition res_pjsip.h:681
const ast_string_field refresh_token
Definition res_pjsip.h:681
int error(const char *format,...)

References ast_asprintf, ast_debug, ast_free, ast_func_read(), ast_func_write(), ast_json_load_string(), ast_json_object_get(), ast_json_string_get(), ast_json_unref(), ast_log, ast_strdup, buf, error(), LOG_ERROR, NULL, ast_sip_auth::oauth_clientid, ast_sip_auth::oauth_secret, ast_sip_auth::refresh_token, and url.

Referenced by set_outbound_initial_authentication_credentials().

◆ get_registrations()

static struct ao2_container * get_registrations ( void  )
static

◆ get_state()

static struct sip_outbound_registration_state * get_state ( const char *  id)
static

Definition at line 686 of file res_pjsip_outbound_registration.c.

687{
689 struct ao2_container *states;
690
691 states = ao2_global_obj_ref(current_states);
692 if (states) {
693 state = ao2_find(states, id, OBJ_SEARCH_KEY);
694 ao2_ref(states, -1);
695 }
696 return state;
697}

References ao2_find, ao2_global_obj_ref, ao2_ref, NULL, and OBJ_SEARCH_KEY.

Referenced by ami_outbound_registration_task(), ami_register(), ami_unregister(), auth_observer(), cli_print_body(), cli_register(), cli_unregister(), and registration_transport_shutdown_cb().

◆ get_uri_option_line()

static struct pjsip_param * get_uri_option_line ( const void *  uri)
static

Definition at line 717 of file res_pjsip_outbound_registration.c.

718{
719 static const pj_str_t LINE_STR = { "line", 4 };
720
721 return ast_sip_pjsip_uri_get_other_param((pjsip_uri *)uri, &LINE_STR);
722}
struct pjsip_param * ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_str_t *param_str)
Find an 'other' SIP/SIPS URI parameter by name.
Definition res_pjsip.c:3511

References ast_sip_pjsip_uri_get_other_param().

Referenced by line_identify().

◆ handle_client_registration()

static int handle_client_registration ( void *  data)
static

Callback function for registering.

Definition at line 1018 of file res_pjsip_outbound_registration.c.

1019{
1020 RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
1021 pjsip_tx_data *tdata;
1022
1023 if (set_outbound_initial_authentication_credentials(client_state->client, &client_state->outbound_auths)) {
1024 ast_log(LOG_WARNING, "Failed to set initial authentication credentials\n");
1025 }
1026
1027 if (client_state->status == SIP_REGISTRATION_STOPPED
1028 || pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
1029 return 0;
1030 }
1031
1032 if (DEBUG_ATLEAST(1)) {
1033 pjsip_regc_info info;
1034
1035 pjsip_regc_get_info(client_state->client, &info);
1036 ast_log(LOG_DEBUG, "Outbound REGISTER attempt %u to '%.*s' with client '%.*s'\n",
1037 client_state->retries + 1,
1038 (int) info.server_uri.slen, info.server_uri.ptr,
1039 (int) info.client_uri.slen, info.client_uri.ptr);
1040 }
1041
1042 if (!add_configured_supported_headers(client_state, tdata)) {
1043 ast_log(LOG_WARNING, "Failed to set supported headers\n");
1044 return -1;
1045 }
1046
1047 registration_client_send(client_state, tdata);
1048
1049 return 0;
1050}
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define LOG_WARNING
static pj_status_t registration_client_send(struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
Helper function which sends a message and cleans up, if needed, on failure.
static int set_outbound_initial_authentication_credentials(pjsip_regc *regc, const struct ast_sip_auth_vector *auth_vector)
static int add_configured_supported_headers(struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
Helper function to add configured supported headers.
Outbound registration client state information (persists for lifetime of regc)

References add_configured_supported_headers(), ao2_cleanup, ast_log, DEBUG_ATLEAST, LOG_DEBUG, LOG_WARNING, RAII_VAR, registration_client_send(), set_outbound_initial_authentication_credentials(), and SIP_REGISTRATION_STOPPED.

Referenced by reregister_immediately_cb(), and sip_outbound_registration_timer_cb().

◆ handle_client_state_destruction()

static int handle_client_state_destruction ( void *  data)
static

Callback function for unregistering (potentially) and destroying state.

Definition at line 1123 of file res_pjsip_outbound_registration.c.

1124{
1125 struct sip_outbound_registration_client_state *client_state = data;
1126
1127 cancel_registration(client_state);
1128
1129 if (client_state->client) {
1130 pjsip_regc_info info;
1131 pjsip_tx_data *tdata;
1132
1133 pjsip_regc_get_info(client_state->client, &info);
1134
1135 if (info.is_busy == PJ_TRUE) {
1136 /* If a client transaction is in progress we defer until it is complete */
1137 ast_debug(1,
1138 "Registration transaction is busy with server '%.*s' from client '%.*s'.\n",
1139 (int) info.server_uri.slen, info.server_uri.ptr,
1140 (int) info.client_uri.slen, info.client_uri.ptr);
1141 client_state->destroy = 1;
1142 ao2_ref(client_state, -1);
1143 return 0;
1144 }
1145
1146 switch (client_state->status) {
1148 break;
1150 ast_debug(1,
1151 "Trying to unregister with server '%.*s' from client '%.*s' before destruction.\n",
1152 (int) info.server_uri.slen, info.server_uri.ptr,
1153 (int) info.client_uri.slen, info.client_uri.ptr);
1154
1156 client_state->destroy = 1;
1157 if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS
1158 && add_configured_supported_headers(client_state, tdata)
1159 && registration_client_send(client_state, tdata) == PJ_SUCCESS) {
1160 ao2_ref(client_state, -1);
1161 return 0;
1162 }
1163 break;
1168 break;
1169 }
1170
1171 pjsip_regc_destroy(client_state->client);
1172 client_state->client = NULL;
1173 }
1174
1179 ao2_ref(client_state, -1);
1180
1181 return 0;
1182}
void ast_sip_security_mechanisms_vector_destroy(struct ast_sip_security_mechanism_vector *security_mechanisms)
Free contents of a security mechanism vector.
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector)
Free contents of an auth vector.
static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
Helper function which cancels the timer on a client.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
unsigned int destroy
Registration should be destroyed after completion of transaction.
pjsip_regc * client
Outbound registration client.

References add_configured_supported_headers(), ao2_ref, ast_debug, ast_sip_auth_vector_destroy(), ast_sip_security_mechanisms_vector_destroy(), cancel_registration(), sip_outbound_registration_client_state::client, sip_outbound_registration_client_state::destroy, NULL, sip_outbound_registration_client_state::outbound_auths, registration_client_send(), sip_outbound_registration_client_state::security_mechanisms, sip_outbound_registration_client_state::server_security_mechanisms, SIP_REGISTRATION_REGISTERED, SIP_REGISTRATION_REJECTED_PERMANENT, SIP_REGISTRATION_REJECTED_TEMPORARY, SIP_REGISTRATION_STOPPED, SIP_REGISTRATION_STOPPING, SIP_REGISTRATION_UNREGISTERED, sip_outbound_registration_client_state::status, and update_client_state_status().

Referenced by handle_registration_response(), and sip_outbound_registration_state_destroy().

◆ handle_registration_response()

static int handle_registration_response ( void *  data)
static

Callback function for handling a response to a registration attempt.

Definition at line 1409 of file res_pjsip_outbound_registration.c.

1410{
1411 struct registration_response *response = data;
1412 pjsip_regc_info info;
1413 char server_uri[PJSIP_MAX_URL_SIZE];
1414 char client_uri[PJSIP_MAX_URL_SIZE];
1415
1416 if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
1417 ao2_ref(response, -1);
1418 return 0;
1419 }
1420
1421 pjsip_regc_get_info(response->client_state->client, &info);
1422 ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
1423 ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
1424 response->client_state->last_status_code = response->code;
1425
1426 ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
1427 response->code, server_uri, client_uri);
1428
1429 if (response->code == 408 || response->code == 503) {
1430 if ((ast_sip_failover_request(response->old_request))) {
1431 int res = registration_client_send(response->client_state, response->old_request);
1432 /* The tdata ref was stolen */
1433 response->old_request = NULL;
1434 if (res == PJ_SUCCESS) {
1435 ao2_ref(response, -1);
1436 return 0;
1437 }
1438 }
1439 } else if ((response->code == 401 || response->code == 407 || response->code == 494)
1440 && (!response->client_state->auth_attempted
1441 || response->rdata->msg_info.cseq->cseq != response->client_state->auth_cseq)) {
1442 int res;
1443 pjsip_cseq_hdr *cseq_hdr;
1444 pjsip_tx_data *tdata;
1445
1447 struct sip_outbound_registration *reg = NULL;
1448 struct ast_sip_endpoint *endpt = NULL;
1449 struct ao2_container *contact_container = NULL;
1450 pjsip_generic_string_hdr *header;
1451 struct pjsip_generic_string_hdr_vector header_vector;
1452 static const pj_str_t security_server = { "Security-Server", 15 };
1453
1454 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
1455 response->client_state->registration_name)) && reg->endpoint &&
1456 (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))) {
1457 /* Retrieve all contacts associated with aors from this endpoint (if set). */
1458 contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors);
1459 }
1460 /* Add server list of security mechanism to client_state and contact status if exists. */
1461 AST_VECTOR_INIT(&header_vector, 1);
1462 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, NULL);
1463 for (; header;
1464 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, header->next)) {
1465 AST_VECTOR_APPEND(&header_vector, header);
1467 }
1468 if (contact_container) {
1469 /* Add server security mechanisms to contact status of all associated contacts to be able to send correct
1470 * Security-Verify headers on subsequent non-REGISTER requests through this outbound registration.
1471 */
1472 ao2_callback(contact_container, OBJ_NODATA, contact_add_security_headers_to_status, &header_vector);
1473 ao2_cleanup(contact_container);
1474 }
1475 AST_VECTOR_FREE(&header_vector);
1476 ao2_cleanup(endpt);
1477 ao2_cleanup(reg);
1478 }
1479
1480 if (response->code == 494) {
1482 response->client_state->retries++;
1483 schedule_registration(response->client_state, 0);
1484 ao2_ref(response, -1);
1485 return 0;
1487 response->rdata, response->old_request, &tdata)) {
1488 response->client_state->auth_attempted = 1;
1489 ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
1490 server_uri, client_uri);
1491 pjsip_tx_data_add_ref(tdata);
1492
1493 res = registration_client_send(response->client_state, tdata);
1494
1495 /* Save the cseq that actually got sent. */
1496 cseq_hdr = (pjsip_cseq_hdr *) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ,
1497 NULL);
1498 response->client_state->auth_cseq = cseq_hdr->cseq;
1499 pjsip_tx_data_dec_ref(tdata);
1500 if (res == PJ_SUCCESS) {
1501 ao2_ref(response, -1);
1502 return 0;
1503 }
1504 } else {
1505 ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
1506 server_uri, client_uri);
1507 }
1508 /* Otherwise, fall through so the failure is processed appropriately */
1509 }
1510
1511 response->client_state->auth_attempted = 0;
1512
1513 if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
1514 /* Check if this is in regards to registering or unregistering */
1515 if (response->expiration) {
1516 int next_registration_round;
1517
1518 /* If the registration went fine simply reschedule registration for the future */
1519 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
1521 response->client_state->retries = 0;
1522 next_registration_round = response->expiration - REREGISTER_BUFFER_TIME;
1523 if (next_registration_round < 0) {
1524 /* Re-register immediately. */
1525 next_registration_round = 0;
1526 }
1527 schedule_registration(response->client_state, next_registration_round);
1528
1529 /* See if we should monitor for transport shutdown */
1530 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1532 response->client_state->registration_name);
1533 }
1534 } else {
1535 ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
1537 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1541 }
1542 }
1543
1545 } else if (response->client_state->destroy) {
1546 /* We need to deal with the pending destruction instead. */
1547 } else if (response->retry_after) {
1548 /* If we have been instructed to retry after a period of time, schedule it as such */
1549 schedule_retry(response, response->retry_after, server_uri, client_uri);
1550 } else if (response->client_state->retry_interval
1551 && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
1552 if (response->client_state->retries == response->client_state->max_retries) {
1553 /* If we received enough temporal responses to exceed our maximum give up permanently */
1555 ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
1556 server_uri, client_uri);
1557 } else {
1558 /* On the other hand if we can still try some more do so */
1559 response->client_state->retries++;
1560 schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
1561 }
1562 } else {
1563 if (response->code == 403
1565 && response->client_state->retries < response->client_state->max_retries) {
1566 /* A forbidden response retry interval is configured and there are retries remaining */
1568 response->client_state->retries++;
1570 ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1571 server_uri, client_uri, response->client_state->forbidden_retry_interval);
1572 } else if (response->client_state->fatal_retry_interval
1573 && response->client_state->retries < response->client_state->max_retries) {
1574 /* Some kind of fatal failure response received, so retry according to configured interval */
1576 response->client_state->retries++;
1578 ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1579 response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
1580 } else {
1581 /* Finally if there's no hope of registering give up */
1583 if (response->rdata) {
1584 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
1585 response->code, server_uri, client_uri);
1586 } else {
1587 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
1588 }
1589 }
1590 }
1591
1592 ast_system_publish_registry("PJSIP", client_uri, server_uri,
1594
1595 if (response->client_state->destroy) {
1596 /* We have a pending deferred destruction to complete now. */
1597 ao2_ref(response->client_state, +1);
1599 }
1600
1601 ao2_ref(response, -1);
1602 return 0;
1603}
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *tdata, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
Definition res_pjsip.c:214
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition res_pjsip.c:2201
void ast_sip_transport_monitor_unregister_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
Definition res_pjsip.c:1816
static void save_response_fields_to_transport(struct registration_response *response)
#define REREGISTER_BUFFER_TIME
Amount of buffer time (in seconds) before expiration that we re-register at.
static void registration_transport_monitor_setup(const char *transport_key, const char *registration_name)
static void registration_transport_shutdown_cb(void *obj)
static int contact_add_security_headers_to_status(void *obj, void *arg, int flags)
static int sip_outbound_registration_is_temporal(unsigned int code, struct sip_outbound_registration_client_state *client_state)
Helper function which determines if a response code is temporal or not.
static int handle_client_state_destruction(void *data)
Callback function for unregistering (potentially) and destroying state.
static void schedule_retry(struct registration_response *response, unsigned int interval, const char *server_uri, const char *client_uri)
static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
Helper function which sets up the timer to re-register in a specific amount of time.
static int monitor_matcher(void *a, void *b)
void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause)
Publish a channel driver outgoing registration message.
struct header * next
Structure for registration response.
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
char transport_key[IP6ADDR_COLON_PORT_BUFLEN]
Key for the reliable transport in use.
pjsip_rx_data * rdata
The response message.
int code
Response code for the registration attempt.
int expiration
Expiration time for registration.
pjsip_tx_data * old_request
Request for which the response was received.
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
unsigned int max_retries
Maximum number of retries permitted.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
unsigned int retries
Current number of retries.
static char server_uri[512]
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

References ao2_callback, ao2_cleanup, ao2_ref, ast_sip_endpoint::aors, ast_copy_pj_str(), ast_debug, ast_log, ast_sip_create_request_with_auth(), ast_sip_failover_request(), ast_sip_get_sorcery(), ast_sip_header_to_security_mechanism(), ast_sip_location_retrieve_contacts_from_aor_list(), AST_SIP_SECURITY_NEG_MEDIASEC, ast_sip_transport_monitor_unregister_key(), ast_sorcery_retrieve_by_id(), ast_system_publish_registry(), AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_INIT, sip_outbound_registration_client_state::auth_attempted, sip_outbound_registration_client_state::auth_cseq, sip_outbound_registration_client_state::client, registration_response::client_state, registration_response::code, contact_add_security_headers_to_status(), sip_outbound_registration_client_state::destroy, sip_outbound_registration::endpoint, registration_response::expiration, sip_outbound_registration_client_state::fatal_retry_interval, sip_outbound_registration_client_state::forbidden_retry_interval, handle_client_state_destruction(), sip_outbound_registration_client_state::last_status_code, LOG_WARNING, sip_outbound_registration_client_state::max_retries, monitor_matcher(), header::next, NULL, OBJ_NODATA, registration_response::old_request, sip_outbound_registration_client_state::outbound_auths, registration_response::rdata, registration_client_send(), sip_outbound_registration_client_state::registration_name, registration_transport_monitor_setup(), registration_transport_shutdown_cb(), REREGISTER_BUFFER_TIME, sip_outbound_registration_client_state::retries, registration_response::retry_after, sip_outbound_registration_client_state::retry_interval, save_response_fields_to_transport(), schedule_registration(), schedule_retry(), sip_outbound_registration_client_state::security_negotiation, sip_outbound_registration_client_state::server_security_mechanisms, server_uri, sip_outbound_registration_is_temporal(), sip_outbound_registration_status_str(), SIP_REGISTRATION_REGISTERED, SIP_REGISTRATION_REJECTED_PERMANENT, SIP_REGISTRATION_REJECTED_TEMPORARY, SIP_REGISTRATION_STOPPED, SIP_REGISTRATION_UNREGISTERED, sip_outbound_registration_client_state::status, registration_response::transport_key, and update_client_state_status().

Referenced by sip_outbound_registration_response_cb().

◆ line_identify()

static struct ast_sip_endpoint * line_identify ( pjsip_rx_data *  rdata)
static

Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration.

Definition at line 725 of file res_pjsip_outbound_registration.c.

726{
727 pjsip_param *line;
728 RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
730
731 if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
732 && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
733 return NULL;
734 }
735
736 states = ao2_global_obj_ref(current_states);
737 if (!states) {
738 return NULL;
739 }
740
742 if (!state || ast_strlen_zero(state->registration->endpoint)) {
743 return NULL;
744 }
745
746 ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
747 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
748
749 return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
750}
static struct pjsip_param * get_uri_option_line(const void *uri)
static int line_identify_relationship(void *obj, void *arg, int flags)
Callback function for matching an outbound registration based on line.

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strlen_zero(), get_uri_option_line(), line_identify_relationship(), NULL, and RAII_VAR.

◆ line_identify_relationship()

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

Callback function for matching an outbound registration based on line.

Definition at line 709 of file res_pjsip_outbound_registration.c.

710{
712 pjsip_param *line = arg;
713
714 return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH : 0;
715}

References CMP_MATCH.

Referenced by line_identify().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2945 of file res_pjsip_outbound_registration.c.

2946{
2947 struct ao2_container *new_states;
2948
2950 if (!shutdown_group) {
2952 }
2953
2954 /* Create outbound registration states container. */
2957 if (!new_states) {
2958 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
2959 unload_module();
2961 }
2963 ao2_ref(new_states, -1);
2964
2965 /*
2966 * Register sorcery object descriptions.
2967 */
2968 ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
2969 ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
2970
2972 unload_module();
2974 }
2975
2976 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
2978 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
2979 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
2980 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_header_params", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_header_params));
2981 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
2982 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
2983 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
2984 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_random_initial_delay", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_random_initial_delay));
2985 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
2986 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
2987 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "fatal_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, fatal_retry_interval));
2989 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent));
2991 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
2992 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_outbound", "no", OPT_YESNO_T, 1, FLDSET(struct sip_outbound_registration, support_outbound));
2995 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
2996 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
2997 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, user_agent));
2998
2999 /*
3000 * Register sorcery observers.
3001 */
3006 || ast_sorcery_observer_add(ast_sip_get_sorcery(), "registration",
3008 ast_log(LOG_ERROR, "Unable to register observers.\n");
3009 unload_module();
3011 }
3012
3013 /* Register how this module identifies endpoints. */
3015
3016 /* Register CLI commands. */
3018 if (!cli_formatter) {
3019 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
3020 unload_module();
3022 }
3023 cli_formatter->name = "registration";
3032
3033 /* Register AMI actions. */
3037
3038 /* Clear any previous statsd gauges in case we weren't shutdown cleanly */
3039 ast_statsd_log("PJSIP.registrations.count", AST_STATSD_GAUGE, 0);
3040 ast_statsd_log("PJSIP.registrations.state.Registered", AST_STATSD_GAUGE, 0);
3041 ast_statsd_log("PJSIP.registrations.state.Unregistered", AST_STATSD_GAUGE, 0);
3042 ast_statsd_log("PJSIP.registrations.state.Rejected", AST_STATSD_GAUGE, 0);
3043
3044 /* Load configuration objects */
3046
3051
3053}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition astobj2.h:901
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition astobj2.h:1303
static int max_retries
Definition chan_iax2.c:356
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_YESNO_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define EVENT_FLAG_REPORTING
Definition manager.h:84
#define EVENT_FLAG_SYSTEM
Definition manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition manager.h:192
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
Definition res_pjsip.c:310
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition pjsip_cli.c:310
static struct ao2_container * new_states
Used on [re]loads to hold new state data.
static int ami_show_outbound_registrations(struct mansession *s, const struct message *m)
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
static void * sip_outbound_registration_alloc(const char *name)
Allocator function for registration information.
static int cli_print_header(void *obj, void *arg, int flags)
static struct ast_serializer_shutdown_group * shutdown_group
static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
static int registration_state_cmp(void *obj, void *arg, int flags)
comparator function for state objects
#define DEFAULT_STATE_BUCKETS
Default number of state container buckets.
static const struct ast_sorcery_observer registration_observer
static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int ami_register(struct mansession *s, const struct message *m)
static int ami_unregister(struct mansession *s, const struct message *m)
static int security_negotiation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int security_mechanisms_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int security_mechanism_to_str(const void *obj, const intptr_t *args, char **buf)
static void network_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
Apply function which finds or allocates a state structure.
static void * cli_retrieve_by_id(const char *id)
static const struct ast_sorcery_observer observer_callbacks_auth
static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
static struct ast_sip_endpoint_identifier line_identifier
static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
static struct ao2_container * cli_get_container(const char *regex)
static struct stasis_subscription * network_change_sub
static int cli_print_body(void *obj, void *arg, int flags)
static int security_negotiation_to_str(const void *obj, const intptr_t *args, char **buf)
static int unload_module(void)
static struct ast_cli_entry cli_outbound_registration[]
static struct ast_sip_cli_formatter_entry * cli_formatter
static int registration_state_hash(const void *obj, const int flags)
hashing function for state objects
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition sorcery.h:837
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:2455
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to load persistent objects.
Definition sorcery.c:1457
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
Definition sorcery.h:1005
#define ast_sorcery_apply_config(sorcery, name)
Definition sorcery.h:455
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition sorcery.h:955
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition sorcery.h:476
int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Add an observer to a sorcery instance.
Definition sorcery.c:584
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1144
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes.
struct stasis_message_type * ast_network_change_type(void)
A stasis_message_type for network changes.
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition statsd.h:32
void AST_OPTIONAL_API_NAME() ast_statsd_log(const char *metric_name, const char *metric_type, intmax_t value)
Send a stat to the configured statsd server.
Definition res_statsd.c:251
CLI Formatter Registry Entry.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
ao2_callback_fn * print_header
void *(* retrieve_by_id)(const char *id)
const char *(* get_id)(const void *obj)
const char * name
ao2_callback_fn * print_body
struct ao2_container *(* get_container)(const char *regex)
#define ARRAY_LEN(a)
Definition utils.h:703

References ami_register(), ami_show_outbound_registrations(), ami_unregister(), ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_global_obj_replace_unref, ao2_ref, ARRAY_LEN, ast_cli_register_multiple, ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_network_change_type(), ast_serializer_shutdown_group_alloc(), ast_sip_get_sorcery(), ast_sip_register_cli_formatter(), ast_sip_register_endpoint_identifier(), ast_sorcery_apply_config, ast_sorcery_apply_default, ast_sorcery_instance_observer_add(), ast_sorcery_load_object(), ast_sorcery_object_field_register, ast_sorcery_object_field_register_custom, ast_sorcery_object_get_id(), ast_sorcery_object_register, ast_sorcery_observer_add(), AST_STATSD_GAUGE, ast_statsd_log(), ast_system_topic(), cli_formatter, cli_get_container(), cli_iterator(), cli_outbound_registration, cli_print_body(), cli_print_header(), cli_retrieve_by_id(), DEFAULT_STATE_BUCKETS, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, FLDSET, ast_sip_cli_formatter_entry::get_container, ast_sip_cli_formatter_entry::get_id, ast_sip_cli_formatter_entry::iterate, line_identifier, LOG_ERROR, max_retries, ast_sip_cli_formatter_entry::name, network_change_stasis_cb(), network_change_sub, new_states, NULL, observer_callbacks_auth, observer_callbacks_registrations, OPT_BOOL_T, OPT_NOOP_T, OPT_STRINGFIELD_T, OPT_UINT_T, OPT_YESNO_T, outbound_auth_handler(), outbound_auths_to_str(), outbound_auths_to_var_list(), ast_sip_cli_formatter_entry::print_body, ast_sip_cli_formatter_entry::print_header, registration_observer, registration_state_cmp(), registration_state_hash(), ast_sip_cli_formatter_entry::retrieve_by_id, security_mechanism_to_str(), security_mechanisms_handler(), security_negotiation_handler(), security_negotiation_to_str(), server_uri, shutdown_group, sip_outbound_registration_alloc(), sip_outbound_registration_apply(), stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), STRFLDSET, and unload_module().

◆ monitor_matcher()

static int monitor_matcher ( void *  a,
void *  b 
)
static

Definition at line 1307 of file res_pjsip_outbound_registration.c.

1308{
1309 char *ma = a;
1310 char *mb = b;
1311
1312 return strcmp(ma, mb) == 0;
1313}
static struct test_val b

References a, and b.

Referenced by handle_registration_response(), and registration_transport_monitor_setup().

◆ my_cli_traverse_objects()

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

Definition at line 2745 of file res_pjsip_outbound_registration.c.

2746{
2747 return ast_sip_cli_traverse_objects(e, cmd, a);
2748}
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pjsip_cli.c:109

References a, and ast_sip_cli_traverse_objects().

◆ network_change_stasis_cb()

static void network_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 2887 of file res_pjsip_outbound_registration.c.

2888{
2889 /* This callback is only concerned with network change messages from the system topic. */
2891 return;
2892 }
2893 ast_debug(3, "Received network change event\n");
2894
2896}

References ast_debug, ast_network_change_type(), and reregister_all().

Referenced by load_module().

◆ outbound_auth_handler()

static int outbound_auth_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 2264 of file res_pjsip_outbound_registration.c.

2265{
2266 struct sip_outbound_registration *registration = obj;
2267
2268 return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
2269}
#define var
Definition ast_expr2f.c:605
int ast_sip_auth_vector_init(struct ast_sip_auth_vector *vector, const char *auth_names)
Initialize an auth vector with the configured values.

References ast_sip_auth_vector_init(), sip_outbound_registration::outbound_auths, and var.

Referenced by load_module().

◆ outbound_auths_to_str()

static int outbound_auths_to_str ( const void *  obj,
const intptr_t *  args,
char **  buf 
)
static

Definition at line 2271 of file res_pjsip_outbound_registration.c.

2272{
2273 const struct sip_outbound_registration *registration = obj;
2274
2275 return ast_sip_auths_to_str(&registration->outbound_auths, buf);
2276}
int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf)
Converts an auths array to a string of comma separated values.

References ast_sip_auths_to_str(), buf, and sip_outbound_registration::outbound_auths.

Referenced by load_module().

◆ outbound_auths_to_var_list()

static int outbound_auths_to_var_list ( const void *  obj,
struct ast_variable **  fields 
)
static

Definition at line 2278 of file res_pjsip_outbound_registration.c.

2279{
2280 const struct sip_outbound_registration *registration = obj;
2281 int i;
2282 struct ast_variable *head = NULL;
2283
2284 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
2285 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
2286 AST_VECTOR_GET(&registration->outbound_auths, i), ""));
2287 }
2288
2289 if (head) {
2290 *fields = head;
2291 }
2292
2293 return 0;
2294}
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)

References ast_variable_list_append, ast_variable_new, AST_VECTOR_GET, AST_VECTOR_SIZE, NULL, and sip_outbound_registration::outbound_auths.

Referenced by load_module().

◆ queue_register()

static int queue_register ( struct sip_outbound_registration_state state)
static

Definition at line 2329 of file res_pjsip_outbound_registration.c.

2330{
2331 ao2_ref(state, +1);
2332 if (ast_sip_push_task(state->client_state->serializer, sip_outbound_registration_perform, state)) {
2333 ao2_ref(state, -1);
2334 return -1;
2335 }
2336
2337 return 0;
2338}

References ao2_ref, ast_sip_push_task(), and sip_outbound_registration_perform().

Referenced by ami_register(), and cli_register().

◆ queue_unregister()

static int queue_unregister ( struct sip_outbound_registration_state state)
static

Definition at line 2318 of file res_pjsip_outbound_registration.c.

2319{
2320 ao2_ref(state, +1);
2321 if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
2322 ao2_ref(state, -1);
2323 return -1;
2324 }
2325
2326 return 0;
2327}
static int unregister_task(void *obj)

References ao2_ref, ast_sip_push_task(), and unregister_task().

Referenced by ami_register(), ami_unregister(), cli_register(), and cli_unregister().

◆ registration_client_send()

static pj_status_t registration_client_send ( struct sip_outbound_registration_client_state client_state,
pjsip_tx_data *  tdata 
)
static

Helper function which sends a message and cleans up, if needed, on failure.

Definition at line 883 of file res_pjsip_outbound_registration.c.

885{
886 pj_status_t status;
887 int *callback_invoked;
888 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
889
890 callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
891 if (!callback_invoked) {
892 pjsip_tx_data_dec_ref(tdata);
893 return PJ_ENOMEM;
894 }
895 *callback_invoked = 0;
896
897 /* Due to the message going out the callback may now be invoked, so bump the count */
898 ao2_ref(client_state, +1);
899 /*
900 * We also bump tdata in expectation of saving it to client_state->last_tdata.
901 * We have to do it BEFORE pjsip_regc_send because if it succeeds, it decrements
902 * the ref count on its own.
903 */
904 pjsip_tx_data_add_ref(tdata);
905
906 /* Add Security-Verify or Security-Client headers */
907 add_security_headers(client_state, tdata);
908
909 /*
910 * Replace the User-Agent header if a different one should be used
911 */
912 if (!ast_strlen_zero(client_state->user_agent)) {
913 static const pj_str_t user_agent_str = { "User-Agent", 10 };
914 pjsip_generic_string_hdr *default_user_agent_hdr;
915 pjsip_generic_string_hdr *user_agent_hdr;
916 pj_str_t user_agent_val;
917 default_user_agent_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &user_agent_str, NULL);
918 user_agent_val = pj_str(client_state->user_agent);
919 user_agent_hdr = pjsip_generic_string_hdr_create(tdata->pool, &user_agent_str, &user_agent_val);
920 if (!user_agent_hdr) {
921 ast_log(LOG_ERROR, "Could not add custom User-Agent to outbound registration %s, sending REGISTER request with non-custom header\n", client_state->registration_name);
922 } else {
923 if (default_user_agent_hdr) {
924 pj_list_erase(default_user_agent_hdr);
925 }
926 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)user_agent_hdr);
927 }
928 }
929
930 /*
931 * Set the transport in case transports were reloaded.
932 * When pjproject removes the extraneous error messages produced,
933 * we can check status and only set the transport and resend if there was an error
934 */
936 pjsip_regc_set_transport(client_state->client, &selector);
937 ast_sip_tpselector_unref(&selector);
938
939 status = pjsip_regc_send(client_state->client, tdata);
940
941 /*
942 * If the attempt to send the message failed and the callback was not invoked we need to
943 * drop the references we just added
944 */
945 if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
946 pjsip_tx_data_dec_ref(tdata);
947 ao2_ref(client_state, -1);
948 return status;
949 }
950
951 /*
952 * Decref the old last_data before replacing it.
953 * BTW, it's quite possible that last_data == tdata
954 * if we're trying successive servers in an SRV set.
955 */
956 if (client_state->last_tdata) {
957 pjsip_tx_data_dec_ref(client_state->last_tdata);
958 }
959 client_state->last_tdata = tdata;
960
961 return status;
962}
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition res_pjsip.c:923
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition res_pjsip.c:893
static void add_security_headers(struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
Adds security negotiation mechanisms of outbound registration client state as Security headers to tda...
char * user_agent
The value for the User-Agent header sent in requests.
char * transport_name
The name of the transport to be used for the registration.
pjsip_tx_data * last_tdata
Last tdata sent We need the original tdata to resend a request on auth failure or timeout....
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

References add_security_headers(), ao2_ref, ast_log, ast_sip_set_tpselector_from_transport_name(), ast_sip_tpselector_unref(), ast_strlen_zero(), ast_threadstorage_get(), sip_outbound_registration_client_state::client, sip_outbound_registration_client_state::last_tdata, LOG_ERROR, NULL, sip_outbound_registration_client_state::registration_name, status, sip_outbound_registration_client_state::transport_name, and sip_outbound_registration_client_state::user_agent.

Referenced by handle_client_registration(), handle_client_state_destruction(), handle_registration_response(), and unregister_task().

◆ registration_deleted_observer()

static void registration_deleted_observer ( const void *  obj)
static

Definition at line 2867 of file res_pjsip_outbound_registration.c.

2868{
2869 const struct sip_outbound_registration *registration = obj;
2870 struct ao2_container *states;
2871
2872 states = ao2_global_obj_ref(current_states);
2873 if (!states) {
2874 /* Global container has gone. Likely shutting down. */
2875 return;
2876 }
2877
2879
2880 ao2_ref(states, -1);
2881}

References ao2_find, ao2_global_obj_ref, ao2_ref, ast_sorcery_object_get_id(), OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

◆ registration_loaded_observer()

static void registration_loaded_observer ( const char *  name,
const struct ast_sorcery sorcery,
const char *  object_type,
int  reloaded 
)
static

Definition at line 2836 of file res_pjsip_outbound_registration.c.

2837{
2838 struct ao2_container *states;
2839
2840 if (strcmp(object_type, "registration")) {
2841 /* Not interested */
2842 return;
2843 }
2844
2845 states = ao2_global_obj_ref(current_states);
2846 if (!states) {
2847 /* Global container has gone. Likely shutting down. */
2848 return;
2849 }
2850
2851 /*
2852 * Refresh the current configured registrations. We don't need to hold
2853 * onto the objects, as the apply handler will cause their states to
2854 * be created appropriately.
2855 */
2857
2858 /* Now to purge dead registrations. */
2860 ao2_ref(states, -1);
2861}
@ OBJ_MULTIPLE
Definition astobj2.h:1049
static int check_state(void *obj, void *arg, int flags)

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ao2_ref, check_state(), get_registrations(), NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

◆ registration_response_destroy()

static void registration_response_destroy ( void *  obj)
static

Registration response structure destructor.

Definition at line 1203 of file res_pjsip_outbound_registration.c.

1204{
1205 struct registration_response *response = obj;
1206
1207 if (response->rdata) {
1208 pjsip_rx_data_free_cloned(response->rdata);
1209 }
1210
1211 if (response->old_request) {
1212 pjsip_tx_data_dec_ref(response->old_request);
1213 }
1214
1215 ao2_cleanup(response->client_state);
1216}

References ao2_cleanup, registration_response::client_state, registration_response::old_request, and registration_response::rdata.

Referenced by sip_outbound_registration_response_cb().

◆ registration_state_cmp()

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

comparator function for state objects

Definition at line 658 of file res_pjsip_outbound_registration.c.

659{
660 const struct sip_outbound_registration_state *object_left = obj;
661 const struct sip_outbound_registration_state *object_right = arg;
662 const char *right_key = arg;
663 int cmp;
664
665 switch (flags & OBJ_SEARCH_MASK) {
667 right_key = ast_sorcery_object_get_id(object_right->registration);
668 /* Fall through */
669 case OBJ_SEARCH_KEY:
670 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
671 break;
673 /* Not supported by container. */
674 ast_assert(0);
675 return 0;
676 default:
677 cmp = 0;
678 break;
679 }
680 if (cmp) {
681 return 0;
682 }
683 return CMP_MATCH;
684}
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition astobj2.h:1072

References ast_assert, ast_sorcery_object_get_id(), CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and sip_outbound_registration_state::registration.

Referenced by load_module().

◆ registration_state_hash()

static int registration_state_hash ( const void *  obj,
const int  flags 
)
static

hashing function for state objects

Definition at line 637 of file res_pjsip_outbound_registration.c.

638{
639 const struct sip_outbound_registration_state *object;
640 const char *key;
641
642 switch (flags & OBJ_SEARCH_MASK) {
643 case OBJ_SEARCH_KEY:
644 key = obj;
645 break;
647 object = obj;
649 break;
650 default:
651 ast_assert(0);
652 return 0;
653 }
654 return ast_str_hash(key);
655}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition strings.h:1259

References ast_assert, ast_sorcery_object_get_id(), ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and sip_outbound_registration_state::registration.

Referenced by load_module().

◆ registration_transport_monitor_setup()

static void registration_transport_monitor_setup ( const char *  transport_key,
const char *  registration_name 
)
static

Definition at line 1315 of file res_pjsip_outbound_registration.c.

1316{
1317 char *monitor;
1318 enum ast_transport_monitor_reg monitor_res;
1319
1320 monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,
1322 if (!monitor) {
1323 return;
1324 }
1325 strcpy(monitor, registration_name);/* Safe */
1326
1327 /*
1328 * We'll ignore if the transport has already been shutdown before we
1329 * register the monitor. We might get into a message spamming infinite
1330 * loop of registration, shutdown, reregistration...
1331 */
1333 monitor, monitor_matcher))) {
1334 ast_log(LOG_NOTICE, "Failed to register transport monitor for regisration %s: %d\n", registration_name, monitor_res);
1335 }
1336 ao2_ref(monitor, -1);
1337}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
#define LOG_NOTICE
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
Register a reliable transport shutdown monitor callback replacing any duplicate.
ast_transport_monitor_reg
Definition res_pjsip.h:4104

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_log, ast_sip_transport_monitor_register_replace_key(), LOG_NOTICE, monitor_matcher(), NULL, and registration_transport_shutdown_cb().

Referenced by handle_registration_response().

◆ registration_transport_shutdown_cb()

static void registration_transport_shutdown_cb ( void *  obj)
static

Definition at line 1292 of file res_pjsip_outbound_registration.c.

1293{
1294 const char *registration_name = obj;
1296
1297 state = get_state(registration_name);
1298 if (!state) {
1299 /* Registration no longer exists or shutting down. */
1300 return;
1301 }
1302 if (ast_sip_push_task(state->client_state->serializer, reregister_immediately_cb, state)) {
1303 ao2_ref(state, -1);
1304 }
1305}
static int reregister_immediately_cb(void *obj)

References ao2_ref, ast_sip_push_task(), get_state(), and reregister_immediately_cb().

Referenced by handle_registration_response(), registration_transport_monitor_setup(), and unload_module().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 3055 of file res_pjsip_outbound_registration.c.

3056{
3058 return 0;
3059}
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
Definition sorcery.c:1506

References ast_sip_get_sorcery(), and ast_sorcery_reload_object().

◆ reregister_all()

static void reregister_all ( void  )
static

◆ reregister_immediately_cb()

static int reregister_immediately_cb ( void *  obj)
static

Definition at line 1255 of file res_pjsip_outbound_registration.c.

1256{
1258
1259 if (state->client_state->status != SIP_REGISTRATION_REGISTERED) {
1260 ao2_ref(state, -1);
1261 return 0;
1262 }
1263
1264 if (DEBUG_ATLEAST(1)) {
1265 pjsip_regc_info info;
1266
1267 pjsip_regc_get_info(state->client_state->client, &info);
1269 "Outbound registration transport to server '%.*s' from client '%.*s' shutdown\n",
1270 (int) info.server_uri.slen, info.server_uri.ptr,
1271 (int) info.client_uri.slen, info.client_uri.ptr);
1272 }
1273
1274 cancel_registration(state->client_state);
1275
1276 ao2_ref(state->client_state, +1);
1277 handle_client_registration(state->client_state);
1278
1279 ao2_ref(state, -1);
1280 return 0;
1281}
static int handle_client_registration(void *data)
Callback function for registering.

References ao2_ref, ast_log, cancel_registration(), DEBUG_ATLEAST, handle_client_registration(), LOG_DEBUG, and SIP_REGISTRATION_REGISTERED.

Referenced by registration_transport_shutdown_cb().

◆ save_response_fields_to_transport()

static void save_response_fields_to_transport ( struct registration_response response)
static

Definition at line 1339 of file res_pjsip_outbound_registration.c.

1340{
1341 static const pj_str_t associated_uri_str = { "P-Associated-URI", 16 };
1342 static const pj_str_t service_route_str = { "Service-Route", 13 };
1343 pjsip_hdr *header = NULL;
1344 pjsip_msg *msg = response->rdata->msg_info.msg;
1345 struct ast_sip_service_route_vector *service_routes = NULL;
1346
1347 /* If no transport is specified then we can't update any */
1349 return;
1350 }
1351
1352 ast_sip_transport_state_set_transport(response->client_state->transport_name, response->rdata->tp_info.transport);
1353
1354 while ((header = pjsip_msg_find_hdr_by_name(msg, &service_route_str, header ? header->next : NULL))) {
1355 char *service_route;
1356 size_t size;
1357
1358 /* The below code takes the approach that if we can't store all service routes then we
1359 * store none at all. This gives a predictable failure condition instead of storing a
1360 * partial list and having partial route headers.
1361 */
1362 size = pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1;
1363 service_route = ast_malloc(size);
1364 if (!service_route) {
1365 if (service_routes) {
1367 service_routes = NULL;
1368 }
1369 break;
1370 }
1371
1372 ast_copy_pj_str(service_route, &((pjsip_generic_string_hdr*)header)->hvalue, size);
1373
1374 if (!service_routes) {
1375 service_routes = ast_sip_service_route_vector_alloc();
1376 if (!service_routes) {
1377 ast_free(service_route);
1378 break;
1379 }
1380 }
1381
1382 if (AST_VECTOR_APPEND(service_routes, service_route)) {
1383 ast_free(service_route);
1385 service_routes = NULL;
1386 break;
1387 }
1388 }
1389
1390 /* If any service routes were handled then store them on the transport */
1391 if (service_routes) {
1393 }
1394
1395 /* If an associated URI is present in the response we need to use it on any outgoing
1396 * traffic on the transport.
1397 */
1398 header = pjsip_msg_find_hdr_by_name(msg, &associated_uri_str, NULL);
1399 if (header) {
1400 char value[pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1];
1401
1402 ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)header)->hvalue, sizeof(value));
1404 }
1405}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
int ast_sip_transport_state_set_transport(const char *transport_name, pjsip_transport *transport)
Sets the PJSIP transport on a child transport.
void ast_sip_service_route_vector_destroy(struct ast_sip_service_route_vector *service_routes)
Destroy a vector of service routes.
struct ast_sip_service_route_vector * ast_sip_service_route_vector_alloc(void)
Allocate a vector of service routes.
int ast_sip_transport_state_set_preferred_identity(const char *transport_name, const char *identity)
Sets the P-Preferred-Identity on a child transport.
int ast_sip_transport_state_set_service_routes(const char *transport_name, struct ast_sip_service_route_vector *service_routes)
Sets the service routes on a child transport.
int value
Definition syslog.c:37

References ast_copy_pj_str(), ast_free, ast_malloc, ast_sip_service_route_vector_alloc(), ast_sip_service_route_vector_destroy(), ast_sip_transport_state_set_preferred_identity(), ast_sip_transport_state_set_service_routes(), ast_sip_transport_state_set_transport(), ast_strlen_zero(), AST_VECTOR_APPEND, registration_response::client_state, header::next, NULL, registration_response::rdata, sip_outbound_registration_client_state::transport_name, and value.

Referenced by handle_registration_response().

◆ schedule_registration()

static void schedule_registration ( struct sip_outbound_registration_client_state client_state,
unsigned int  seconds 
)
static

Helper function which sets up the timer to re-register in a specific amount of time.

Definition at line 1071 of file res_pjsip_outbound_registration.c.

1072{
1073 pj_time_val delay = { .sec = seconds, };
1074 pjsip_regc_info info;
1075
1076 cancel_registration(client_state);
1077
1078 pjsip_regc_get_info(client_state->client, &info);
1079 ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
1080 (int) info.server_uri.slen, info.server_uri.ptr,
1081 (int) info.client_uri.slen, info.client_uri.ptr,
1082 seconds);
1083
1084 ao2_ref(client_state, +1);
1085 if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
1086 ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
1087 (int) info.server_uri.slen, info.server_uri.ptr,
1088 (int) info.client_uri.slen, info.client_uri.ptr);
1089 ao2_ref(client_state, -1);
1090 }
1091 client_state->registration_expires = ((int) time(NULL)) + seconds;
1092}
unsigned int registration_expires
Expected time of registration lapse/expiration.

References ao2_ref, ast_debug, ast_log, ast_sip_get_pjsip_endpoint(), cancel_registration(), sip_outbound_registration_client_state::client, LOG_WARNING, NULL, sip_outbound_registration_client_state::registration_expires, and sip_outbound_registration_client_state::timer.

Referenced by handle_registration_response(), schedule_retry(), and sip_outbound_registration_perform().

◆ schedule_retry()

static void schedule_retry ( struct registration_response response,
unsigned int  interval,
const char *  server_uri,
const char *  client_uri 
)
static

Definition at line 1238 of file res_pjsip_outbound_registration.c.

1240{
1242 schedule_registration(response->client_state, interval);
1243
1244 if (response->rdata) {
1245 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
1246 "registration attempt to '%s', retrying in '%u'\n",
1247 response->code, server_uri, client_uri, interval);
1248 } else {
1249 ast_log(LOG_WARNING, "No response received from '%s' on "
1250 "registration attempt to '%s', retrying in '%u'\n",
1251 server_uri, client_uri, interval);
1252 }
1253}

References ast_log, registration_response::client_state, registration_response::code, LOG_WARNING, registration_response::rdata, schedule_registration(), server_uri, SIP_REGISTRATION_REJECTED_TEMPORARY, and update_client_state_status().

Referenced by handle_registration_response().

◆ security_mechanism_to_str()

static int security_mechanism_to_str ( const void *  obj,
const intptr_t *  args,
char **  buf 
)
static

Definition at line 2229 of file res_pjsip_outbound_registration.c.

2230{
2231 const struct sip_outbound_registration *registration = obj;
2232
2234}
int ast_sip_security_mechanisms_to_str(const struct ast_sip_security_mechanism_vector *security_mechanisms, int add_qvalue, char **buf)
Writes the security mechanisms of an endpoint into a buffer as a string and returns the buffer.
struct ast_sip_security_mechanism_vector security_mechanisms
Client security mechanisms (RFC 3329).

References ast_sip_security_mechanisms_to_str(), buf, and sip_outbound_registration::security_mechanisms.

Referenced by load_module().

◆ security_mechanisms_handler()

static int security_mechanisms_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 2250 of file res_pjsip_outbound_registration.c.

2251{
2252 struct sip_outbound_registration *registration = obj;
2253
2254 return ast_sip_security_mechanism_vector_init(&registration->security_mechanisms, var->value);
2255}
int ast_sip_security_mechanism_vector_init(struct ast_sip_security_mechanism_vector *security_mechanism, const char *value)
Initialize security mechanism vector from string of security mechanisms.

References ast_sip_security_mechanism_vector_init(), sip_outbound_registration::security_mechanisms, and var.

Referenced by load_module().

◆ security_negotiation_handler()

static int security_negotiation_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 2257 of file res_pjsip_outbound_registration.c.

2258{
2259 struct sip_outbound_registration *registration = obj;
2260
2261 return ast_sip_set_security_negotiation(&registration->security_negotiation, var->value);
2262}
int ast_sip_set_security_negotiation(enum ast_sip_security_negotiation *security_negotiation, const char *val)
Set the security negotiation based on a given string.
enum ast_sip_security_negotiation security_negotiation
Type of security negotiation to use (RFC 3329).

References ast_sip_set_security_negotiation(), sip_outbound_registration::security_negotiation, and var.

Referenced by load_module().

◆ security_negotiation_to_str()

static int security_negotiation_to_str ( const void *  obj,
const intptr_t *  args,
char **  buf 
)
static

Definition at line 2241 of file res_pjsip_outbound_registration.c.

2242{
2243 const struct sip_outbound_registration *registration = obj;
2246 }
2247 return 0;
2248}
static const char * security_negotiation_map[]
#define ARRAY_IN_BOUNDS(v, a)
Checks to see if value is within the bounds of the given array.
Definition utils.h:724

References ARRAY_IN_BOUNDS, ast_strdup, buf, sip_outbound_registration::security_negotiation, and security_negotiation_map.

Referenced by load_module().

◆ set_outbound_initial_authentication_credentials()

static int set_outbound_initial_authentication_credentials ( pjsip_regc *  regc,
const struct ast_sip_auth_vector auth_vector 
)
static

Definition at line 1950 of file res_pjsip_outbound_registration.c.

1952{
1953 size_t auth_size = AST_VECTOR_SIZE(auth_vector);
1954 struct ast_sip_auth *auths[auth_size];
1955 const char *access_token;
1956 pjsip_cred_info auth_creds[1];
1957 pjsip_auth_clt_pref prefs;
1958 int res = 0;
1959 int idx;
1960
1961 memset(auths, 0, sizeof(auths));
1962 if (ast_sip_retrieve_auths(auth_vector, auths)) {
1963 res = -1;
1964 goto cleanup;
1965 }
1966
1967 for (idx = 0; idx < auth_size; ++idx) {
1968 switch (auths[idx]->type) {
1970 pj_cstr(&auth_creds[0].username, auths[idx]->auth_user);
1971 pj_cstr(&auth_creds[0].scheme, "Bearer");
1972 pj_cstr(&auth_creds[0].realm, auths[idx]->realm);
1973 ast_debug(2, "Obtaining Google OAuth access token\n");
1974 access_token = fetch_google_access_token(auths[idx]);
1975 if (!access_token) {
1976 ast_log(LOG_WARNING, "Obtaining Google OAuth access token failed\n");
1977 access_token = auths[idx]->auth_pass;
1978 res = -1;
1979 }
1980 ast_debug(2, "Setting data to '%s'\n", access_token);
1981
1982 pj_cstr(&auth_creds[0].data, access_token);
1983 auth_creds[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
1984
1985 pjsip_regc_set_credentials(regc, 1, auth_creds);
1986
1987 /* for oauth, send auth without waiting for unauthorized response */
1988 prefs.initial_auth = PJ_TRUE;
1989 pj_cstr(&prefs.algorithm, "oauth");
1990 pjsip_regc_set_prefs(regc, &prefs);
1991
1992 if (access_token != auths[idx]->auth_pass) {
1993 ast_free((char *) access_token);
1994 }
1995 break;
1996 default:
1997 /* other cases handled after receiving auth rejection */
1998 break;
1999 }
2000 }
2001
2002cleanup:
2003 ast_sip_cleanup_auths(auths, auth_size);
2004 return res;
2005}
static const char type[]
void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
Clean up retrieved auth structures from memory.
int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
Retrieve relevant SIP auth structures from sorcery.
@ AST_SIP_AUTH_TYPE_GOOGLE_OAUTH
Definition res_pjsip.h:583
static const char * fetch_google_access_token(const struct ast_sip_auth *auth)
Get google oauth2 access token using refresh token.
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition res_stasis.c:327
const ast_string_field realm
Definition res_pjsip.h:681
const ast_string_field auth_user
Definition res_pjsip.h:681
const ast_string_field auth_pass
Definition res_pjsip.h:681

References ast_debug, ast_free, ast_log, AST_SIP_AUTH_TYPE_GOOGLE_OAUTH, ast_sip_cleanup_auths(), ast_sip_retrieve_auths(), AST_VECTOR_SIZE, ast_sip_auth::auth_pass, ast_sip_auth::auth_user, cleanup(), fetch_google_access_token(), LOG_WARNING, ast_sip_auth::realm, and type.

Referenced by handle_client_registration().

◆ sip_dialog_create_contact()

static int sip_dialog_create_contact ( pj_pool_t *  pool,
pj_str_t *  contact,
const char *  user,
const pj_str_t *  target,
pjsip_tpselector *  selector,
const char *  line,
const char *  header_params 
)
static

Helper function which populates a pj_str_t with a contact header.

Definition at line 1793 of file res_pjsip_outbound_registration.c.

1795{
1796 pj_str_t tmp, local_addr;
1797 pjsip_uri *uri;
1798 pjsip_sip_uri *sip_uri;
1799 pjsip_transport_type_e type;
1800 int local_port;
1801
1802 pj_strdup_with_null(pool, &tmp, target);
1803
1804 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
1805 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
1806 return -1;
1807 }
1808
1809 sip_uri = pjsip_uri_get_uri(uri);
1810
1811 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
1812 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
1813 if (type == PJSIP_TRANSPORT_UNSPECIFIED
1814 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
1815 type = PJSIP_TRANSPORT_TLS;
1816 }
1817 } else if (!sip_uri->transport_param.slen) {
1818 type = PJSIP_TRANSPORT_UDP;
1819 } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
1820 return -1;
1821 }
1822
1823 if (pj_strchr(&sip_uri->host, ':')) {
1824 type |= PJSIP_TRANSPORT_IPV6;
1825 }
1826
1827 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
1828 pool, type, selector, &local_addr, &local_port) != PJ_SUCCESS) {
1829 return -1;
1830 }
1831
1832 if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
1833 type |= PJSIP_TRANSPORT_IPV6;
1834 }
1835
1836 contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
1837 contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
1838 "<%s:%s@%s%.*s%s:%d%s%s%s%s>%s%s",
1839 ((pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) && PJSIP_URI_SCHEME_IS_SIPS(uri)) ? "sips" : "sip",
1840 user,
1841 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1842 (int)local_addr.slen,
1843 local_addr.ptr,
1844 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1845 local_port,
1846 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1847 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
1848 !ast_strlen_zero(line) ? ";line=" : "",
1849 S_OR(line, ""),
1850 !ast_strlen_zero(header_params) ? ";" : "",
1851 S_OR(header_params, ""));
1852
1853 return 0;
1854}
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
structure to hold users read from phoneprov_users.conf

References ast_sip_get_pjsip_endpoint(), ast_strlen_zero(), sip_outbound_registration::line, S_OR, and type.

Referenced by sip_outbound_registration_regc_alloc().

◆ sip_outbound_registration_alloc()

static void * sip_outbound_registration_alloc ( const char *  name)
static

Allocator function for registration information.

Definition at line 1778 of file res_pjsip_outbound_registration.c.

1779{
1780 struct sip_outbound_registration *registration;
1781
1782 registration = ast_sorcery_generic_alloc(sizeof(*registration),
1784 if (!registration || ast_string_field_init(registration, 256)) {
1785 ao2_cleanup(registration);
1786 return NULL;
1787 }
1788
1789 return registration;
1790}
static void sip_outbound_registration_destroy(void *obj)
Destructor function for registration information.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition sorcery.c:1792
#define ast_string_field_init(x, size)
Initialize a field pool and fields.

References ao2_cleanup, ast_sorcery_generic_alloc(), ast_string_field_init, NULL, and sip_outbound_registration_destroy().

Referenced by load_module().

◆ sip_outbound_registration_apply()

static int sip_outbound_registration_apply ( const struct ast_sorcery sorcery,
void *  obj 
)
static

Apply function which finds or allocates a state structure.

Definition at line 2145 of file res_pjsip_outbound_registration.c.

2146{
2147 RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
2150 struct sip_outbound_registration *applied = obj;
2151
2152 if (!states) {
2153 /* Global container has gone. Likely shutting down. */
2154 return -1;
2155 }
2157
2158 ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
2159
2160 if (ast_strlen_zero(applied->server_uri)) {
2161 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'\n",
2162 ast_sorcery_object_get_id(applied));
2163 return -1;
2164 } else if (ast_sip_validate_uri_length(applied->server_uri)) {
2165 ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2166 ast_sorcery_object_get_id(applied));
2167 return -1;
2168 } else if (ast_strlen_zero(applied->client_uri)) {
2169 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
2170 ast_sorcery_object_get_id(applied));
2171 return -1;
2172 } else if (ast_sip_validate_uri_length(applied->client_uri)) {
2173 ast_log(LOG_ERROR, "Client URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2174 ast_sorcery_object_get_id(applied));
2175 return -1;
2176 } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
2177 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
2178 ast_sorcery_object_get_id(applied));
2179 return -1;
2180 } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
2181 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
2182 ast_sorcery_object_get_id(applied));
2183 return -1;
2184 }
2185
2186 if (state && can_reuse_registration(state->registration, applied)) {
2187 ast_debug(4,
2188 "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
2189 ast_sorcery_object_get_id(applied));
2190
2191 /*
2192 * This is OK to replace without relinking the state in the
2193 * current_states container since state->registration and
2194 * applied have the same key.
2195 */
2196 ao2_lock(states);
2197 ao2_replace(state->registration, applied);
2198 ao2_unlock(states);
2199 return 0;
2200 }
2201
2202 if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
2203 return -1;
2204 }
2205
2206 if (ast_sip_push_task_wait_serializer(new_state->client_state->serializer,
2208 return -1;
2209 }
2210
2211 if (ast_sip_push_task(new_state->client_state->serializer,
2213 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
2214 ast_sorcery_object_get_id(new_state->registration));
2215 ao2_ref(new_state, -1);
2216 return -1;
2217 }
2218
2219 ao2_lock(states);
2220 if (state) {
2221 ao2_unlink(states, state);
2222 }
2223 ao2_link(states, new_state);
2224 ao2_unlock(states);
2225
2226 return 0;
2227}
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition astobj2.h:1578
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition res_pjsip.c:2179
static int sip_outbound_registration_regc_alloc(void *data)
Helper function that allocates a pjsip registration client and configures it.
static struct sip_outbound_registration_state * sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
Allocator function for registration state.
static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
int ast_sip_validate_uri_length(const char *uri)
Definition location.c:529
unsigned int line
Whether to add a line parameter to the outbound Contact or not.

References ao2_bump, ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_link, ao2_lock, ao2_ref, ao2_replace, ao2_unlink, ao2_unlock, ast_debug, ast_log, ast_sip_push_task(), ast_sip_push_task_wait_serializer(), ast_sip_validate_uri_length(), ast_sorcery_object_get_id(), ast_strlen_zero(), can_reuse_registration(), sip_outbound_registration::client_uri, sip_outbound_registration::endpoint, sip_outbound_registration::line, LOG_ERROR, NULL, OBJ_SEARCH_KEY, RAII_VAR, sip_outbound_registration::server_uri, sip_outbound_registration_perform(), sip_outbound_registration_regc_alloc(), and sip_outbound_registration_state_alloc().

Referenced by load_module().

◆ sip_outbound_registration_client_state_destroy()

static void sip_outbound_registration_client_state_destroy ( void *  obj)
static

Destructor function for client registration state.

Definition at line 1699 of file res_pjsip_outbound_registration.c.

1700{
1701 struct sip_outbound_registration_client_state *client_state = obj;
1702
1703 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);
1704 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
1706
1708 ast_free(client_state->transport_name);
1709 ast_free(client_state->registration_name);
1710 ast_free(client_state->user_agent);
1711 if (client_state->last_tdata) {
1712 pjsip_tx_data_dec_ref(client_state->last_tdata);
1713 }
1714}
void AST_OPTIONAL_API_NAME() ast_statsd_log_string_va(const char *metric_name, const char *metric_type, const char *value, double sample_rate,...)
Send a stat to the configured statsd server.
Definition res_statsd.c:205
void AST_OPTIONAL_API_NAME() ast_statsd_log_string(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:136
struct ast_taskprocessor * serializer
Serializer for stuff and things.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.

References ast_free, AST_STATSD_GAUGE, ast_statsd_log_string(), ast_statsd_log_string_va(), ast_taskprocessor_unreference(), sip_outbound_registration_client_state::last_tdata, sip_outbound_registration_client_state::registration_name, sip_outbound_registration_client_state::serializer, sip_outbound_registration_status_str(), sip_outbound_registration_client_state::status, sip_outbound_registration_client_state::transport_name, and sip_outbound_registration_client_state::user_agent.

Referenced by sip_outbound_registration_state_alloc().

◆ sip_outbound_registration_destroy()

static void sip_outbound_registration_destroy ( void *  obj)
static

Destructor function for registration information.

Definition at line 1767 of file res_pjsip_outbound_registration.c.

1768{
1769 struct sip_outbound_registration *registration = obj;
1770
1773
1774 ast_string_field_free_memory(registration);
1775}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

References ast_sip_auth_vector_destroy(), ast_sip_security_mechanisms_vector_destroy(), ast_string_field_free_memory, sip_outbound_registration::outbound_auths, and sip_outbound_registration::security_mechanisms.

Referenced by sip_outbound_registration_alloc().

◆ sip_outbound_registration_is_temporal()

static int sip_outbound_registration_is_temporal ( unsigned int  code,
struct sip_outbound_registration_client_state client_state 
)
static

Helper function which determines if a response code is temporal or not.

Definition at line 1219 of file res_pjsip_outbound_registration.c.

1221{
1222 /* Shamelessly taken from pjsua */
1223 if (code == PJSIP_SC_REQUEST_TIMEOUT ||
1224 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
1225 code == PJSIP_SC_BAD_GATEWAY ||
1226 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
1227 code == PJSIP_SC_SERVER_TIMEOUT ||
1228 ((code == PJSIP_SC_UNAUTHORIZED ||
1229 code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
1230 !client_state->auth_rejection_permanent) ||
1231 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
1232 return 1;
1233 } else {
1234 return 0;
1235 }
1236}
unsigned int auth_rejection_permanent
Treat authentication challenges that we cannot handle as permanent failures.

References sip_outbound_registration_client_state::auth_rejection_permanent, registration_response::client_state, and registration_response::code.

Referenced by handle_registration_response().

◆ sip_outbound_registration_perform()

static int sip_outbound_registration_perform ( void *  data)
static

Helper function which performs a single registration.

Definition at line 2101 of file res_pjsip_outbound_registration.c.

2102{
2104 struct sip_outbound_registration *registration = ao2_bump(state->registration);
2105 size_t i;
2106 int max_delay;
2107
2108 /* Just in case the client state is being reused for this registration, free the auth information */
2109 ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
2110 ast_sip_security_mechanisms_vector_destroy(&state->client_state->security_mechanisms);
2111 ast_sip_security_mechanisms_vector_destroy(&state->client_state->server_security_mechanisms);
2112
2113 AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
2114 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
2115 char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
2116
2117 if (name && AST_VECTOR_APPEND(&state->client_state->outbound_auths, name)) {
2118 ast_free(name);
2119 }
2120 }
2121 ast_sip_security_mechanisms_vector_copy(&state->client_state->security_mechanisms,
2122 &registration->security_mechanisms);
2123 state->client_state->retry_interval = registration->retry_interval;
2124 state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
2125 state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
2126 state->client_state->max_retries = registration->max_retries;
2127 state->client_state->retries = 0;
2128 state->client_state->support_path = registration->support_path;
2129 state->client_state->support_outbound = registration->support_outbound;
2130 state->client_state->security_negotiation = registration->security_negotiation;
2131 state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
2132 max_delay = registration->max_random_initial_delay;
2133
2134 pjsip_regc_update_expires(state->client_state->client, registration->expiration);
2135
2136 /* n mod 0 is undefined, so don't let that happen */
2137 schedule_registration(state->client_state, (max_delay ? ast_random() % max_delay : 0) + 1);
2138
2139 ao2_ref(registration, -1);
2140 ao2_ref(state, -1);
2141 return 0;
2142}
void ast_sip_security_mechanisms_vector_copy(struct ast_sip_security_mechanism_vector *dst, const struct ast_sip_security_mechanism_vector *src)
Duplicate a security mechanism.
unsigned int auth_rejection_permanent
Treat authentication challenges that we cannot handle as permanent failures.
unsigned int expiration
Requested expiration time.
unsigned int support_outbound
Whether Outbound support is enabled.
unsigned int support_path
Whether Path support is enabled.
unsigned int max_random_initial_delay
Maximum random initial delay interval for initial registrations.
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
unsigned int max_retries
Maximum number of retries permitted.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
long int ast_random(void)
Definition utils.c:2348

References ao2_bump, ao2_ref, ast_free, ast_random(), ast_sip_auth_vector_destroy(), ast_sip_security_mechanisms_vector_copy(), ast_sip_security_mechanisms_vector_destroy(), ast_strdup, AST_VECTOR_APPEND, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_SIZE, sip_outbound_registration::auth_rejection_permanent, sip_outbound_registration::expiration, sip_outbound_registration::fatal_retry_interval, sip_outbound_registration::forbidden_retry_interval, sip_outbound_registration::max_random_initial_delay, sip_outbound_registration::max_retries, name, sip_outbound_registration::outbound_auths, sip_outbound_registration::retry_interval, schedule_registration(), sip_outbound_registration::security_mechanisms, sip_outbound_registration::security_negotiation, sip_outbound_registration::support_outbound, and sip_outbound_registration::support_path.

Referenced by auth_observer(), queue_register(), and sip_outbound_registration_apply().

◆ sip_outbound_registration_regc_alloc()

static int sip_outbound_registration_regc_alloc ( void *  data)
static

Helper function that allocates a pjsip registration client and configures it.

Definition at line 2008 of file res_pjsip_outbound_registration.c.

2009{
2012 ao2_bump(state->registration), ao2_cleanup);
2013 pj_pool_t *pool;
2014 pj_str_t tmp;
2015 pjsip_uri *uri;
2016 pj_str_t server_uri, client_uri, contact_uri;
2017 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
2018
2019 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
2020 if (!pool) {
2021 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
2023 return -1;
2024 }
2025
2026 pj_strdup2_with_null(pool, &tmp, registration->server_uri);
2027 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
2028 if (!uri) {
2029 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
2031 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2032 return -1;
2033 }
2034
2035 pj_strdup2_with_null(pool, &tmp, registration->client_uri);
2036 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
2037 if (!uri) {
2038 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
2040 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2041 return -1;
2042 }
2043
2044 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2045
2046 ast_assert(state->client_state->client == NULL);
2047 if (pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
2049 &state->client_state->client) != PJ_SUCCESS) {
2050 return -1;
2051 }
2052
2054 pjsip_regc_set_transport(state->client_state->client, &selector);
2055
2057 pjsip_route_hdr route_set, *route;
2058 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
2059 pj_str_t tmp;
2060
2061 pj_list_init(&route_set);
2062
2063 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp,
2065 route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client),
2066 &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL);
2067 if (!route) {
2068 ast_sip_tpselector_unref(&selector);
2069 return -1;
2070 }
2071 pj_list_insert_nodes_before(&route_set, route);
2072
2073 pjsip_regc_set_route_set(state->client_state->client, &route_set);
2074 }
2075
2076 if (state->registration->line) {
2077 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
2078 }
2079
2081
2082 if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client),
2083 &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
2084 state->client_state->line, registration->contact_header_params)) {
2085 ast_sip_tpselector_unref(&selector);
2086 return -1;
2087 }
2088
2089 ast_sip_tpselector_unref(&selector);
2090
2091 pj_cstr(&client_uri, registration->client_uri);
2092 if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri,
2093 &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
2094 return -1;
2095 }
2096
2097 return 0;
2098}
static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const char *user, const pj_str_t *target, pjsip_tpselector *selector, const char *line, const char *header_params)
Helper function which populates a pj_str_t with a contact header.
static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
Callback function for outbound registration client.
char * ast_generate_random_string(char *buf, size_t size)
Create a pseudo-random string of a fixed length.
Definition strings.c:226

References ao2_bump, ao2_cleanup, ast_assert, ast_generate_random_string(), ast_log, ast_sip_get_pjsip_endpoint(), ast_sip_set_tpselector_from_transport_name(), ast_sip_tpselector_unref(), ast_sorcery_object_get_id(), ast_strlen_zero(), sip_outbound_registration::client_uri, sip_outbound_registration::contact_header_params, sip_outbound_registration::contact_user, sip_outbound_registration::expiration, LOG_ERROR, NULL, sip_outbound_registration::outbound_proxy, RAII_VAR, sip_outbound_registration_state::registration, S_OR, sip_outbound_registration::server_uri, server_uri, sip_dialog_create_contact(), sip_outbound_registration_response_cb(), and sip_outbound_registration::transport.

Referenced by sip_outbound_registration_apply().

◆ sip_outbound_registration_response_cb()

static void sip_outbound_registration_response_cb ( struct pjsip_regc_cbparam *  param)
static

Callback function for outbound registration client.

Definition at line 1606 of file res_pjsip_outbound_registration.c.

1607{
1608 struct sip_outbound_registration_client_state *client_state = param->token;
1609 struct registration_response *response;
1610 int *callback_invoked;
1611
1612 callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
1613
1614 ast_assert(callback_invoked != NULL);
1616
1617 *callback_invoked = 1;
1618
1619 response = ao2_alloc(sizeof(*response), registration_response_destroy);
1620 if (!response) {
1621 ao2_ref(client_state, -1);
1622 return;
1623 }
1624 response->code = param->code;
1625 response->expiration = param->expiration;
1626 /*
1627 * Transfer client_state reference to response so the
1628 * nominal path will not dec the client_state ref in this
1629 * pjproject callback thread.
1630 */
1631 response->client_state = client_state;
1632
1633 ast_debug(1, "Received REGISTER response %d(%.*s)\n",
1634 param->code, (int) param->reason.slen, param->reason.ptr);
1635
1636 if (param->rdata) {
1637 struct pjsip_retry_after_hdr *retry_after;
1638 pjsip_transaction *tsx;
1639
1640 retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER,
1641 NULL);
1642 response->retry_after = retry_after ? retry_after->ivalue : 0;
1643
1644 /*
1645 * If we got a response from the server, we have to use the tdata
1646 * from the transaction, not the tdata saved when we sent the
1647 * request. If we use the saved tdata, we won't process responses
1648 * like 423 Interval Too Brief correctly and we'll wind up sending
1649 * the bad Expires value again.
1650 */
1651 pjsip_tx_data_dec_ref(client_state->last_tdata);
1652
1653 tsx = pjsip_rdata_get_tsx(param->rdata);
1654 response->old_request = tsx->last_tx;
1655 pjsip_tx_data_add_ref(response->old_request);
1656 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
1657 AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(param->rdata->tp_info.transport,
1658 response->transport_key);
1659
1660 } else {
1661 /* old_request steals the reference */
1662 response->old_request = client_state->last_tdata;
1663 }
1664 client_state->last_tdata = NULL;
1665
1666 /*
1667 * Transfer response reference to serializer task so the
1668 * nominal path will not dec the response ref in this
1669 * pjproject callback thread.
1670 */
1671 if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
1672 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
1673 ao2_cleanup(response);
1674 }
1675}
#define AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(_transport, _dest)
Fill a buffer with a pjsip transport's remote ip address and port.
Definition res_pjsip.h:91
static int handle_registration_response(void *data)
Callback function for handling a response to a registration attempt.
static void registration_response_destroy(void *obj)
Registration response structure destructor.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_assert, ast_debug, ast_log, AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR, ast_sip_push_task(), ast_threadstorage_get(), registration_response::client_state, registration_response::code, registration_response::expiration, handle_registration_response(), sip_outbound_registration_client_state::last_tdata, LOG_WARNING, NULL, registration_response::old_request, registration_response::rdata, registration_response_destroy(), registration_response::retry_after, sip_outbound_registration_client_state::serializer, and registration_response::transport_key.

Referenced by sip_outbound_registration_regc_alloc().

◆ sip_outbound_registration_state_alloc()

static struct sip_outbound_registration_state * sip_outbound_registration_state_alloc ( struct sip_outbound_registration registration)
static

Allocator function for registration state.

Definition at line 1717 of file res_pjsip_outbound_registration.c.

1718{
1720 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1721
1723 if (!state) {
1724 return NULL;
1725 }
1726 state->client_state = ao2_alloc(sizeof(*state->client_state),
1728 if (!state->client_state) {
1730 return NULL;
1731 }
1732
1733 state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
1734 pj_timer_entry_init(&state->client_state->timer, 0, state->client_state,
1736 state->client_state->transport_name = ast_strdup(registration->transport);
1737 state->client_state->registration_name =
1739 state->client_state->user_agent = ast_strdup(registration->user_agent);
1740
1741 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);
1742 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
1743 sip_outbound_registration_status_str(state->client_state->status));
1744
1745 if (!state->client_state->transport_name
1746 || !state->client_state->registration_name) {
1748 return NULL;
1749 }
1750
1751 /* Create name with seq number appended. */
1752 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outreg/%s",
1754
1755 state->client_state->serializer = ast_sip_create_serializer_group(tps_name,
1757 if (!state->client_state->serializer) {
1759 return NULL;
1760 }
1761
1762 state->registration = ao2_bump(registration);
1763 return state;
1764}
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition res_pjsip.c:2089
static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
Timer callback function, used just for registrations.
static void sip_outbound_registration_state_destroy(void *obj)
Destructor function for registration state.
static void sip_outbound_registration_client_state_destroy(void *obj)
Destructor function for client registration state.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).

References ao2_alloc, ao2_bump, ao2_cleanup, ast_sip_create_serializer_group(), ast_sorcery_object_get_id(), AST_STATSD_GAUGE, ast_statsd_log_string(), ast_statsd_log_string_va(), ast_strdup, ast_taskprocessor_build_name(), AST_TASKPROCESSOR_MAX_NAME, NULL, sip_outbound_registration_state::registration, shutdown_group, sip_outbound_registration_client_state_destroy(), sip_outbound_registration_state_destroy(), sip_outbound_registration_status_str(), sip_outbound_registration_timer_cb(), SIP_REGISTRATION_UNREGISTERED, sip_outbound_registration::transport, and sip_outbound_registration::user_agent.

Referenced by sip_outbound_registration_apply().

◆ sip_outbound_registration_state_destroy()

static void sip_outbound_registration_state_destroy ( void *  obj)
static

Destructor function for registration state.

Definition at line 1678 of file res_pjsip_outbound_registration.c.

1679{
1681
1682 ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
1683 state->registration ? state->registration->server_uri : "",
1684 state->registration ? state->registration->client_uri : "");
1685 ao2_cleanup(state->registration);
1686
1687 if (!state->client_state) {
1688 /* Nothing to do */
1689 } else if (!state->client_state->serializer) {
1690 ao2_ref(state->client_state, -1);
1691 } else if (ast_sip_push_task(state->client_state->serializer,
1692 handle_client_state_destruction, state->client_state)) {
1693 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
1694 ao2_ref(state->client_state, -1);
1695 }
1696}

References ao2_cleanup, ao2_ref, ast_debug, ast_log, ast_sip_push_task(), handle_client_state_destruction(), and LOG_WARNING.

Referenced by sip_outbound_registration_state_alloc().

◆ sip_outbound_registration_status_str()

static const char * sip_outbound_registration_status_str ( enum sip_outbound_registration_status  state)
static

◆ sip_outbound_registration_timer_cb()

static void sip_outbound_registration_timer_cb ( pj_timer_heap_t *  timer_heap,
struct pj_timer_entry *  entry 
)
static

Timer callback function, used just for registrations.

Definition at line 1053 of file res_pjsip_outbound_registration.c.

1054{
1055 struct sip_outbound_registration_client_state *client_state = entry->user_data;
1056
1057 entry->id = 0;
1058
1059 /*
1060 * Transfer client_state reference to serializer task so the
1061 * nominal path will not dec the client_state ref in this
1062 * pjproject callback thread.
1063 */
1064 if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
1065 ast_log(LOG_WARNING, "Scheduled outbound registration could not be executed.\n");
1066 ao2_ref(client_state, -1);
1067 }
1068}

References ao2_ref, ast_log, ast_sip_push_task(), handle_client_registration(), LOG_WARNING, and sip_outbound_registration_client_state::serializer.

Referenced by sip_outbound_registration_state_alloc().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2898 of file res_pjsip_outbound_registration.c.

2899{
2900 int remaining;
2901
2903
2904 ast_manager_unregister("PJSIPShowRegistrationsOutbound");
2905 ast_manager_unregister("PJSIPUnregister");
2906 ast_manager_unregister("PJSIPRegister");
2907
2911
2913
2916
2918
2919 ao2_global_obj_release(current_states);
2920
2922
2923 /* Wait for registration serializers to get destroyed. */
2924 ast_debug(2, "Waiting for registration transactions to complete for unload.\n");
2926 if (remaining) {
2927 /*
2928 * NOTE: We probably have a sip_outbound_registration_client_state
2929 * ref leak if the remaining count cannot reach zero after a few
2930 * minutes of trying to unload.
2931 */
2932 ast_log(LOG_WARNING, "Unload incomplete. Could not stop %d outbound registrations. Try again later.\n",
2933 remaining);
2934 return -1;
2935 }
2936
2937 ast_debug(2, "Successful shutdown.\n");
2938
2941
2942 return 0;
2943}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition astobj2.h:859
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7698
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Definition res_pjsip.c:315
void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a transport shutdown monitor from all reliable transports.
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition pjsip_cli.c:326
#define MAX_UNLOAD_TIMEOUT_TIME
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.
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:2487
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Remove an observer from a sorcery instance.
Definition sorcery.c:601
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
Definition sorcery.c:1125
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1201

References ao2_cleanup, ao2_global_obj_release, ARRAY_LEN, ast_cli_unregister_multiple(), ast_debug, ast_log, ast_manager_unregister(), ast_serializer_shutdown_group_join(), ast_sip_get_sorcery(), ast_sip_transport_monitor_unregister_all(), ast_sip_unregister_cli_formatter(), ast_sip_unregister_endpoint_identifier(), ast_sorcery_instance_observer_remove(), ast_sorcery_object_unregister(), ast_sorcery_observer_remove(), cli_formatter, cli_outbound_registration, line_identifier, LOG_WARNING, MAX_UNLOAD_TIMEOUT_TIME, network_change_sub, NULL, observer_callbacks_auth, observer_callbacks_registrations, registration_transport_shutdown_cb(), shutdown_group, and stasis_unsubscribe_and_join().

Referenced by load_module().

◆ unregister_all()

static void unregister_all ( void  )
static

Definition at line 2340 of file res_pjsip_outbound_registration.c.

2341{
2342 struct ao2_container *states;
2343
2344 states = ao2_global_obj_ref(current_states);
2345 if (!states) {
2346 return;
2347 }
2348
2349 /* Clean out all the states and let sorcery handle recreating the registrations */
2351 ao2_ref(states, -1);
2352}

References ao2_callback, ao2_global_obj_ref, ao2_ref, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by ami_unregister(), cli_unregister(), and reregister_all().

◆ unregister_task()

static int unregister_task ( void *  obj)
static

Definition at line 2296 of file res_pjsip_outbound_registration.c.

2297{
2299 struct pjsip_regc *client = state->client_state->client;
2300 pjsip_tx_data *tdata;
2301 pjsip_regc_info info;
2302
2303 pjsip_regc_get_info(client, &info);
2304 ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
2305 state->registration->server_uri, state->registration->client_uri);
2306
2307 cancel_registration(state->client_state);
2308
2309 if (pjsip_regc_unregister(client, &tdata) == PJ_SUCCESS
2310 && add_configured_supported_headers(state->client_state, tdata)) {
2311 registration_client_send(state->client_state, tdata);
2312 }
2313
2314 ao2_ref(state, -1);
2315 return 0;
2316}

References add_configured_supported_headers(), ao2_ref, ast_debug, cancel_registration(), and registration_client_send().

Referenced by queue_unregister().

◆ update_client_state_status()

static void update_client_state_status ( struct sip_outbound_registration_client_state client_state,
enum sip_outbound_registration_status  status 
)
static

Definition at line 1094 of file res_pjsip_outbound_registration.c.

1095{
1096 const char *status_old;
1097 const char *status_new;
1098
1099 if (client_state->status == status) {
1100 /* Status state did not change at all. */
1101 return;
1102 }
1103
1104 status_old = sip_outbound_registration_status_str(client_state->status);
1106 client_state->status = status;
1107
1108 if (!strcmp(status_old, status_new)) {
1109 /*
1110 * The internal status state may have changed but the status
1111 * state we tell the world did not change at all.
1112 */
1113 return;
1114 }
1115
1116 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
1117 status_old);
1118 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
1119 status_new);
1120}

References AST_STATSD_GAUGE, ast_statsd_log_string_va(), sip_outbound_registration_status_str(), status, and sip_outbound_registration_client_state::status.

Referenced by handle_client_state_destruction(), handle_registration_response(), and schedule_retry().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Outbound Registration Support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .reload = reload_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", .optional_modules = "res_statsd", }
static

Definition at line 3069 of file res_pjsip_outbound_registration.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 3069 of file res_pjsip_outbound_registration.c.

◆ cli_formatter

struct ast_sip_cli_formatter_entry* cli_formatter
static

Definition at line 2769 of file res_pjsip_outbound_registration.c.

Referenced by load_module(), and unload_module().

◆ cli_outbound_registration

struct ast_cli_entry cli_outbound_registration[]
static

Definition at line 2750 of file res_pjsip_outbound_registration.c.

2750 {
2751 AST_CLI_DEFINE(cli_unregister, "Unregisters outbound registration target"),
2752 AST_CLI_DEFINE(cli_register, "Registers an outbound registration target"),
2753 AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
2754 .command = "pjsip list registrations",
2755 .usage = "Usage: pjsip list registrations [ like <pattern> ]\n"
2756 " List the configured PJSIP Registrations\n"
2757 " Optional regular expression pattern is used to filter the list.\n"),
2758 AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
2759 .command = "pjsip show registrations",
2760 .usage = "Usage: pjsip show registrations [ like <pattern> ]\n"
2761 " Show the configured PJSIP Registrations\n"
2762 " Optional regular expression pattern is used to filter the list.\n"),
2763 AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
2764 .command = "pjsip show registration",
2765 .usage = "Usage: pjsip show registration <id>\n"
2766 " Show the configured PJSIP Registration\n"),
2767};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
static char * cli_register(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * my_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
char * usage
Definition utils/frame.c:37

Referenced by load_module(), and unload_module().

◆ line_identifier

struct ast_sip_endpoint_identifier line_identifier
static
Initial value:
= {
.identify_endpoint = line_identify,
}
static struct ast_sip_endpoint * line_identify(pjsip_rx_data *rdata)
Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing regist...

Definition at line 752 of file res_pjsip_outbound_registration.c.

752 {
753 .identify_endpoint = line_identify,
754};

Referenced by load_module(), and unload_module().

◆ network_change_sub

struct stasis_subscription* network_change_sub
static

subscription id for network change events

Definition at line 634 of file res_pjsip_outbound_registration.c.

Referenced by load_module(), and unload_module().

◆ observer_callbacks_auth

const struct ast_sorcery_observer observer_callbacks_auth
static
Initial value:
= {
.loaded = auth_observer,
}
static void auth_observer(const char *type)

Definition at line 2807 of file res_pjsip_outbound_registration.c.

2807 {
2808 .loaded = auth_observer,
2809};

Referenced by load_module(), and unload_module().

◆ observer_callbacks_registrations

const struct ast_sorcery_instance_observer observer_callbacks_registrations
static
Initial value:
= {
.object_type_loaded = registration_loaded_observer,
}
static void registration_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)

Definition at line 2863 of file res_pjsip_outbound_registration.c.

2863 {
2864 .object_type_loaded = registration_loaded_observer,
2865};

Referenced by load_module(), pjsip_outbound_registration_metrics_init(), pjsip_outbound_registration_metrics_unload_cb(), and unload_module().

◆ OUTBOUND_NAME

pj_str_t OUTBOUND_NAME = { "outbound", 8 }
static

Definition at line 767 of file res_pjsip_outbound_registration.c.

767{ "outbound", 8 };

Referenced by add_configured_supported_headers().

◆ PATH_NAME

pj_str_t PATH_NAME = { "path", 4 }
static

Definition at line 766 of file res_pjsip_outbound_registration.c.

766{ "path", 4 };

Referenced by add_configured_supported_headers().

◆ registration_observer

const struct ast_sorcery_observer registration_observer
static
Initial value:
= {
}
static void registration_deleted_observer(const void *obj)

Definition at line 2883 of file res_pjsip_outbound_registration.c.

2883 {
2885};

Referenced by load_module(), pjsip_outbound_registration_metrics_init(), and pjsip_outbound_registration_metrics_unload_cb().

◆ security_negotiation_map

const char* security_negotiation_map[]
static
Initial value:
= {
}
@ AST_SIP_SECURITY_NEG_NONE
Definition res_pjsip.h:353

Definition at line 2236 of file res_pjsip_outbound_registration.c.

2236 {
2238 [AST_SIP_SECURITY_NEG_MEDIASEC] = "mediasec",
2239};

Referenced by security_negotiation_to_str().

◆ shutdown_group

struct ast_serializer_shutdown_group* shutdown_group
static

Shutdown group to monitor sip_outbound_registration_client_state serializers.

Definition at line 627 of file res_pjsip_outbound_registration.c.

Referenced by load_module(), sip_outbound_registration_state_alloc(), and unload_module().