Asterisk - The Open Source Telephony Project GIT-master-4f2b068
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/taskpool.h"
#include "asterisk/serializer_shutdown_group.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 631 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 450 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 625 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 447 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 453 of file res_pjsip_outbound_registration.c.

453 {
454 /*! \brief Currently unregistered */
456 /*! \brief Registered, yay! */
458 /*! \brief Registration was rejected, but response was temporal */
460 /*! \brief Registration was rejected, permanently */
462 /*! \brief Registration is stopping. */
464 /*! \brief Registration has been stopped */
466};
@ 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 3070 of file res_pjsip_outbound_registration.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3070 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 1001 of file res_pjsip_outbound_registration.c.

1002{
1003 if (client_state->support_path) {
1004 if (!add_to_supported_header(tdata, &PATH_NAME)) {
1005 return 0;
1006 }
1007 }
1008
1009 if (client_state->support_outbound) {
1010 if (!add_to_supported_header(tdata, &OUTBOUND_NAME)) {
1011 return 0;
1012 }
1013 }
1014
1015 return 1;
1016}
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 822 of file res_pjsip_outbound_registration.c.

824{
825 int add_sec_client_header = 0;
826 struct sip_outbound_registration *reg = NULL;
827 struct ast_sip_endpoint *endpt = NULL;
828 struct ao2_container *contact_container;
829 struct ast_sip_contact_status *contact_status = NULL;
830 struct ast_sip_security_mechanism_vector *sec_mechs = NULL;
831 static const pj_str_t security_verify = { "Security-Verify", 15 };
832 static const pj_str_t security_client = { "Security-Client", 15 };
833
835 return;
836 }
837
838 /* Get contact status through registration -> endpoint name -> aor -> contact (if set) */
839 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", client_state->registration_name))
840 && !ast_strlen_zero(reg->endpoint) && (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))
841 && (contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors))) {
842 /* Retrieve all contacts associated with aors from this endpoint
843 * and find the first one that has security mechanisms.
844 */
845 ao2_callback(contact_container, OBJ_NODATA, contact_has_security_mechanisms, &contact_status);
846 if (contact_status) {
847 ao2_lock(contact_status);
848 sec_mechs = &contact_status->security_mechanisms;
849 }
850 ao2_cleanup(contact_container);
851 }
852 /* Use client_state->server_security_mechanisms if contact_status does not exist. */
853 if (!contact_status && AST_VECTOR_SIZE(&client_state->server_security_mechanisms)) {
854 sec_mechs = &client_state->server_security_mechanisms;
855 }
856 if (client_state->status == SIP_REGISTRATION_REJECTED_TEMPORARY || client_state->auth_attempted) {
857 if (sec_mechs != NULL && pjsip_msg_find_hdr_by_name(tdata->msg, &security_verify, NULL) == NULL) {
858 ast_sip_add_security_headers(sec_mechs, "Security-Verify", 0, tdata);
859 }
860 if (client_state->last_status_code == 494) {
861 ast_sip_remove_headers_by_name_and_value(tdata->msg, &security_client, NULL);
862 } else {
863 /* necessary if a retry occures */
864 add_sec_client_header = (pjsip_msg_find_hdr_by_name(tdata->msg, &security_client, NULL) == NULL) ? 1 : 0;
865 }
866 } else {
867 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
868 }
869
870 if (add_sec_client_header) {
871 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
872 }
873
874 /* Cleanup */
875 if (contact_status) {
876 ao2_unlock(contact_status);
877 ao2_cleanup(contact_status);
878 }
879 ao2_cleanup(endpt);
880 ao2_cleanup(reg);
881}
#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:1061
const ast_string_field aors
Definition res_pjsip.h:1090
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 966 of file res_pjsip_outbound_registration.c.

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

2609{
2610 struct sip_ami_outbound *ami = arg;
2611
2612 ami->registration = obj;
2614}
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2133
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 2572 of file res_pjsip_outbound_registration.c.

2573{
2574 struct sip_ami_outbound *ami = obj;
2575 struct ast_str *buf;
2577
2578 buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
2579 if (!buf) {
2580 return -1;
2581 }
2582
2584
2586 pjsip_regc_info info;
2587
2588 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
2589 ++ami->registered;
2590 } else {
2591 ++ami->not_registered;
2592 }
2593
2594 ast_str_append(&buf, 0, "Status: %s\r\n",
2595 sip_outbound_registration_status_str(state->client_state->status));
2596
2597 pjsip_regc_get_info(state->client_state->client, &info);
2598 ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
2599 ao2_ref(state, -1);
2600 }
2601
2602 astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
2603 ast_free(buf);
2604
2606}
#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:3227
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 2528 of file res_pjsip_outbound_registration.c.

2529{
2530 const char *registration_name = astman_get_header(m, "Registration");
2532
2533 if (ast_strlen_zero(registration_name)) {
2534 astman_send_error(s, m, "Registration parameter missing.");
2535 return 0;
2536 }
2537
2538 if (strcmp(registration_name, "*all") == 0) {
2540 astman_send_ack(s, m, "Reregistrations queued.");
2541 return 0;
2542 }
2543
2544 state = get_state(registration_name);
2545 if (!state) {
2546 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2547 return 0;
2548 }
2549
2550 /* We need to serialize the unregister and register so they need
2551 * to be queued as separate tasks.
2552 */
2553 if (queue_unregister(state)) {
2554 astman_send_ack(s, m, "Failed to queue unregistration");
2555 } else if (queue_register(state)) {
2556 astman_send_ack(s, m, "Failed to queue unregistration");
2557 } else {
2558 astman_send_ack(s, m, "Reregistration sent");
2559 }
2560
2561 ao2_ref(state, -1);
2562 return 0;
2563}
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 2616 of file res_pjsip_outbound_registration.c.

2618{
2619 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2620 struct sip_ami_outbound ami_outbound = { .ami = &ami };
2621 struct ao2_container *regs;
2622
2623 regs = get_registrations();
2624 if (!regs) {
2625 astman_send_error(s, m, "Unable to retrieve "
2626 "outbound registrations\n");
2627 return -1;
2628 }
2629
2630 astman_send_listack(s, m, "Following are Events for each Outbound registration",
2631 "start");
2632
2634
2635 astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
2636 ami_outbound.registered + ami_outbound.not_registered);
2637 astman_append(s,
2638 "Registered: %d\r\n"
2639 "NotRegistered: %d\r\n",
2640 ami_outbound.registered,
2641 ami_outbound.not_registered);
2643
2644 ao2_ref(regs, -1);
2645 return 0;
2646}
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:3225
const struct message * m
Definition res_pjsip.h:3229

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 2496 of file res_pjsip_outbound_registration.c.

2497{
2498 const char *registration_name = astman_get_header(m, "Registration");
2500
2501 if (ast_strlen_zero(registration_name)) {
2502 astman_send_error(s, m, "Registration parameter missing.");
2503 return 0;
2504 }
2505
2506 if (strcmp(registration_name, "*all") == 0) {
2508 astman_send_ack(s, m, "Unregistrations queued.");
2509 return 0;
2510 }
2511
2512 state = get_state(registration_name);
2513 if (!state) {
2514 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2515 return 0;
2516 }
2517
2518 if (queue_unregister(state)) {
2519 astman_send_ack(s, m, "Failed to queue unregistration");
2520 } else {
2521 astman_send_ack(s, m, "Unregistration sent");
2522 }
2523
2524 ao2_ref(state, -1);
2525 return 0;
2526}
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 3070 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 2772 of file res_pjsip_outbound_registration.c.

2773{
2774 struct sip_outbound_registration *registration;
2776 struct ao2_container *regs;
2777 const char *registration_id;
2778 struct ao2_iterator i;
2779
2780 ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
2781
2782 regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
2784 if (!regs || ao2_container_count(regs) == 0) {
2785 ao2_cleanup(regs);
2786 return;
2787 }
2788
2789 i = ao2_iterator_init(regs, 0);
2790 for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
2791 registration_id = ast_sorcery_object_get_id(registration);
2792 state = get_state(registration_id);
2793 if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
2794 ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
2795
2796 if (ast_sip_push_task(state->client_state->serializer,
2798 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
2799 ao2_ref(state, -1);
2800 }
2801 }
2803 }
2805 ao2_cleanup(regs);
2806}
#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.
#define ast_sip_push_task(serializer, sip_task, task_data)
Definition res_pjsip.h:2094
#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 1867 of file res_pjsip_outbound_registration.c.

1869{
1870 int rc = 1;
1872 struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
1873 struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
1874 struct ast_variable *vc = NULL;
1875
1876 if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
1877 rc = 0;
1878 ast_debug(4, "Registration '%s' changed. Can't re-use.\n", ast_sorcery_object_get_id(existing));
1879 } else {
1880 ast_debug(4, "Registration '%s' didn't change. Can re-use\n", ast_sorcery_object_get_id(existing));
1881 }
1882
1886
1887 return rc;
1888}
static struct ast_sorcery * sorcery
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260
#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 758 of file res_pjsip_outbound_registration.c.

759{
760 if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
761 &client_state->timer, client_state->timer.id)) {
762 /* The timer was successfully cancelled, drop the refcount of client_state */
763 ao2_ref(client_state, -1);
764 }
765}
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:514
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 2812 of file res_pjsip_outbound_registration.c.

2813{
2815 struct sip_outbound_registration *registration;
2816
2817 registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
2818 ast_sorcery_object_get_id(state->registration));
2819 if (!registration) {
2820 /* This is a dead registration */
2821 return CMP_MATCH;
2822 }
2823
2824 ao2_ref(registration, -1);
2825 return 0;
2826}
@ 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 2361 of file res_pjsip_outbound_registration.c.

2363{
2364 char *result = NULL;
2365 int wordlen;
2366 int which = 0;
2367 struct sip_outbound_registration *registration;
2369 struct ao2_iterator i;
2370
2371 if (pos != 3) {
2372 return NULL;
2373 }
2374
2375 wordlen = strlen(word);
2376 if (wordlen == 0 && ++which > state) {
2377 return ast_strdup("*all");
2378 }
2379
2382 if (!registrations) {
2383 return NULL;
2384 }
2385
2387 while ((registration = ao2_iterator_next(&i))) {
2388 const char *name = ast_sorcery_object_get_id(registration);
2389
2390 if (!strncasecmp(word, name, wordlen) && ++which > state) {
2392 }
2393
2394 ao2_ref(registration, -1);
2395 if (result) {
2396 break;
2397 }
2398 }
2400
2402 return result;
2403}
#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 2648 of file res_pjsip_outbound_registration.c.

2649{
2651 struct ao2_container *s_container;
2652
2654 if (!container) {
2655 return NULL;
2656 }
2657
2660 if (!s_container) {
2661 return NULL;
2662 }
2663
2664 if (ao2_container_dup(s_container, container, 0)) {
2665 ao2_ref(s_container, -1);
2666 return NULL;
2667 }
2668
2669 return s_container;
2670}
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:981

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 2672 of file res_pjsip_outbound_registration.c.

2673{
2675
2676 return 0;
2677}
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
static struct @522 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 2708 of file res_pjsip_outbound_registration.c.

2709{
2710 struct sip_outbound_registration *registration = obj;
2711 struct ast_sip_cli_context *context = arg;
2712 const char *id = ast_sorcery_object_get_id(registration);
2714 int expsecs;
2715#define REGISTRATION_URI_FIELD_LEN 53
2716
2717 ast_assert(context->output_buffer != NULL);
2718 expsecs = state ? state->client_state->registration_expires - ((int) time(NULL)) : 0;
2719
2720 ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s %-26s %-16s %s%d%s\n",
2721 id,
2722 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2723 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2727 : "n/a",
2729 state ? " (exp. " : "", abs(expsecs), state ? (expsecs < 0 ? "s ago)" : "s)") : "");
2731
2732 if (context->show_details
2733 || (context->show_details_only_level_0 && context->indent_level == 0)) {
2734 ast_str_append(&context->output_buffer, 0, "\n");
2736 }
2737
2738 return 0;
2739}
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:779
#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 2696 of file res_pjsip_outbound_registration.c.

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

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 2448 of file res_pjsip_outbound_registration.c.

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

2680{
2681 struct ao2_container *states;
2682 void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
2683
2684 if (!obj) {
2685 /* if the object no longer exists then remove its state */
2686 states = ao2_global_obj_ref(current_states);
2687 if (states) {
2689 ao2_ref(states, -1);
2690 }
2691 }
2692
2693 return obj;
2694}
#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 2405 of file res_pjsip_outbound_registration.c.

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

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 799 of file res_pjsip_outbound_registration.c.

800{
801 struct ast_sip_contact *contact = obj;
802 struct pjsip_generic_string_hdr_vector *header_vector = arg;
803 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
804
805 if (!contact_status) {
806 return 0;
807 }
808 if (AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
809 goto out;
810 }
811
812 ao2_lock(contact_status);
814 ao2_unlock(contact_status);
815
816out:
817 ao2_cleanup(contact_status);
818 return 0;
819}
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 782 of file res_pjsip_outbound_registration.c.

783{
784 struct ast_sip_contact *contact = obj;
785 struct ast_sip_contact_status **ret = arg;
786 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
787
788 if (!contact_status) {
789 return 0;
790 }
791 if (!AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
792 ao2_cleanup(contact_status);
793 return 0;
794 }
795 *ret = contact_status;
796 return CMP_MATCH | CMP_STOP;
797}
@ 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 1891 of file res_pjsip_outbound_registration.c.

1892{
1893 char *cmd = NULL;
1894 const char *token;
1895 const char *url = "https://www.googleapis.com/oauth2/v3/token";
1896 char buf[4096];
1897 int res;
1898 struct ast_json_error error;
1899 struct ast_json *json;
1900
1901 /* set timeout to be shorter than default 180s (also checks func_curl is available) */
1902 if (ast_func_write(NULL, "CURLOPT(conntimeout)", "10")) {
1903 ast_log(LOG_ERROR, "CURL is unavailable. This is required for Google OAuth 2.0 authentication. Please ensure it is loaded.\n");
1904 return NULL;
1905 }
1906
1907 res = ast_asprintf(&cmd,
1908 "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
1909 url, auth->oauth_clientid, auth->oauth_secret, auth->refresh_token);
1910 if (res < 0) {
1911 return NULL;
1912 }
1913
1914 ast_debug(2, "Performing Google OAuth 2.0 authentication using command: %s\n", cmd);
1915
1916 buf[0] = '\0';
1917 res = ast_func_read(NULL, cmd, buf, sizeof(buf));
1918 ast_free(cmd);
1919 if (res) {
1920 ast_log(LOG_ERROR, "Could not retrieve Google OAuth 2.0 authentication\n");
1921 return NULL;
1922 }
1923
1924 ast_debug(2, "Google OAuth 2.0 authentication returned: %s\n", buf);
1925
1926 json = ast_json_load_string(buf, &error);
1927 if (!json) {
1928 ast_log(LOG_ERROR, "Could not parse Google OAuth 2.0 authentication: %d(%d) %s: '%s'\n",
1929 error.line, error.column, error.text, buf);
1930 return NULL;
1931 }
1932
1933 token = ast_json_string_get(ast_json_object_get(json, "access_token"));
1934 if (!token) {
1935 ast_log(LOG_ERROR, "Could not find Google OAuth 2.0 access_token in: '%s'\n",
1936 buf);
1937 }
1938 token = ast_strdup(token);
1939 ast_json_unref(json);
1940 return token;
1941}
#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 687 of file res_pjsip_outbound_registration.c.

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

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 718 of file res_pjsip_outbound_registration.c.

719{
720 static const pj_str_t LINE_STR = { "line", 4 };
721
722 return ast_sip_pjsip_uri_get_other_param((pjsip_uri *)uri, &LINE_STR);
723}
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:3482

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 1019 of file res_pjsip_outbound_registration.c.

1020{
1021 RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
1022 pjsip_tx_data *tdata;
1023
1024 if (set_outbound_initial_authentication_credentials(client_state->client, &client_state->outbound_auths)) {
1025 ast_log(LOG_WARNING, "Failed to set initial authentication credentials\n");
1026 }
1027
1028 if (client_state->status == SIP_REGISTRATION_STOPPED
1029 || pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
1030 return 0;
1031 }
1032
1033 if (DEBUG_ATLEAST(1)) {
1034 pjsip_regc_info info;
1035
1036 pjsip_regc_get_info(client_state->client, &info);
1037 ast_log(LOG_DEBUG, "Outbound REGISTER attempt %u to '%.*s' with client '%.*s'\n",
1038 client_state->retries + 1,
1039 (int) info.server_uri.slen, info.server_uri.ptr,
1040 (int) info.client_uri.slen, info.client_uri.ptr);
1041 }
1042
1043 if (!add_configured_supported_headers(client_state, tdata)) {
1044 ast_log(LOG_WARNING, "Failed to set supported headers\n");
1045 return -1;
1046 }
1047
1048 registration_client_send(client_state, tdata);
1049
1050 return 0;
1051}
#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 1124 of file res_pjsip_outbound_registration.c.

1125{
1126 struct sip_outbound_registration_client_state *client_state = data;
1127
1128 cancel_registration(client_state);
1129
1130 if (client_state->client) {
1131 pjsip_regc_info info;
1132 pjsip_tx_data *tdata;
1133
1134 pjsip_regc_get_info(client_state->client, &info);
1135
1136 if (info.is_busy == PJ_TRUE) {
1137 /* If a client transaction is in progress we defer until it is complete */
1138 ast_debug(1,
1139 "Registration transaction is busy with server '%.*s' from client '%.*s'.\n",
1140 (int) info.server_uri.slen, info.server_uri.ptr,
1141 (int) info.client_uri.slen, info.client_uri.ptr);
1142 client_state->destroy = 1;
1143 ao2_ref(client_state, -1);
1144 return 0;
1145 }
1146
1147 switch (client_state->status) {
1149 break;
1151 ast_debug(1,
1152 "Trying to unregister with server '%.*s' from client '%.*s' before destruction.\n",
1153 (int) info.server_uri.slen, info.server_uri.ptr,
1154 (int) info.client_uri.slen, info.client_uri.ptr);
1155
1157 client_state->destroy = 1;
1158 if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS
1159 && add_configured_supported_headers(client_state, tdata)
1160 && registration_client_send(client_state, tdata) == PJ_SUCCESS) {
1161 ao2_ref(client_state, -1);
1162 return 0;
1163 }
1164 break;
1169 break;
1170 }
1171
1172 pjsip_regc_destroy(client_state->client);
1173 client_state->client = NULL;
1174 }
1175
1180 ao2_ref(client_state, -1);
1181
1182 return 0;
1183}
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 1410 of file res_pjsip_outbound_registration.c.

1411{
1412 struct registration_response *response = data;
1413 pjsip_regc_info info;
1414 char server_uri[PJSIP_MAX_URL_SIZE];
1415 char client_uri[PJSIP_MAX_URL_SIZE];
1416
1417 if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
1418 ao2_ref(response, -1);
1419 return 0;
1420 }
1421
1422 pjsip_regc_get_info(response->client_state->client, &info);
1423 ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
1424 ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
1425 response->client_state->last_status_code = response->code;
1426
1427 ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
1428 response->code, server_uri, client_uri);
1429
1430 if (response->code == 408 || response->code == 503) {
1431 if ((ast_sip_failover_request(response->old_request))) {
1432 int res = registration_client_send(response->client_state, response->old_request);
1433 /* The tdata ref was stolen */
1434 response->old_request = NULL;
1435 if (res == PJ_SUCCESS) {
1436 ao2_ref(response, -1);
1437 return 0;
1438 }
1439 }
1440 } else if ((response->code == 401 || response->code == 407 || response->code == 494)
1441 && (!response->client_state->auth_attempted
1442 || response->rdata->msg_info.cseq->cseq != response->client_state->auth_cseq)) {
1443 int res;
1444 pjsip_cseq_hdr *cseq_hdr;
1445 pjsip_tx_data *tdata;
1446
1448 struct sip_outbound_registration *reg = NULL;
1449 struct ast_sip_endpoint *endpt = NULL;
1450 struct ao2_container *contact_container = NULL;
1451 pjsip_generic_string_hdr *header;
1452 struct pjsip_generic_string_hdr_vector header_vector;
1453 static const pj_str_t security_server = { "Security-Server", 15 };
1454
1455 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
1456 response->client_state->registration_name)) && reg->endpoint &&
1457 (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))) {
1458 /* Retrieve all contacts associated with aors from this endpoint (if set). */
1459 contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors);
1460 }
1461 /* Add server list of security mechanism to client_state and contact status if exists. */
1462 AST_VECTOR_INIT(&header_vector, 1);
1463 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, NULL);
1464 for (; header;
1465 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, header->next)) {
1466 AST_VECTOR_APPEND(&header_vector, header);
1468 }
1469 if (contact_container) {
1470 /* Add server security mechanisms to contact status of all associated contacts to be able to send correct
1471 * Security-Verify headers on subsequent non-REGISTER requests through this outbound registration.
1472 */
1473 ao2_callback(contact_container, OBJ_NODATA, contact_add_security_headers_to_status, &header_vector);
1474 ao2_cleanup(contact_container);
1475 }
1476 AST_VECTOR_FREE(&header_vector);
1477 ao2_cleanup(endpt);
1478 ao2_cleanup(reg);
1479 }
1480
1481 if (response->code == 494) {
1483 response->client_state->retries++;
1484 schedule_registration(response->client_state, 0);
1485 ao2_ref(response, -1);
1486 return 0;
1488 response->rdata, response->old_request, &tdata)) {
1489 response->client_state->auth_attempted = 1;
1490 ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
1491 server_uri, client_uri);
1492 pjsip_tx_data_add_ref(tdata);
1493
1494 res = registration_client_send(response->client_state, tdata);
1495
1496 /* Save the cseq that actually got sent. */
1497 cseq_hdr = (pjsip_cseq_hdr *) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ,
1498 NULL);
1499 response->client_state->auth_cseq = cseq_hdr->cseq;
1500 pjsip_tx_data_dec_ref(tdata);
1501 if (res == PJ_SUCCESS) {
1502 ao2_ref(response, -1);
1503 return 0;
1504 }
1505 } else {
1506 ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
1507 server_uri, client_uri);
1508 }
1509 /* Otherwise, fall through so the failure is processed appropriately */
1510 }
1511
1512 response->client_state->auth_attempted = 0;
1513
1514 if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
1515 /* Check if this is in regards to registering or unregistering */
1516 if (response->expiration) {
1517 int next_registration_round;
1518
1519 /* If the registration went fine simply reschedule registration for the future */
1520 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
1522 response->client_state->retries = 0;
1523 next_registration_round = response->expiration - REREGISTER_BUFFER_TIME;
1524 if (next_registration_round < 0) {
1525 /* Re-register immediately. */
1526 next_registration_round = 0;
1527 }
1528 schedule_registration(response->client_state, next_registration_round);
1529
1530 /* See if we should monitor for transport shutdown */
1531 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1533 response->client_state->registration_name);
1534 }
1535 } else {
1536 ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
1538 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1542 }
1543 }
1544
1546 } else if (response->client_state->destroy) {
1547 /* We need to deal with the pending destruction instead. */
1548 } else if (response->retry_after) {
1549 /* If we have been instructed to retry after a period of time, schedule it as such */
1550 schedule_retry(response, response->retry_after, server_uri, client_uri);
1551 } else if (response->client_state->retry_interval
1552 && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
1553 if (response->client_state->retries == response->client_state->max_retries) {
1554 /* If we received enough temporal responses to exceed our maximum give up permanently */
1556 ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
1557 server_uri, client_uri);
1558 } else {
1559 /* On the other hand if we can still try some more do so */
1560 response->client_state->retries++;
1561 schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
1562 }
1563 } else {
1564 if (response->code == 403
1566 && response->client_state->retries < response->client_state->max_retries) {
1567 /* A forbidden response retry interval is configured and there are retries remaining */
1569 response->client_state->retries++;
1571 ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1572 server_uri, client_uri, response->client_state->forbidden_retry_interval);
1573 } else if (response->client_state->fatal_retry_interval
1574 && response->client_state->retries < response->client_state->max_retries) {
1575 /* Some kind of fatal failure response received, so retry according to configured interval */
1577 response->client_state->retries++;
1579 ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1580 response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
1581 } else {
1582 /* Finally if there's no hope of registering give up */
1584 if (response->rdata) {
1585 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
1586 response->code, server_uri, client_uri);
1587 } else {
1588 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
1589 }
1590 }
1591 }
1592
1593 ast_system_publish_registry("PJSIP", client_uri, server_uri,
1595
1596 if (response->client_state->destroy) {
1597 /* We have a pending deferred destruction to complete now. */
1598 ao2_ref(response->client_state, +1);
1600 }
1601
1602 ao2_ref(response, -1);
1603 return 0;
1604}
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:208
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:2172
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:1810
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 726 of file res_pjsip_outbound_registration.c.

727{
728 pjsip_param *line;
729 RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
731
732 if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
733 && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
734 return NULL;
735 }
736
737 states = ao2_global_obj_ref(current_states);
738 if (!states) {
739 return NULL;
740 }
741
743 if (!state || ast_strlen_zero(state->registration->endpoint)) {
744 return NULL;
745 }
746
747 ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
748 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
749
750 return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
751}
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 710 of file res_pjsip_outbound_registration.c.

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

References CMP_MATCH.

Referenced by line_identify().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2946 of file res_pjsip_outbound_registration.c.

2947{
2948 struct ao2_container *new_states;
2949
2951 if (!shutdown_group) {
2953 }
2954
2955 /* Create outbound registration states container. */
2958 if (!new_states) {
2959 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
2960 unload_module();
2962 }
2964 ao2_ref(new_states, -1);
2965
2966 /*
2967 * Register sorcery object descriptions.
2968 */
2969 ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
2970 ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
2971
2973 unload_module();
2975 }
2976
2977 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
2979 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
2980 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
2981 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));
2982 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
2983 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
2984 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
2985 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));
2986 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
2987 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));
2988 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));
2990 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));
2992 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
2993 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_outbound", "no", OPT_YESNO_T, 1, FLDSET(struct sip_outbound_registration, support_outbound));
2996 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
2997 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
2998 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, user_agent));
2999
3000 /*
3001 * Register sorcery observers.
3002 */
3007 || ast_sorcery_observer_add(ast_sip_get_sorcery(), "registration",
3009 ast_log(LOG_ERROR, "Unable to register observers.\n");
3010 unload_module();
3012 }
3013
3014 /* Register how this module identifies endpoints. */
3016
3017 /* Register CLI commands. */
3019 if (!cli_formatter) {
3020 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
3021 unload_module();
3023 }
3024 cli_formatter->name = "registration";
3033
3034 /* Register AMI actions. */
3038
3039 /* Clear any previous statsd gauges in case we weren't shutdown cleanly */
3040 ast_statsd_log("PJSIP.registrations.count", AST_STATSD_GAUGE, 0);
3041 ast_statsd_log("PJSIP.registrations.state.Registered", AST_STATSD_GAUGE, 0);
3042 ast_statsd_log("PJSIP.registrations.state.Unregistered", AST_STATSD_GAUGE, 0);
3043 ast_statsd_log("PJSIP.registrations.state.Rejected", AST_STATSD_GAUGE, 0);
3044
3045 /* Load configuration objects */
3047
3052
3054}
@ 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:304
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:706

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 1308 of file res_pjsip_outbound_registration.c.

1309{
1310 char *ma = a;
1311 char *mb = b;
1312
1313 return strcmp(ma, mb) == 0;
1314}
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 2746 of file res_pjsip_outbound_registration.c.

2747{
2748 return ast_sip_cli_traverse_objects(e, cmd, a);
2749}
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 2888 of file res_pjsip_outbound_registration.c.

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

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 2265 of file res_pjsip_outbound_registration.c.

2266{
2267 struct sip_outbound_registration *registration = obj;
2268
2269 return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
2270}
#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 2272 of file res_pjsip_outbound_registration.c.

2273{
2274 const struct sip_outbound_registration *registration = obj;
2275
2276 return ast_sip_auths_to_str(&registration->outbound_auths, buf);
2277}
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 2279 of file res_pjsip_outbound_registration.c.

2280{
2281 const struct sip_outbound_registration *registration = obj;
2282 int i;
2283 struct ast_variable *head = NULL;
2284
2285 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
2286 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
2287 AST_VECTOR_GET(&registration->outbound_auths, i), ""));
2288 }
2289
2290 if (head) {
2291 *fields = head;
2292 }
2293
2294 return 0;
2295}
#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 2330 of file res_pjsip_outbound_registration.c.

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

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 2319 of file res_pjsip_outbound_registration.c.

2320{
2321 ao2_ref(state, +1);
2322 if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
2323 ao2_ref(state, -1);
2324 return -1;
2325 }
2326
2327 return 0;
2328}
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 884 of file res_pjsip_outbound_registration.c.

886{
887 pj_status_t status;
888 int *callback_invoked;
889 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
890
891 callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
892 if (!callback_invoked) {
893 pjsip_tx_data_dec_ref(tdata);
894 return PJ_ENOMEM;
895 }
896 *callback_invoked = 0;
897
898 /* Due to the message going out the callback may now be invoked, so bump the count */
899 ao2_ref(client_state, +1);
900 /*
901 * We also bump tdata in expectation of saving it to client_state->last_tdata.
902 * We have to do it BEFORE pjsip_regc_send because if it succeeds, it decrements
903 * the ref count on its own.
904 */
905 pjsip_tx_data_add_ref(tdata);
906
907 /* Add Security-Verify or Security-Client headers */
908 add_security_headers(client_state, tdata);
909
910 /*
911 * Replace the User-Agent header if a different one should be used
912 */
913 if (!ast_strlen_zero(client_state->user_agent)) {
914 static const pj_str_t user_agent_str = { "User-Agent", 10 };
915 pjsip_generic_string_hdr *default_user_agent_hdr;
916 pjsip_generic_string_hdr *user_agent_hdr;
917 pj_str_t user_agent_val;
918 default_user_agent_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &user_agent_str, NULL);
919 user_agent_val = pj_str(client_state->user_agent);
920 user_agent_hdr = pjsip_generic_string_hdr_create(tdata->pool, &user_agent_str, &user_agent_val);
921 if (!user_agent_hdr) {
922 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);
923 } else {
924 if (default_user_agent_hdr) {
925 pj_list_erase(default_user_agent_hdr);
926 }
927 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)user_agent_hdr);
928 }
929 }
930
931 /*
932 * Set the transport in case transports were reloaded.
933 * When pjproject removes the extraneous error messages produced,
934 * we can check status and only set the transport and resend if there was an error
935 */
937 pjsip_regc_set_transport(client_state->client, &selector);
938 ast_sip_tpselector_unref(&selector);
939
940 status = pjsip_regc_send(client_state->client, tdata);
941
942 /*
943 * If the attempt to send the message failed and the callback was not invoked we need to
944 * drop the references we just added
945 */
946 if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
947 pjsip_tx_data_dec_ref(tdata);
948 ao2_ref(client_state, -1);
949 return status;
950 }
951
952 /*
953 * Decref the old last_data before replacing it.
954 * BTW, it's quite possible that last_data == tdata
955 * if we're trying successive servers in an SRV set.
956 */
957 if (client_state->last_tdata) {
958 pjsip_tx_data_dec_ref(client_state->last_tdata);
959 }
960 client_state->last_tdata = tdata;
961
962 return status;
963}
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition res_pjsip.c:917
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:887
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 2868 of file res_pjsip_outbound_registration.c.

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

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 2837 of file res_pjsip_outbound_registration.c.

2838{
2839 struct ao2_container *states;
2840
2841 if (strcmp(object_type, "registration")) {
2842 /* Not interested */
2843 return;
2844 }
2845
2846 states = ao2_global_obj_ref(current_states);
2847 if (!states) {
2848 /* Global container has gone. Likely shutting down. */
2849 return;
2850 }
2851
2852 /*
2853 * Refresh the current configured registrations. We don't need to hold
2854 * onto the objects, as the apply handler will cause their states to
2855 * be created appropriately.
2856 */
2858
2859 /* Now to purge dead registrations. */
2861 ao2_ref(states, -1);
2862}
@ 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 1204 of file res_pjsip_outbound_registration.c.

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

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 659 of file res_pjsip_outbound_registration.c.

660{
661 const struct sip_outbound_registration_state *object_left = obj;
662 const struct sip_outbound_registration_state *object_right = arg;
663 const char *right_key = arg;
664 int cmp;
665
666 switch (flags & OBJ_SEARCH_MASK) {
668 right_key = ast_sorcery_object_get_id(object_right->registration);
669 /* Fall through */
670 case OBJ_SEARCH_KEY:
671 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
672 break;
674 /* Not supported by container. */
675 ast_assert(0);
676 return 0;
677 default:
678 cmp = 0;
679 break;
680 }
681 if (cmp) {
682 return 0;
683 }
684 return CMP_MATCH;
685}
@ 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 638 of file res_pjsip_outbound_registration.c.

639{
640 const struct sip_outbound_registration_state *object;
641 const char *key;
642
643 switch (flags & OBJ_SEARCH_MASK) {
644 case OBJ_SEARCH_KEY:
645 key = obj;
646 break;
648 object = obj;
650 break;
651 default:
652 ast_assert(0);
653 return 0;
654 }
655 return ast_str_hash(key);
656}
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 1316 of file res_pjsip_outbound_registration.c.

1317{
1318 char *monitor;
1319 enum ast_transport_monitor_reg monitor_res;
1320
1321 monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,
1323 if (!monitor) {
1324 return;
1325 }
1326 strcpy(monitor, registration_name);/* Safe */
1327
1328 /*
1329 * We'll ignore if the transport has already been shutdown before we
1330 * register the monitor. We might get into a message spamming infinite
1331 * loop of registration, shutdown, reregistration...
1332 */
1334 monitor, monitor_matcher))) {
1335 ast_log(LOG_NOTICE, "Failed to register transport monitor for regisration %s: %d\n", registration_name, monitor_res);
1336 }
1337 ao2_ref(monitor, -1);
1338}
#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:4129

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 1293 of file res_pjsip_outbound_registration.c.

1294{
1295 const char *registration_name = obj;
1297
1298 state = get_state(registration_name);
1299 if (!state) {
1300 /* Registration no longer exists or shutting down. */
1301 return;
1302 }
1303 if (ast_sip_push_task(state->client_state->serializer, reregister_immediately_cb, state)) {
1304 ao2_ref(state, -1);
1305 }
1306}
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 3056 of file res_pjsip_outbound_registration.c.

3057{
3059 return 0;
3060}
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 1256 of file res_pjsip_outbound_registration.c.

1257{
1259
1260 if (state->client_state->status != SIP_REGISTRATION_REGISTERED) {
1261 ao2_ref(state, -1);
1262 return 0;
1263 }
1264
1265 if (DEBUG_ATLEAST(1)) {
1266 pjsip_regc_info info;
1267
1268 pjsip_regc_get_info(state->client_state->client, &info);
1270 "Outbound registration transport to server '%.*s' from client '%.*s' shutdown\n",
1271 (int) info.server_uri.slen, info.server_uri.ptr,
1272 (int) info.client_uri.slen, info.client_uri.ptr);
1273 }
1274
1275 cancel_registration(state->client_state);
1276
1277 ao2_ref(state->client_state, +1);
1278 handle_client_registration(state->client_state);
1279
1280 ao2_ref(state, -1);
1281 return 0;
1282}
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 1340 of file res_pjsip_outbound_registration.c.

1341{
1342 static const pj_str_t associated_uri_str = { "P-Associated-URI", 16 };
1343 static const pj_str_t service_route_str = { "Service-Route", 13 };
1344 pjsip_hdr *header = NULL;
1345 pjsip_msg *msg = response->rdata->msg_info.msg;
1346 struct ast_sip_service_route_vector *service_routes = NULL;
1347
1348 /* If no transport is specified then we can't update any */
1350 return;
1351 }
1352
1353 ast_sip_transport_state_set_transport(response->client_state->transport_name, response->rdata->tp_info.transport);
1354
1355 while ((header = pjsip_msg_find_hdr_by_name(msg, &service_route_str, header ? header->next : NULL))) {
1356 char *service_route;
1357 size_t size;
1358
1359 /* The below code takes the approach that if we can't store all service routes then we
1360 * store none at all. This gives a predictable failure condition instead of storing a
1361 * partial list and having partial route headers.
1362 */
1363 size = pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1;
1364 service_route = ast_malloc(size);
1365 if (!service_route) {
1366 if (service_routes) {
1368 service_routes = NULL;
1369 }
1370 break;
1371 }
1372
1373 ast_copy_pj_str(service_route, &((pjsip_generic_string_hdr*)header)->hvalue, size);
1374
1375 if (!service_routes) {
1376 service_routes = ast_sip_service_route_vector_alloc();
1377 if (!service_routes) {
1378 ast_free(service_route);
1379 break;
1380 }
1381 }
1382
1383 if (AST_VECTOR_APPEND(service_routes, service_route)) {
1384 ast_free(service_route);
1386 service_routes = NULL;
1387 break;
1388 }
1389 }
1390
1391 /* If any service routes were handled then store them on the transport */
1392 if (service_routes) {
1394 }
1395
1396 /* If an associated URI is present in the response we need to use it on any outgoing
1397 * traffic on the transport.
1398 */
1399 header = pjsip_msg_find_hdr_by_name(msg, &associated_uri_str, NULL);
1400 if (header) {
1401 char value[pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1];
1402
1403 ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)header)->hvalue, sizeof(value));
1405 }
1406}
#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 1072 of file res_pjsip_outbound_registration.c.

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

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

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 2230 of file res_pjsip_outbound_registration.c.

2231{
2232 const struct sip_outbound_registration *registration = obj;
2233
2235}
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 2251 of file res_pjsip_outbound_registration.c.

2252{
2253 struct sip_outbound_registration *registration = obj;
2254
2255 return ast_sip_security_mechanism_vector_init(&registration->security_mechanisms, var->value);
2256}
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 2258 of file res_pjsip_outbound_registration.c.

2259{
2260 struct sip_outbound_registration *registration = obj;
2261
2262 return ast_sip_set_security_negotiation(&registration->security_negotiation, var->value);
2263}
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 2242 of file res_pjsip_outbound_registration.c.

2243{
2244 const struct sip_outbound_registration *registration = obj;
2247 }
2248 return 0;
2249}
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:727

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 1951 of file res_pjsip_outbound_registration.c.

1953{
1954 size_t auth_size = AST_VECTOR_SIZE(auth_vector);
1955 struct ast_sip_auth *auths[auth_size];
1956 const char *access_token;
1957 pjsip_cred_info auth_creds[1];
1958 pjsip_auth_clt_pref prefs;
1959 int res = 0;
1960 int idx;
1961
1962 memset(auths, 0, sizeof(auths));
1963 if (ast_sip_retrieve_auths(auth_vector, auths)) {
1964 res = -1;
1965 goto cleanup;
1966 }
1967
1968 for (idx = 0; idx < auth_size; ++idx) {
1969 switch (auths[idx]->type) {
1971 pj_cstr(&auth_creds[0].username, auths[idx]->auth_user);
1972 pj_cstr(&auth_creds[0].scheme, "Bearer");
1973 pj_cstr(&auth_creds[0].realm, auths[idx]->realm);
1974 ast_debug(2, "Obtaining Google OAuth access token\n");
1975 access_token = fetch_google_access_token(auths[idx]);
1976 if (!access_token) {
1977 ast_log(LOG_WARNING, "Obtaining Google OAuth access token failed\n");
1978 access_token = auths[idx]->auth_pass;
1979 res = -1;
1980 }
1981 ast_debug(2, "Setting data to '%s'\n", access_token);
1982
1983 pj_cstr(&auth_creds[0].data, access_token);
1984 auth_creds[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
1985
1986 pjsip_regc_set_credentials(regc, 1, auth_creds);
1987
1988 /* for oauth, send auth without waiting for unauthorized response */
1989 prefs.initial_auth = PJ_TRUE;
1990 pj_cstr(&prefs.algorithm, "oauth");
1991 pjsip_regc_set_prefs(regc, &prefs);
1992
1993 if (access_token != auths[idx]->auth_pass) {
1994 ast_free((char *) access_token);
1995 }
1996 break;
1997 default:
1998 /* other cases handled after receiving auth rejection */
1999 break;
2000 }
2001 }
2002
2003cleanup:
2004 ast_sip_cleanup_auths(auths, auth_size);
2005 return res;
2006}
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 1794 of file res_pjsip_outbound_registration.c.

1796{
1797 pj_str_t tmp, local_addr;
1798 pjsip_uri *uri;
1799 pjsip_sip_uri *sip_uri;
1800 pjsip_transport_type_e type;
1801 int local_port;
1802
1803 pj_strdup_with_null(pool, &tmp, target);
1804
1805 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
1806 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
1807 return -1;
1808 }
1809
1810 sip_uri = pjsip_uri_get_uri(uri);
1811
1812 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
1813 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
1814 if (type == PJSIP_TRANSPORT_UNSPECIFIED
1815 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
1816 type = PJSIP_TRANSPORT_TLS;
1817 }
1818 } else if (!sip_uri->transport_param.slen) {
1819 type = PJSIP_TRANSPORT_UDP;
1820 } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
1821 return -1;
1822 }
1823
1824 if (pj_strchr(&sip_uri->host, ':')) {
1825 type |= PJSIP_TRANSPORT_IPV6;
1826 }
1827
1828 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
1829 pool, type, selector, &local_addr, &local_port) != PJ_SUCCESS) {
1830 return -1;
1831 }
1832
1833 if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
1834 type |= PJSIP_TRANSPORT_IPV6;
1835 }
1836
1837 contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
1838 contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
1839 "<%s:%s@%s%.*s%s:%d%s%s%s%s>%s%s",
1840 ((pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) && PJSIP_URI_SCHEME_IS_SIPS(uri)) ? "sips" : "sip",
1841 user,
1842 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1843 (int)local_addr.slen,
1844 local_addr.ptr,
1845 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1846 local_port,
1847 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1848 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
1849 !ast_strlen_zero(line) ? ";line=" : "",
1850 S_OR(line, ""),
1851 !ast_strlen_zero(header_params) ? ";" : "",
1852 S_OR(header_params, ""));
1853
1854 return 0;
1855}
#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 1779 of file res_pjsip_outbound_registration.c.

1780{
1781 struct sip_outbound_registration *registration;
1782
1783 registration = ast_sorcery_generic_alloc(sizeof(*registration),
1785 if (!registration || ast_string_field_init(registration, 256)) {
1786 ao2_cleanup(registration);
1787 return NULL;
1788 }
1789
1790 return registration;
1791}
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 2146 of file res_pjsip_outbound_registration.c.

2147{
2148 RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
2151 struct sip_outbound_registration *applied = obj;
2152
2153 if (!states) {
2154 /* Global container has gone. Likely shutting down. */
2155 return -1;
2156 }
2158
2159 ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
2160
2161 if (ast_strlen_zero(applied->server_uri)) {
2162 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'\n",
2163 ast_sorcery_object_get_id(applied));
2164 return -1;
2165 } else if (ast_sip_validate_uri_length(applied->server_uri)) {
2166 ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2167 ast_sorcery_object_get_id(applied));
2168 return -1;
2169 } else if (ast_strlen_zero(applied->client_uri)) {
2170 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
2171 ast_sorcery_object_get_id(applied));
2172 return -1;
2173 } else if (ast_sip_validate_uri_length(applied->client_uri)) {
2174 ast_log(LOG_ERROR, "Client URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2175 ast_sorcery_object_get_id(applied));
2176 return -1;
2177 } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
2178 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
2179 ast_sorcery_object_get_id(applied));
2180 return -1;
2181 } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
2182 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
2183 ast_sorcery_object_get_id(applied));
2184 return -1;
2185 }
2186
2187 if (state && can_reuse_registration(state->registration, applied)) {
2188 ast_debug(4,
2189 "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
2190 ast_sorcery_object_get_id(applied));
2191
2192 /*
2193 * This is OK to replace without relinking the state in the
2194 * current_states container since state->registration and
2195 * applied have the same key.
2196 */
2197 ao2_lock(states);
2198 ao2_replace(state->registration, applied);
2199 ao2_unlock(states);
2200 return 0;
2201 }
2202
2203 if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
2204 return -1;
2205 }
2206
2207 if (ast_sip_push_task_wait_serializer(new_state->client_state->serializer,
2209 return -1;
2210 }
2211
2212 if (ast_sip_push_task(new_state->client_state->serializer,
2214 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
2215 ast_sorcery_object_get_id(new_state->registration));
2216 ao2_ref(new_state, -1);
2217 return -1;
2218 }
2219
2220 ao2_lock(states);
2221 if (state) {
2222 ao2_unlink(states, state);
2223 }
2224 ao2_link(states, new_state);
2225 ao2_unlock(states);
2226
2227 return 0;
2228}
#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
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
Definition res_pjsip.h:2189
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 1700 of file res_pjsip_outbound_registration.c.

1701{
1702 struct sip_outbound_registration_client_state *client_state = obj;
1703
1704 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);
1705 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
1707
1709 ast_free(client_state->transport_name);
1710 ast_free(client_state->registration_name);
1711 ast_free(client_state->user_agent);
1712 if (client_state->last_tdata) {
1713 pjsip_tx_data_dec_ref(client_state->last_tdata);
1714 }
1715}
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 1768 of file res_pjsip_outbound_registration.c.

1769{
1770 struct sip_outbound_registration *registration = obj;
1771
1774
1775 ast_string_field_free_memory(registration);
1776}
#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 1220 of file res_pjsip_outbound_registration.c.

1222{
1223 /* Shamelessly taken from pjsua */
1224 if (code == PJSIP_SC_REQUEST_TIMEOUT ||
1225 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
1226 code == PJSIP_SC_BAD_GATEWAY ||
1227 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
1228 code == PJSIP_SC_SERVER_TIMEOUT ||
1229 ((code == PJSIP_SC_UNAUTHORIZED ||
1230 code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
1231 !client_state->auth_rejection_permanent) ||
1232 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
1233 return 1;
1234 } else {
1235 return 0;
1236 }
1237}
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 2102 of file res_pjsip_outbound_registration.c.

2103{
2105 struct sip_outbound_registration *registration = ao2_bump(state->registration);
2106 size_t i;
2107 int max_delay;
2108
2109 /* Just in case the client state is being reused for this registration, free the auth information */
2110 ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
2111 ast_sip_security_mechanisms_vector_destroy(&state->client_state->security_mechanisms);
2112 ast_sip_security_mechanisms_vector_destroy(&state->client_state->server_security_mechanisms);
2113
2114 AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
2115 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
2116 char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
2117
2118 if (name && AST_VECTOR_APPEND(&state->client_state->outbound_auths, name)) {
2119 ast_free(name);
2120 }
2121 }
2122 ast_sip_security_mechanisms_vector_copy(&state->client_state->security_mechanisms,
2123 &registration->security_mechanisms);
2124 state->client_state->retry_interval = registration->retry_interval;
2125 state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
2126 state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
2127 state->client_state->max_retries = registration->max_retries;
2128 state->client_state->retries = 0;
2129 state->client_state->support_path = registration->support_path;
2130 state->client_state->support_outbound = registration->support_outbound;
2131 state->client_state->security_negotiation = registration->security_negotiation;
2132 state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
2133 max_delay = registration->max_random_initial_delay;
2134
2135 pjsip_regc_update_expires(state->client_state->client, registration->expiration);
2136
2137 /* n mod 0 is undefined, so don't let that happen */
2138 schedule_registration(state->client_state, (max_delay ? ast_random() % max_delay : 0) + 1);
2139
2140 ao2_ref(registration, -1);
2141 ao2_ref(state, -1);
2142 return 0;
2143}
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 2009 of file res_pjsip_outbound_registration.c.

2010{
2013 ao2_bump(state->registration), ao2_cleanup);
2014 pj_pool_t *pool;
2015 pj_str_t tmp;
2016 pjsip_uri *uri;
2017 pj_str_t server_uri, client_uri, contact_uri;
2018 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
2019
2020 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
2021 if (!pool) {
2022 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
2024 return -1;
2025 }
2026
2027 pj_strdup2_with_null(pool, &tmp, registration->server_uri);
2028 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
2029 if (!uri) {
2030 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
2032 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2033 return -1;
2034 }
2035
2036 pj_strdup2_with_null(pool, &tmp, registration->client_uri);
2037 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
2038 if (!uri) {
2039 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
2041 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2042 return -1;
2043 }
2044
2045 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2046
2047 ast_assert(state->client_state->client == NULL);
2048 if (pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
2050 &state->client_state->client) != PJ_SUCCESS) {
2051 return -1;
2052 }
2053
2055 pjsip_regc_set_transport(state->client_state->client, &selector);
2056
2058 pjsip_route_hdr route_set, *route;
2059 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
2060 pj_str_t tmp;
2061
2062 pj_list_init(&route_set);
2063
2064 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp,
2066 route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client),
2067 &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL);
2068 if (!route) {
2069 ast_sip_tpselector_unref(&selector);
2070 return -1;
2071 }
2072 pj_list_insert_nodes_before(&route_set, route);
2073
2074 pjsip_regc_set_route_set(state->client_state->client, &route_set);
2075 }
2076
2077 if (state->registration->line) {
2078 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
2079 }
2080
2082
2083 if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client),
2084 &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
2085 state->client_state->line, registration->contact_header_params)) {
2086 ast_sip_tpselector_unref(&selector);
2087 return -1;
2088 }
2089
2090 ast_sip_tpselector_unref(&selector);
2091
2092 pj_cstr(&client_uri, registration->client_uri);
2093 if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri,
2094 &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
2095 return -1;
2096 }
2097
2098 return 0;
2099}
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 1607 of file res_pjsip_outbound_registration.c.

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

1719{
1721 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1722
1724 if (!state) {
1725 return NULL;
1726 }
1727 state->client_state = ao2_alloc(sizeof(*state->client_state),
1729 if (!state->client_state) {
1731 return NULL;
1732 }
1733
1734 state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
1735 pj_timer_entry_init(&state->client_state->timer, 0, state->client_state,
1737 state->client_state->transport_name = ast_strdup(registration->transport);
1738 state->client_state->registration_name =
1740 state->client_state->user_agent = ast_strdup(registration->user_agent);
1741
1742 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);
1743 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
1744 sip_outbound_registration_status_str(state->client_state->status));
1745
1746 if (!state->client_state->transport_name
1747 || !state->client_state->registration_name) {
1749 return NULL;
1750 }
1751
1752 /* Create name with seq number appended. */
1753 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outreg/%s",
1755
1756 state->client_state->serializer = ast_sip_create_serializer_group(tps_name,
1758 if (!state->client_state->serializer) {
1760 return NULL;
1761 }
1762
1763 state->registration = ao2_bump(registration);
1764 return state;
1765}
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:2083
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 1679 of file res_pjsip_outbound_registration.c.

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

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 1054 of file res_pjsip_outbound_registration.c.

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

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 2899 of file res_pjsip_outbound_registration.c.

2900{
2901 int remaining;
2902
2904
2905 ast_manager_unregister("PJSIPShowRegistrationsOutbound");
2906 ast_manager_unregister("PJSIPUnregister");
2907 ast_manager_unregister("PJSIPRegister");
2908
2912
2914
2917
2919
2920 ao2_global_obj_release(current_states);
2921
2923
2924 /* Wait for registration serializers to get destroyed. */
2925 ast_debug(2, "Waiting for registration transactions to complete for unload.\n");
2927 if (remaining) {
2928 /*
2929 * NOTE: We probably have a sip_outbound_registration_client_state
2930 * ref leak if the remaining count cannot reach zero after a few
2931 * minutes of trying to unload.
2932 */
2933 ast_log(LOG_WARNING, "Unload incomplete. Could not stop %d outbound registrations. Try again later.\n",
2934 remaining);
2935 return -1;
2936 }
2937
2938 ast_debug(2, "Successful shutdown.\n");
2939
2942
2943 return 0;
2944}
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:309
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 2341 of file res_pjsip_outbound_registration.c.

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

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 2297 of file res_pjsip_outbound_registration.c.

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

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 1095 of file res_pjsip_outbound_registration.c.

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

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 3070 of file res_pjsip_outbound_registration.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 3070 of file res_pjsip_outbound_registration.c.

◆ cli_formatter

struct ast_sip_cli_formatter_entry* cli_formatter
static

Definition at line 2770 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 2751 of file res_pjsip_outbound_registration.c.

2751 {
2752 AST_CLI_DEFINE(cli_unregister, "Unregisters outbound registration target"),
2753 AST_CLI_DEFINE(cli_register, "Registers an outbound registration target"),
2754 AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
2755 .command = "pjsip list registrations",
2756 .usage = "Usage: pjsip list registrations [ like <pattern> ]\n"
2757 " List the configured PJSIP Registrations\n"
2758 " Optional regular expression pattern is used to filter the list.\n"),
2759 AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
2760 .command = "pjsip show registrations",
2761 .usage = "Usage: pjsip show registrations [ like <pattern> ]\n"
2762 " Show the configured PJSIP Registrations\n"
2763 " Optional regular expression pattern is used to filter the list.\n"),
2764 AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
2765 .command = "pjsip show registration",
2766 .usage = "Usage: pjsip show registration <id>\n"
2767 " Show the configured PJSIP Registration\n"),
2768};
#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 753 of file res_pjsip_outbound_registration.c.

753 {
754 .identify_endpoint = line_identify,
755};

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 635 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 2808 of file res_pjsip_outbound_registration.c.

2808 {
2809 .loaded = auth_observer,
2810};

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 2864 of file res_pjsip_outbound_registration.c.

2864 {
2865 .object_type_loaded = registration_loaded_observer,
2866};

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 768 of file res_pjsip_outbound_registration.c.

768{ "outbound", 8 };

Referenced by add_configured_supported_headers().

◆ PATH_NAME

pj_str_t PATH_NAME = { "path", 4 }
static

Definition at line 767 of file res_pjsip_outbound_registration.c.

767{ "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 2884 of file res_pjsip_outbound_registration.c.

2884 {
2886};

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 2237 of file res_pjsip_outbound_registration.c.

2237 {
2239 [AST_SIP_SECURITY_NEG_MEDIASEC] = "mediasec",
2240};

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 628 of file res_pjsip_outbound_registration.c.

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