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

Go to the source code of this file.

Data Structures

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

Macros

#define DEFAULT_STATE_BUCKETS   53
 Default number of state container buckets. More...
 
#define LINE_PARAMETER_SIZE   8
 Size of the buffer for creating a unique string for the line. More...
 
#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. More...
 

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 __init_register_callback_invoked (void)
 Some thread local storage used to determine if the running thread invoked the callback. More...
 
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. More...
 
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. More...
 
static int add_to_supported_header (pjsip_tx_data *tdata, pj_str_t *name)
 Helper function to add string to Supported header. More...
 
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)
 
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. More...
 
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. More...
 
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. More...
 
static int handle_client_state_destruction (void *data)
 Callback function for unregistering (potentially) and destroying state. More...
 
static int handle_registration_response (void *data)
 Callback function for handling a response to a registration attempt. More...
 
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. More...
 
static int line_identify_relationship (void *obj, void *arg, int flags)
 Callback function for matching an outbound registration based on line. More...
 
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. More...
 
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. More...
 
static int registration_state_cmp (void *obj, void *arg, int flags)
 comparator function for state objects More...
 
static int registration_state_hash (const void *obj, const int flags)
 hashing function for state objects More...
 
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. More...
 
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. More...
 
static void * sip_outbound_registration_alloc (const char *name)
 Allocator function for registration information. More...
 
static int sip_outbound_registration_apply (const struct ast_sorcery *sorcery, void *obj)
 Apply function which finds or allocates a state structure. More...
 
static void sip_outbound_registration_client_state_destroy (void *obj)
 Destructor function for client registration state. More...
 
static void sip_outbound_registration_destroy (void *obj)
 Destructor function for registration information. More...
 
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. More...
 
static int sip_outbound_registration_perform (void *data)
 Helper function which performs a single registration. More...
 
static int sip_outbound_registration_regc_alloc (void *data)
 Helper function that allocates a pjsip registration client and configures it. More...
 
static void sip_outbound_registration_response_cb (struct pjsip_regc_cbparam *param)
 Callback function for outbound registration client. More...
 
static struct sip_outbound_registration_statesip_outbound_registration_state_alloc (struct sip_outbound_registration *registration)
 Allocator function for registration state. More...
 
static void sip_outbound_registration_state_destroy (void *obj)
 Destructor function for registration state. More...
 
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. More...
 
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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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 struct ast_threadstorage register_callback_invoked = { .once = PTHREAD_ONCE_INIT , .key_init = __init_register_callback_invoked , .custom_init = NULL , }
 
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 460 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 279 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 454 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 276 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 282 of file res_pjsip_outbound_registration.c.

282 {
283 /*! \brief Currently unregistered */
285 /*! \brief Registered, yay! */
287 /*! \brief Registration was rejected, but response was temporal */
289 /*! \brief Registration was rejected, permanently */
291 /*! \brief Registration is stopping. */
293 /*! \brief Registration has been stopped */
295};
@ 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

◆ __init_register_callback_invoked()

static void __init_register_callback_invoked ( void  )
static

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

Definition at line 273 of file res_pjsip_outbound_registration.c.

282{

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2910 of file res_pjsip_outbound_registration.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

845{
846 if (client_state->support_path) {
847 if (!add_to_supported_header(tdata, &PATH_NAME)) {
848 return 0;
849 }
850 }
851
852 if (client_state->support_outbound) {
854 return 0;
855 }
856 }
857
858 return 1;
859}
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 651 of file res_pjsip_outbound_registration.c.

653{
654 int add_require_header = 1;
655 int add_proxy_require_header = 1;
656 int add_sec_client_header = 0;
657 struct sip_outbound_registration *reg = NULL;
658 struct ast_sip_endpoint *endpt = NULL;
659 struct ao2_container *contact_container;
660 struct ast_sip_contact_status *contact_status = NULL;
661 struct ast_sip_security_mechanism_vector *sec_mechs = NULL;
662 static const pj_str_t security_verify = { "Security-Verify", 15 };
663 static const pj_str_t security_client = { "Security-Client", 15 };
664 static const pj_str_t proxy_require = { "Proxy-Require", 13 };
665 static const pj_str_t require = { "Require", 7 };
666
668 return;
669 }
670
671 /* Get contact status through registration -> endpoint name -> aor -> contact (if set) */
672 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", client_state->registration_name))
673 && !ast_strlen_zero(reg->endpoint) && (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))
674 && (contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors))) {
675 /* Retrieve all contacts associated with aors from this endpoint
676 * and find the first one that has security mechanisms.
677 */
678 ao2_callback(contact_container, 0, contact_has_security_mechanisms, &contact_status);
679 if (contact_status) {
680 ao2_lock(contact_status);
681 sec_mechs = &contact_status->security_mechanisms;
682 }
683 ao2_cleanup(contact_container);
684 }
685 /* Use client_state->server_security_mechanisms if contact_status does not exist. */
686 if (!contact_status && AST_VECTOR_SIZE(&client_state->server_security_mechanisms)) {
687 sec_mechs = &client_state->server_security_mechanisms;
688 }
689 if (client_state->status == SIP_REGISTRATION_REJECTED_TEMPORARY || client_state->auth_attempted) {
690 if (sec_mechs != NULL && pjsip_msg_find_hdr_by_name(tdata->msg, &security_verify, NULL) == NULL) {
691 ast_sip_add_security_headers(sec_mechs, "Security-Verify", 0, tdata);
692 }
693 if (client_state->last_status_code == 494) {
694 ast_sip_remove_headers_by_name_and_value(tdata->msg, &security_client, NULL);
695 } else {
696 /* necessary if a retry occures */
697 add_sec_client_header = (pjsip_msg_find_hdr_by_name(tdata->msg, &security_client, NULL) == NULL) ? 1 : 0;
698 }
699 add_require_header =
700 (pjsip_msg_find_hdr_by_name(tdata->msg, &require, NULL) == NULL) ? 1 : 0;
701 add_proxy_require_header =
702 (pjsip_msg_find_hdr_by_name(tdata->msg, &proxy_require, NULL) == NULL) ? 1 : 0;
703 } else {
704 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
705 }
706
707 if (add_require_header) {
708 ast_sip_add_header(tdata, "Require", "mediasec");
709 }
710 if (add_proxy_require_header) {
711 ast_sip_add_header(tdata, "Proxy-Require", "mediasec");
712 }
713 if (add_sec_client_header) {
714 ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
715 }
716
717 /* Cleanup */
718 if (contact_status) {
719 ao2_unlock(contact_status);
720 ao2_cleanup(contact_status);
721 }
722 ao2_cleanup(endpt);
723 ao2_cleanup(reg);
724}
#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
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:357
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:2008
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:1853
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:961
const ast_string_field aors
Definition: res_pjsip.h:990
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:609

References ao2_callback, ao2_cleanup, ao2_lock, ao2_unlock, ast_sip_endpoint::aors, ast_sip_add_header(), 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, 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 809 of file res_pjsip_outbound_registration.c.

810{
811 pjsip_supported_hdr *hdr;
812 int i;
813
814 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
815 if (!hdr) {
816 /* insert a new Supported header */
817 hdr = pjsip_supported_hdr_create(tdata->pool);
818 if (!hdr) {
819 pjsip_tx_data_dec_ref(tdata);
820 return 0;
821 }
822
823 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
824 }
825
826 /* Don't add the value if it's already there */
827 for (i = 0; i < hdr->count; ++i) {
828 if (pj_stricmp(&hdr->values[i], name) == 0) {
829 return 1;
830 }
831 }
832
833 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
834 return 0;
835 }
836
837 /* add on to the existing Supported header */
838 pj_strassign(&hdr->values[hdr->count++], name);
839
840 return 1;
841}
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 2448 of file res_pjsip_outbound_registration.c.

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

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

Referenced by ami_show_outbound_registrations().

◆ ami_outbound_registration_task()

static int ami_outbound_registration_task ( void *  obj)
static

Definition at line 2412 of file res_pjsip_outbound_registration.c.

2413{
2414 struct sip_ami_outbound *ami = obj;
2415 struct ast_str *buf;
2417
2418 buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
2419 if (!buf) {
2420 return -1;
2421 }
2422
2424
2426 pjsip_regc_info info;
2427
2428 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
2429 ++ami->registered;
2430 } else {
2431 ++ami->not_registered;
2432 }
2433
2434 ast_str_append(&buf, 0, "Status: %s\r\n",
2435 sip_outbound_registration_status_str(state->client_state->status));
2436
2437 pjsip_regc_get_info(state->client_state->client, &info);
2438 ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
2439 ao2_ref(state, -1);
2440 }
2441
2442 astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
2443 ast_free(buf);
2444
2446}
#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
enum cc_state state
Definition: ccss.c:393
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
def info(msg)
int ast_sip_format_auths_ami(const struct ast_sip_auth_vector *auths, struct ast_sip_ami *ami)
Format auth details for AMI.
Definition: config_auth.c:195
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:2317
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
struct mansession * s
Definition: res_pjsip.h:3047
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_to_pjsip::info(), 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(), SIP_REGISTRATION_REGISTERED, and state.

Referenced by ami_outbound_registration_detail().

◆ ami_register()

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

Definition at line 2368 of file res_pjsip_outbound_registration.c.

2369{
2370 const char *registration_name = astman_get_header(m, "Registration");
2372
2373 if (ast_strlen_zero(registration_name)) {
2374 astman_send_error(s, m, "Registration parameter missing.");
2375 return 0;
2376 }
2377
2378 if (strcmp(registration_name, "*all") == 0) {
2380 astman_send_ack(s, m, "Reregistrations queued.");
2381 return 0;
2382 }
2383
2384 state = get_state(registration_name);
2385 if (!state) {
2386 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2387 return 0;
2388 }
2389
2390 /* We need to serialize the unregister and register so they need
2391 * to be queued as separate tasks.
2392 */
2393 if (queue_unregister(state)) {
2394 astman_send_ack(s, m, "Failed to queue unregistration");
2395 } else if (queue_register(state)) {
2396 astman_send_ack(s, m, "Failed to queue unregistration");
2397 } else {
2398 astman_send_ack(s, m, "Reregistration sent");
2399 }
2400
2401 ao2_ref(state, -1);
2402 return 0;
2403}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
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(), reregister_all(), and state.

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

2458{
2459 struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2460 struct sip_ami_outbound ami_outbound = { .ami = &ami };
2461 struct ao2_container *regs;
2462
2463 regs = get_registrations();
2464 if (!regs) {
2465 astman_send_error(s, m, "Unable to retrieve "
2466 "outbound registrations\n");
2467 return -1;
2468 }
2469
2470 astman_send_listack(s, m, "Following are Events for each Outbound registration",
2471 "start");
2472
2474
2475 astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
2476 ami_outbound.registered + ami_outbound.not_registered);
2477 astman_append(s,
2478 "Registered: %d\r\n"
2479 "NotRegistered: %d\r\n",
2480 ami_outbound.registered,
2481 ami_outbound.not_registered);
2483
2484 ao2_ref(regs, -1);
2485 return 0;
2486}
@ OBJ_NODATA
Definition: astobj2.h:1044
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3431
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:3467
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
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:3045
const struct message * m
Definition: res_pjsip.h:3049

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

2337{
2338 const char *registration_name = astman_get_header(m, "Registration");
2340
2341 if (ast_strlen_zero(registration_name)) {
2342 astman_send_error(s, m, "Registration parameter missing.");
2343 return 0;
2344 }
2345
2346 if (strcmp(registration_name, "*all") == 0) {
2348 astman_send_ack(s, m, "Unregistrations queued.");
2349 return 0;
2350 }
2351
2352 state = get_state(registration_name);
2353 if (!state) {
2354 astman_send_error(s, m, "Unable to retrieve registration entry\n");
2355 return 0;
2356 }
2357
2358 if (queue_unregister(state)) {
2359 astman_send_ack(s, m, "Failed to queue unregistration");
2360 } else {
2361 astman_send_ack(s, m, "Unregistration sent");
2362 }
2363
2364 ao2_ref(state, -1);
2365 return 0;
2366}
static void unregister_all(void)

References ao2_ref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), get_state(), queue_unregister(), state, 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 2910 of file res_pjsip_outbound_registration.c.

◆ auth_observer()

static void auth_observer ( const char *  type)
static

Definition at line 2612 of file res_pjsip_outbound_registration.c.

2613{
2614 struct sip_outbound_registration *registration;
2616 struct ao2_container *regs;
2617 const char *registration_id;
2618 struct ao2_iterator i;
2619
2620 ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
2621
2622 regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
2624 if (!regs || ao2_container_count(regs) == 0) {
2625 ao2_cleanup(regs);
2626 return;
2627 }
2628
2629 i = ao2_iterator_init(regs, 0);
2630 for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
2631 registration_id = ast_sorcery_object_get_id(registration);
2632 state = get_state(registration_id);
2633 if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
2634 ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
2635
2636 if (ast_sip_push_task(state->client_state->serializer,
2638 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
2639 ao2_ref(state, -1);
2640 }
2641 }
2643 }
2645 ao2_cleanup(regs);
2646}
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:2099
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
static int sip_outbound_registration_perform(void *data)
Helper function which performs a single registration.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
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(), SIP_REGISTRATION_REJECTED_PERMANENT, and state.

◆ can_reuse_registration()

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

Definition at line 1707 of file res_pjsip_outbound_registration.c.

1709{
1710 int rc = 1;
1712 struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
1713 struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
1714 struct ast_variable *vc = NULL;
1715
1716 if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
1717 rc = 0;
1718 ast_debug(4, "Registration '%s' changed. Can't re-use.\n", ast_sorcery_object_get_id(existing));
1719 } else {
1720 ast_debug(4, "Registration '%s' didn't change. Can re-use\n", ast_sorcery_object_get_id(existing));
1721 }
1722
1726
1727 return rc;
1728}
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
static struct ast_sorcery * sorcery
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1137
int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
Create a changeset given two object sets.
Definition: sorcery.c:1663
Full structure for sorcery.
Definition: sorcery.c:230
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 587 of file res_pjsip_outbound_registration.c.

588{
589 if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
590 &client_state->timer, client_state->timer.id)) {
591 /* The timer was successfully cancelled, drop the refcount of client_state */
592 ao2_ref(client_state, -1);
593 }
594}
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
pj_timer_entry timer
Timer entry for retrying on temporal responses.

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

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

◆ check_state()

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

Definition at line 2652 of file res_pjsip_outbound_registration.c.

2653{
2655 struct sip_outbound_registration *registration;
2656
2657 registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
2658 ast_sorcery_object_get_id(state->registration));
2659 if (!registration) {
2660 /* This is a dead registration */
2661 return CMP_MATCH;
2662 }
2663
2664 ao2_ref(registration, -1);
2665 return 0;
2666}
@ 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 2201 of file res_pjsip_outbound_registration.c.

2203{
2204 char *result = NULL;
2205 int wordlen;
2206 int which = 0;
2207 struct sip_outbound_registration *registration;
2209 struct ao2_iterator i;
2210
2211 if (pos != 3) {
2212 return NULL;
2213 }
2214
2215 wordlen = strlen(word);
2216 if (wordlen == 0 && ++which > state) {
2217 return ast_strdup("*all");
2218 }
2219
2222 if (!registrations) {
2223 return NULL;
2224 }
2225
2227 while ((registration = ao2_iterator_next(&i))) {
2228 const char *name = ast_sorcery_object_get_id(registration);
2229
2230 if (!strncasecmp(word, name, wordlen) && ++which > state) {
2232 }
2233
2234 ao2_ref(registration, -1);
2235 if (result) {
2236 break;
2237 }
2238 }
2240
2242 return result;
2243}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
static PGresult * result
Definition: cel_pgsql.c:84
static struct registrations registrations
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, registrations, 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 2488 of file res_pjsip_outbound_registration.c.

2489{
2491 struct ao2_container *s_container;
2492
2494 if (!container) {
2495 return NULL;
2496 }
2497
2500 if (!s_container) {
2501 return NULL;
2502 }
2503
2504 if (ao2_container_dup(s_container, container, 0)) {
2505 ao2_ref(s_container, -1);
2506 return NULL;
2507 }
2508
2509 return s_container;
2510}
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:501
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:1954
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2464
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2440
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References AO2_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 2512 of file res_pjsip_outbound_registration.c.

2513{
2515
2516 return 0;
2517}
const char * args

References ao2_callback, args, 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 2548 of file res_pjsip_outbound_registration.c.

2549{
2550 struct sip_outbound_registration *registration = obj;
2551 struct ast_sip_cli_context *context = arg;
2552 const char *id = ast_sorcery_object_get_id(registration);
2554 int expsecs;
2555#define REGISTRATION_URI_FIELD_LEN 53
2556
2557 ast_assert(context->output_buffer != NULL);
2558 expsecs = state ? state->client_state->registration_expires - ((int) time(NULL)) : 0;
2559
2560 ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s %-26s %-16s %s%d%s\n",
2561 id,
2562 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2563 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2567 : "n/a",
2568 (state ? sip_outbound_registration_status_str(state->client_state->status) : "Unregistered"),
2569 state ? " (exp. " : "", abs(expsecs), state ? (expsecs < 0 ? "s ago)" : "s)") : "");
2571
2572 if (context->show_details
2573 || (context->show_details_only_level_0 && context->indent_level == 0)) {
2574 ast_str_append(&context->output_buffer, 0, "\n");
2576 }
2577
2578 return 0;
2579}
#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.
Definition: res_pjsip_cli.h:34
struct sip_outbound_registration * registration
Outbound registration configuration object.
#define ast_assert(a)
Definition: utils.h:739
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

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, voicemailpwcheck::context, 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 2536 of file res_pjsip_outbound_registration.c.

2537{
2538 struct ast_sip_cli_context *context = arg;
2539
2540 ast_assert(context->output_buffer != NULL);
2541
2542 ast_str_append(&context->output_buffer, 0,
2543 " <Registration/ServerURI..............................> <Auth....................> <Status.......>\n");
2544
2545 return 0;
2546}

References ast_assert, ast_str_append(), voicemailpwcheck::context, 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 2288 of file res_pjsip_outbound_registration.c.

2289{
2291 const char *registration_name;
2292
2293 switch (cmd) {
2294 case CLI_INIT:
2295 e->command = "pjsip send register";
2296 e->usage =
2297 "Usage: pjsip send register <registration> | *all \n"
2298 " Unregisters the specified (or all) outbound "
2299 "registration(s) then starts registration(s) and schedules re-registrations.\n";
2300 return NULL;
2301 case CLI_GENERATE:
2302 return cli_complete_registration(a->line, a->word, a->pos, a->n);
2303 }
2304
2305 if (a->argc != 4) {
2306 return CLI_SHOWUSAGE;
2307 }
2308
2309 registration_name = a->argv[3];
2310
2311 if (strcmp(registration_name, "*all") == 0) {
2313 ast_cli(a->fd, "Re-register all queued\n");
2314 return CLI_SUCCESS;
2315 }
2316
2317 state = get_state(registration_name);
2318 if (!state) {
2319 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2320 return CLI_FAILURE;
2321 }
2322
2323 /* We need to serialize the unregister and register so they need
2324 * to be queued as separate tasks.
2325 */
2326 if (queue_unregister(state)) {
2327 ast_cli(a->fd, "Failed to queue unregistration\n");
2328 } else if (queue_register(state)) {
2329 ast_cli(a->fd, "Failed to queue registration\n");
2330 }
2331
2332 ao2_ref(state, -1);
2333 return CLI_SUCCESS;
2334}
#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(), state, and ast_cli_entry::usage.

◆ cli_retrieve_by_id()

static void * cli_retrieve_by_id ( const char *  id)
static

Definition at line 2519 of file res_pjsip_outbound_registration.c.

2520{
2521 struct ao2_container *states;
2522 void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
2523
2524 if (!obj) {
2525 /* if the object no longer exists then remove its state */
2526 states = ao2_global_obj_ref(current_states);
2527 if (states) {
2529 ao2_ref(states, -1);
2530 }
2531 }
2532
2533 return obj;
2534}
#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 2245 of file res_pjsip_outbound_registration.c.

2246{
2248 const char *registration_name;
2249
2250 switch (cmd) {
2251 case CLI_INIT:
2252 e->command = "pjsip send unregister";
2253 e->usage =
2254 "Usage: pjsip send unregister <registration> | *all\n"
2255 " Unregisters the specified (or all) outbound registration(s) "
2256 "and stops future registration attempts.\n";
2257 return NULL;
2258 case CLI_GENERATE:
2259 return cli_complete_registration(a->line, a->word, a->pos, a->n);
2260 }
2261
2262 if (a->argc != 4) {
2263 return CLI_SHOWUSAGE;
2264 }
2265
2266 registration_name = a->argv[3];
2267
2268 if (strcmp(registration_name, "*all") == 0) {
2270 ast_cli(a->fd, "Unregister all queued\n");
2271 return CLI_SUCCESS;
2272 }
2273
2274 state = get_state(registration_name);
2275 if (!state) {
2276 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2277 return CLI_FAILURE;
2278 }
2279
2280 if (queue_unregister(state)) {
2281 ast_cli(a->fd, "Failed to queue unregistration\n");
2282 }
2283
2284 ao2_ref(state, -1);
2285 return CLI_SUCCESS;
2286}

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(), state, 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 628 of file res_pjsip_outbound_registration.c.

629{
630 struct ast_sip_contact *contact = obj;
631 struct pjsip_generic_string_hdr_vector *header_vector = arg;
632 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
633
634 if (!contact_status) {
635 return -1;
636 }
637 if (AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
638 goto out;
639 }
640
641 ao2_lock(contact_status);
643 ao2_unlock(contact_status);
644
645out:
646 ao2_cleanup(contact_status);
647 return 0;
648}
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:392
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:862

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

612{
613 struct ast_sip_contact *contact = obj;
614 struct ast_sip_contact_status **ret = arg;
615 struct ast_sip_contact_status *contact_status = ast_sip_get_contact_status(contact);
616
617 if (!contact_status) {
618 return -1;
619 }
620 if (!AST_VECTOR_SIZE(&contact_status->security_mechanisms)) {
621 ao2_cleanup(contact_status);
622 return -1;
623 }
624 *ret = contact_status;
625 return 0;
626}

References ao2_cleanup, ast_sip_get_contact_status(), AST_VECTOR_SIZE, 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 1731 of file res_pjsip_outbound_registration.c.

1732{
1733 char *cmd = NULL;
1734 const char *token;
1735 const char *url = "https://www.googleapis.com/oauth2/v3/token";
1736 char buf[4096];
1737 int res;
1738 struct ast_json_error error;
1739 struct ast_json *json;
1740
1741 /* set timeout to be shorter than default 180s (also checks func_curl is available) */
1742 if (ast_func_write(NULL, "CURLOPT(conntimeout)", "10")) {
1743 ast_log(LOG_ERROR, "CURL is unavailable. This is required for Google OAuth 2.0 authentication. Please ensure it is loaded.\n");
1744 return NULL;
1745 }
1746
1747 res = ast_asprintf(&cmd,
1748 "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
1749 url, auth->oauth_clientid, auth->oauth_secret, auth->refresh_token);
1750 if (res < 0) {
1751 return NULL;
1752 }
1753
1754 ast_debug(2, "Performing Google OAuth 2.0 authentication using command: %s\n", cmd);
1755
1756 buf[0] = '\0';
1757 res = ast_func_read(NULL, cmd, buf, sizeof(buf));
1758 ast_free(cmd);
1759 if (res) {
1760 ast_log(LOG_ERROR, "Could not retrieve Google OAuth 2.0 authentication\n");
1761 return NULL;
1762 }
1763
1764 ast_debug(2, "Google OAuth 2.0 authentication returned: %s\n", buf);
1765
1766 json = ast_json_load_string(buf, &error);
1767 if (!json) {
1768 ast_log(LOG_ERROR, "Could not parse Google OAuth 2.0 authentication: %d(%d) %s: '%s'\n",
1769 error.line, error.column, error.text, buf);
1770 return NULL;
1771 }
1772
1773 token = ast_json_string_get(ast_json_object_get(json, "access_token"));
1774 if (!token) {
1775 ast_log(LOG_ERROR, "Could not find Google OAuth 2.0 access_token in: '%s'\n",
1776 buf);
1777 }
1778 token = ast_strdup(token);
1779 ast_json_unref(json);
1780 return token;
1781}
#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:597
const ast_string_field oauth_secret
Definition: res_pjsip.h:597
const ast_string_field refresh_token
Definition: res_pjsip.h:597
int error(const char *format,...)
Definition: utils/frame.c:999

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

517{
519 struct ao2_container *states;
520
521 states = ao2_global_obj_ref(current_states);
522 if (states) {
523 state = ao2_find(states, id, OBJ_SEARCH_KEY);
524 ao2_ref(states, -1);
525 }
526 return state;
527}

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

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

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

References ast_sip_pjsip_uri_get_other_param().

Referenced by line_identify().

◆ handle_client_registration()

static int handle_client_registration ( void *  data)
static

Callback function for registering.

Definition at line 862 of file res_pjsip_outbound_registration.c.

863{
864 RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
865 pjsip_tx_data *tdata;
866
867 if (set_outbound_initial_authentication_credentials(client_state->client, &client_state->outbound_auths)) {
868 ast_log(LOG_WARNING, "Failed to set initial authentication credentials\n");
869 }
870
871 if (client_state->status == SIP_REGISTRATION_STOPPED
872 || pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
873 return 0;
874 }
875
876 if (DEBUG_ATLEAST(1)) {
877 pjsip_regc_info info;
878
879 pjsip_regc_get_info(client_state->client, &info);
880 ast_log(LOG_DEBUG, "Outbound REGISTER attempt %u to '%.*s' with client '%.*s'\n",
881 client_state->retries + 1,
882 (int) info.server_uri.slen, info.server_uri.ptr,
883 (int) info.client_uri.slen, info.client_uri.ptr);
884 }
885
886 if (!add_configured_supported_headers(client_state, tdata)) {
887 ast_log(LOG_WARNING, "Failed to set supported headers\n");
888 return -1;
889 }
890
891 registration_client_send(client_state, tdata);
892
893 return 0;
894}
#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, sip_to_pjsip::info(), 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 967 of file res_pjsip_outbound_registration.c.

968{
969 struct sip_outbound_registration_client_state *client_state = data;
970
971 cancel_registration(client_state);
972
973 if (client_state->client) {
974 pjsip_regc_info info;
975 pjsip_tx_data *tdata;
976
977 pjsip_regc_get_info(client_state->client, &info);
978
979 if (info.is_busy == PJ_TRUE) {
980 /* If a client transaction is in progress we defer until it is complete */
981 ast_debug(1,
982 "Registration transaction is busy with server '%.*s' from client '%.*s'.\n",
983 (int) info.server_uri.slen, info.server_uri.ptr,
984 (int) info.client_uri.slen, info.client_uri.ptr);
985 client_state->destroy = 1;
986 ao2_ref(client_state, -1);
987 return 0;
988 }
989
990 switch (client_state->status) {
992 break;
994 ast_debug(1,
995 "Trying to unregister with server '%.*s' from client '%.*s' before destruction.\n",
996 (int) info.server_uri.slen, info.server_uri.ptr,
997 (int) info.client_uri.slen, info.client_uri.ptr);
998
1000 client_state->destroy = 1;
1001 if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS
1002 && add_configured_supported_headers(client_state, tdata)
1003 && registration_client_send(client_state, tdata) == PJ_SUCCESS) {
1004 ao2_ref(client_state, -1);
1005 return 0;
1006 }
1007 break;
1012 break;
1013 }
1014
1015 pjsip_regc_destroy(client_state->client);
1016 client_state->client = NULL;
1017 }
1018
1023 ao2_ref(client_state, -1);
1024
1025 return 0;
1026}
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, sip_to_pjsip::info(), 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 1250 of file res_pjsip_outbound_registration.c.

1251{
1252 struct registration_response *response = data;
1253 pjsip_regc_info info;
1254 char server_uri[PJSIP_MAX_URL_SIZE];
1255 char client_uri[PJSIP_MAX_URL_SIZE];
1256
1257 if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
1258 ao2_ref(response, -1);
1259 return 0;
1260 }
1261
1262 pjsip_regc_get_info(response->client_state->client, &info);
1263 ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
1264 ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
1265 response->client_state->last_status_code = response->code;
1266
1267 ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
1268 response->code, server_uri, client_uri);
1269
1270 if (response->code == 408 || response->code == 503) {
1271 if ((ast_sip_failover_request(response->old_request))) {
1272 int res = registration_client_send(response->client_state, response->old_request);
1273 /* The tdata ref was stolen */
1274 response->old_request = NULL;
1275 if (res == PJ_SUCCESS) {
1276 ao2_ref(response, -1);
1277 return 0;
1278 }
1279 }
1280 } else if ((response->code == 401 || response->code == 407 || response->code == 494)
1281 && (!response->client_state->auth_attempted
1282 || response->rdata->msg_info.cseq->cseq != response->client_state->auth_cseq)) {
1283 int res;
1284 pjsip_cseq_hdr *cseq_hdr;
1285 pjsip_tx_data *tdata;
1286
1288 struct sip_outbound_registration *reg = NULL;
1289 struct ast_sip_endpoint *endpt = NULL;
1290 struct ao2_container *contact_container = NULL;
1291 pjsip_generic_string_hdr *header;
1292 struct pjsip_generic_string_hdr_vector header_vector;
1293 static const pj_str_t security_server = { "Security-Server", 15 };
1294
1295 if ((reg = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
1296 response->client_state->registration_name)) && reg->endpoint &&
1297 (endpt = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", reg->endpoint))) {
1298 /* Retrieve all contacts associated with aors from this endpoint (if set). */
1299 contact_container = ast_sip_location_retrieve_contacts_from_aor_list(endpt->aors);
1300 }
1301 /* Add server list of security mechanism to client_state and contact status if exists. */
1302 AST_VECTOR_INIT(&header_vector, 1);
1303 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, NULL);
1304 for (; header;
1305 header = pjsip_msg_find_hdr_by_name(response->rdata->msg_info.msg, &security_server, header->next)) {
1306 AST_VECTOR_APPEND(&header_vector, header);
1308 }
1309 if (contact_container) {
1310 /* Add server security mechanisms to contact status of all associated contacts to be able to send correct
1311 * Security-Verify headers on subsequent non-REGISTER requests through this outbound registration.
1312 */
1313 ao2_callback(contact_container, OBJ_NODATA, contact_add_security_headers_to_status, &header_vector);
1314 ao2_cleanup(contact_container);
1315 }
1316 AST_VECTOR_FREE(&header_vector);
1317 ao2_cleanup(endpt);
1318 ao2_cleanup(reg);
1319 }
1320
1321 if (response->code == 494) {
1323 response->client_state->retries++;
1324 schedule_registration(response->client_state, 0);
1325 ao2_ref(response, -1);
1326 return 0;
1328 response->rdata, response->old_request, &tdata)) {
1329 response->client_state->auth_attempted = 1;
1330 ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
1331 server_uri, client_uri);
1332 pjsip_tx_data_add_ref(tdata);
1333
1334 res = registration_client_send(response->client_state, tdata);
1335
1336 /* Save the cseq that actually got sent. */
1337 cseq_hdr = (pjsip_cseq_hdr *) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ,
1338 NULL);
1339 response->client_state->auth_cseq = cseq_hdr->cseq;
1340 pjsip_tx_data_dec_ref(tdata);
1341 if (res == PJ_SUCCESS) {
1342 ao2_ref(response, -1);
1343 return 0;
1344 }
1345 } else {
1346 ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
1347 server_uri, client_uri);
1348 }
1349 /* Otherwise, fall through so the failure is processed appropriately */
1350 }
1351
1352 response->client_state->auth_attempted = 0;
1353
1354 if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
1355 /* Check if this is in regards to registering or unregistering */
1356 if (response->expiration) {
1357 int next_registration_round;
1358
1359 /* If the registration went fine simply reschedule registration for the future */
1360 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
1362 response->client_state->retries = 0;
1363 next_registration_round = response->expiration - REREGISTER_BUFFER_TIME;
1364 if (next_registration_round < 0) {
1365 /* Re-register immediately. */
1366 next_registration_round = 0;
1367 }
1368 schedule_registration(response->client_state, next_registration_round);
1369
1370 /* See if we should monitor for transport shutdown */
1371 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1373 response->client_state->registration_name);
1374 }
1375 } else {
1376 ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
1378 if (PJSIP_TRANSPORT_IS_RELIABLE(response->rdata->tp_info.transport)) {
1382 }
1383 }
1384
1386 } else if (response->client_state->destroy) {
1387 /* We need to deal with the pending destruction instead. */
1388 } else if (response->retry_after) {
1389 /* If we have been instructed to retry after a period of time, schedule it as such */
1390 schedule_retry(response, response->retry_after, server_uri, client_uri);
1391 } else if (response->client_state->retry_interval
1392 && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
1393 if (response->client_state->retries == response->client_state->max_retries) {
1394 /* If we received enough temporal responses to exceed our maximum give up permanently */
1396 ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
1397 server_uri, client_uri);
1398 } else {
1399 /* On the other hand if we can still try some more do so */
1400 response->client_state->retries++;
1401 schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
1402 }
1403 } else {
1404 if (response->code == 403
1406 && response->client_state->retries < response->client_state->max_retries) {
1407 /* A forbidden response retry interval is configured and there are retries remaining */
1409 response->client_state->retries++;
1411 ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1412 server_uri, client_uri, response->client_state->forbidden_retry_interval);
1413 } else if (response->client_state->fatal_retry_interval
1414 && response->client_state->retries < response->client_state->max_retries) {
1415 /* Some kind of fatal failure response received, so retry according to configured interval */
1417 response->client_state->retries++;
1419 ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1420 response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
1421 } else {
1422 /* Finally if there's no hope of registering give up */
1424 if (response->rdata) {
1425 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
1426 response->code, server_uri, client_uri);
1427 } else {
1428 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
1429 }
1430 }
1431 }
1432
1433 ast_system_publish_registry("PJSIP", client_uri, server_uri,
1435
1436 if (response->client_state->destroy) {
1437 /* We have a pending deferred destruction to complete now. */
1438 ao2_ref(response->client_state, +1);
1440 }
1441
1442 ao2_ref(response, -1);
1443 return 0;
1444}
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *tdata, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
Definition: res_pjsip.c:214
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2201
void ast_sip_transport_monitor_unregister_key(const char *transport_key, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
Definition: res_pjsip.c:1816
static void save_response_fields_to_transport(struct registration_response *response)
#define REREGISTER_BUFFER_TIME
Amount of buffer time (in seconds) before expiration that we re-register at.
static void registration_transport_monitor_setup(const char *transport_key, const char *registration_name)
static void registration_transport_shutdown_cb(void *obj)
static int contact_add_security_headers_to_status(void *obj, void *arg, int flags)
static int sip_outbound_registration_is_temporal(unsigned int code, struct sip_outbound_registration_client_state *client_state)
Helper function which determines if a response code is temporal or not.
static int handle_client_state_destruction(void *data)
Callback function for unregistering (potentially) and destroying state.
static void schedule_retry(struct registration_response *response, unsigned int interval, const char *server_uri, const char *client_uri)
static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
Helper function which sets up the timer to re-register in a specific amount of time.
static int monitor_matcher(void *a, void *b)
void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause)
Publish a channel driver outgoing registration message.
struct header * next
Structure for registration response.
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
char transport_key[IP6ADDR_COLON_PORT_BUFLEN]
Key for the reliable transport in use.
pjsip_rx_data * rdata
The response message.
int code
Response code for the registration attempt.
int expiration
Expiration time for registration.
pjsip_tx_data * old_request
Request for which the response was received.
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
unsigned int max_retries
Maximum number of retries permitted.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
unsigned int retries
Current number of retries.
static char server_uri[512]
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

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_to_pjsip::info(), 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 555 of file res_pjsip_outbound_registration.c.

556{
557 pjsip_param *line;
558 RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
560
561 if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
562 && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
563 return NULL;
564 }
565
566 states = ao2_global_obj_ref(current_states);
567 if (!states) {
568 return NULL;
569 }
570
572 if (!state || ast_strlen_zero(state->registration->endpoint)) {
573 return NULL;
574 }
575
576 ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
577 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
578
579 return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
580}
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 539 of file res_pjsip_outbound_registration.c.

540{
542 pjsip_param *line = arg;
543
544 return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH : 0;
545}

References CMP_MATCH.

Referenced by line_identify().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2786 of file res_pjsip_outbound_registration.c.

2787{
2788 struct ao2_container *new_states;
2789
2791 if (!shutdown_group) {
2793 }
2794
2795 /* Create outbound registration states container. */
2798 if (!new_states) {
2799 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
2800 unload_module();
2802 }
2804 ao2_ref(new_states, -1);
2805
2806 /*
2807 * Register sorcery object descriptions.
2808 */
2809 ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
2810 ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
2811
2813 unload_module();
2815 }
2816
2817 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
2819 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
2820 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
2821 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));
2822 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
2823 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
2824 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
2825 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));
2826 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
2827 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));
2828 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));
2830 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));
2832 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
2833 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_outbound", "no", OPT_YESNO_T, 1, FLDSET(struct sip_outbound_registration, support_outbound));
2836 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
2837 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
2838 ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, user_agent));
2839
2840 /*
2841 * Register sorcery observers.
2842 */
2847 || ast_sorcery_observer_add(ast_sip_get_sorcery(), "registration",
2849 ast_log(LOG_ERROR, "Unable to register observers.\n");
2850 unload_module();
2852 }
2853
2854 /* Register how this module identifies endpoints. */
2856
2857 /* Register CLI commands. */
2859 if (!cli_formatter) {
2860 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
2861 unload_module();
2863 }
2864 cli_formatter->name = "registration";
2873
2874 /* Register AMI actions. */
2878
2879 /* Clear any previous statsd gauges in case we weren't shutdown cleanly */
2880 ast_statsd_log("PJSIP.registrations.count", AST_STATSD_GAUGE, 0);
2881 ast_statsd_log("PJSIP.registrations.state.Registered", AST_STATSD_GAUGE, 0);
2882 ast_statsd_log("PJSIP.registrations.state.Unregistered", AST_STATSD_GAUGE, 0);
2883 ast_statsd_log("PJSIP.registrations.state.Rejected", AST_STATSD_GAUGE, 0);
2884
2885 /* Load configuration objects */
2887
2892
2894}
@ 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:332
#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:191
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
Definition: res_pjsip.c:310
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition: pjsip_cli.c:310
static struct ao2_container * new_states
Used on [re]loads to hold new state data.
static int ami_show_outbound_registrations(struct mansession *s, const struct message *m)
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
static void * sip_outbound_registration_alloc(const char *name)
Allocator function for registration information.
static int cli_print_header(void *obj, void *arg, int flags)
static struct ast_serializer_shutdown_group * shutdown_group
static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
static int registration_state_cmp(void *obj, void *arg, int flags)
comparator function for state objects
#define DEFAULT_STATE_BUCKETS
Default number of state container buckets.
static const struct ast_sorcery_observer registration_observer
static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int ami_register(struct mansession *s, const struct message *m)
static int ami_unregister(struct mansession *s, const struct message *m)
static int security_negotiation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int security_mechanisms_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int security_mechanism_to_str(const void *obj, const intptr_t *args, char **buf)
static void network_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
Apply function which finds or allocates a state structure.
static void * cli_retrieve_by_id(const char *id)
static const struct ast_sorcery_observer observer_callbacks_auth
static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
static struct ast_sip_endpoint_identifier line_identifier
static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
static struct ao2_container * cli_get_container(const char *regex)
static struct stasis_subscription * network_change_sub
static int cli_print_body(void *obj, void *arg, int flags)
static int security_negotiation_to_str(const void *obj, const intptr_t *args, char **buf)
static int unload_module(void)
static struct ast_cli_entry cli_outbound_registration[]
static struct ast_sip_cli_formatter_entry * cli_formatter
static int registration_state_hash(const void *obj, const int flags)
hashing function for state objects
#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:2391
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:1393
#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:520
@ 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:1023
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:1077
#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_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:232
CLI Formatter Registry Entry.
Definition: res_pjsip_cli.h:52
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Definition: res_pjsip_cli.h:66
ao2_callback_fn * print_header
Definition: res_pjsip_cli.h:60
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
const char * name
Definition: res_pjsip_cli.h:58
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229
#define ARRAY_LEN(a)
Definition: utils.h:666

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

1152{
1153 char *ma = a;
1154 char *mb = b;
1155
1156 return strcmp(ma, mb) == 0;
1157}
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 2586 of file res_pjsip_outbound_registration.c.

2587{
2588 return ast_sip_cli_traverse_objects(e, cmd, a);
2589}
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 2728 of file res_pjsip_outbound_registration.c.

2729{
2730 /* This callback is only concerned with network change messages from the system topic. */
2732 return;
2733 }
2734 ast_debug(3, "Received network change event\n");
2735
2737}
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.

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

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

2106{
2107 struct sip_outbound_registration *registration = obj;
2108
2109 return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
2110}
#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 2112 of file res_pjsip_outbound_registration.c.

2113{
2114 const struct sip_outbound_registration *registration = obj;
2115
2116 return ast_sip_auths_to_str(&registration->outbound_auths, buf);
2117}
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 2119 of file res_pjsip_outbound_registration.c.

2120{
2121 const struct sip_outbound_registration *registration = obj;
2122 int i;
2123 struct ast_variable *head = NULL;
2124
2125 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
2126 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
2127 AST_VECTOR_GET(&registration->outbound_auths, i), ""));
2128 }
2129
2130 if (head) {
2131 *fields = head;
2132 }
2133
2134 return 0;
2135}
#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 2170 of file res_pjsip_outbound_registration.c.

2171{
2172 ao2_ref(state, +1);
2173 if (ast_sip_push_task(state->client_state->serializer, sip_outbound_registration_perform, state)) {
2174 ao2_ref(state, -1);
2175 return -1;
2176 }
2177
2178 return 0;
2179}

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

2160{
2161 ao2_ref(state, +1);
2162 if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
2163 ao2_ref(state, -1);
2164 return -1;
2165 }
2166
2167 return 0;
2168}
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 727 of file res_pjsip_outbound_registration.c.

729{
730 pj_status_t status;
731 int *callback_invoked;
732 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
733
734 callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
735 if (!callback_invoked) {
736 pjsip_tx_data_dec_ref(tdata);
737 return PJ_ENOMEM;
738 }
739 *callback_invoked = 0;
740
741 /* Due to the message going out the callback may now be invoked, so bump the count */
742 ao2_ref(client_state, +1);
743 /*
744 * We also bump tdata in expectation of saving it to client_state->last_tdata.
745 * We have to do it BEFORE pjsip_regc_send because if it succeeds, it decrements
746 * the ref count on its own.
747 */
748 pjsip_tx_data_add_ref(tdata);
749
750 /* Add Security-Verify or Security-Client headers */
751 add_security_headers(client_state, tdata);
752
753 /*
754 * Replace the User-Agent header if a different one should be used
755 */
756 if (!ast_strlen_zero(client_state->user_agent)) {
757 static const pj_str_t user_agent_str = { "User-Agent", 10 };
758 pjsip_generic_string_hdr *default_user_agent_hdr;
759 pjsip_generic_string_hdr *user_agent_hdr;
760 pj_str_t user_agent_val;
761 default_user_agent_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &user_agent_str, NULL);
762 user_agent_val = pj_str(client_state->user_agent);
763 user_agent_hdr = pjsip_generic_string_hdr_create(tdata->pool, &user_agent_str, &user_agent_val);
764 if (!user_agent_hdr) {
765 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);
766 } else {
767 if (default_user_agent_hdr) {
768 pj_list_erase(default_user_agent_hdr);
769 }
770 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)user_agent_hdr);
771 }
772 }
773
774 /*
775 * Set the transport in case transports were reloaded.
776 * When pjproject removes the extraneous error messages produced,
777 * we can check status and only set the transport and resend if there was an error
778 */
780 pjsip_regc_set_transport(client_state->client, &selector);
781 ast_sip_tpselector_unref(&selector);
782
783 status = pjsip_regc_send(client_state->client, tdata);
784
785 /*
786 * If the attempt to send the message failed and the callback was not invoked we need to
787 * drop the references we just added
788 */
789 if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
790 pjsip_tx_data_dec_ref(tdata);
791 ao2_ref(client_state, -1);
792 return status;
793 }
794
795 /*
796 * Decref the old last_data before replacing it.
797 * BTW, it's quite possible that last_data == tdata
798 * if we're trying successive servers in an SRV set.
799 */
800 if (client_state->last_tdata) {
801 pjsip_tx_data_dec_ref(client_state->last_tdata);
802 }
803 client_state->last_tdata = tdata;
804
805 return status;
806}
jack_status_t status
Definition: app_jack.c:146
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:923
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition: res_pjsip.c:893
static void add_security_headers(struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
Adds security negotiation mechanisms of outbound registration client state as Security headers to tda...
static struct ast_threadstorage register_callback_invoked
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, register_callback_invoked, 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 2708 of file res_pjsip_outbound_registration.c.

2709{
2710 const struct sip_outbound_registration *registration = obj;
2711 struct ao2_container *states;
2712
2713 states = ao2_global_obj_ref(current_states);
2714 if (!states) {
2715 /* Global container has gone. Likely shutting down. */
2716 return;
2717 }
2718
2720
2721 ao2_ref(states, -1);
2722}

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

2678{
2679 struct ao2_container *states;
2680
2681 if (strcmp(object_type, "registration")) {
2682 /* Not interested */
2683 return;
2684 }
2685
2686 states = ao2_global_obj_ref(current_states);
2687 if (!states) {
2688 /* Global container has gone. Likely shutting down. */
2689 return;
2690 }
2691
2692 /*
2693 * Refresh the current configured registrations. We don't need to hold
2694 * onto the objects, as the apply handler will cause their states to
2695 * be created appropriately.
2696 */
2698
2699 /* Now to purge dead registrations. */
2701 ao2_ref(states, -1);
2702}
@ 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 1047 of file res_pjsip_outbound_registration.c.

1048{
1049 struct registration_response *response = obj;
1050
1051 if (response->rdata) {
1052 pjsip_rx_data_free_cloned(response->rdata);
1053 }
1054
1055 if (response->old_request) {
1056 pjsip_tx_data_dec_ref(response->old_request);
1057 }
1058
1059 ao2_cleanup(response->client_state);
1060}

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

489{
490 const struct sip_outbound_registration_state *object_left = obj;
491 const struct sip_outbound_registration_state *object_right = arg;
492 const char *right_key = arg;
493 int cmp;
494
495 switch (flags & OBJ_SEARCH_MASK) {
497 right_key = ast_sorcery_object_get_id(object_right->registration);
498 /* Fall through */
499 case OBJ_SEARCH_KEY:
500 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
501 break;
503 /* Not supported by container. */
504 ast_assert(0);
505 return 0;
506 default:
507 cmp = 0;
508 break;
509 }
510 if (cmp) {
511 return 0;
512 }
513 return CMP_MATCH;
514}
@ 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 467 of file res_pjsip_outbound_registration.c.

468{
469 const struct sip_outbound_registration_state *object;
470 const char *key;
471
472 switch (flags & OBJ_SEARCH_MASK) {
473 case OBJ_SEARCH_KEY:
474 key = obj;
475 break;
477 object = obj;
479 break;
480 default:
481 ast_assert(0);
482 return 0;
483 }
484 return ast_str_hash(key);
485}
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 1159 of file res_pjsip_outbound_registration.c.

1160{
1161 char *monitor;
1162
1163 monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,
1165 if (!monitor) {
1166 return;
1167 }
1168 strcpy(monitor, registration_name);/* Safe */
1169
1170 /*
1171 * We'll ignore if the transport has already been shutdown before we
1172 * register the monitor. We might get into a message spamming infinite
1173 * loop of registration, shutdown, reregistration...
1174 */
1176 monitor, monitor_matcher);
1177 ao2_ref(monitor, -1);
1178}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
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.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_sip_transport_monitor_register_replace_key(), 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 1136 of file res_pjsip_outbound_registration.c.

1137{
1138 const char *registration_name = obj;
1140
1141 state = get_state(registration_name);
1142 if (!state) {
1143 /* Registration no longer exists or shutting down. */
1144 return;
1145 }
1146 if (ast_sip_push_task(state->client_state->serializer, reregister_immediately_cb, state)) {
1147 ao2_ref(state, -1);
1148 }
1149}
static int reregister_immediately_cb(void *obj)

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

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

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2896 of file res_pjsip_outbound_registration.c.

2897{
2899 return 0;
2900}
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:1442

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

1100{
1102
1103 if (state->client_state->status != SIP_REGISTRATION_REGISTERED) {
1104 ao2_ref(state, -1);
1105 return 0;
1106 }
1107
1108 if (DEBUG_ATLEAST(1)) {
1109 pjsip_regc_info info;
1110
1111 pjsip_regc_get_info(state->client_state->client, &info);
1113 "Outbound registration transport to server '%.*s' from client '%.*s' shutdown\n",
1114 (int) info.server_uri.slen, info.server_uri.ptr,
1115 (int) info.client_uri.slen, info.client_uri.ptr);
1116 }
1117
1118 cancel_registration(state->client_state);
1119
1120 ao2_ref(state->client_state, +1);
1121 handle_client_registration(state->client_state);
1122
1123 ao2_ref(state, -1);
1124 return 0;
1125}
static int handle_client_registration(void *data)
Callback function for registering.

References ao2_ref, ast_log, cancel_registration(), DEBUG_ATLEAST, handle_client_registration(), sip_to_pjsip::info(), 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 1180 of file res_pjsip_outbound_registration.c.

1181{
1182 static const pj_str_t associated_uri_str = { "P-Associated-URI", 16 };
1183 static const pj_str_t service_route_str = { "Service-Route", 13 };
1184 pjsip_hdr *header = NULL;
1185 pjsip_msg *msg = response->rdata->msg_info.msg;
1186 struct ast_sip_service_route_vector *service_routes = NULL;
1187
1188 /* If no transport is specified then we can't update any */
1190 return;
1191 }
1192
1193 ast_sip_transport_state_set_transport(response->client_state->transport_name, response->rdata->tp_info.transport);
1194
1195 while ((header = pjsip_msg_find_hdr_by_name(msg, &service_route_str, header ? header->next : NULL))) {
1196 char *service_route;
1197 size_t size;
1198
1199 /* The below code takes the approach that if we can't store all service routes then we
1200 * store none at all. This gives a predictable failure condition instead of storing a
1201 * partial list and having partial route headers.
1202 */
1203 size = pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1;
1204 service_route = ast_malloc(size);
1205 if (!service_route) {
1206 if (service_routes) {
1208 service_routes = NULL;
1209 }
1210 break;
1211 }
1212
1213 ast_copy_pj_str(service_route, &((pjsip_generic_string_hdr*)header)->hvalue, size);
1214
1215 if (!service_routes) {
1216 service_routes = ast_sip_service_route_vector_alloc();
1217 if (!service_routes) {
1218 ast_free(service_route);
1219 break;
1220 }
1221 }
1222
1223 if (AST_VECTOR_APPEND(service_routes, service_route)) {
1224 ast_free(service_route);
1226 service_routes = NULL;
1227 break;
1228 }
1229 }
1230
1231 /* If any service routes were handled then store them on the transport */
1232 if (service_routes) {
1234 }
1235
1236 /* If an associated URI is present in the response we need to use it on any outgoing
1237 * traffic on the transport.
1238 */
1239 header = pjsip_msg_find_hdr_by_name(msg, &associated_uri_str, NULL);
1240 if (header) {
1241 char value[pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1];
1242
1243 ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)header)->hvalue, sizeof(value));
1245 }
1246}
#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 915 of file res_pjsip_outbound_registration.c.

916{
917 pj_time_val delay = { .sec = seconds, };
918 pjsip_regc_info info;
919
920 cancel_registration(client_state);
921
922 pjsip_regc_get_info(client_state->client, &info);
923 ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
924 (int) info.server_uri.slen, info.server_uri.ptr,
925 (int) info.client_uri.slen, info.client_uri.ptr,
926 seconds);
927
928 ao2_ref(client_state, +1);
929 if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
930 ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
931 (int) info.server_uri.slen, info.server_uri.ptr,
932 (int) info.client_uri.slen, info.client_uri.ptr);
933 ao2_ref(client_state, -1);
934 }
935 client_state->registration_expires = ((int) time(NULL)) + seconds;
936}
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, sip_to_pjsip::info(), 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 1082 of file res_pjsip_outbound_registration.c.

1084{
1086 schedule_registration(response->client_state, interval);
1087
1088 if (response->rdata) {
1089 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
1090 "registration attempt to '%s', retrying in '%u'\n",
1091 response->code, server_uri, client_uri, interval);
1092 } else {
1093 ast_log(LOG_WARNING, "No response received from '%s' on "
1094 "registration attempt to '%s', retrying in '%u'\n",
1095 server_uri, client_uri, interval);
1096 }
1097}

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

2071{
2072 const struct sip_outbound_registration *registration = obj;
2073
2075}
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 2091 of file res_pjsip_outbound_registration.c.

2092{
2093 struct sip_outbound_registration *registration = obj;
2094
2095 return ast_sip_security_mechanism_vector_init(&registration->security_mechanisms, var->value);
2096}
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 2098 of file res_pjsip_outbound_registration.c.

2099{
2100 struct sip_outbound_registration *registration = obj;
2101
2102 return ast_sip_set_security_negotiation(&registration->security_negotiation, var->value);
2103}
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 2082 of file res_pjsip_outbound_registration.c.

2083{
2084 const struct sip_outbound_registration *registration = obj;
2087 }
2088 return 0;
2089}
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:687

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

1793{
1794 size_t auth_size = AST_VECTOR_SIZE(auth_vector);
1795 struct ast_sip_auth *auths[auth_size];
1796 const char *access_token;
1797 pjsip_cred_info auth_creds[1];
1798 pjsip_auth_clt_pref prefs;
1799 int res = 0;
1800 int idx;
1801
1802 memset(auths, 0, sizeof(auths));
1803 if (ast_sip_retrieve_auths(auth_vector, auths)) {
1804 res = -1;
1805 goto cleanup;
1806 }
1807
1808 for (idx = 0; idx < auth_size; ++idx) {
1809 switch (auths[idx]->type) {
1811 pj_cstr(&auth_creds[0].username, auths[idx]->auth_user);
1812 pj_cstr(&auth_creds[0].scheme, "Bearer");
1813 pj_cstr(&auth_creds[0].realm, auths[idx]->realm);
1814 ast_debug(2, "Obtaining Google OAuth access token\n");
1815 access_token = fetch_google_access_token(auths[idx]);
1816 if (!access_token) {
1817 ast_log(LOG_WARNING, "Obtaining Google OAuth access token failed\n");
1818 access_token = auths[idx]->auth_pass;
1819 res = -1;
1820 }
1821 ast_debug(2, "Setting data to '%s'\n", access_token);
1822
1823 pj_cstr(&auth_creds[0].data, access_token);
1824 auth_creds[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
1825
1826 pjsip_regc_set_credentials(regc, 1, auth_creds);
1827
1828 /* for oauth, send auth without waiting for unauthorized response */
1829 prefs.initial_auth = PJ_TRUE;
1830 pj_cstr(&prefs.algorithm, "oauth");
1831 pjsip_regc_set_prefs(regc, &prefs);
1832
1833 if (access_token != auths[idx]->auth_pass) {
1834 ast_free((char *) access_token);
1835 }
1836 break;
1837 default:
1838 /* other cases handled after receiving auth rejection */
1839 break;
1840 }
1841 }
1842
1843cleanup:
1844 ast_sip_cleanup_auths(auths, auth_size);
1845 return res;
1846}
static const char type[]
Definition: chan_ooh323.c:109
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
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:572
static const char * fetch_google_access_token(const struct ast_sip_auth *auth)
Get google oauth2 access token using refresh token.
const ast_string_field realm
Definition: res_pjsip.h:597
const ast_string_field auth_user
Definition: res_pjsip.h:597
const ast_string_field auth_pass
Definition: res_pjsip.h:597

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

1636{
1637 pj_str_t tmp, local_addr;
1638 pjsip_uri *uri;
1639 pjsip_sip_uri *sip_uri;
1640 pjsip_transport_type_e type;
1641 int local_port;
1642
1643 pj_strdup_with_null(pool, &tmp, target);
1644
1645 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
1646 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
1647 return -1;
1648 }
1649
1650 sip_uri = pjsip_uri_get_uri(uri);
1651
1652 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
1653 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
1654 if (type == PJSIP_TRANSPORT_UNSPECIFIED
1655 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
1656 type = PJSIP_TRANSPORT_TLS;
1657 }
1658 } else if (!sip_uri->transport_param.slen) {
1659 type = PJSIP_TRANSPORT_UDP;
1660 } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
1661 return -1;
1662 }
1663
1664 if (pj_strchr(&sip_uri->host, ':')) {
1665 type |= PJSIP_TRANSPORT_IPV6;
1666 }
1667
1668 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
1669 pool, type, selector, &local_addr, &local_port) != PJ_SUCCESS) {
1670 return -1;
1671 }
1672
1673 if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
1674 type |= PJSIP_TRANSPORT_IPV6;
1675 }
1676
1677 contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
1678 contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
1679 "<%s:%s@%s%.*s%s:%d%s%s%s%s>%s%s",
1680 ((pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) && PJSIP_URI_SCHEME_IS_SIPS(uri)) ? "sips" : "sip",
1681 user,
1682 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1683 (int)local_addr.slen,
1684 local_addr.ptr,
1685 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1686 local_port,
1687 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1688 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
1689 !ast_strlen_zero(line) ? ";line=" : "",
1690 S_OR(line, ""),
1691 !ast_strlen_zero(header_params) ? ";" : "",
1692 S_OR(header_params, ""));
1693
1694 return 0;
1695}
static int tmp()
Definition: bt_open.c:389
#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 users.conf

References ast_sip_get_pjsip_endpoint(), ast_strlen_zero(), sip_outbound_registration::line, S_OR, tmp(), 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 1619 of file res_pjsip_outbound_registration.c.

1620{
1621 struct sip_outbound_registration *registration;
1622
1623 registration = ast_sorcery_generic_alloc(sizeof(*registration),
1625 if (!registration || ast_string_field_init(registration, 256)) {
1626 ao2_cleanup(registration);
1627 return NULL;
1628 }
1629
1630 return registration;
1631}
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:1728
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

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

1987{
1988 RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1991 struct sip_outbound_registration *applied = obj;
1992
1993 if (!states) {
1994 /* Global container has gone. Likely shutting down. */
1995 return -1;
1996 }
1998
1999 ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
2000
2001 if (ast_strlen_zero(applied->server_uri)) {
2002 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'\n",
2003 ast_sorcery_object_get_id(applied));
2004 return -1;
2005 } else if (ast_sip_validate_uri_length(applied->server_uri)) {
2006 ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2007 ast_sorcery_object_get_id(applied));
2008 return -1;
2009 } else if (ast_strlen_zero(applied->client_uri)) {
2010 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
2011 ast_sorcery_object_get_id(applied));
2012 return -1;
2013 } else if (ast_sip_validate_uri_length(applied->client_uri)) {
2014 ast_log(LOG_ERROR, "Client URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
2015 ast_sorcery_object_get_id(applied));
2016 return -1;
2017 } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
2018 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
2019 ast_sorcery_object_get_id(applied));
2020 return -1;
2021 } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
2022 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
2023 ast_sorcery_object_get_id(applied));
2024 return -1;
2025 }
2026
2027 if (state && can_reuse_registration(state->registration, applied)) {
2028 ast_debug(4,
2029 "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
2030 ast_sorcery_object_get_id(applied));
2031
2032 /*
2033 * This is OK to replace without relinking the state in the
2034 * current_states container since state->registration and
2035 * applied have the same key.
2036 */
2037 ao2_lock(states);
2038 ao2_replace(state->registration, applied);
2039 ao2_unlock(states);
2040 return 0;
2041 }
2042
2043 if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
2044 return -1;
2045 }
2046
2047 if (ast_sip_push_task_wait_serializer(new_state->client_state->serializer,
2049 return -1;
2050 }
2051
2052 if (ast_sip_push_task(new_state->client_state->serializer,
2054 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
2055 ast_sorcery_object_get_id(new_state->registration));
2056 ao2_ref(new_state, -1);
2057 return -1;
2058 }
2059
2060 ao2_lock(states);
2061 if (state) {
2062 ao2_unlink(states, state);
2063 }
2064 ao2_link(states, new_state);
2065 ao2_unlock(states);
2066
2067 return 0;
2068}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:2179
static int sip_outbound_registration_regc_alloc(void *data)
Helper function that allocates a pjsip registration client and configures it.
static struct sip_outbound_registration_state * sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
Allocator function for registration state.
static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
int ast_sip_validate_uri_length(const char *uri)
Definition: location.c:528
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 1540 of file res_pjsip_outbound_registration.c.

1541{
1542 struct sip_outbound_registration_client_state *client_state = obj;
1543
1544 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);
1545 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
1547
1549 ast_free(client_state->transport_name);
1550 ast_free(client_state->registration_name);
1551 ast_free(client_state->user_agent);
1552 if (client_state->last_tdata) {
1553 pjsip_tx_data_dec_ref(client_state->last_tdata);
1554 }
1555}
void ast_statsd_log_string_va(const char *metric_name, const char *metric_type, const char *value, double sample_rate,...)
Send a stat to the configured statsd server.
Definition: res_statsd.c:186
void 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:117
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 1608 of file res_pjsip_outbound_registration.c.

1609{
1610 struct sip_outbound_registration *registration = obj;
1611
1614
1615 ast_string_field_free_memory(registration);
1616}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

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

1065{
1066 /* Shamelessly taken from pjsua */
1067 if (code == PJSIP_SC_REQUEST_TIMEOUT ||
1068 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
1069 code == PJSIP_SC_BAD_GATEWAY ||
1070 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
1071 code == PJSIP_SC_SERVER_TIMEOUT ||
1072 ((code == PJSIP_SC_UNAUTHORIZED ||
1073 code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
1074 !client_state->auth_rejection_permanent) ||
1075 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
1076 return 1;
1077 } else {
1078 return 0;
1079 }
1080}
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 1942 of file res_pjsip_outbound_registration.c.

1943{
1945 struct sip_outbound_registration *registration = ao2_bump(state->registration);
1946 size_t i;
1947 int max_delay;
1948
1949 /* Just in case the client state is being reused for this registration, free the auth information */
1950 ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
1951 ast_sip_security_mechanisms_vector_destroy(&state->client_state->security_mechanisms);
1952 ast_sip_security_mechanisms_vector_destroy(&state->client_state->server_security_mechanisms);
1953
1954 AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
1955 for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1956 char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1957
1958 if (name && AST_VECTOR_APPEND(&state->client_state->outbound_auths, name)) {
1959 ast_free(name);
1960 }
1961 }
1962 ast_sip_security_mechanisms_vector_copy(&state->client_state->security_mechanisms,
1963 &registration->security_mechanisms);
1964 state->client_state->retry_interval = registration->retry_interval;
1965 state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
1966 state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
1967 state->client_state->max_retries = registration->max_retries;
1968 state->client_state->retries = 0;
1969 state->client_state->support_path = registration->support_path;
1970 state->client_state->support_outbound = registration->support_outbound;
1971 state->client_state->security_negotiation = registration->security_negotiation;
1972 state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
1973 max_delay = registration->max_random_initial_delay;
1974
1975 pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1976
1977 /* n mod 0 is undefined, so don't let that happen */
1978 schedule_registration(state->client_state, (max_delay ? ast_random() % max_delay : 0) + 1);
1979
1980 ao2_ref(registration, -1);
1981 ao2_ref(state, -1);
1982 return 0;
1983}
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:2312

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

1850{
1853 ao2_bump(state->registration), ao2_cleanup);
1854 pj_pool_t *pool;
1855 pj_str_t tmp;
1856 pjsip_uri *uri;
1857 pj_str_t server_uri, client_uri, contact_uri;
1858 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1859
1860 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
1861 if (!pool) {
1862 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
1864 return -1;
1865 }
1866
1867 pj_strdup2_with_null(pool, &tmp, registration->server_uri);
1868 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1869 if (!uri) {
1870 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
1872 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1873 return -1;
1874 }
1875
1876 pj_strdup2_with_null(pool, &tmp, registration->client_uri);
1877 uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1878 if (!uri) {
1879 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
1881 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1882 return -1;
1883 }
1884
1885 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1886
1887 ast_assert(state->client_state->client == NULL);
1888 if (pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
1890 &state->client_state->client) != PJ_SUCCESS) {
1891 return -1;
1892 }
1893
1895 pjsip_regc_set_transport(state->client_state->client, &selector);
1896
1898 pjsip_route_hdr route_set, *route;
1899 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1900 pj_str_t tmp;
1901
1902 pj_list_init(&route_set);
1903
1904 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp,
1906 route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client),
1907 &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL);
1908 if (!route) {
1909 ast_sip_tpselector_unref(&selector);
1910 return -1;
1911 }
1912 pj_list_insert_nodes_before(&route_set, route);
1913
1914 pjsip_regc_set_route_set(state->client_state->client, &route_set);
1915 }
1916
1917 if (state->registration->line) {
1918 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
1919 }
1920
1922
1923 if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client),
1924 &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
1925 state->client_state->line, registration->contact_header_params)) {
1926 ast_sip_tpselector_unref(&selector);
1927 return -1;
1928 }
1929
1930 ast_sip_tpselector_unref(&selector);
1931
1932 pj_cstr(&client_uri, registration->client_uri);
1933 if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri,
1934 &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
1935 return -1;
1936 }
1937
1938 return 0;
1939}
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(), tmp(), 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 1447 of file res_pjsip_outbound_registration.c.

1448{
1449 struct sip_outbound_registration_client_state *client_state = param->token;
1450 struct registration_response *response;
1451 int *callback_invoked;
1452
1453 callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
1454
1455 ast_assert(callback_invoked != NULL);
1457
1458 *callback_invoked = 1;
1459
1460 response = ao2_alloc(sizeof(*response), registration_response_destroy);
1461 if (!response) {
1462 ao2_ref(client_state, -1);
1463 return;
1464 }
1465 response->code = param->code;
1466 response->expiration = param->expiration;
1467 /*
1468 * Transfer client_state reference to response so the
1469 * nominal path will not dec the client_state ref in this
1470 * pjproject callback thread.
1471 */
1472 response->client_state = client_state;
1473
1474 ast_debug(1, "Received REGISTER response %d(%.*s)\n",
1475 param->code, (int) param->reason.slen, param->reason.ptr);
1476
1477 if (param->rdata) {
1478 struct pjsip_retry_after_hdr *retry_after;
1479 pjsip_transaction *tsx;
1480
1481 retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER,
1482 NULL);
1483 response->retry_after = retry_after ? retry_after->ivalue : 0;
1484
1485 /*
1486 * If we got a response from the server, we have to use the tdata
1487 * from the transaction, not the tdata saved when we sent the
1488 * request. If we use the saved tdata, we won't process responses
1489 * like 423 Interval Too Brief correctly and we'll wind up sending
1490 * the bad Expires value again.
1491 */
1492 pjsip_tx_data_dec_ref(client_state->last_tdata);
1493
1494 tsx = pjsip_rdata_get_tsx(param->rdata);
1495 response->old_request = tsx->last_tx;
1496 pjsip_tx_data_add_ref(response->old_request);
1497 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
1498 AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR(param->rdata->tp_info.transport,
1499 response->transport_key);
1500
1501 } else {
1502 /* old_request steals the reference */
1503 response->old_request = client_state->last_tdata;
1504 }
1505 client_state->last_tdata = NULL;
1506
1507 /*
1508 * Transfer response reference to serializer task so the
1509 * nominal path will not dec the response ref in this
1510 * pjproject callback thread.
1511 */
1512 if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
1513 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
1514 ao2_cleanup(response);
1515 }
1516}
#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:90
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, register_callback_invoked, 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 1558 of file res_pjsip_outbound_registration.c.

1559{
1561 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1562
1564 if (!state) {
1565 return NULL;
1566 }
1567 state->client_state = ao2_alloc(sizeof(*state->client_state),
1569 if (!state->client_state) {
1571 return NULL;
1572 }
1573
1574 state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
1575 pj_timer_entry_init(&state->client_state->timer, 0, state->client_state,
1577 state->client_state->transport_name = ast_strdup(registration->transport);
1578 state->client_state->registration_name =
1580 state->client_state->user_agent = ast_strdup(registration->user_agent);
1581
1582 ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);
1583 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
1584 sip_outbound_registration_status_str(state->client_state->status));
1585
1586 if (!state->client_state->transport_name
1587 || !state->client_state->registration_name) {
1589 return NULL;
1590 }
1591
1592 /* Create name with seq number appended. */
1593 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outreg/%s",
1595
1596 state->client_state->serializer = ast_sip_create_serializer_group(tps_name,
1598 if (!state->client_state->serializer) {
1600 return NULL;
1601 }
1602
1603 state->registration = ao2_bump(registration);
1604 return state;
1605}
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:2089
static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
Timer callback function, used just for registrations.
static void sip_outbound_registration_state_destroy(void *obj)
Destructor function for registration state.
static void sip_outbound_registration_client_state_destroy(void *obj)
Destructor function for client registration state.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:61

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, state, 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 1519 of file res_pjsip_outbound_registration.c.

1520{
1522
1523 ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
1524 state->registration ? state->registration->server_uri : "",
1525 state->registration ? state->registration->client_uri : "");
1526 ao2_cleanup(state->registration);
1527
1528 if (!state->client_state) {
1529 /* Nothing to do */
1530 } else if (!state->client_state->serializer) {
1531 ao2_ref(state->client_state, -1);
1532 } else if (ast_sip_push_task(state->client_state->serializer,
1533 handle_client_state_destruction, state->client_state)) {
1534 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
1535 ao2_ref(state->client_state, -1);
1536 }
1537}

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

898{
899 struct sip_outbound_registration_client_state *client_state = entry->user_data;
900
901 entry->id = 0;
902
903 /*
904 * Transfer client_state reference to serializer task so the
905 * nominal path will not dec the client_state ref in this
906 * pjproject callback thread.
907 */
908 if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
909 ast_log(LOG_WARNING, "Scheduled outbound registration could not be executed.\n");
910 ao2_ref(client_state, -1);
911 }
912}
Definition: search.h:40

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

2740{
2741 int remaining;
2742
2744
2745 ast_manager_unregister("PJSIPShowRegistrationsOutbound");
2746 ast_manager_unregister("PJSIPUnregister");
2747 ast_manager_unregister("PJSIPRegister");
2748
2752
2754
2757
2759
2760 ao2_global_obj_release(current_states);
2761
2763
2764 /* Wait for registration serializers to get destroyed. */
2765 ast_debug(2, "Waiting for registration transactions to complete for unload.\n");
2767 if (remaining) {
2768 /*
2769 * NOTE: We probably have a sip_outbound_registration_client_state
2770 * ref leak if the remaining count cannot reach zero after a few
2771 * minutes of trying to unload.
2772 */
2773 ast_log(LOG_WARNING, "Unload incomplete. Could not stop %d outbound registrations. Try again later.\n",
2774 remaining);
2775 return -1;
2776 }
2777
2778 ast_debug(2, "Successful shutdown.\n");
2779
2782
2783 return 0;
2784}
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8057
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Definition: res_pjsip.c:315
void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a transport shutdown monitor from all reliable transports.
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
#define MAX_UNLOAD_TIMEOUT_TIME
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:2423
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:537
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
Definition: sorcery.c:1061
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1134
int ast_serializer_shutdown_group_join(struct ast_serializer_shutdown_group *shutdown_group, int timeout)
Wait for the serializers in the group to shutdown with timeout.
Definition: threadpool.c:1241

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

2182{
2183 struct ao2_container *states;
2184
2185 states = ao2_global_obj_ref(current_states);
2186 if (!states) {
2187 return;
2188 }
2189
2190 /* Clean out all the states and let sorcery handle recreating the registrations */
2192 ao2_ref(states, -1);
2193}

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

2138{
2140 struct pjsip_regc *client = state->client_state->client;
2141 pjsip_tx_data *tdata;
2142 pjsip_regc_info info;
2143
2144 pjsip_regc_get_info(client, &info);
2145 ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
2146 state->registration->server_uri, state->registration->client_uri);
2147
2148 cancel_registration(state->client_state);
2149
2150 if (pjsip_regc_unregister(client, &tdata) == PJ_SUCCESS
2151 && add_configured_supported_headers(state->client_state, tdata)) {
2152 registration_client_send(state->client_state, tdata);
2153 }
2154
2155 ao2_ref(state, -1);
2156 return 0;
2157}

References add_configured_supported_headers(), ao2_ref, ast_debug, cancel_registration(), sip_to_pjsip::info(), 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 938 of file res_pjsip_outbound_registration.c.

939{
940 const char *status_old;
941 const char *status_new;
942
943 if (client_state->status == status) {
944 /* Status state did not change at all. */
945 return;
946 }
947
948 status_old = sip_outbound_registration_status_str(client_state->status);
950 client_state->status = status;
951
952 if (!strcmp(status_old, status_new)) {
953 /*
954 * The internal status state may have changed but the status
955 * state we tell the world did not change at all.
956 */
957 return;
958 }
959
960 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
961 status_old);
962 ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
963 status_new);
964}

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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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 2910 of file res_pjsip_outbound_registration.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2910 of file res_pjsip_outbound_registration.c.

◆ cli_formatter

struct ast_sip_cli_formatter_entry* cli_formatter
static

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

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

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

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

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

Referenced by add_configured_supported_headers().

◆ PATH_NAME

pj_str_t PATH_NAME = { "path", 4 }
static

Definition at line 596 of file res_pjsip_outbound_registration.c.

Referenced by add_configured_supported_headers().

◆ register_callback_invoked

struct ast_threadstorage register_callback_invoked = { .once = PTHREAD_ONCE_INIT , .key_init = __init_register_callback_invoked , .custom_init = NULL , }
static

◆ registration_observer

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

Definition at line 2724 of file res_pjsip_outbound_registration.c.

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:355

Definition at line 2077 of file res_pjsip_outbound_registration.c.

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

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