Asterisk - The Open Source Telephony Project  18.5.0
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  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 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 const char * fetch_google_access_token (const struct ast_sip_auth *auth)
 
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 (pjsip_transport *transport, 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 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 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 412 of file res_pjsip_outbound_registration.c.

Referenced by load_module().

◆ LINE_PARAMETER_SIZE

#define LINE_PARAMETER_SIZE   8

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

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

Referenced by unload_module().

◆ REGISTRATION_URI_FIELD_LEN

#define REGISTRATION_URI_FIELD_LEN   53

Referenced by cli_print_body().

◆ REREGISTER_BUFFER_TIME

#define REREGISTER_BUFFER_TIME   10

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

Definition at line 248 of file res_pjsip_outbound_registration.c.

Referenced by handle_registration_response().

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

254  {
255  /*! \brief Currently unregistered */
257  /*! \brief Registered, yay! */
259  /*! \brief Registration was rejected, but response was temporal */
261  /*! \brief Registration was rejected, permanently */
263  /*! \brief Registration is stopping. */
265  /*! \brief Registration has been stopped */
267 };
Registration was rejected, permanently.
Registration was rejected, but response was temporal.
Registration has been stopped.

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

254 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2628 of file res_pjsip_outbound_registration.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

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

651 {
652  if (client_state->support_path) {
653  if (!add_to_supported_header(tdata, &PATH_NAME)) {
654  return 0;
655  }
656  }
657 
658  if (client_state->support_outbound) {
659  if (!add_to_supported_header(tdata, &OUTBOUND_NAME)) {
660  return 0;
661  }
662  }
663 
664  return 1;
665 }
unsigned int support_outbound
Determines whether SIP Outbound support should be advertised.
static pj_str_t OUTBOUND_NAME
static pj_str_t PATH_NAME
unsigned int support_path
Determines whether SIP Path support should be advertised.
static int add_to_supported_header(pjsip_tx_data *tdata, pj_str_t *name)
Helper function to add string to Supported header.

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

References NULL.

Referenced by add_configured_supported_headers().

616 {
617  pjsip_supported_hdr *hdr;
618  int i;
619 
620  hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
621  if (!hdr) {
622  /* insert a new Supported header */
623  hdr = pjsip_supported_hdr_create(tdata->pool);
624  if (!hdr) {
625  pjsip_tx_data_dec_ref(tdata);
626  return 0;
627  }
628 
629  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
630  }
631 
632  /* Don't add the value if it's already there */
633  for (i = 0; i < hdr->count; ++i) {
634  if (pj_stricmp(&hdr->values[i], name) == 0) {
635  return 1;
636  }
637  }
638 
639  if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
640  return 0;
641  }
642 
643  /* add on to the existing Supported header */
644  pj_strassign(&hdr->values[hdr->count++], name);
645 
646  return 1;
647 }
#define NULL
Definition: resample.c:96
static const char name[]
Definition: cdr_mysql.c:74

◆ ami_outbound_registration_detail()

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

Definition at line 2171 of file res_pjsip_outbound_registration.c.

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

Referenced by ami_show_outbound_registrations().

2172 {
2173  struct sip_ami_outbound *ami = arg;
2174 
2175  ami->registration = obj;
2177 }
static int ami_outbound_registration_task(void *obj)
#define NULL
Definition: resample.c:96
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:5204
struct sip_outbound_registration * registration

◆ ami_outbound_registration_task()

static int ami_outbound_registration_task ( void *  obj)
static

Definition at line 2135 of file res_pjsip_outbound_registration.c.

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, sip_outbound_registration_client_state::client, sip_outbound_registration_state::client_state, 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, state, and sip_outbound_registration_client_state::status.

Referenced by ami_outbound_registration_detail().

2136 {
2137  struct sip_ami_outbound *ami = obj;
2138  struct ast_str *buf;
2140 
2141  buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
2142  if (!buf) {
2143  return -1;
2144  }
2145 
2147 
2148  if ((state = get_state(ast_sorcery_object_get_id(ami->registration)))) {
2149  pjsip_regc_info info;
2150 
2152  ++ami->registered;
2153  } else {
2154  ++ami->not_registered;
2155  }
2156 
2157  ast_str_append(&buf, 0, "Status: %s\r\n",
2159 
2160  pjsip_regc_get_info(state->client_state->client, &info);
2161  ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
2162  ao2_ref(state, -1);
2163  }
2164 
2165  astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
2166  ast_free(buf);
2167 
2169 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
enum sip_outbound_registration_status status
Current state of this registration.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Outbound registration state information (persists for lifetime that registration should exist) ...
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
struct sip_outbound_registration_client_state * client_state
Client state information.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct mansession * s
Definition: res_pjsip.h:2739
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
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static struct sip_outbound_registration_state * get_state(const char *id)
def info(msg)
#define ast_free(a)
Definition: astmm.h:182
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
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 sip_outbound_registration * registration
pjsip_regc * client
Outbound registration client.

◆ ami_register()

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

Definition at line 2091 of file res_pjsip_outbound_registration.c.

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

2092 {
2093  const char *registration_name = astman_get_header(m, "Registration");
2095 
2096  if (ast_strlen_zero(registration_name)) {
2097  astman_send_error(s, m, "Registration parameter missing.");
2098  return 0;
2099  }
2100 
2101  if (strcmp(registration_name, "*all") == 0) {
2102  reregister_all();
2103  astman_send_ack(s, m, "Reregistrations queued.");
2104  return 0;
2105  }
2106 
2107  state = get_state(registration_name);
2108  if (!state) {
2109  astman_send_error(s, m, "Unable to retrieve registration entry\n");
2110  return 0;
2111  }
2112 
2113  /* We need to serialize the unregister and register so they need
2114  * to be queued as separate tasks.
2115  */
2116  if (queue_unregister(state)) {
2117  astman_send_ack(s, m, "Failed to queue unregistration");
2118  } else if (queue_register(state)) {
2119  astman_send_ack(s, m, "Failed to queue unregistration");
2120  } else {
2121  astman_send_ack(s, m, "Reregistration sent");
2122  }
2123 
2124  ao2_ref(state, -1);
2125  return 0;
2126 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
Outbound registration state information (persists for lifetime that registration should exist) ...
static int queue_unregister(struct sip_outbound_registration_state *state)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct sip_outbound_registration_state * get_state(const char *id)
static int queue_register(struct sip_outbound_registration_state *state)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
static void reregister_all(void)

◆ ami_show_outbound_registrations()

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

Definition at line 2179 of file res_pjsip_outbound_registration.c.

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

2181 {
2182  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2183  struct sip_ami_outbound ami_outbound = { .ami = &ami };
2184  struct ao2_container *regs;
2185 
2186  regs = get_registrations();
2187  if (!regs) {
2188  astman_send_error(s, m, "Unable to retrieve "
2189  "outbound registrations\n");
2190  return -1;
2191  }
2192 
2193  astman_send_listack(s, m, "Following are Events for each Outbound registration",
2194  "start");
2195 
2197 
2198  astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
2199  ami_outbound.registered + ami_outbound.not_registered);
2200  astman_append(s,
2201  "Registered: %d\r\n"
2202  "NotRegistered: %d\r\n",
2203  ami_outbound.registered,
2204  ami_outbound.not_registered);
2206 
2207  ao2_ref(regs, -1);
2208  return 0;
2209 }
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
const struct message * m
Definition: res_pjsip.h:2741
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
AMI variable container.
Definition: res_pjsip.h:2737
static struct ao2_container * get_registrations(void)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct mansession * s
Definition: res_pjsip.h:2739
static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
Generic container type.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ ami_unregister()

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

Definition at line 2059 of file res_pjsip_outbound_registration.c.

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

2060 {
2061  const char *registration_name = astman_get_header(m, "Registration");
2063 
2064  if (ast_strlen_zero(registration_name)) {
2065  astman_send_error(s, m, "Registration parameter missing.");
2066  return 0;
2067  }
2068 
2069  if (strcmp(registration_name, "*all") == 0) {
2070  unregister_all();
2071  astman_send_ack(s, m, "Unregistrations queued.");
2072  return 0;
2073  }
2074 
2075  state = get_state(registration_name);
2076  if (!state) {
2077  astman_send_error(s, m, "Unable to retrieve registration entry\n");
2078  return 0;
2079  }
2080 
2081  if (queue_unregister(state)) {
2082  astman_send_ack(s, m, "Failed to queue unregistration");
2083  } else {
2084  astman_send_ack(s, m, "Unregistration sent");
2085  }
2086 
2087  ao2_ref(state, -1);
2088  return 0;
2089 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
Outbound registration state information (persists for lifetime that registration should exist) ...
static int queue_unregister(struct sip_outbound_registration_state *state)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static void unregister_all(void)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct sip_outbound_registration_state * get_state(const char *id)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

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

◆ auth_observer()

static void auth_observer ( const char *  type)
static

Definition at line 2332 of file res_pjsip_outbound_registration.c.

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(), sip_outbound_registration_state::client_state, get_state(), LOG_ERROR, NULL, sip_outbound_registration_client_state::serializer, sip_outbound_registration_perform(), SIP_REGISTRATION_REJECTED_PERMANENT, state, and sip_outbound_registration_client_state::status.

2333 {
2334  struct sip_outbound_registration *registration;
2336  struct ao2_container *regs;
2337  const char *registration_id;
2338  struct ao2_iterator i;
2339 
2340  ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
2341 
2342  regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
2344  if (!regs || ao2_container_count(regs) == 0) {
2345  ao2_cleanup(regs);
2346  return;
2347  }
2348 
2349  i = ao2_iterator_init(regs, 0);
2350  for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
2351  registration_id = ast_sorcery_object_get_id(registration);
2352  state = get_state(registration_id);
2353  if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
2354  ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
2355 
2358  ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
2359  ao2_ref(state, -1);
2360  }
2361  }
2362  ao2_cleanup(state);
2363  }
2365  ao2_cleanup(regs);
2366 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
enum sip_outbound_registration_status status
Current state of this registration.
Perform no matching, return all objects.
Definition: sorcery.h:123
Outbound registration state information (persists for lifetime that registration should exist) ...
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
static int sip_outbound_registration_perform(void *data)
Helper function which performs a single registration.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Outbound registration information.
#define LOG_ERROR
Definition: logger.h:285
Registration was rejected, permanently.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
static struct sip_outbound_registration_state * get_state(const char *id)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ast_taskprocessor * serializer
Serializer for stuff and things.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ can_reuse_registration()

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

Definition at line 1461 of file res_pjsip_outbound_registration.c.

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

1463 {
1464  int rc = 1;
1466  struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
1467  struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
1468  struct ast_variable *vc = NULL;
1469 
1470  if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
1471  rc = 0;
1472  ast_debug(4, "Registration '%s' changed. Can't re-use.\n", ast_sorcery_object_get_id(existing));
1473  } else {
1474  ast_debug(4, "Registration '%s' didn't change. Can re-use\n", ast_sorcery_object_get_id(existing));
1475  }
1476 
1480 
1481  return rc;
1482 }
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Structure for variables, used for configurations and for channel variables.
Full structure for sorcery.
Definition: sorcery.c:230
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1136
static struct ast_sorcery * sorcery
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
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

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

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

545 {
546  if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
547  &client_state->timer, client_state->timer.id)) {
548  /* The timer was successfully cancelled, drop the refcount of client_state */
549  ao2_ref(client_state, -1);
550  }
551 }
pj_timer_entry timer
Timer entry for retrying on temporal responses.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ check_state()

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

Definition at line 2372 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), CMP_MATCH, and sip_outbound_registration_state::registration.

Referenced by registration_loaded_observer().

2373 {
2374  struct sip_outbound_registration_state *state = obj;
2375  struct sip_outbound_registration *registration;
2376 
2377  registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
2379  if (!registration) {
2380  /* This is a dead registration */
2381  return CMP_MATCH;
2382  }
2383 
2384  ao2_ref(registration, -1);
2385  return 0;
2386 }
Outbound registration state information (persists for lifetime that registration should exist) ...
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct sip_outbound_registration * registration
Outbound registration configuration object.
Outbound registration information.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ cli_complete_registration()

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

Definition at line 1924 of file res_pjsip_outbound_registration.c.

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

1926 {
1927  char *result = NULL;
1928  int wordlen;
1929  int which = 0;
1930  struct sip_outbound_registration *registration;
1931  struct ao2_container *registrations;
1932  struct ao2_iterator i;
1933 
1934  if (pos != 3) {
1935  return NULL;
1936  }
1937 
1938  wordlen = strlen(word);
1939  if (wordlen == 0 && ++which > state) {
1940  return ast_strdup("*all");
1941  }
1942 
1943  registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1945  if (!registrations) {
1946  return NULL;
1947  }
1948 
1949  i = ao2_iterator_init(registrations, 0);
1950  while ((registration = ao2_iterator_next(&i))) {
1951  const char *name = ast_sorcery_object_get_id(registration);
1952 
1953  if (!strncasecmp(word, name, wordlen) && ++which > state) {
1954  result = ast_strdup(name);
1955  }
1956 
1957  ao2_ref(registration, -1);
1958  if (result) {
1959  break;
1960  }
1961  }
1963 
1964  ao2_ref(registrations, -1);
1965  return result;
1966 }
Perform no matching, return all objects.
Definition: sorcery.h:123
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Return all matching objects.
Definition: sorcery.h:120
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Outbound registration information.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static const char name[]
Definition: cdr_mysql.c:74
static struct registrations registrations
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static PGresult * result
Definition: cel_pgsql.c:88
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word

◆ cli_get_container()

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

Definition at line 2211 of file res_pjsip_outbound_registration.c.

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, and RAII_VAR.

Referenced by load_module().

2212 {
2214  struct ao2_container *s_container;
2215 
2217  if (!container) {
2218  return NULL;
2219  }
2220 
2223  if (!s_container) {
2224  return NULL;
2225  }
2226 
2227  if (ao2_container_dup(s_container, container, 0)) {
2228  ao2_ref(s_container, -1);
2229  return NULL;
2230  }
2231 
2232  return s_container;
2233 }
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
#define NULL
Definition: resample.c:96
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:1949
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
struct ao2_container * container
Definition: res_fax.c:502
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.
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:948
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.

◆ cli_iterator()

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

Definition at line 2235 of file res_pjsip_outbound_registration.c.

References ao2_callback, and OBJ_NODATA.

Referenced by load_module().

2236 {
2237  ao2_callback(container, OBJ_NODATA, callback, args);
2238 
2239  return 0;
2240 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
const char * args
struct ao2_container * container
Definition: res_fax.c:502

◆ cli_print_body()

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

Definition at line 2271 of file res_pjsip_outbound_registration.c.

References ao2_cleanup, ast_assert, ast_sip_cli_print_sorcery_objectset(), ast_sorcery_object_get_id(), ast_str_append(), AST_VECTOR_GET, AST_VECTOR_SIZE, sip_outbound_registration_state::client_state, context, get_state(), ast_sip_cli_context::indent_level, NULL, sip_outbound_registration::outbound_auths, ast_sip_cli_context::output_buffer, REGISTRATION_URI_FIELD_LEN, sip_outbound_registration::server_uri, ast_sip_cli_context::show_details, ast_sip_cli_context::show_details_only_level_0, sip_outbound_registration_status_str(), and sip_outbound_registration_client_state::status.

Referenced by load_module().

2272 {
2273  struct sip_outbound_registration *registration = obj;
2274  struct ast_sip_cli_context *context = arg;
2275  const char *id = ast_sorcery_object_get_id(registration);
2277 #define REGISTRATION_URI_FIELD_LEN 53
2278 
2279  ast_assert(context->output_buffer != NULL);
2280 
2281  ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s %-16s %-16s\n",
2282  id,
2283  (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2284  (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
2285  registration->server_uri,
2286  AST_VECTOR_SIZE(&registration->outbound_auths)
2287  ? AST_VECTOR_GET(&registration->outbound_auths, 0)
2288  : "n/a",
2289  (state ? sip_outbound_registration_status_str(state->client_state->status) : "Unregistered"));
2290  ao2_cleanup(state);
2291 
2292  if (context->show_details
2293  || (context->show_details_only_level_0 && context->indent_level == 0)) {
2294  ast_str_append(&context->output_buffer, 0, "\n");
2295  ast_sip_cli_print_sorcery_objectset(registration, context, 0);
2296  }
2297 
2298  return 0;
2299 }
struct ast_str * output_buffer
Definition: res_pjsip_cli.h:36
enum sip_outbound_registration_status status
Current state of this registration.
const ast_string_field server_uri
URI for the registrar.
Outbound registration state information (persists for lifetime that registration should exist) ...
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define REGISTRATION_URI_FIELD_LEN
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
struct sip_outbound_registration_client_state * client_state
Client state information.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Outbound registration information.
static struct sip_outbound_registration_state * get_state(const char *id)
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object&#39;s ast_variable list.
Definition: pjsip_cli.c:36
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
unsigned show_details_only_level_0
Definition: res_pjsip_cli.h:46

◆ cli_print_header()

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

Definition at line 2259 of file res_pjsip_outbound_registration.c.

References ast_assert, ast_str_append(), context, NULL, and ast_sip_cli_context::output_buffer.

Referenced by load_module().

2260 {
2261  struct ast_sip_cli_context *context = arg;
2262 
2263  ast_assert(context->output_buffer != NULL);
2264 
2265  ast_str_append(&context->output_buffer, 0,
2266  " <Registration/ServerURI..............................> <Auth..........> <Status.......>\n");
2267 
2268  return 0;
2269 }
struct ast_str * output_buffer
Definition: res_pjsip_cli.h:36
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ cli_register()

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

Definition at line 2011 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), cli_complete_registration(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_state(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, queue_register(), queue_unregister(), reregister_all(), state, ast_cli_entry::usage, and ast_cli_args::word.

2012 {
2014  const char *registration_name;
2015 
2016  switch (cmd) {
2017  case CLI_INIT:
2018  e->command = "pjsip send register";
2019  e->usage =
2020  "Usage: pjsip send register <registration> | *all \n"
2021  " Unregisters the specified (or all) outbound "
2022  "registration(s) then starts registration(s) and schedules re-registrations.\n";
2023  return NULL;
2024  case CLI_GENERATE:
2025  return cli_complete_registration(a->line, a->word, a->pos, a->n);
2026  }
2027 
2028  if (a->argc != 4) {
2029  return CLI_SHOWUSAGE;
2030  }
2031 
2032  registration_name = a->argv[3];
2033 
2034  if (strcmp(registration_name, "*all") == 0) {
2035  reregister_all();
2036  ast_cli(a->fd, "Re-register all queued\n");
2037  return CLI_SUCCESS;
2038  }
2039 
2040  state = get_state(registration_name);
2041  if (!state) {
2042  ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2043  return CLI_FAILURE;
2044  }
2045 
2046  /* We need to serialize the unregister and register so they need
2047  * to be queued as separate tasks.
2048  */
2049  if (queue_unregister(state)) {
2050  ast_cli(a->fd, "Failed to queue unregistration\n");
2051  } else if (queue_register(state)) {
2052  ast_cli(a->fd, "Failed to queue registration\n");
2053  }
2054 
2055  ao2_ref(state, -1);
2056  return CLI_SUCCESS;
2057 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static char * cli_complete_registration(const char *line, const char *word, int pos, int state)
const int argc
Definition: cli.h:160
Definition: cli.h:152
Outbound registration state information (persists for lifetime that registration should exist) ...
static int queue_unregister(struct sip_outbound_registration_state *state)
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static struct sip_outbound_registration_state * get_state(const char *id)
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
static int queue_register(struct sip_outbound_registration_state *state)
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
static void reregister_all(void)

◆ cli_retrieve_by_id()

static void* cli_retrieve_by_id ( const char *  id)
static

Definition at line 2242 of file res_pjsip_outbound_registration.c.

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

2243 {
2244  struct ao2_container *states;
2245  void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
2246 
2247  if (!obj) {
2248  /* if the object no longer exists then remove its state */
2249  states = ao2_global_obj_ref(current_states);
2250  if (states) {
2251  ao2_find(states, id, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
2252  ao2_ref(states, -1);
2253  }
2254  }
2255 
2256  return obj;
2257 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
Generic container type.

◆ cli_unregister()

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

Definition at line 1968 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), cli_complete_registration(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_state(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, queue_unregister(), state, unregister_all(), ast_cli_entry::usage, and ast_cli_args::word.

1969 {
1971  const char *registration_name;
1972 
1973  switch (cmd) {
1974  case CLI_INIT:
1975  e->command = "pjsip send unregister";
1976  e->usage =
1977  "Usage: pjsip send unregister <registration> | *all\n"
1978  " Unregisters the specified (or all) outbound registration(s) "
1979  "and stops future registration attempts.\n";
1980  return NULL;
1981  case CLI_GENERATE:
1982  return cli_complete_registration(a->line, a->word, a->pos, a->n);
1983  }
1984 
1985  if (a->argc != 4) {
1986  return CLI_SHOWUSAGE;
1987  }
1988 
1989  registration_name = a->argv[3];
1990 
1991  if (strcmp(registration_name, "*all") == 0) {
1992  unregister_all();
1993  ast_cli(a->fd, "Unregister all queued\n");
1994  return CLI_SUCCESS;
1995  }
1996 
1997  state = get_state(registration_name);
1998  if (!state) {
1999  ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
2000  return CLI_FAILURE;
2001  }
2002 
2003  if (queue_unregister(state)) {
2004  ast_cli(a->fd, "Failed to queue unregistration\n");
2005  }
2006 
2007  ao2_ref(state, -1);
2008  return CLI_SUCCESS;
2009 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static char * cli_complete_registration(const char *line, const char *word, int pos, int state)
const int argc
Definition: cli.h:160
Definition: cli.h:152
Outbound registration state information (persists for lifetime that registration should exist) ...
static int queue_unregister(struct sip_outbound_registration_state *state)
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
static void unregister_all(void)
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static struct sip_outbound_registration_state * get_state(const char *id)
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164

◆ fetch_google_access_token()

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

Definition at line 1485 of file res_pjsip_outbound_registration.c.

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, ast_json_error::column, ast_json_error::line, LOG_ERROR, NULL, ast_sip_auth::oauth_clientid, ast_sip_auth::oauth_secret, ast_sip_auth::refresh_token, ast_json_error::text, and url.

Referenced by set_outbound_initial_authentication_credentials().

1486 {
1487  char *cmd = NULL;
1488  const char *token;
1489  const char *url = "https://www.googleapis.com/oauth2/v3/token";
1490  char buf[4096];
1491  int res;
1492  struct ast_json_error error;
1493  struct ast_json *json;
1494 
1495  /* set timeout to be shorter than default 180s (also checks func_curl is available) */
1496  if (ast_func_write(NULL, "CURLOPT(conntimeout)", "10")) {
1497  ast_log(LOG_ERROR, "CURL is unavailable. This is required for Google OAuth 2.0 authentication. Please ensure it is loaded.\n");
1498  return NULL;
1499  }
1500 
1501  res = ast_asprintf(&cmd,
1502  "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
1503  url, auth->oauth_clientid, auth->oauth_secret, auth->refresh_token);
1504  if (res < 0) {
1505  return NULL;
1506  }
1507 
1508  ast_debug(2, "Performing Google OAuth 2.0 authentication using command: %s\n", cmd);
1509 
1510  buf[0] = '\0';
1511  res = ast_func_read(NULL, cmd, buf, sizeof(buf));
1512  ast_free(cmd);
1513  if (res) {
1514  ast_log(LOG_ERROR, "Could not retrieve Google OAuth 2.0 authentication\n");
1515  return NULL;
1516  }
1517 
1518  ast_debug(2, "Google OAuth 2.0 authentication returned: %s\n", buf);
1519 
1520  json = ast_json_load_string(buf, &error);
1521  if (!json) {
1522  ast_log(LOG_ERROR, "Could not parse Google OAuth 2.0 authentication: %d(%d) %s: '%s'\n",
1523  error.line, error.column, error.text, buf);
1524  return NULL;
1525  }
1526 
1527  token = ast_json_string_get(ast_json_object_get(json, "access_token"));
1528  if (!token) {
1529  ast_log(LOG_ERROR, "Could not find Google OAuth 2.0 access_token in: '%s'\n",
1530  buf);
1531  }
1532  token = ast_strdup(token);
1533  ast_json_unref(json);
1534  return token;
1535 }
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
const ast_string_field oauth_secret
Definition: res_pjsip.h:460
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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:546
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
JSON parsing error information.
Definition: json.h:829
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
const ast_string_field oauth_clientid
Definition: res_pjsip.h:458
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
#define LOG_ERROR
Definition: logger.h:285
#define ast_free(a)
Definition: astmm.h:182
const ast_string_field refresh_token
Definition: res_pjsip.h:456
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
Abstract JSON element (object, array, string, int, ...).
int error(const char *format,...)
Definition: utils/frame.c:999
static char url[512]
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function

◆ get_registrations()

static struct ao2_container* get_registrations ( void  )
static

Definition at line 481 of file res_pjsip_outbound_registration.c.

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

Referenced by ami_show_outbound_registrations(), and registration_loaded_observer().

482 {
484  ast_sip_get_sorcery(), "registration",
486 
487  return registrations;
488 }
Perform no matching, return all objects.
Definition: sorcery.h:123
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
static struct registrations registrations
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
Generic container type.

◆ get_state()

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

Definition at line 468 of file res_pjsip_outbound_registration.c.

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

469 {
471  struct ao2_container *states;
472 
473  states = ao2_global_obj_ref(current_states);
474  if (states) {
475  state = ao2_find(states, id, OBJ_SEARCH_KEY);
476  ao2_ref(states, -1);
477  }
478  return state;
479 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Generic container type.

◆ get_uri_option_line()

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

Definition at line 499 of file res_pjsip_outbound_registration.c.

References NULL.

Referenced by line_identify().

500 {
501  pjsip_sip_uri *pjuri;
502  static const pj_str_t LINE_STR = { "line", 4 };
503 
504  if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
505  return NULL;
506  }
507  pjuri = pjsip_uri_get_uri(uri);
508  return pjsip_param_find(&pjuri->other_param, &LINE_STR);
509 }
#define NULL
Definition: resample.c:96

◆ handle_client_registration()

static int handle_client_registration ( void *  data)
static

Callback function for registering.

Definition at line 668 of file res_pjsip_outbound_registration.c.

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

669 {
670  RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
671  pjsip_tx_data *tdata;
672 
673  if (set_outbound_initial_authentication_credentials(client_state->client, &client_state->outbound_auths)) {
674  ast_log(LOG_WARNING, "Failed to set initial authentication credentials\n");
675  }
676 
677  if (client_state->status == SIP_REGISTRATION_STOPPED
678  || pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
679  return 0;
680  }
681 
682  if (DEBUG_ATLEAST(1)) {
683  pjsip_regc_info info;
684 
685  pjsip_regc_get_info(client_state->client, &info);
686  ast_log(LOG_DEBUG, "Outbound REGISTER attempt %u to '%.*s' with client '%.*s'\n",
687  client_state->retries + 1,
688  (int) info.server_uri.slen, info.server_uri.ptr,
689  (int) info.client_uri.slen, info.client_uri.ptr);
690  }
691 
692  if (!add_configured_supported_headers(client_state, tdata)) {
693  ast_log(LOG_WARNING, "Failed to set supported headers\n");
694  return -1;
695  }
696 
697  registration_client_send(client_state, tdata);
698 
699  return 0;
700 }
#define LOG_WARNING
Definition: logger.h:274
Outbound registration client state information (persists for lifetime of regc)
#define LOG_DEBUG
Definition: logger.h:241
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int set_outbound_initial_authentication_credentials(pjsip_regc *regc, const struct ast_sip_auth_vector *auth_vector)
def info(msg)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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.
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
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.
Registration has been stopped.

◆ handle_client_state_destruction()

static int handle_client_state_destruction ( void *  data)
static

Callback function for unregistering (potentially) and destroying state.

Definition at line 772 of file res_pjsip_outbound_registration.c.

References add_configured_supported_headers(), ao2_ref, ast_debug, ast_sip_auth_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_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().

773 {
774  struct sip_outbound_registration_client_state *client_state = data;
775 
776  cancel_registration(client_state);
777 
778  if (client_state->client) {
779  pjsip_regc_info info;
780  pjsip_tx_data *tdata;
781 
782  pjsip_regc_get_info(client_state->client, &info);
783 
784  if (info.is_busy == PJ_TRUE) {
785  /* If a client transaction is in progress we defer until it is complete */
786  ast_debug(1,
787  "Registration transaction is busy with server '%.*s' from client '%.*s'.\n",
788  (int) info.server_uri.slen, info.server_uri.ptr,
789  (int) info.client_uri.slen, info.client_uri.ptr);
790  client_state->destroy = 1;
791  ao2_ref(client_state, -1);
792  return 0;
793  }
794 
795  switch (client_state->status) {
797  break;
799  ast_debug(1,
800  "Trying to unregister with server '%.*s' from client '%.*s' before destruction.\n",
801  (int) info.server_uri.slen, info.server_uri.ptr,
802  (int) info.client_uri.slen, info.client_uri.ptr);
803 
805  client_state->destroy = 1;
806  if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS
807  && add_configured_supported_headers(client_state, tdata)
808  && registration_client_send(client_state, tdata) == PJ_SUCCESS) {
809  ao2_ref(client_state, -1);
810  return 0;
811  }
812  break;
817  break;
818  }
819 
820  pjsip_regc_destroy(client_state->client);
821  client_state->client = NULL;
822  }
823 
826  ao2_ref(client_state, -1);
827 
828  return 0;
829 }
static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector)
Free contents of an auth vector.
enum sip_outbound_registration_status status
Current state of this registration.
Outbound registration client state information (persists for lifetime of regc)
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Registration was rejected, permanently.
def info(msg)
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
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.
unsigned int destroy
Registration should be destroyed after completion of transaction.
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.
Registration was rejected, but response was temporal.
pjsip_regc * client
Outbound registration client.
Registration has been stopped.
static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
Helper function which cancels the timer on a client.

◆ handle_registration_response()

static int handle_registration_response ( void *  data)
static

Callback function for handling a response to a registration attempt.

Definition at line 1056 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_copy_pj_str(), ast_debug, ast_log, ast_sip_create_request_with_auth(), ast_sip_failover_request(), ast_sip_transport_monitor_unregister(), ast_system_publish_registry(), sip_outbound_registration_client_state::auth_attempted, sip_outbound_registration_client_state::auth_cseq, sip_outbound_registration_client_state::client, registration_response::client_state, sip_outbound_registration::client_uri, registration_response::code, sip_outbound_registration_client_state::destroy, 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(), LOG_WARNING, sip_outbound_registration_client_state::max_retries, monitor_matcher(), NULL, 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::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, and update_client_state_status().

Referenced by sip_outbound_registration_response_cb().

1057 {
1058  struct registration_response *response = data;
1059  pjsip_regc_info info;
1060  char server_uri[PJSIP_MAX_URL_SIZE];
1061  char client_uri[PJSIP_MAX_URL_SIZE];
1062 
1063  if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
1064  ao2_ref(response, -1);
1065  return 0;
1066  }
1067 
1068  pjsip_regc_get_info(response->client_state->client, &info);
1069  ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
1070  ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
1071 
1072  ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
1073  response->code, server_uri, client_uri);
1074 
1075  if (response->code == 408 || response->code == 503) {
1076  if ((ast_sip_failover_request(response->old_request))) {
1077  int res = registration_client_send(response->client_state, response->old_request);
1078  /* The tdata ref was stolen */
1079  response->old_request = NULL;
1080  if (res == PJ_SUCCESS) {
1081  ao2_ref(response, -1);
1082  return 0;
1083  }
1084  }
1085  } else if ((response->code == 401 || response->code == 407)
1086  && (!response->client_state->auth_attempted
1087  || response->rdata->msg_info.cseq->cseq != response->client_state->auth_cseq)) {
1088  int res;
1089  pjsip_cseq_hdr *cseq_hdr;
1090  pjsip_tx_data *tdata;
1091 
1093  response->rdata, response->old_request, &tdata)) {
1094  response->client_state->auth_attempted = 1;
1095  ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
1096  server_uri, client_uri);
1097  pjsip_tx_data_add_ref(tdata);
1098  res = registration_client_send(response->client_state, tdata);
1099 
1100  /* Save the cseq that actually got sent. */
1101  cseq_hdr = (pjsip_cseq_hdr *) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ,
1102  NULL);
1103  response->client_state->auth_cseq = cseq_hdr->cseq;
1104  pjsip_tx_data_dec_ref(tdata);
1105  if (res == PJ_SUCCESS) {
1106  ao2_ref(response, -1);
1107  return 0;
1108  }
1109  } else {
1110  ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
1111  server_uri, client_uri);
1112  }
1113  /* Otherwise, fall through so the failure is processed appropriately */
1114  }
1115 
1116  response->client_state->auth_attempted = 0;
1117 
1118  if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
1119  /* Check if this is in regards to registering or unregistering */
1120  if (response->expiration) {
1121  int next_registration_round;
1122 
1123  /* If the registration went fine simply reschedule registration for the future */
1124  ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
1126  response->client_state->retries = 0;
1127  next_registration_round = response->expiration - REREGISTER_BUFFER_TIME;
1128  if (next_registration_round < 0) {
1129  /* Re-register immediately. */
1130  next_registration_round = 0;
1131  }
1132  schedule_registration(response->client_state, next_registration_round);
1133 
1134  /* See if we should monitor for transport shutdown */
1135  registration_transport_monitor_setup(response->rdata->tp_info.transport,
1136  response->client_state->registration_name);
1137  } else {
1138  ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
1140  ast_sip_transport_monitor_unregister(response->rdata->tp_info.transport,
1142  monitor_matcher);
1143  }
1144 
1146  } else if (response->client_state->destroy) {
1147  /* We need to deal with the pending destruction instead. */
1148  } else if (response->retry_after) {
1149  /* If we have been instructed to retry after a period of time, schedule it as such */
1150  schedule_retry(response, response->retry_after, server_uri, client_uri);
1151  } else if (response->client_state->retry_interval
1152  && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
1153  if (response->client_state->retries == response->client_state->max_retries) {
1154  /* If we received enough temporal responses to exceed our maximum give up permanently */
1156  ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
1157  server_uri, client_uri);
1158  } else {
1159  /* On the other hand if we can still try some more do so */
1160  response->client_state->retries++;
1161  schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
1162  }
1163  } else {
1164  if (response->code == 403
1166  && response->client_state->retries < response->client_state->max_retries) {
1167  /* A forbidden response retry interval is configured and there are retries remaining */
1169  response->client_state->retries++;
1171  ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1172  server_uri, client_uri, response->client_state->forbidden_retry_interval);
1173  } else if (response->client_state->fatal_retry_interval
1174  && response->client_state->retries < response->client_state->max_retries) {
1175  /* Some kind of fatal failure response received, so retry according to configured interval */
1177  response->client_state->retries++;
1179  ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
1180  response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
1181  } else {
1182  /* Finally if there's no hope of registering give up */
1184  if (response->rdata) {
1185  ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
1186  response->code, server_uri, client_uri);
1187  } else {
1188  ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
1189  }
1190  }
1191  }
1192 
1193  ast_system_publish_registry("PJSIP", client_uri, server_uri,
1195 
1196  if (response->client_state->destroy) {
1197  /* We have a pending deferred destruction to complete now. */
1198  ao2_ref(response->client_state, +1);
1200  }
1201 
1202  ao2_ref(response, -1);
1203  return 0;
1204 }
unsigned int auth_attempted
Non-zero if we have attempted sending a REGISTER with authentication.
static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
static void registration_transport_monitor_setup(pjsip_transport *transport, const char *registration_name)
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.
pjsip_tx_data * old_request
Request for which the response was received.
#define LOG_WARNING
Definition: logger.h:274
enum sip_outbound_registration_status status
Current state of this registration.
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
static void save_response_fields_to_transport(struct registration_response *response)
static int handle_client_state_destruction(void *data)
Callback function for unregistering (potentially) and destroying state.
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
#define NULL
Definition: resample.c:96
Structure for registration response.
unsigned int max_retries
Maximum number of retries permitted.
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:4871
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
static void registration_transport_shutdown_cb(void *obj)
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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:3412
char * registration_name
The name of the registration sorcery object.
void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
#define REREGISTER_BUFFER_TIME
Amount of buffer time (in seconds) before expiration that we re-register at.
int code
Response code for the registration attempt.
int expiration
Expiration time for registration.
Registration was rejected, permanently.
def info(msg)
static int monitor_matcher(void *a, void *b)
static char server_uri[512]
unsigned int retries
Current number of retries.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
static void schedule_retry(struct registration_response *response, unsigned int interval, const char *server_uri, const char *client_uri)
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.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
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.
unsigned int destroy
Registration should be destroyed after completion of transaction.
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.
pjsip_rx_data * rdata
The response message.
Registration was rejected, but response was temporal.
pjsip_regc * client
Outbound registration client.
Registration has been stopped.

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

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(), sip_outbound_registration::line, line_identify_relationship(), NULL, and RAII_VAR.

513 {
514  pjsip_param *line;
515  RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
517 
518  if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
519  && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
520  return NULL;
521  }
522 
523  states = ao2_global_obj_ref(current_states);
524  if (!states) {
525  return NULL;
526  }
527 
528  state = ao2_callback(states, 0, line_identify_relationship, line);
529  if (!state || ast_strlen_zero(state->registration->endpoint)) {
530  return NULL;
531  }
532 
533  ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
534  ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
535 
536  return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
537 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
static struct pjsip_param * get_uri_option_line(const void *uri)
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static int line_identify_relationship(void *obj, void *arg, int flags)
Callback function for matching an outbound registration based on line.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.
pjsip_rx_data * rdata
The response message.

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

References sip_outbound_registration_state::client_state, CMP_MATCH, sip_outbound_registration::line, and sip_outbound_registration_client_state::line.

Referenced by line_identify().

492 {
494  pjsip_param *line = arg;
495 
496  return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH : 0;
497 }
Outbound registration state information (persists for lifetime that registration should exist) ...
char line[LINE_PARAMETER_SIZE]
Optional line parameter placed into Contact.
struct sip_outbound_registration_client_state * client_state
Client state information.

◆ load_module()

static int load_module ( void  )
static

Definition at line 2508 of file res_pjsip_outbound_registration.c.

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(), sip_outbound_registration::auth_rejection_permanent, cli_get_container(), cli_iterator(), cli_print_body(), cli_print_header(), cli_retrieve_by_id(), sip_outbound_registration::client_uri, sip_outbound_registration::contact_header_params, sip_outbound_registration::contact_user, DEFAULT_STATE_BUCKETS, sip_outbound_registration::endpoint, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, sip_outbound_registration::expiration, sip_outbound_registration::fatal_retry_interval, FLDSET, sip_outbound_registration::forbidden_retry_interval, ast_sip_cli_formatter_entry::get_container, ast_sip_cli_formatter_entry::get_id, ast_sip_cli_formatter_entry::iterate, sip_outbound_registration::line, LOG_ERROR, sip_outbound_registration::max_retries, ast_sip_cli_formatter_entry::name, network_change_stasis_cb(), new_states, NULL, 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(), sip_outbound_registration::outbound_proxy, ast_sip_cli_formatter_entry::print_body, ast_sip_cli_formatter_entry::print_header, registration_state_cmp(), registration_state_hash(), ast_sip_cli_formatter_entry::retrieve_by_id, sip_outbound_registration::retry_interval, sip_outbound_registration::server_uri, sip_outbound_registration_alloc(), sip_outbound_registration_apply(), stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), STRFLDSET, sip_outbound_registration::support_outbound, sip_outbound_registration::support_path, sip_outbound_registration::transport, and unload_module().

Referenced by reload_module().

2509 {
2510  struct ao2_container *new_states;
2511 
2513  if (!shutdown_group) {
2514  return AST_MODULE_LOAD_DECLINE;
2515  }
2516 
2517  /* Create outbound registration states container. */
2520  if (!new_states) {
2521  ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
2522  unload_module();
2523  return AST_MODULE_LOAD_DECLINE;
2524  }
2525  ao2_global_obj_replace_unref(current_states, new_states);
2526  ao2_ref(new_states, -1);
2527 
2528  /*
2529  * Register sorcery object descriptions.
2530  */
2531  ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
2532  ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
2533 
2535  unload_module();
2536  return AST_MODULE_LOAD_DECLINE;
2537  }
2538 
2539  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
2541  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
2542  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
2543  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));
2544  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
2545  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
2546  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
2547  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
2548  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));
2549  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));
2551  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));
2553  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
2554  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_outbound", "no", OPT_YESNO_T, 1, FLDSET(struct sip_outbound_registration, support_outbound));
2555  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
2556  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
2557 
2558  /*
2559  * Register sorcery observers.
2560  */
2565  || ast_sorcery_observer_add(ast_sip_get_sorcery(), "registration",
2567  ast_log(LOG_ERROR, "Unable to register observers.\n");
2568  unload_module();
2569  return AST_MODULE_LOAD_DECLINE;
2570  }
2571 
2572  /* Register how this module identifies endpoints. */
2574 
2575  /* Register CLI commands. */
2577  if (!cli_formatter) {
2578  ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
2579  unload_module();
2580  return AST_MODULE_LOAD_DECLINE;
2581  }
2582  cli_formatter->name = "registration";
2591 
2592  /* Register AMI actions. */
2596 
2597  /* Clear any previous statsd gauges in case we weren't shutdown cleanly */
2598  ast_statsd_log("PJSIP.registrations.count", AST_STATSD_GAUGE, 0);
2599  ast_statsd_log("PJSIP.registrations.state.Registered", AST_STATSD_GAUGE, 0);
2600  ast_statsd_log("PJSIP.registrations.state.Unregistered", AST_STATSD_GAUGE, 0);
2601  ast_statsd_log("PJSIP.registrations.state.Rejected", AST_STATSD_GAUGE, 0);
2602 
2603  /* Load configuration objects */
2604  ast_sorcery_load_object(ast_sip_get_sorcery(), "registration");
2605 
2610 
2611  return AST_MODULE_LOAD_SUCCESS;
2612 }
struct ao2_container *(* get_container)(const char *regex)
Definition: res_pjsip_cli.h:64
static void * cli_retrieve_by_id(const char *id)
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void network_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: res_pjsip_cli.h:52
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
static struct ast_sip_endpoint_identifier line_identifier
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229
struct stasis_message_type * ast_network_change_type(void)
A stasis_message_type for network changes.
static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
Apply function which finds or allocates a state structure.
static struct stasis_subscription * network_change_sub
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
Definition: res_pjsip_cli.h:66
Type for a default handler that should do nothing.
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:1079
static const struct ast_sorcery_observer observer_callbacks_auth
static int registration_state_hash(const void *obj, const int flags)
hashing function for state objects
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_sorcery_apply_config(sorcery, name)
Definition: sorcery.h:456
#define NULL
Definition: resample.c:96
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
static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Definition: pjsip_cli.c:310
static const struct ast_sorcery_observer registration_observer
Type for default option handler for bools (ast_true/ast_false)
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_log
Definition: astobj2.c:42
#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 FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Register a SIP endpoint identifier.
Definition: res_pjsip.c:3508
Type for default option handler for unsigned integers.
static int unload_module(void)
static int ami_register(struct mansession *s, const struct message *m)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define DEFAULT_STATE_BUCKETS
Default number of state container buckets.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
void *(* retrieve_by_id)(const char *id)
Definition: res_pjsip_cli.h:68
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:838
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:222
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
static struct ast_cli_entry cli_outbound_registration[]
Outbound registration information.
static int ami_show_outbound_registrations(struct mansession *s, const struct message *m)
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
Type for default option handler for bools (ast_true/ast_false)
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:477
static int max_retries
Definition: chan_iax2.c:328
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes. ...
static char server_uri[512]
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void * sip_outbound_registration_alloc(const char *name)
Allocator function for registration information.
const char *(* get_id)(const void *obj)
Definition: res_pjsip_cli.h:70
static int registration_state_cmp(void *obj, void *arg, int flags)
comparator function for state objects
#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 EVENT_FLAG_REPORTING
Definition: manager.h:80
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
static struct ao2_container * cli_get_container(const char *regex)
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ao2_container * new_states
Used on [re]loads to hold new state data.
static struct ast_sip_cli_formatter_entry * cli_formatter
static int ami_unregister(struct mansession *s, const struct message *m)
static int cli_print_body(void *obj, void *arg, int flags)
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:1025
static int cli_print_header(void *obj, void *arg, int flags)
Type for default option handler for stringfields.
ao2_callback_fn * print_header
Definition: res_pjsip_cli.h:60
Generic container type.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
ao2_callback_fn * print_body
Definition: res_pjsip_cli.h:62
const char * name
Definition: res_pjsip_cli.h:58
static struct ast_serializer_shutdown_group * shutdown_group
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)

◆ monitor_matcher()

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

Definition at line 954 of file res_pjsip_outbound_registration.c.

References a, and b.

Referenced by handle_registration_response().

955 {
956  char *ma = a;
957  char *mb = b;
958 
959  return strcmp(ma, mb) == 0;
960 }
static struct test_val b
static struct test_val a

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

References ast_sip_cli_traverse_objects().

2307 {
2308  return ast_sip_cli_traverse_objects(e, cmd, a);
2309 }
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pjsip_cli.c:109

◆ network_change_stasis_cb()

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

Definition at line 2450 of file res_pjsip_outbound_registration.c.

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

Referenced by load_module().

2451 {
2452  /* This callback is only concerned with network change messages from the system topic. */
2453  if (stasis_message_type(message) != ast_network_change_type()) {
2454  return;
2455  }
2456  ast_debug(3, "Received network change event\n");
2457 
2458  reregister_all();
2459 }
struct stasis_message_type * ast_network_change_type(void)
A stasis_message_type for network changes.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static void reregister_all(void)

◆ outbound_auth_handler()

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

Definition at line 1828 of file res_pjsip_outbound_registration.c.

References ast_sip_auth_vector_init(), sip_outbound_registration::outbound_auths, and ast_variable::value.

Referenced by load_module().

1829 {
1830  struct sip_outbound_registration *registration = obj;
1831 
1832  return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
1833 }
int ast_sip_auth_vector_init(struct ast_sip_auth_vector *vector, const char *auth_names)
Initialize an auth vector with the configured values.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
Outbound registration information.

◆ outbound_auths_to_str()

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

Definition at line 1835 of file res_pjsip_outbound_registration.c.

References ast_sip_auths_to_str(), and sip_outbound_registration::outbound_auths.

Referenced by load_module().

1836 {
1837  const struct sip_outbound_registration *registration = obj;
1838 
1839  return ast_sip_auths_to_str(&registration->outbound_auths, buf);
1840 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
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.
Outbound registration information.

◆ outbound_auths_to_var_list()

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

Definition at line 1842 of file res_pjsip_outbound_registration.c.

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

1843 {
1844  const struct sip_outbound_registration *registration = obj;
1845  int i;
1846  struct ast_variable *head = NULL;
1847 
1848  for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
1849  ast_variable_list_append(&head, ast_variable_new("outbound_auth",
1850  AST_VECTOR_GET(&registration->outbound_auths, i), ""));
1851  }
1852 
1853  if (head) {
1854  *fields = head;
1855  }
1856 
1857  return 0;
1858 }
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
#define ast_variable_new(name, value, filename)
Outbound registration information.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_variable_list_append(head, new_var)

◆ queue_register()

static int queue_register ( struct sip_outbound_registration_state state)
static

Definition at line 1893 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_sip_push_task(), sip_outbound_registration_state::client_state, sip_outbound_registration_client_state::serializer, and sip_outbound_registration_perform().

Referenced by ami_register(), and cli_register().

1894 {
1895  ao2_ref(state, +1);
1897  ao2_ref(state, -1);
1898  return -1;
1899  }
1900 
1901  return 0;
1902 }
static int sip_outbound_registration_perform(void *data)
Helper function which performs a single registration.
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
struct ast_taskprocessor * serializer
Serializer for stuff and things.

◆ queue_unregister()

static int queue_unregister ( struct sip_outbound_registration_state state)
static

Definition at line 1882 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_sip_push_task(), sip_outbound_registration_state::client_state, sip_outbound_registration_client_state::serializer, and unregister_task().

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

1883 {
1884  ao2_ref(state, +1);
1886  ao2_ref(state, -1);
1887  return -1;
1888  }
1889 
1890  return 0;
1891 }
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
struct ast_taskprocessor * serializer
Serializer for stuff and things.
static int unregister_task(void *obj)

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

References ao2_ref, ast_sip_set_tpselector_from_transport_name(), ast_sip_tpselector_unref(), ast_threadstorage_get(), sip_outbound_registration_client_state::client, sip_outbound_registration_client_state::last_tdata, register_callback_invoked, status, and sip_outbound_registration_client_state::transport_name.

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

559 {
560  pj_status_t status;
561  int *callback_invoked;
562  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
563 
564  callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
565  if (!callback_invoked) {
566  pjsip_tx_data_dec_ref(tdata);
567  return PJ_ENOMEM;
568  }
569  *callback_invoked = 0;
570 
571  /* Due to the message going out the callback may now be invoked, so bump the count */
572  ao2_ref(client_state, +1);
573  /*
574  * We also bump tdata in expectation of saving it to client_state->last_tdata.
575  * We have to do it BEFORE pjsip_regc_send because if it succeeds, it decrements
576  * the ref count on its own.
577  */
578  pjsip_tx_data_add_ref(tdata);
579 
580  /*
581  * Set the transport in case transports were reloaded.
582  * When pjproject removes the extraneous error messages produced,
583  * we can check status and only set the transport and resend if there was an error
584  */
586  pjsip_regc_set_transport(client_state->client, &selector);
587  ast_sip_tpselector_unref(&selector);
588 
589  status = pjsip_regc_send(client_state->client, tdata);
590 
591  /*
592  * If the attempt to send the message failed and the callback was not invoked we need to
593  * drop the references we just added
594  */
595  if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
596  pjsip_tx_data_dec_ref(tdata);
597  ao2_ref(client_state, -1);
598  return status;
599  }
600 
601  /*
602  * Decref the old last_data before replacing it.
603  * BTW, it's quite possible that last_data == tdata
604  * if we're trying successive servers in an SRV set.
605  */
606  if (client_state->last_tdata) {
607  pjsip_tx_data_dec_ref(client_state->last_tdata);
608  }
609  client_state->last_tdata = tdata;
610 
611  return status;
612 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static struct ast_threadstorage register_callback_invoked
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_tx_data * last_tdata
Last tdata sent We need the original tdata to resend a request on auth failure or timeout...
char * transport_name
The name of the transport to be used for the registration.
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
jack_status_t status
Definition: app_jack.c:146
pjsip_regc * client
Outbound registration client.
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:3957

◆ registration_deleted_observer()

static void registration_deleted_observer ( const void *  obj)
static

Definition at line 2430 of file res_pjsip_outbound_registration.c.

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

2431 {
2432  const struct sip_outbound_registration *registration = obj;
2433  struct ao2_container *states;
2434 
2435  states = ao2_global_obj_ref(current_states);
2436  if (!states) {
2437  /* Global container has gone. Likely shutting down. */
2438  return;
2439  }
2440 
2442 
2443  ao2_ref(states, -1);
2444 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Outbound registration information.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Generic container type.

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

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

2400 {
2401  struct ao2_container *states;
2402 
2403  if (strcmp(object_type, "registration")) {
2404  /* Not interested */
2405  return;
2406  }
2407 
2408  states = ao2_global_obj_ref(current_states);
2409  if (!states) {
2410  /* Global container has gone. Likely shutting down. */
2411  return;
2412  }
2413 
2414  /*
2415  * Refresh the current configured registrations. We don't need to hold
2416  * onto the objects, as the apply handler will cause their states to
2417  * be created appropriately.
2418  */
2420 
2421  /* Now to purge dead registrations. */
2423  ao2_ref(states, -1);
2424 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
static struct ao2_container * get_registrations(void)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int check_state(void *obj, void *arg, int flags)
Generic container type.

◆ registration_response_destroy()

static void registration_response_destroy ( void *  obj)
static

Registration response structure destructor.

Definition at line 848 of file res_pjsip_outbound_registration.c.

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

Referenced by sip_outbound_registration_response_cb().

849 {
850  struct registration_response *response = obj;
851 
852  if (response->rdata) {
853  pjsip_rx_data_free_cloned(response->rdata);
854  }
855 
856  if (response->old_request) {
857  pjsip_tx_data_dec_ref(response->old_request);
858  }
859 
860  ao2_cleanup(response->client_state);
861 }
pjsip_tx_data * old_request
Request for which the response was received.
Structure for registration response.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
pjsip_rx_data * rdata
The response message.

◆ registration_state_cmp()

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

comparator function for state objects

Definition at line 440 of file res_pjsip_outbound_registration.c.

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

441 {
442  const struct sip_outbound_registration_state *object_left = obj;
443  const struct sip_outbound_registration_state *object_right = arg;
444  const char *right_key = arg;
445  int cmp;
446 
447  switch (flags & OBJ_SEARCH_MASK) {
448  case OBJ_SEARCH_OBJECT:
449  right_key = ast_sorcery_object_get_id(object_right->registration);
450  /* Fall through */
451  case OBJ_SEARCH_KEY:
452  cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
453  break;
455  /* Not supported by container. */
456  ast_assert(0);
457  return 0;
458  default:
459  cmp = 0;
460  break;
461  }
462  if (cmp) {
463  return 0;
464  }
465  return CMP_MATCH;
466 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ast_assert(a)
Definition: utils.h:695
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct sip_outbound_registration * registration
Outbound registration configuration object.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ registration_state_hash()

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

hashing function for state objects

Definition at line 419 of file res_pjsip_outbound_registration.c.

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

420 {
421  const struct sip_outbound_registration_state *object;
422  const char *key;
423 
424  switch (flags & OBJ_SEARCH_MASK) {
425  case OBJ_SEARCH_KEY:
426  key = obj;
427  break;
428  case OBJ_SEARCH_OBJECT:
429  object = obj;
431  break;
432  default:
433  ast_assert(0);
434  return 0;
435  }
436  return ast_str_hash(key);
437 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ast_assert(a)
Definition: utils.h:695
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct sip_outbound_registration * registration
Outbound registration configuration object.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ registration_transport_monitor_setup()

static void registration_transport_monitor_setup ( pjsip_transport *  transport,
const char *  registration_name 
)
static

Definition at line 962 of file res_pjsip_outbound_registration.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_sip_transport_monitor_register(), monitor, NULL, and registration_transport_shutdown_cb().

Referenced by handle_registration_response().

963 {
964  char *monitor;
965 
966  if (!PJSIP_TRANSPORT_IS_RELIABLE(transport)) {
967  return;
968  }
969  monitor = ao2_alloc_options(strlen(registration_name) + 1, NULL,
971  if (!monitor) {
972  return;
973  }
974  strcpy(monitor, registration_name);/* Safe */
975 
976  /*
977  * We'll ignore if the transport has already been shutdown before we
978  * register the monitor. We might get into a message spamming infinite
979  * loop of registration, shutdown, reregistration...
980  */
982  monitor);
983  ao2_ref(monitor, -1);
984 }
enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *ao2_data)
Register a reliable transport shutdown monitor callback.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
static void registration_transport_shutdown_cb(void *obj)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static unsigned int monitor
Definition: chan_phone.c:116

◆ registration_transport_shutdown_cb()

static void registration_transport_shutdown_cb ( void *  obj)
static

Definition at line 939 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_sip_push_task(), sip_outbound_registration_state::client_state, get_state(), reregister_immediately_cb(), sip_outbound_registration_client_state::serializer, and state.

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

940 {
941  const char *registration_name = obj;
943 
944  state = get_state(registration_name);
945  if (!state) {
946  /* Registration no longer exists or shutting down. */
947  return;
948  }
950  ao2_ref(state, -1);
951  }
952 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
Outbound registration state information (persists for lifetime that registration should exist) ...
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
static struct sip_outbound_registration_state * get_state(const char *id)
struct ast_taskprocessor * serializer
Serializer for stuff and things.
static int reregister_immediately_cb(void *obj)

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2614 of file res_pjsip_outbound_registration.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_sip_get_sorcery(), ast_sorcery_reload_object(), ASTERISK_GPL_KEY, load_module(), reload(), and unload_module().

2615 {
2617  return 0;
2618 }
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
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

◆ reregister_all()

static void reregister_all ( void  )
static

Definition at line 1918 of file res_pjsip_outbound_registration.c.

References ast_sip_get_sorcery(), ast_sorcery_load_object(), and unregister_all().

Referenced by ami_register(), cli_register(), and network_change_stasis_cb().

1919 {
1920  unregister_all();
1921  ast_sorcery_load_object(ast_sip_get_sorcery(), "registration");
1922 }
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
static void unregister_all(void)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ reregister_immediately_cb()

static int reregister_immediately_cb ( void *  obj)
static

Definition at line 900 of file res_pjsip_outbound_registration.c.

References ao2_ref, ast_log, cancel_registration(), sip_outbound_registration_client_state::client, sip_outbound_registration_state::client_state, DEBUG_ATLEAST, handle_client_registration(), sip_to_pjsip::info(), LOG_DEBUG, SIP_REGISTRATION_REGISTERED, and sip_outbound_registration_client_state::status.

Referenced by registration_transport_shutdown_cb().

901 {
903 
905  ao2_ref(state, -1);
906  return 0;
907  }
908 
909  if (DEBUG_ATLEAST(1)) {
910  pjsip_regc_info info;
911 
912  pjsip_regc_get_info(state->client_state->client, &info);
914  "Outbound registration transport to server '%.*s' from client '%.*s' shutdown\n",
915  (int) info.server_uri.slen, info.server_uri.ptr,
916  (int) info.client_uri.slen, info.client_uri.ptr);
917  }
918 
920 
921  ao2_ref(state->client_state, +1);
923 
924  ao2_ref(state, -1);
925  return 0;
926 }
enum sip_outbound_registration_status status
Current state of this registration.
Outbound registration state information (persists for lifetime that registration should exist) ...
#define LOG_DEBUG
Definition: logger.h:241
#define ast_log
Definition: astobj2.c:42
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
def info(msg)
static int handle_client_registration(void *data)
Callback function for registering.
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
pjsip_regc * client
Outbound registration client.
static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
Helper function which cancels the timer on a client.

◆ save_response_fields_to_transport()

static void save_response_fields_to_transport ( struct registration_response response)
static

Definition at line 986 of file res_pjsip_outbound_registration.c.

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, NULL, registration_response::rdata, sip_outbound_registration_client_state::transport_name, and value.

Referenced by handle_registration_response().

987 {
988  static const pj_str_t associated_uri_str = { "P-Associated-URI", 16 };
989  static const pj_str_t service_route_str = { "Service-Route", 13 };
990  pjsip_hdr *header = NULL;
991  pjsip_msg *msg = response->rdata->msg_info.msg;
992  struct ast_sip_service_route_vector *service_routes = NULL;
993 
994  /* If no transport is specified then we can't update any */
995  if (ast_strlen_zero(response->client_state->transport_name)) {
996  return;
997  }
998 
999  ast_sip_transport_state_set_transport(response->client_state->transport_name, response->rdata->tp_info.transport);
1000 
1001  while ((header = pjsip_msg_find_hdr_by_name(msg, &service_route_str, header ? header->next : NULL))) {
1002  char *service_route;
1003  size_t size;
1004 
1005  /* The below code takes the approach that if we can't store all service routes then we
1006  * store none at all. This gives a predictable failure condition instead of storing a
1007  * partial list and having partial route headers.
1008  */
1009  size = pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1;
1010  service_route = ast_malloc(size);
1011  if (!service_route) {
1012  if (service_routes) {
1013  ast_sip_service_route_vector_destroy(service_routes);
1014  service_routes = NULL;
1015  }
1016  break;
1017  }
1018 
1019  ast_copy_pj_str(service_route, &((pjsip_generic_string_hdr*)header)->hvalue, size);
1020 
1021  if (!service_routes) {
1022  service_routes = ast_sip_service_route_vector_alloc();
1023  if (!service_routes) {
1024  ast_free(service_route);
1025  break;
1026  }
1027  }
1028 
1029  if (AST_VECTOR_APPEND(service_routes, service_route)) {
1030  ast_free(service_route);
1031  ast_sip_service_route_vector_destroy(service_routes);
1032  service_routes = NULL;
1033  break;
1034  }
1035  }
1036 
1037  /* If any service routes were handled then store them on the transport */
1038  if (service_routes) {
1040  }
1041 
1042  /* If an associated URI is present in the response we need to use it on any outgoing
1043  * traffic on the transport.
1044  */
1045  header = pjsip_msg_find_hdr_by_name(msg, &associated_uri_str, NULL);
1046  if (header) {
1047  char value[pj_strlen(&((pjsip_generic_string_hdr*)header)->hvalue) + 1];
1048 
1049  ast_copy_pj_str(value, &((pjsip_generic_string_hdr*)header)->hvalue, sizeof(value));
1051  }
1052 }
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
int ast_sip_transport_state_set_preferred_identity(const char *transport_name, const char *identity)
Sets the P-Preferred-Identity on a child transport.
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ast_sip_service_route_vector * ast_sip_service_route_vector_alloc(void)
Allocate a vector of service routes.
void ast_sip_service_route_vector_destroy(struct ast_sip_service_route_vector *service_routes)
Destroy a vector of service routes.
#define ast_free(a)
Definition: astmm.h:182
int ast_sip_transport_state_set_transport(const char *transport_name, pjsip_transport *transport)
Sets the PJSIP transport on a child transport.
char * transport_name
The name of the transport to be used for the registration.
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
pjsip_rx_data * rdata
The response message.
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.

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

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, and sip_outbound_registration_client_state::timer.

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

722 {
723  pj_time_val delay = { .sec = seconds, };
724  pjsip_regc_info info;
725 
726  cancel_registration(client_state);
727 
728  pjsip_regc_get_info(client_state->client, &info);
729  ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
730  (int) info.server_uri.slen, info.server_uri.ptr,
731  (int) info.client_uri.slen, info.client_uri.ptr,
732  seconds);
733 
734  ao2_ref(client_state, +1);
735  if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
736  ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
737  (int) info.server_uri.slen, info.server_uri.ptr,
738  (int) info.client_uri.slen, info.client_uri.ptr);
739  ao2_ref(client_state, -1);
740  }
741 }
#define LOG_WARNING
Definition: logger.h:274
pj_timer_entry timer
Timer entry for retrying on temporal responses.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
def info(msg)
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
pjsip_regc * client
Outbound registration client.
static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
Helper function which cancels the timer on a client.

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

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

Referenced by handle_registration_response().

885 {
887  schedule_registration(response->client_state, interval);
888 
889  if (response->rdata) {
890  ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
891  "registration attempt to '%s', retrying in '%u'\n",
892  response->code, server_uri, client_uri, interval);
893  } else {
894  ast_log(LOG_WARNING, "No response received from '%s' on "
895  "registration attempt to '%s', retrying in '%u'\n",
896  server_uri, client_uri, interval);
897  }
898 }
static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
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.
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
int code
Response code for the registration attempt.
static char server_uri[512]
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
pjsip_rx_data * rdata
The response message.
Registration was rejected, but response was temporal.

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

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

1547 {
1548  size_t auth_size = AST_VECTOR_SIZE(auth_vector);
1549  struct ast_sip_auth *auths[auth_size];
1550  const char *access_token;
1551  pjsip_cred_info auth_creds[1];
1552  pjsip_auth_clt_pref prefs;
1553  int res = 0;
1554  int idx;
1555 
1556  memset(auths, 0, sizeof(auths));
1557  if (ast_sip_retrieve_auths(auth_vector, auths)) {
1558  res = -1;
1559  goto cleanup;
1560  }
1561 
1562  for (idx = 0; idx < auth_size; ++idx) {
1563  switch (auths[idx]->type) {
1565  pj_cstr(&auth_creds[0].username, auths[idx]->auth_user);
1566  pj_cstr(&auth_creds[0].scheme, "Bearer");
1567  pj_cstr(&auth_creds[0].realm, auths[idx]->realm);
1568  ast_debug(2, "Obtaining Google OAuth access token\n");
1569  access_token = fetch_google_access_token(auths[idx]);
1570  if (!access_token) {
1571  ast_log(LOG_WARNING, "Obtaining Google OAuth access token failed\n");
1572  access_token = auths[idx]->auth_pass;
1573  res = -1;
1574  }
1575  ast_debug(2, "Setting data to '%s'\n", access_token);
1576 
1577  pj_cstr(&auth_creds[0].data, access_token);
1578  auth_creds[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
1579 
1580  pjsip_regc_set_credentials(regc, 1, auth_creds);
1581 
1582  /* for oauth, send auth without waiting for unauthorized response */
1583  prefs.initial_auth = PJ_TRUE;
1584  pj_cstr(&prefs.algorithm, "oauth");
1585  pjsip_regc_set_prefs(regc, &prefs);
1586 
1587  if (access_token != auths[idx]->auth_pass) {
1588  ast_free((char *) access_token);
1589  }
1590  break;
1591  default:
1592  /* other cases handled after receiving auth rejection */
1593  break;
1594  }
1595  }
1596 
1597 cleanup:
1598  ast_sip_cleanup_auths(auths, auth_size);
1599  return res;
1600 }
static const char type[]
Definition: chan_ooh323.c:109
static const char * fetch_google_access_token(const struct ast_sip_auth *auth)
#define LOG_WARNING
Definition: logger.h:274
int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out)
Retrieve relevant SIP auth structures from sorcery.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const ast_string_field realm
Definition: res_pjsip.h:448
void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths)
Clean up retrieved auth structures from memory.
#define ast_free(a)
Definition: astmm.h:182
const ast_string_field auth_pass
Definition: res_pjsip.h:452
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
const ast_string_field auth_user
Definition: res_pjsip.h:450
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

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

References ast_sip_get_pjsip_endpoint(), ast_strlen_zero, S_OR, tmp(), and type.

Referenced by sip_outbound_registration_regc_alloc().

1390 {
1391  pj_str_t tmp, local_addr;
1392  pjsip_uri *uri;
1393  pjsip_sip_uri *sip_uri;
1394  pjsip_transport_type_e type;
1395  int local_port;
1396 
1397  pj_strdup_with_null(pool, &tmp, target);
1398 
1399  if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
1400  (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
1401  return -1;
1402  }
1403 
1404  sip_uri = pjsip_uri_get_uri(uri);
1405 
1406  type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
1407  if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
1408  if (type == PJSIP_TRANSPORT_UNSPECIFIED
1409  || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
1410  type = PJSIP_TRANSPORT_TLS;
1411  }
1412  } else if (!sip_uri->transport_param.slen) {
1413  type = PJSIP_TRANSPORT_UDP;
1414  } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
1415  return -1;
1416  }
1417 
1418  if (pj_strchr(&sip_uri->host, ':')) {
1419  type |= PJSIP_TRANSPORT_IPV6;
1420  }
1421 
1422  if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
1423  pool, type, selector, &local_addr, &local_port) != PJ_SUCCESS) {
1424  return -1;
1425  }
1426 
1427  if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
1428  type |= PJSIP_TRANSPORT_IPV6;
1429  }
1430 
1431  contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
1432  contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
1433  "<%s:%s@%s%.*s%s:%d%s%s%s%s>%s%s",
1434  ((pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) && PJSIP_URI_SCHEME_IS_SIPS(uri)) ? "sips" : "sip",
1435  user,
1436  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1437  (int)local_addr.slen,
1438  local_addr.ptr,
1439  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1440  local_port,
1441  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1442  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
1443  !ast_strlen_zero(line) ? ";line=" : "",
1444  S_OR(line, ""),
1445  !ast_strlen_zero(header_params) ? ";" : "",
1446  S_OR(header_params, ""));
1447 
1448  return 0;
1449 }
static const char type[]
Definition: chan_ooh323.c:109
static int tmp()
Definition: bt_open.c:389
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define ast_strlen_zero(foo)
Definition: strings.h:52
structure to hold users read from users.conf
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ sip_outbound_registration_alloc()

static void* sip_outbound_registration_alloc ( const char *  name)
static

Allocator function for registration information.

Definition at line 1373 of file res_pjsip_outbound_registration.c.

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

Referenced by load_module().

1374 {
1375  struct sip_outbound_registration *registration;
1376 
1377  registration = ast_sorcery_generic_alloc(sizeof(*registration),
1379  if (!registration || ast_string_field_init(registration, 256)) {
1380  ao2_cleanup(registration);
1381  return NULL;
1382  }
1383 
1384  return registration;
1385 }
#define NULL
Definition: resample.c:96
static void sip_outbound_registration_destroy(void *obj)
Destructor function for registration information.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
Outbound registration information.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728

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

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

1745 {
1746  RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1749  struct sip_outbound_registration *applied = obj;
1750 
1751  if (!states) {
1752  /* Global container has gone. Likely shutting down. */
1753  return -1;
1754  }
1756 
1757  ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
1758 
1759  if (ast_strlen_zero(applied->server_uri)) {
1760  ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'\n",
1761  ast_sorcery_object_get_id(applied));
1762  return -1;
1763  } else if (ast_sip_validate_uri_length(applied->server_uri)) {
1764  ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
1765  ast_sorcery_object_get_id(applied));
1766  return -1;
1767  } else if (ast_strlen_zero(applied->client_uri)) {
1768  ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
1769  ast_sorcery_object_get_id(applied));
1770  return -1;
1771  } else if (ast_sip_validate_uri_length(applied->client_uri)) {
1772  ast_log(LOG_ERROR, "Client URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s'\n",
1773  ast_sorcery_object_get_id(applied));
1774  return -1;
1775  } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
1776  ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
1777  ast_sorcery_object_get_id(applied));
1778  return -1;
1779  } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
1780  ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
1781  ast_sorcery_object_get_id(applied));
1782  return -1;
1783  }
1784 
1785  if (state && can_reuse_registration(state->registration, applied)) {
1786  ast_debug(4,
1787  "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
1788  ast_sorcery_object_get_id(applied));
1789 
1790  /*
1791  * This is OK to replace without relinking the state in the
1792  * current_states container since state->registration and
1793  * applied have the same key.
1794  */
1795  ao2_lock(states);
1796  ao2_replace(state->registration, applied);
1797  ao2_unlock(states);
1798  return 0;
1799  }
1800 
1801  if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
1802  return -1;
1803  }
1804 
1805  if (ast_sip_push_task_wait_serializer(new_state->client_state->serializer,
1807  return -1;
1808  }
1809 
1810  if (ast_sip_push_task(new_state->client_state->serializer,
1812  ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
1813  ast_sorcery_object_get_id(new_state->registration));
1814  ao2_ref(new_state, -1);
1815  return -1;
1816  }
1817 
1818  ao2_lock(states);
1819  if (state) {
1820  ao2_unlink(states, state);
1821  }
1822  ao2_link(states, new_state);
1823  ao2_unlock(states);
1824 
1825  return 0;
1826 }
static struct sip_outbound_registration_state * sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
Allocator function for registration state.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const ast_string_field client_uri
URI for the AOR.
const ast_string_field server_uri
URI for the registrar.
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
static int sip_outbound_registration_perform(void *data)
Helper function which performs a single registration.
static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:5218
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Outbound registration information.
#define LOG_ERROR
Definition: logger.h:285
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int ast_sip_validate_uri_length(const char *uri)
Definition: location.c:525
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field endpoint
Endpoint to use for related incoming calls.
Generic container type.
static int sip_outbound_registration_regc_alloc(void *data)
Helper function that allocates a pjsip registration client and configures it.
unsigned int line
Whether to add a line parameter to the outbound Contact or not.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

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, and sip_outbound_registration_client_state::transport_name.

Referenced by sip_outbound_registration_state_alloc().

1298 {
1299  struct sip_outbound_registration_client_state *client_state = obj;
1300 
1301  ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);
1302  ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
1304 
1306  ast_free(client_state->transport_name);
1307  ast_free(client_state->registration_name);
1308  if (client_state->last_tdata) {
1309  pjsip_tx_data_dec_ref(client_state->last_tdata);
1310  }
1311 }
enum sip_outbound_registration_status status
Current state of this registration.
Outbound registration client state information (persists for lifetime of regc)
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:111
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
pjsip_tx_data * last_tdata
Last tdata sent We need the original tdata to resend a request on auth failure or timeout...
char * registration_name
The name of the registration sorcery object.
struct ast_taskprocessor * serializer
Serializer for stuff and things.
#define ast_free(a)
Definition: astmm.h:182
char * transport_name
The name of the transport to be used for the registration.
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
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:176

◆ sip_outbound_registration_destroy()

static void sip_outbound_registration_destroy ( void *  obj)
static

Destructor function for registration information.

Definition at line 1363 of file res_pjsip_outbound_registration.c.

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

Referenced by sip_outbound_registration_alloc().

1364 {
1365  struct sip_outbound_registration *registration = obj;
1366 
1368 
1369  ast_string_field_free_memory(registration);
1370 }
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector)
Free contents of an auth vector.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
Outbound registration information.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

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

References sip_outbound_registration_client_state::auth_rejection_permanent.

Referenced by handle_registration_response().

866 {
867  /* Shamelessly taken from pjsua */
868  if (code == PJSIP_SC_REQUEST_TIMEOUT ||
869  code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
870  code == PJSIP_SC_BAD_GATEWAY ||
871  code == PJSIP_SC_SERVICE_UNAVAILABLE ||
872  code == PJSIP_SC_SERVER_TIMEOUT ||
873  ((code == PJSIP_SC_UNAUTHORIZED ||
874  code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
875  !client_state->auth_rejection_permanent) ||
876  PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
877  return 1;
878  } else {
879  return 0;
880  }
881 }
unsigned int auth_rejection_permanent
Treat authentication challenges that we cannot handle as permanent failures.

◆ sip_outbound_registration_perform()

static int sip_outbound_registration_perform ( void *  data)
static

Helper function which performs a single registration.

Definition at line 1708 of file res_pjsip_outbound_registration.c.

References ao2_bump, ao2_ref, ast_free, ast_random(), ast_sip_auth_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_client_state::auth_rejection_permanent, sip_outbound_registration_client_state::client, sip_outbound_registration_state::client_state, sip_outbound_registration::expiration, sip_outbound_registration::fatal_retry_interval, sip_outbound_registration_client_state::fatal_retry_interval, sip_outbound_registration::forbidden_retry_interval, sip_outbound_registration_client_state::forbidden_retry_interval, sip_outbound_registration::max_retries, sip_outbound_registration_client_state::max_retries, name, sip_outbound_registration::outbound_auths, sip_outbound_registration_client_state::outbound_auths, sip_outbound_registration_state::registration, sip_outbound_registration_client_state::retries, sip_outbound_registration::retry_interval, sip_outbound_registration_client_state::retry_interval, schedule_registration(), sip_outbound_registration::support_outbound, sip_outbound_registration_client_state::support_outbound, sip_outbound_registration::support_path, and sip_outbound_registration_client_state::support_path.

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

1709 {
1710  struct sip_outbound_registration_state *state = data;
1711  struct sip_outbound_registration *registration = ao2_bump(state->registration);
1712  size_t i;
1713 
1714  /* Just in case the client state is being reused for this registration, free the auth information */
1716 
1718  for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1719  char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1720 
1721  if (name && AST_VECTOR_APPEND(&state->client_state->outbound_auths, name)) {
1722  ast_free(name);
1723  }
1724  }
1725  state->client_state->retry_interval = registration->retry_interval;
1727  state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
1728  state->client_state->max_retries = registration->max_retries;
1729  state->client_state->retries = 0;
1730  state->client_state->support_path = registration->support_path;
1731  state->client_state->support_outbound = registration->support_outbound;
1733 
1734  pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1735 
1736  schedule_registration(state->client_state, (ast_random() % 10) + 1);
1737 
1738  ao2_ref(registration, -1);
1739  ao2_ref(state, -1);
1740  return 0;
1741 }
unsigned int support_path
Whether Path support is enabled.
unsigned int max_retries
Maximum number of retries permitted.
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.
unsigned int support_outbound
Determines whether SIP Outbound support should be advertised.
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector)
Free contents of an auth vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
Outbound registration state information (persists for lifetime that registration should exist) ...
unsigned int expiration
Requested expiration time.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
unsigned int max_retries
Maximum number of retries permitted.
unsigned int support_outbound
Whether Outbound support is enabled.
#define ao2_bump(obj)
Definition: astobj2.h:491
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
struct sip_outbound_registration_client_state * client_state
Client state information.
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
unsigned int forbidden_retry_interval
Interval at which retries should occur for permanent responses.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define ao2_ref(o, delta)
Definition: astobj2.h:464
long int ast_random(void)
Definition: main/utils.c:2064
unsigned int support_path
Determines whether SIP Path support should be advertised.
struct sip_outbound_registration * registration
Outbound registration configuration object.
Outbound registration information.
unsigned int auth_rejection_permanent
Treat authentication challenges that we cannot handle as permanent failures.
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
unsigned int retry_interval
Interval at which retries should occur for temporal responses.
unsigned int retries
Current number of retries.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
unsigned int auth_rejection_permanent
Treat authentication challenges that we cannot handle as permanent failures.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
unsigned int fatal_retry_interval
Interval at which retries should occur for all permanent responses.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
pjsip_regc * client
Outbound registration client.

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

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_state::client, sip_outbound_registration_state::client_state, sip_outbound_registration::client_uri, sip_outbound_registration::contact_header_params, sip_outbound_registration::contact_user, sip_outbound_registration::expiration, sip_outbound_registration::line, sip_outbound_registration_client_state::line, LOG_ERROR, NULL, sip_outbound_registration::outbound_proxy, pool, RAII_VAR, sip_outbound_registration_state::registration, S_OR, sip_outbound_registration::server_uri, sip_dialog_create_contact(), sip_outbound_registration_response_cb(), tmp(), and sip_outbound_registration::transport.

Referenced by sip_outbound_registration_apply().

1604 {
1605  struct sip_outbound_registration_state *state = data;
1607  ao2_bump(state->registration), ao2_cleanup);
1608  pj_pool_t *pool;
1609  pj_str_t tmp;
1610  pjsip_uri *uri;
1611  pj_str_t server_uri, client_uri, contact_uri;
1612  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1613 
1614  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
1615  if (!pool) {
1616  ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
1618  return -1;
1619  }
1620 
1621  pj_strdup2_with_null(pool, &tmp, registration->server_uri);
1622  uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1623  if (!uri) {
1624  ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
1626  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1627  return -1;
1628  }
1629 
1630  pj_strdup2_with_null(pool, &tmp, registration->client_uri);
1631  uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1632  if (!uri) {
1633  ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
1635  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1636  return -1;
1637  }
1638 
1640  pj_strdup2_with_null(pool, &tmp, registration->outbound_proxy);
1641  uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1642  if (!uri) {
1643  ast_log(LOG_ERROR, "Invalid outbound proxy URI '%s' specified on outbound registration '%s'\n",
1645  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1646  return -1;
1647  }
1648  }
1649 
1650  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1651 
1652 
1653  ast_assert(state->client_state->client == NULL);
1654  if (pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
1656  &state->client_state->client) != PJ_SUCCESS) {
1657  return -1;
1658  }
1659 
1661  pjsip_regc_set_transport(state->client_state->client, &selector);
1662 
1664  pjsip_route_hdr route_set, *route;
1665  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1666  pj_str_t tmp;
1667 
1668  pj_list_init(&route_set);
1669 
1670  pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp,
1672  route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client),
1673  &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL);
1674  if (!route) {
1675  ast_sip_tpselector_unref(&selector);
1676  return -1;
1677  }
1678  pj_list_insert_nodes_before(&route_set, route);
1679 
1680  pjsip_regc_set_route_set(state->client_state->client, &route_set);
1681  }
1682 
1683  if (state->registration->line) {
1684  ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
1685  }
1686 
1687  pj_cstr(&server_uri, registration->server_uri);
1688 
1689  if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client),
1690  &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
1692  ast_sip_tpselector_unref(&selector);
1693  return -1;
1694  }
1695 
1696  ast_sip_tpselector_unref(&selector);
1697 
1698  pj_cstr(&client_uri, registration->client_uri);
1699  if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri,
1700  &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
1701  return -1;
1702  }
1703 
1704  return 0;
1705 }
static int tmp()
Definition: bt_open.c:389
static pj_pool_t * pool
Global memory pool for configuration and timers.
const ast_string_field client_uri
URI for the AOR.
const ast_string_field server_uri
URI for the registrar.
Outbound registration state information (persists for lifetime that registration should exist) ...
unsigned int expiration
Requested expiration time.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
char line[LINE_PARAMETER_SIZE]
Optional line parameter placed into Contact.
static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
Callback function for outbound registration client.
const ast_string_field contact_user
Optional user for contact header.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
struct sip_outbound_registration_client_state * client_state
Client state information.
const ast_string_field outbound_proxy
Outbound proxy to use.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static 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.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
const ast_string_field transport
Explicit transport to use for registration.
struct sip_outbound_registration * registration
Outbound registration configuration object.
Outbound registration information.
#define LOG_ERROR
Definition: logger.h:285
char * ast_generate_random_string(char *buf, size_t size)
Create a pseudo-random string of a fixed length.
Definition: strings.c:227
static char server_uri[512]
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
pjsip_regc * client
Outbound registration client.
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:3957
unsigned int line
Whether to add a line parameter to the outbound Contact or not.

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

References ao2_alloc, ao2_cleanup, ao2_ref, ast_assert, ast_debug, ast_log, 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, and sip_outbound_registration_client_state::serializer.

Referenced by sip_outbound_registration_regc_alloc().

1208 {
1209  struct sip_outbound_registration_client_state *client_state = param->token;
1210  struct registration_response *response;
1211  int *callback_invoked;
1212 
1213  callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
1214 
1215  ast_assert(callback_invoked != NULL);
1216  ast_assert(client_state != NULL);
1217 
1218  *callback_invoked = 1;
1219 
1220  response = ao2_alloc(sizeof(*response), registration_response_destroy);
1221  if (!response) {
1222  ao2_ref(client_state, -1);
1223  return;
1224  }
1225  response->code = param->code;
1226  response->expiration = param->expiration;
1227  /*
1228  * Transfer client_state reference to response so the
1229  * nominal path will not dec the client_state ref in this
1230  * pjproject callback thread.
1231  */
1232  response->client_state = client_state;
1233 
1234  ast_debug(1, "Received REGISTER response %d(%.*s)\n",
1235  param->code, (int) param->reason.slen, param->reason.ptr);
1236 
1237  if (param->rdata) {
1238  struct pjsip_retry_after_hdr *retry_after;
1239  pjsip_transaction *tsx;
1240 
1241  retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER,
1242  NULL);
1243  response->retry_after = retry_after ? retry_after->ivalue : 0;
1244 
1245  /*
1246  * If we got a response from the server, we have to use the tdata
1247  * from the transaction, not the tdata saved when we sent the
1248  * request. If we use the saved tdata, we won't process responses
1249  * like 423 Interval Too Brief correctly and we'll wind up sending
1250  * the bad Expires value again.
1251  */
1252  pjsip_tx_data_dec_ref(client_state->last_tdata);
1253 
1254  tsx = pjsip_rdata_get_tsx(param->rdata);
1255  response->old_request = tsx->last_tx;
1256  pjsip_tx_data_add_ref(response->old_request);
1257  pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
1258  } else {
1259  /* old_request steals the reference */
1260  response->old_request = client_state->last_tdata;
1261  }
1262  client_state->last_tdata = NULL;
1263 
1264  /*
1265  * Transfer response reference to serializer task so the
1266  * nominal path will not dec the response ref in this
1267  * pjproject callback thread.
1268  */
1269  if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
1270  ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
1271  ao2_cleanup(response);
1272  }
1273 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
pjsip_tx_data * old_request
Request for which the response was received.
#define LOG_WARNING
Definition: logger.h:274
#define ast_assert(a)
Definition: utils.h:695
Outbound registration client state information (persists for lifetime of regc)
#define NULL
Definition: resample.c:96
static struct ast_threadstorage register_callback_invoked
Structure for registration response.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_tx_data * last_tdata
Last tdata sent We need the original tdata to resend a request on auth failure or timeout...
int code
Response code for the registration attempt.
int expiration
Expiration time for registration.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_taskprocessor * serializer
Serializer for stuff and things.
static int handle_registration_response(void *data)
Callback function for handling a response to a registration attempt.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct sip_outbound_registration_client_state * client_state
Outbound registration client state.
static void registration_response_destroy(void *obj)
Registration response structure destructor.
pjsip_rx_data * rdata
The response message.

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

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, sip_outbound_registration_state::client_state, NULL, sip_outbound_registration_state::registration, sip_outbound_registration_client_state::registration_name, sip_outbound_registration_client_state::serializer, 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_client_state::status, sip_outbound_registration_client_state::timer, sip_outbound_registration::transport, and sip_outbound_registration_client_state::transport_name.

Referenced by sip_outbound_registration_apply().

1315 {
1317  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1318 
1319  state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
1320  if (!state) {
1321  return NULL;
1322  }
1323  state->client_state = ao2_alloc(sizeof(*state->client_state),
1325  if (!state->client_state) {
1326  ao2_cleanup(state);
1327  return NULL;
1328  }
1329 
1331  pj_timer_entry_init(&state->client_state->timer, 0, state->client_state,
1333  state->client_state->transport_name = ast_strdup(registration->transport);
1335  ast_strdup(ast_sorcery_object_get_id(registration));
1336 
1337  ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);
1338  ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
1340 
1341  if (!state->client_state->transport_name
1342  || !state->client_state->registration_name) {
1343  ao2_cleanup(state);
1344  return NULL;
1345  }
1346 
1347  /* Create name with seq number appended. */
1348  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outreg/%s",
1349  ast_sorcery_object_get_id(registration));
1350 
1352  shutdown_group);
1353  if (!state->client_state->serializer) {
1354  ao2_cleanup(state);
1355  return NULL;
1356  }
1357 
1358  state->registration = ao2_bump(registration);
1359  return state;
1360 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
enum sip_outbound_registration_status status
Current state of this registration.
pj_timer_entry timer
Timer entry for retrying on temporal responses.
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:60
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:111
#define ao2_bump(obj)
Definition: astobj2.h:491
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
struct sip_outbound_registration_client_state * client_state
Client state information.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
const ast_string_field transport
Explicit transport to use for registration.
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5128
char * registration_name
The name of the registration sorcery object.
struct sip_outbound_registration * registration
Outbound registration configuration object.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_taskprocessor * serializer
Serializer for stuff and things.
char * transport_name
The name of the transport to be used for the registration.
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.
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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_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:176
static struct ast_serializer_shutdown_group * shutdown_group

◆ sip_outbound_registration_state_destroy()

static void sip_outbound_registration_state_destroy ( void *  obj)
static

Destructor function for registration state.

Definition at line 1276 of file res_pjsip_outbound_registration.c.

References ao2_cleanup, ao2_ref, ast_debug, ast_log, ast_sip_push_task(), sip_outbound_registration_state::client_state, sip_outbound_registration::client_uri, handle_client_state_destruction(), LOG_WARNING, sip_outbound_registration_state::registration, sip_outbound_registration_client_state::serializer, and sip_outbound_registration::server_uri.

Referenced by sip_outbound_registration_state_alloc().

1277 {
1278  struct sip_outbound_registration_state *state = obj;
1279 
1280  ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
1281  state->registration ? state->registration->server_uri : "",
1282  state->registration ? state->registration->client_uri : "");
1283  ao2_cleanup(state->registration);
1284 
1285  if (!state->client_state) {
1286  /* Nothing to do */
1287  } else if (!state->client_state->serializer) {
1288  ao2_ref(state->client_state, -1);
1289  } else if (ast_sip_push_task(state->client_state->serializer,
1291  ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
1292  ao2_ref(state->client_state, -1);
1293  }
1294 }
#define LOG_WARNING
Definition: logger.h:274
const ast_string_field client_uri
URI for the AOR.
const ast_string_field server_uri
URI for the registrar.
Outbound registration state information (persists for lifetime that registration should exist) ...
static int handle_client_state_destruction(void *data)
Callback function for unregistering (potentially) and destroying state.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct sip_outbound_registration * registration
Outbound registration configuration object.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
struct ast_taskprocessor * serializer
Serializer for stuff and things.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ sip_outbound_registration_status_str()

static const char* sip_outbound_registration_status_str ( enum sip_outbound_registration_status  state)
static

Definition at line 278 of file res_pjsip_outbound_registration.c.

References SIP_REGISTRATION_REGISTERED, SIP_REGISTRATION_REJECTED_PERMANENT, SIP_REGISTRATION_REJECTED_TEMPORARY, SIP_REGISTRATION_STOPPED, SIP_REGISTRATION_STOPPING, SIP_REGISTRATION_UNREGISTERED, and str.

Referenced by ami_outbound_registration_task(), cli_print_body(), handle_registration_response(), sip_outbound_registration_client_state_destroy(), sip_outbound_registration_state_alloc(), and update_client_state_status().

279 {
280  const char *str;
281 
282  str = "Unregistered";
283  switch (state) {
287  break;
289  str = "Registered";
290  break;
293  str = "Rejected";
294  break;
295  }
296  return str;
297 }
const char * str
Definition: app_jack.c:147
Registration was rejected, permanently.
Registration was rejected, but response was temporal.
Registration has been stopped.

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

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

704 {
705  struct sip_outbound_registration_client_state *client_state = entry->user_data;
706 
707  entry->id = 0;
708 
709  /*
710  * Transfer client_state reference to serializer task so the
711  * nominal path will not dec the client_state ref in this
712  * pjproject callback thread.
713  */
714  if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
715  ast_log(LOG_WARNING, "Scheduled outbound registration could not be executed.\n");
716  ao2_ref(client_state, -1);
717  }
718 }
#define LOG_WARNING
Definition: logger.h:274
Outbound registration client state information (persists for lifetime of regc)
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
struct ast_taskprocessor * serializer
Serializer for stuff and things.
static int handle_client_registration(void *data)
Callback function for registering.
Definition: search.h:40

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2461 of file res_pjsip_outbound_registration.c.

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(), LOG_WARNING, MAX_UNLOAD_TIMEOUT_TIME, NULL, registration_transport_shutdown_cb(), and stasis_unsubscribe_and_join().

Referenced by load_module(), and reload_module().

2462 {
2463  int remaining;
2464 
2466 
2467  ast_manager_unregister("PJSIPShowRegistrationsOutbound");
2468  ast_manager_unregister("PJSIPUnregister");
2469  ast_manager_unregister("PJSIPRegister");
2470 
2473  cli_formatter = NULL;
2474 
2476 
2479 
2481 
2482  ao2_global_obj_release(current_states);
2483 
2485 
2486  /* Wait for registration serializers to get destroyed. */
2487  ast_debug(2, "Waiting for registration transactions to complete for unload.\n");
2489  if (remaining) {
2490  /*
2491  * NOTE: We probably have a sip_outbound_registration_client_state
2492  * ref leak if the remaining count cannot reach zero after a few
2493  * minutes of trying to unload.
2494  */
2495  ast_log(LOG_WARNING, "Unload incomplete. Could not stop %d outbound registrations. Try again later.\n",
2496  remaining);
2497  return -1;
2498  }
2499 
2500  ast_debug(2, "Successful shutdown.\n");
2501 
2503  shutdown_group = NULL;
2504 
2505  return 0;
2506 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define MAX_UNLOAD_TIMEOUT_TIME
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define LOG_WARNING
Definition: logger.h:274
static struct ast_sip_endpoint_identifier line_identifier
static struct stasis_subscription * network_change_sub
static const struct ast_sorcery_observer observer_callbacks_auth
#define NULL
Definition: resample.c:96
int ast_serializer_shutdown_group_join(struct ast_serializer_shutdown_group *shutdown_group, int timeout)
Wait for the serializers in the group to shutdown with timeout.
Definition: threadpool.c:1241
static void registration_transport_shutdown_cb(void *obj)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
Definition: sorcery.c:1061
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
Definition: pjsip_cli.c:326
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
static struct ast_cli_entry cli_outbound_registration[]
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_sip_cli_formatter_entry * cli_formatter
void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
Unregister a SIP endpoint identifier.
Definition: res_pjsip.c:3513
static struct ast_serializer_shutdown_group * shutdown_group
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
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.

◆ unregister_all()

static void unregister_all ( void  )
static

Definition at line 1904 of file res_pjsip_outbound_registration.c.

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

1905 {
1906  struct ao2_container *states;
1907 
1908  states = ao2_global_obj_ref(current_states);
1909  if (!states) {
1910  return;
1911  }
1912 
1913  /* Clean out all the states and let sorcery handle recreating the registrations */
1915  ao2_ref(states, -1);
1916 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Generic container type.

◆ unregister_task()

static int unregister_task ( void *  obj)
static

Definition at line 1860 of file res_pjsip_outbound_registration.c.

References add_configured_supported_headers(), ao2_ref, ast_debug, cancel_registration(), sip_outbound_registration_client_state::client, sip_outbound_registration_state::client_state, sip_outbound_registration::client_uri, sip_to_pjsip::info(), sip_outbound_registration_state::registration, registration_client_send(), and sip_outbound_registration::server_uri.

Referenced by queue_unregister().

1861 {
1862  struct sip_outbound_registration_state *state = obj;
1863  struct pjsip_regc *client = state->client_state->client;
1864  pjsip_tx_data *tdata;
1865  pjsip_regc_info info;
1866 
1867  pjsip_regc_get_info(client, &info);
1868  ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
1869  state->registration->server_uri, state->registration->client_uri);
1870 
1872 
1873  if (pjsip_regc_unregister(client, &tdata) == PJ_SUCCESS
1874  && add_configured_supported_headers(state->client_state, tdata)) {
1875  registration_client_send(state->client_state, tdata);
1876  }
1877 
1878  ao2_ref(state, -1);
1879  return 0;
1880 }
const ast_string_field client_uri
URI for the AOR.
const ast_string_field server_uri
URI for the registrar.
Outbound registration state information (persists for lifetime that registration should exist) ...
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct sip_outbound_registration_client_state * client_state
Client state information.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct sip_outbound_registration * registration
Outbound registration configuration object.
def info(msg)
static int add_configured_supported_headers(struct sip_outbound_registration_client_state *client_state, pjsip_tx_data *tdata)
Helper function to add configured supported headers.
static 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.
pjsip_regc * client
Outbound registration client.
static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
Helper function which cancels the timer on a client.

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

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

744 {
745  const char *status_old;
746  const char *status_new;
747 
748  if (client_state->status == status) {
749  /* Status state did not change at all. */
750  return;
751  }
752 
753  status_old = sip_outbound_registration_status_str(client_state->status);
755  client_state->status = status;
756 
757  if (!strcmp(status_old, status_new)) {
758  /*
759  * The internal status state may have changed but the status
760  * state we tell the world did not change at all.
761  */
762  return;
763  }
764 
765  ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
766  status_old);
767  ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
768  status_new);
769 }
enum sip_outbound_registration_status status
Current state of this registration.
static const char * sip_outbound_registration_status_str(enum sip_outbound_registration_status state)
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
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:176
jack_status_t status
Definition: app_jack.c:146

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 2628 of file res_pjsip_outbound_registration.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2628 of file res_pjsip_outbound_registration.c.

◆ cli_formatter

struct ast_sip_cli_formatter_entry* cli_formatter
static

Definition at line 2330 of file res_pjsip_outbound_registration.c.

◆ cli_outbound_registration

struct ast_cli_entry cli_outbound_registration[]
static

Definition at line 2311 of file res_pjsip_outbound_registration.c.

◆ 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 &#39;line&#39; parameter to establish a relationship to an outgoing regist...

Definition at line 539 of file res_pjsip_outbound_registration.c.

◆ network_change_sub

struct stasis_subscription* network_change_sub
static

subscription id for network change events

Definition at line 416 of file res_pjsip_outbound_registration.c.

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

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

◆ OUTBOUND_NAME

pj_str_t OUTBOUND_NAME = { "outbound", 8 }
static

Definition at line 554 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 553 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 2446 of file res_pjsip_outbound_registration.c.

◆ shutdown_group

struct ast_serializer_shutdown_group* shutdown_group
static

Shutdown group to monitor sip_outbound_registration_client_state serializers.

Definition at line 409 of file res_pjsip_outbound_registration.c.