Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_pjsip_outbound_publish.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_simple.h>
#include "asterisk/res_pjproject.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_outbound_publish.h"
#include "asterisk/module.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/threadpool.h"
#include "asterisk/datastore.h"
#include "res_pjsip/include/res_pjsip_private.h"
Include dependency graph for res_pjsip_outbound_publish.c:

Go to the source code of this file.

Data Structures

struct  ast_sip_outbound_publish
 Outbound publish information. More...
 
struct  ast_sip_outbound_publish_client
 Outbound publish client state information (persists for lifetime of a publish) More...
 
struct  ast_sip_outbound_publish_state
 Outbound publish state information (persists for lifetime of a publish) More...
 
struct  publisher_handlers
 
struct  sip_outbound_publish_message
 Queued outbound publish message. More...
 
struct  sip_outbound_publisher
 

Macros

#define ADD_TO_NEW_STATES(__obj)
 
#define DATASTORE_BUCKETS   53
 
#define DEFAULT_PUBLISHER_BUCKETS   119
 
#define DEFAULT_STATE_BUCKETS   31
 Default number of client state container buckets. More...
 
#define DESTROY_CLIENT()
 
#define MAX_UNLOAD_TIMEOUT_TIME   35 /* Seconds */
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static AO2_GLOBAL_OBJ_STATIC (current_states)
 
 AO2_STRING_FIELD_CMP_FN (sip_outbound_publisher, user)
 
 AO2_STRING_FIELD_HASH_FN (sip_outbound_publisher, user)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_sip_publish_client_add_datastore (struct ast_sip_outbound_publish_client *client, struct ast_datastore *datastore)
 Add a datastore to a SIP event publisher. More...
 
struct ast_datastoreast_sip_publish_client_alloc_datastore (const struct ast_datastore_info *info, const char *uid)
 Alternative for ast_datastore_alloc() More...
 
struct ast_sip_outbound_publish_clientast_sip_publish_client_get (const char *name)
 Find a publish client using its name. More...
 
struct ast_datastoreast_sip_publish_client_get_datastore (struct ast_sip_outbound_publish_client *client, const char *name)
 Retrieve an event publisher datastore. More...
 
const char * ast_sip_publish_client_get_from_uri (struct ast_sip_outbound_publish_client *client)
 Get the From URI the client will use. More...
 
const char * ast_sip_publish_client_get_to_uri (struct ast_sip_outbound_publish_client *client)
 Get the To URI the client will use. More...
 
const char * ast_sip_publish_client_get_user_from_uri (struct ast_sip_outbound_publish_client *client, const char *user, char *uri, size_t size)
 Get the From URI the client will use for a specific user. More...
 
const char * ast_sip_publish_client_get_user_to_uri (struct ast_sip_outbound_publish_client *client, const char *user, char *uri, size_t size)
 Get the To URI the client will use for a specific user. More...
 
void ast_sip_publish_client_remove (struct ast_sip_outbound_publish_client *client, const char *user)
 Remove the user from the client (stopping it from publishing) More...
 
void ast_sip_publish_client_remove_datastore (struct ast_sip_outbound_publish_client *client, const char *name)
 Remove a publication datastore from an event publisher. More...
 
int ast_sip_publish_client_send (struct ast_sip_outbound_publish_client *client, const struct ast_sip_body *body)
 Send an outgoing PUBLISH message using a client. More...
 
int ast_sip_publish_client_user_send (struct ast_sip_outbound_publish_client *client, const char *user, const struct ast_sip_body *body)
 Send an outgoing PUBLISH message based on the user. More...
 
int ast_sip_register_event_publisher_handler (struct ast_sip_event_publisher_handler *handler)
 Register an event publisher handler. More...
 
void ast_sip_unregister_event_publisher_handler (struct ast_sip_event_publisher_handler *handler)
 Unregister a publish handler. More...
 
static int can_reuse_publish (struct ast_sip_outbound_publish *existing, struct ast_sip_outbound_publish *applied)
 
static int cancel_and_unpublish (void *obj, void *arg, int flags)
 Helper function which cancels and un-publishes a no longer used client. More...
 
static void cancel_publish_refresh (struct sip_outbound_publisher *publisher)
 Helper function which cancels the refresh timer on a publisher. More...
 
static int cancel_refresh_timer_task (void *data)
 Task for cancelling a refresh timer. More...
 
static int current_state_reusable (struct ast_sip_outbound_publish *publish, struct ast_sip_outbound_publish_state *current_state)
 
static int datastore_cmp (void *obj, void *arg, int flags)
 
static int datastore_hash (const void *obj, int flags)
 
static int explicit_publish_destroy (void *data)
 
static struct ast_sip_event_publisher_handlerfind_publisher_handler_for_event_name (const char *event_name)
 
static struct ao2_containerget_publishes_and_update_state (void)
 
static int load_module (void)
 
static int outbound_auth_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int outbound_publish_state_cmp (void *obj, void *arg, int flags)
 comparator function for client objects More...
 
static int outbound_publish_state_hash (const void *obj, const int flags)
 hashing function for state objects More...
 
static int publisher_client_send (void *obj, void *arg, void *data, int flags)
 
static int reload_module (void)
 
static void schedule_publish_refresh (struct sip_outbound_publisher *publisher, int expiration)
 Helper function which sets up the timer to send publication. More...
 
static int send_unpublish_task (void *data)
 Task for sending an unpublish. More...
 
static void set_transport (struct sip_outbound_publisher *publisher, pjsip_tx_data *tdata)
 
static void * sip_outbound_publish_alloc (const char *name)
 Allocator function for publish information. More...
 
static int sip_outbound_publish_apply (const struct ast_sorcery *sorcery, void *obj)
 Apply function which finds or allocates a state structure. More...
 
static void sip_outbound_publish_callback (struct pjsip_publishc_cbparam *param)
 Callback function for publish client responses. More...
 
static struct sip_outbound_publishersip_outbound_publish_client_add_publisher (struct ast_sip_outbound_publish_client *client, const char *user)
 
static void sip_outbound_publish_client_destroy (void *obj)
 Destructor function for publish client. More...
 
static struct sip_outbound_publishersip_outbound_publish_client_get_publisher (struct ast_sip_outbound_publish_client *client, const char *user)
 
static void sip_outbound_publish_datastore_destroy (void *obj)
 
static void sip_outbound_publish_destroy (void *obj)
 Destructor function for publish information. More...
 
static struct ast_sip_outbound_publish_statesip_outbound_publish_state_alloc (struct ast_sip_outbound_publish *publish)
 Allocator function for publish client. More...
 
static void sip_outbound_publish_state_destroy (void *obj)
 Destructor function for publish state. More...
 
static void sip_outbound_publish_synchronize (struct ast_sip_event_publisher_handler *removed)
 Helper function which starts or stops publish clients when applicable. More...
 
static void sip_outbound_publish_timer_cb (pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
 Publish client timer callback function. More...
 
static struct sip_outbound_publishersip_outbound_publisher_alloc (struct ast_sip_outbound_publish_client *client, const char *user)
 
static void sip_outbound_publisher_destroy (void *obj)
 Destructor function for publish client. More...
 
static int sip_outbound_publisher_init (void *data)
 Helper function that allocates a pjsip publish client and configures it. More...
 
static int sip_outbound_publisher_reinit (void *obj, void *arg, int flags)
 
static int sip_outbound_publisher_reinit_all (void *data)
 
static int sip_outbound_publisher_set_uri (pj_pool_t *pool, const char *uri, const char *user, pj_str_t *res_uri)
 
static int sip_outbound_publisher_set_uris (pj_pool_t *pool, struct sip_outbound_publisher *publisher, pj_str_t *server_uri, pj_str_t *to_uri, pj_str_t *from_uri)
 
static struct ast_sip_outbound_publish_statesip_publish_state_get (const char *id)
 
static int sip_publisher_service_queue (void *data)
 
static void stop_publishing (struct ast_sip_outbound_publish_client *client, struct ast_sip_event_publisher_handler *handler)
 
static void sub_add_handler (struct ast_sip_event_publisher_handler *handler)
 
static int unload_module (void)
 
static int validate_publish_config (struct ast_sip_outbound_publish *publish)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Outbound Publish 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_CHANNEL_DEPEND, .requires = "res_pjproject,res_pjsip", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static ast_rwlock_t load_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
 Used for locking while loading/reloading. More...
 
static struct ao2_containernew_states
 Used on [re]loads to hold new state data. More...
 
static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE
 
struct publisher_handlers publisher_handlers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct ast_serializer_shutdown_groupshutdown_group
 

Macro Definition Documentation

◆ ADD_TO_NEW_STATES

#define ADD_TO_NEW_STATES (   __obj)
Value:
do { if (__obj) { \
ao2_link(new_states, __obj); \
ao2_ref(__obj, -1); } } while (0)
static struct ao2_container * new_states
Used on [re]loads to hold new state data.

Referenced by sip_outbound_publish_apply().

◆ DATASTORE_BUCKETS

#define DATASTORE_BUCKETS   53

Definition at line 1363 of file res_pjsip_outbound_publish.c.

Referenced by sip_outbound_publish_state_alloc().

◆ DEFAULT_PUBLISHER_BUCKETS

#define DEFAULT_PUBLISHER_BUCKETS   119

Definition at line 257 of file res_pjsip_outbound_publish.c.

◆ DEFAULT_STATE_BUCKETS

#define DEFAULT_STATE_BUCKETS   31

Default number of client state container buckets.

Definition at line 268 of file res_pjsip_outbound_publish.c.

Referenced by sip_outbound_publish_apply().

◆ DESTROY_CLIENT

#define DESTROY_CLIENT ( )
Value:
do { \
pjsip_publishc_destroy(publisher->client); \
publisher->client = NULL; \
ao2_ref(publisher, -1); } while (0)
#define NULL
Definition: resample.c:96

Referenced by sip_outbound_publish_callback().

◆ 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 262 of file res_pjsip_outbound_publish.c.

Referenced by unload_module().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1707 of file res_pjsip_outbound_publish.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1707 of file res_pjsip_outbound_publish.c.

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( current_states  )
static

◆ AO2_STRING_FIELD_CMP_FN()

AO2_STRING_FIELD_CMP_FN ( sip_outbound_publisher  ,
user   
)

◆ AO2_STRING_FIELD_HASH_FN()

AO2_STRING_FIELD_HASH_FN ( sip_outbound_publisher  ,
user   
)

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1707 of file res_pjsip_outbound_publish.c.

◆ ast_sip_publish_client_add_datastore()

int ast_sip_publish_client_add_datastore ( struct ast_sip_outbound_publish_client client,
struct ast_datastore datastore 
)

Add a datastore to a SIP event publisher.

Note that SIP uses reference counted datastores. The datastore passed into this function must have been allocated using ao2_alloc() or there will be serious problems.

Parameters
clientThe publication client to add the datastore to
datastoreThe datastore to be added to the subscription
Return values
0Success
-1Failure

Definition at line 724 of file res_pjsip_outbound_publish.c.

References ao2_link, ast_assert, ast_strlen_zero, ast_sip_outbound_publish_client::datastores, ast_datastore::info, NULL, and ast_datastore::uid.

Referenced by asterisk_start_devicestate_publishing(), and asterisk_start_mwi_publishing().

726 {
727  ast_assert(datastore != NULL);
728  ast_assert(datastore->info != NULL);
729  ast_assert(!ast_strlen_zero(datastore->uid));
730 
731  if (!ao2_link(client->datastores, datastore)) {
732  return -1;
733  }
734  return 0;
735 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
const char * uid
Definition: datastore.h:69
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_datastore_info * info
Definition: datastore.h:71
struct ao2_container * datastores
Publisher datastores set up by handlers.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_sip_publish_client_alloc_datastore()

struct ast_datastore* ast_sip_publish_client_alloc_datastore ( const struct ast_datastore_info info,
const char *  uid 
)

Alternative for ast_datastore_alloc()

There are two major differences between this and ast_datastore_alloc() 1) This allocates a refcounted object 2) This will fill in a uid if one is not provided

DO NOT call ast_datastore_free() on a datastore allocated in this way since that function will attempt to free the datastore rather than play nicely with its refcount.

Parameters
infoCallbacks for datastore
uidIdentifier for datastore
Return values
NULLFailed to allocate datastore
non-NULLNewly allocated datastore

Definition at line 694 of file res_pjsip_outbound_publish.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_strdup, ast_strlen_zero, ast_uuid_generate_str(), AST_UUID_STR_LEN, sip_to_pjsip::info(), NULL, RAII_VAR, sip_outbound_publish_datastore_destroy(), and ast_datastore::uid.

Referenced by asterisk_start_devicestate_publishing(), and asterisk_start_mwi_publishing().

695 {
696  RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
697  const char *uid_ptr = uid;
698  char uuid_buf[AST_UUID_STR_LEN];
699 
700  if (!info) {
701  return NULL;
702  }
703 
704  datastore = ao2_alloc(sizeof(*datastore), sip_outbound_publish_datastore_destroy);
705  if (!datastore) {
706  return NULL;
707  }
708 
709  datastore->info = info;
710  if (ast_strlen_zero(uid)) {
711  /* They didn't provide an ID so we'll provide one ourself */
712  uid_ptr = ast_uuid_generate_str(uuid_buf, sizeof(uuid_buf));
713  }
714 
715  datastore->uid = ast_strdup(uid_ptr);
716  if (!datastore->uid) {
717  return NULL;
718  }
719 
720  ao2_ref(datastore, +1);
721  return datastore;
722 }
#define AST_UUID_STR_LEN
Definition: uuid.h:27
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
static void sip_outbound_publish_datastore_destroy(void *obj)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#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
def info(msg)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:143
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_sip_publish_client_get()

struct ast_sip_outbound_publish_client* ast_sip_publish_client_get ( const char *  name)

Find a publish client using its name.

Parameters
nameThe name of the publish client
Return values
NULLfailure
non-NULLsuccess
Note
The publish client is returned with its reference count increased and must be released using ao2_cleanup.

Definition at line 528 of file res_pjsip_outbound_publish.c.

References ao2_ref, ast_sip_outbound_publish_state::client, NULL, and sip_publish_state_get().

Referenced by asterisk_publication_devicestate_refresh(), asterisk_publication_mwi_refresh(), and send_refresh_cb().

529 {
531 
532  if (!state) {
533  return NULL;
534  }
535 
536  ao2_ref(state->client, +1);
537  ao2_ref(state, -1);
538  return state->client;
539 }
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#define NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static const char name[]
Definition: cdr_mysql.c:74
static struct ast_sip_outbound_publish_state * sip_publish_state_get(const char *id)

◆ ast_sip_publish_client_get_datastore()

struct ast_datastore* ast_sip_publish_client_get_datastore ( struct ast_sip_outbound_publish_client client,
const char *  name 
)

Retrieve an event publisher datastore.

The datastore retrieved will have its reference count incremented. When the caller is done with the datastore, the reference counted needs to be decremented using ao2_ref().

Parameters
clientThe publication client from which to retrieve the datastore
nameThe name of the datastore to retrieve
Return values
NULLFailed to find the specified datastore
non-NULLThe specified datastore

Definition at line 737 of file res_pjsip_outbound_publish.c.

References ao2_find, ast_sip_outbound_publish_client::datastores, and OBJ_SEARCH_KEY.

Referenced by asterisk_publication_devicestate_refresh(), asterisk_publication_mwi_refresh(), asterisk_stop_devicestate_publishing(), and asterisk_stop_mwi_publishing().

739 {
740  return ao2_find(client->datastores, name, OBJ_SEARCH_KEY);
741 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ao2_container * datastores
Publisher datastores set up by handlers.
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ ast_sip_publish_client_get_from_uri()

const char* ast_sip_publish_client_get_from_uri ( struct ast_sip_outbound_publish_client client)

Get the From URI the client will use.

Since
14.0.0
Parameters
clientThe publication client to get the From URI
Return values
From-urion success
Empty-stringon failure

Definition at line 541 of file res_pjsip_outbound_publish.c.

References sip_outbound_publisher::client, ast_sip_outbound_publish::from_uri, ast_sip_outbound_publish_client::publish, publish, S_OR, ast_sip_outbound_publish::server_uri, and sip_outbound_publish_client_add_publisher().

542 {
543  struct ast_sip_outbound_publish *publish = client->publish;
544 
545  return S_OR(publish->from_uri, S_OR(publish->server_uri, ""));
546 }
unsigned char publish
Definition: res_corosync.c:241
Outbound publish information.
const ast_string_field server_uri
URI for the entity and server.
struct ast_sip_outbound_publish * publish
Outbound publish information.
const ast_string_field from_uri
URI for the From header.
#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

◆ ast_sip_publish_client_get_to_uri()

const char* ast_sip_publish_client_get_to_uri ( struct ast_sip_outbound_publish_client client)

Get the To URI the client will use.

Since
14.0.0
Parameters
clientThe publication client to get the To URI
Return values
From-urion success
Empty-stringon failure

Definition at line 591 of file res_pjsip_outbound_publish.c.

References ast_sip_outbound_publish_client::publish, publish, S_OR, ast_sip_outbound_publish::server_uri, and ast_sip_outbound_publish::to_uri.

592 {
593  struct ast_sip_outbound_publish *publish = client->publish;
594 
595  return S_OR(publish->to_uri, S_OR(publish->server_uri, ""));
596 }
unsigned char publish
Definition: res_corosync.c:241
Outbound publish information.
const ast_string_field server_uri
URI for the entity and server.
struct ast_sip_outbound_publish * publish
Outbound publish information.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const ast_string_field to_uri
URI for the To header.

◆ ast_sip_publish_client_get_user_from_uri()

const char* ast_sip_publish_client_get_user_from_uri ( struct ast_sip_outbound_publish_client client,
const char *  user,
char *  uri,
size_t  size 
)

Get the From URI the client will use for a specific user.

Since
14.0.0
Parameters
clientThe publication client to get the From URI of a user
userThe user to retrieve the From URI for
uriA buffer to place the URI into
sizeThe size of the buffer
Return values
From-urion success
Empty-stringon failure

Definition at line 575 of file res_pjsip_outbound_publish.c.

References ao2_ref, ast_copy_string(), sip_outbound_publisher::from_uri, NULL, and sip_outbound_publish_client_get_publisher().

Referenced by exten_state_publisher_cb().

577 {
578  struct sip_outbound_publisher *publisher;
579 
580  publisher = sip_outbound_publish_client_get_publisher(client, user);
581  if (!publisher) {
582  return NULL;
583  }
584 
585  ast_copy_string(uri, publisher->from_uri, size);
586  ao2_ref(publisher, -1);
587 
588  return uri;
589 }
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct sip_outbound_publisher * sip_outbound_publish_client_get_publisher(struct ast_sip_outbound_publish_client *client, const char *user)
char * from_uri
The From URI for this specific publisher.
structure to hold users read from users.conf
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_sip_publish_client_get_user_to_uri()

const char* ast_sip_publish_client_get_user_to_uri ( struct ast_sip_outbound_publish_client client,
const char *  user,
char *  uri,
size_t  size 
)

Get the To URI the client will use for a specific user.

Since
14.0.0
Parameters
clientThe publication client to get the To URI of a user
userThe user to retrieve the To URI for
uriA buffer to place the URI into
sizeThe size of the buffer
Return values
To-urion success
Empty-stringon failure

Definition at line 598 of file res_pjsip_outbound_publish.c.

References ao2_ref, ast_copy_string(), NULL, sip_outbound_publish_client_get_publisher(), and sip_outbound_publisher::to_uri.

Referenced by exten_state_publisher_cb().

600 {
601  struct sip_outbound_publisher *publisher;
602 
603  publisher = sip_outbound_publish_client_get_publisher(client, user);
604  if (!publisher) {
605  return NULL;
606  }
607 
608  ast_copy_string(uri, publisher->to_uri, size);
609  ao2_ref(publisher, -1);
610 
611  return uri;
612 }
#define NULL
Definition: resample.c:96
char * to_uri
The To URI for this specific publisher.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct sip_outbound_publisher * sip_outbound_publish_client_get_publisher(struct ast_sip_outbound_publish_client *client, const char *user)
structure to hold users read from users.conf
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_sip_publish_client_remove()

void ast_sip_publish_client_remove ( struct ast_sip_outbound_publish_client client,
const char *  user 
)

Remove the user from the client (stopping it from publishing)

Parameters
clientThe publication client
userThe user to remove

Definition at line 1125 of file res_pjsip_outbound_publish.c.

References ao2_find, load_lock, lock, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, ast_sip_outbound_publish_client::publishers, and SCOPED_WRLOCK.

1127 {
1130 }
static ast_rwlock_t load_lock
Used for locking while loading/reloading.
#define SCOPED_WRLOCK(varname, lock)
scoped lock specialization for write locks
Definition: lock.h:597
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
structure to hold users read from users.conf
struct ao2_container * publishers
Container of all the client publishing objects.

◆ ast_sip_publish_client_remove_datastore()

void ast_sip_publish_client_remove_datastore ( struct ast_sip_outbound_publish_client client,
const char *  name 
)

Remove a publication datastore from an event publisher.

This operation may cause the datastore's free() callback to be called if the reference count reaches zero.

Parameters
clientThe publication client to remove the datastore from
nameThe name of the datastore to remove

Definition at line 743 of file res_pjsip_outbound_publish.c.

References ao2_find, ast_sip_outbound_publish_client::datastores, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by asterisk_start_devicestate_publishing(), asterisk_start_mwi_publishing(), asterisk_stop_devicestate_publishing(), and asterisk_stop_mwi_publishing().

745 {
747 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ao2_container * datastores
Publisher datastores set up by handlers.
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ ast_sip_publish_client_send()

int ast_sip_publish_client_send ( struct ast_sip_outbound_publish_client client,
const struct ast_sip_body body 
)

Send an outgoing PUBLISH message using a client.

Parameters
clientThe publication client to send from
bodyAn optional body to add to the PUBLISH
Return values
-1failure
0success

Definition at line 842 of file res_pjsip_outbound_publish.c.

References ao2_callback_data, lock, OBJ_NODATA, publisher_client_send(), ast_sip_outbound_publish_client::publishers, and SCOPED_AO2LOCK.

Referenced by asterisk_publisher_devstate_cb(), asterisk_publisher_mwistate_cb(), and send_refresh_cb().

844 {
845  SCOPED_AO2LOCK(lock, client);
846  int res = 0;
847 
849  publisher_client_send, (void *)body, &res);
850  return res;
851 }
static int publisher_client_send(void *obj, void *arg, void *data, int flags)
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
struct ao2_container * publishers
Container of all the client publishing objects.

◆ ast_sip_publish_client_user_send()

int ast_sip_publish_client_user_send ( struct ast_sip_outbound_publish_client client,
const char *  user,
const struct ast_sip_body body 
)

Send an outgoing PUBLISH message based on the user.

Parameters
clientThe publication client to send from
userThe user to send to
bodyAn optional body to add to the PUBLISH
Return values
-1failure
0success

Definition at line 1109 of file res_pjsip_outbound_publish.c.

References ao2_ref, publisher_client_send(), and sip_outbound_publish_client_get_publisher().

Referenced by exten_state_publisher_cb().

1111 {
1112  struct sip_outbound_publisher *publisher;
1113  int res;
1114 
1115  publisher = sip_outbound_publish_client_get_publisher(client, user);
1116  if (!publisher) {
1117  return -1;
1118  }
1119 
1120  publisher_client_send(publisher, (void *)body, &res, 0);
1121  ao2_ref(publisher, -1);
1122  return res;
1123 }
static int publisher_client_send(void *obj, void *arg, void *data, int flags)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct sip_outbound_publisher * sip_outbound_publish_client_get_publisher(struct ast_sip_outbound_publish_client *client, const char *user)
structure to hold users read from users.conf

◆ ast_sip_register_event_publisher_handler()

int ast_sip_register_event_publisher_handler ( struct ast_sip_event_publisher_handler handler)

Register an event publisher handler.

Return values
0Handler was registered successfully
non-zeroHandler was not registered successfully

Definition at line 614 of file res_pjsip_outbound_publish.c.

References ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero, ast_sip_event_publisher_handler::event_name, find_publisher_handler_for_event_name(), lock, LOG_ERROR, NULL, SCOPED_LOCK, sip_outbound_publish_synchronize(), ast_sip_event_publisher_handler::start_publishing, ast_sip_event_publisher_handler::stop_publishing, and sub_add_handler().

Referenced by load_module().

615 {
616  struct ast_sip_event_publisher_handler *existing;
618 
619  if (!handler->start_publishing || !handler->stop_publishing) {
620  ast_log(LOG_ERROR, "Handler does not implement required callbacks. Cannot register\n");
621  return -1;
622  } else if (ast_strlen_zero(handler->event_name)) {
623  ast_log(LOG_ERROR, "No event package specified for event publisher handler. Cannot register\n");
624  return -1;
625  }
626 
628  if (existing) {
629  ast_log(LOG_ERROR, "Unable to register event publisher handler for event %s. "
630  "A handler is already registered\n", handler->event_name);
631  return -1;
632  }
633 
634  sub_add_handler(handler);
635 
637 
638  return 0;
639 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int(* start_publishing)(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
Called when a publisher should start publishing.
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
int(* stop_publishing)(struct ast_sip_outbound_publish_client *client)
Called when a publisher should stop publishing.
#define ast_log
Definition: astobj2.c:42
Callbacks that event publisher handlers will define.
ast_mutex_t lock
Definition: app_meetme.c:1091
const char * event_name
The name of the event this handler deals with.
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
static struct ast_sip_event_publisher_handler * find_publisher_handler_for_event_name(const char *event_name)
#define LOG_ERROR
Definition: logger.h:285
static void sub_add_handler(struct ast_sip_event_publisher_handler *handler)
static void sip_outbound_publish_synchronize(struct ast_sip_event_publisher_handler *removed)
Helper function which starts or stops publish clients when applicable.

◆ ast_sip_unregister_event_publisher_handler()

void ast_sip_unregister_event_publisher_handler ( struct ast_sip_event_publisher_handler handler)

Unregister a publish handler.

Definition at line 641 of file res_pjsip_outbound_publish.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, lock, sip_outbound_publish_message::next, SCOPED_LOCK, and sip_outbound_publish_synchronize().

Referenced by load_module(), and unload_module().

642 {
643  struct ast_sip_event_publisher_handler *iter;
646  if (handler == iter) {
648  break;
649  }
650  }
652 
654 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Callbacks that event publisher handlers will define.
ast_mutex_t lock
Definition: app_meetme.c:1091
struct ast_sip_event_publisher_handler * next
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
static void sip_outbound_publish_synchronize(struct ast_sip_event_publisher_handler *removed)
Helper function which starts or stops publish clients when applicable.
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ can_reuse_publish()

static int can_reuse_publish ( struct ast_sip_outbound_publish existing,
struct ast_sip_outbound_publish applied 
)
static

Definition at line 1239 of file res_pjsip_outbound_publish.c.

References AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_outbound_publish::event, ast_sip_outbound_publish::from_uri, ast_sip_outbound_publish::outbound_auths, ast_sip_outbound_publish::outbound_proxy, ast_sip_outbound_publish::server_uri, and ast_sip_outbound_publish::to_uri.

Referenced by current_state_reusable().

1240 {
1241  int i;
1242 
1243  if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->from_uri, applied->from_uri) ||
1244  strcmp(existing->to_uri, applied->to_uri) || strcmp(existing->outbound_proxy, applied->outbound_proxy) ||
1245  strcmp(existing->event, applied->event) ||
1246  AST_VECTOR_SIZE(&existing->outbound_auths) != AST_VECTOR_SIZE(&applied->outbound_auths)) {
1247  return 0;
1248  }
1249 
1250  for (i = 0; i < AST_VECTOR_SIZE(&existing->outbound_auths); ++i) {
1251  if (strcmp(AST_VECTOR_GET(&existing->outbound_auths, i), AST_VECTOR_GET(&applied->outbound_auths, i))) {
1252  return 0;
1253  }
1254  }
1255 
1256  return 1;
1257 }
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
const ast_string_field outbound_proxy
Outbound proxy to use.
const ast_string_field server_uri
URI for the entity and server.
const ast_string_field event
The event type to publish.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
const ast_string_field from_uri
URI for the From header.
const ast_string_field to_uri
URI for the To header.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ cancel_and_unpublish()

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

Helper function which cancels and un-publishes a no longer used client.

Definition at line 1152 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_ref, ast_log, ast_sip_push_task(), ast_sorcery_object_get_id(), cancel_refresh_timer_task(), sip_outbound_publisher::destroy, explicit_publish_destroy(), lock, LOG_WARNING, sip_outbound_publisher::owner, ast_sip_outbound_publish_client::publish, SCOPED_AO2LOCK, send_unpublish_task(), sip_outbound_publisher::sending, sip_outbound_publisher::serializer, and ast_sip_outbound_publish_client::started.

Referenced by sip_outbound_publish_state_destroy(), sip_outbound_publish_synchronize(), and stop_publishing().

1153 {
1154  struct sip_outbound_publisher *publisher = obj;
1155  struct ast_sip_outbound_publish_client *client = publisher->owner;
1156 
1157  SCOPED_AO2LOCK(lock, publisher);
1158 
1159  if (!client->started) {
1160  /* If the publisher was never started, there's nothing to unpublish, so just
1161  * destroy the publication and remove its reference to the publisher.
1162  */
1163  if (ast_sip_push_task(publisher->serializer, explicit_publish_destroy, ao2_bump(publisher))) {
1164  ao2_ref(publisher, -1);
1165  }
1166  return 0;
1167  }
1168 
1169  if (ast_sip_push_task(publisher->serializer, cancel_refresh_timer_task, ao2_bump(publisher))) {
1170  ast_log(LOG_WARNING, "Could not stop refresh timer on outbound publish '%s'\n",
1172  ao2_ref(publisher, -1);
1173  }
1174 
1175  /* If nothing is being sent right now send the unpublish - the destroy will happen in the subsequent callback */
1176  if (!publisher->sending) {
1177  if (ast_sip_push_task(publisher->serializer, send_unpublish_task, ao2_bump(publisher))) {
1178  ast_log(LOG_WARNING, "Could not send unpublish message on outbound publish '%s'\n",
1180  ao2_ref(publisher, -1);
1181  }
1182  }
1183  publisher->destroy = 1;
1184  return 0;
1185 }
unsigned int started
Publishing has been fully started and event type informed.
#define LOG_WARNING
Definition: logger.h:274
static int explicit_publish_destroy(void *data)
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
Outbound publish client state information (persists for lifetime of a publish)
static int send_unpublish_task(void *data)
Task for sending an unpublish.
ast_mutex_t lock
Definition: app_meetme.c:1091
#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 ast_taskprocessor * serializer
Serializer for stuff and things.
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
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_sip_outbound_publish * publish
Outbound publish information.
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
struct sip_outbound_publish_message * sending
The message currently being sent.
unsigned int destroy
Publish client should be destroyed.
static int cancel_refresh_timer_task(void *data)
Task for cancelling a refresh timer.

◆ cancel_publish_refresh()

static void cancel_publish_refresh ( struct sip_outbound_publisher publisher)
static

Helper function which cancels the refresh timer on a publisher.

Definition at line 363 of file res_pjsip_outbound_publish.c.

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

Referenced by cancel_refresh_timer_task(), and schedule_publish_refresh().

364 {
365  if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
366  &publisher->timer, 0)) {
367  /* The timer was successfully cancelled, drop the refcount of the publisher */
368  ao2_ref(publisher, -1);
369  }
370 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pj_timer_entry timer
Timer entry for refreshing publish.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ cancel_refresh_timer_task()

static int cancel_refresh_timer_task ( void *  data)
static

Task for cancelling a refresh timer.

Definition at line 417 of file res_pjsip_outbound_publish.c.

References ao2_ref, and cancel_publish_refresh().

Referenced by cancel_and_unpublish(), and sip_outbound_publish_client_add_publisher().

418 {
419  struct sip_outbound_publisher *publisher = data;
420 
421  cancel_publish_refresh(publisher);
422  ao2_ref(publisher, -1);
423 
424  return 0;
425 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void cancel_publish_refresh(struct sip_outbound_publisher *publisher)
Helper function which cancels the refresh timer on a publisher.

◆ current_state_reusable()

static int current_state_reusable ( struct ast_sip_outbound_publish publish,
struct ast_sip_outbound_publish_state current_state 
)
static

Definition at line 1492 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ao2_ref, ast_log, ast_sip_push_task_wait_servant(), ast_sorcery_object_get_id(), can_reuse_publish(), ast_sip_outbound_publish_state::client, LOG_ERROR, ast_sip_outbound_publish::multi_user, NULL, ast_sip_outbound_publish_client::publish, publish, ast_sip_outbound_publish_client::publishers, and sip_outbound_publisher_reinit_all().

Referenced by sip_outbound_publish_apply().

1494 {
1495  struct ast_sip_outbound_publish *old_publish;
1496 
1497  /*
1498  * Don't maintain the old state/client objects if the multi_user option changed.
1499  */
1500  if ((!publish->multi_user && current_state->client->publish->multi_user) ||
1501  (publish->multi_user && !current_state->client->publish->multi_user)) {
1502  return 0;
1503  }
1504 
1505 
1506  if (!can_reuse_publish(current_state->client->publish, publish)) {
1507  /*
1508  * Something significant has changed in the configuration, so we are
1509  * unable to use the old state object. The current state needs to go
1510  * away and a new one needs to be created.
1511  */
1512  return 0;
1513  }
1514 
1515  /*
1516  * We can reuse the current state object so keep it, but swap out the
1517  * underlying publish object with the new one.
1518  */
1519  old_publish = current_state->client->publish;
1520  current_state->client->publish = publish;
1522  current_state->client->publishers)) {
1523  /*
1524  * If the state object fails to re-initialize then swap
1525  * the old publish info back in.
1526  */
1527  current_state->client->publish = publish;
1528  ast_log(LOG_ERROR, "Unable to reinitialize client(s) for outbound publish '%s'\n",
1529  ast_sorcery_object_get_id(current_state->client->publish));
1530  return -1;
1531  }
1532 
1533  /*
1534  * Since we swapped out the publish object the new one needs a ref
1535  * while the old one needs to go away.
1536  */
1537  ao2_ref(current_state->client->publish, +1);
1538  ao2_cleanup(old_publish);
1539 
1540  /* Tell the caller that the current state object should be used */
1541  return 1;
1542 }
static int sip_outbound_publisher_reinit_all(void *data)
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#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
unsigned int multi_user
The publishing client is used for multiple users when true.
unsigned char publish
Definition: res_corosync.c:241
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define LOG_ERROR
Definition: logger.h:285
Outbound publish information.
struct ast_sip_outbound_publish * publish
Outbound publish information.
struct ao2_container * publishers
Container of all the client publishing objects.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int can_reuse_publish(struct ast_sip_outbound_publish *existing, struct ast_sip_outbound_publish *applied)

◆ datastore_cmp()

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

Definition at line 1387 of file res_pjsip_outbound_publish.c.

References CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and ast_datastore::uid.

Referenced by sip_outbound_publish_state_alloc().

1388 {
1389  const struct ast_datastore *object_left = obj;
1390  const struct ast_datastore *object_right = arg;
1391  const char *right_key = arg;
1392  int cmp;
1393 
1394  switch (flags & OBJ_SEARCH_MASK) {
1395  case OBJ_SEARCH_OBJECT:
1396  right_key = object_right->uid;
1397  /* Fall through */
1398  case OBJ_SEARCH_KEY:
1399  cmp = strcmp(object_left->uid, right_key);
1400  break;
1402  cmp = strncmp(object_left->uid, right_key, strlen(right_key));
1403  break;
1404  default:
1405  /*
1406  * What arg points to is specific to this traversal callback
1407  * and has no special meaning to astobj2.
1408  */
1409  cmp = 0;
1410  break;
1411  }
1412  if (cmp) {
1413  return 0;
1414  }
1415  /*
1416  * At this point the traversal callback is identical to a sorted
1417  * container.
1418  */
1419  return CMP_MATCH;
1420 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Structure for a data store object.
Definition: datastore.h:68
const char * uid
Definition: datastore.h:69
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ datastore_hash()

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

Definition at line 1365 of file res_pjsip_outbound_publish.c.

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and ast_datastore::uid.

Referenced by sip_outbound_publish_state_alloc().

1366 {
1367  const struct ast_datastore *datastore;
1368  const char *uid;
1369 
1370  switch (flags & OBJ_SEARCH_MASK) {
1371  case OBJ_SEARCH_KEY:
1372  uid = obj;
1373  break;
1374  case OBJ_SEARCH_OBJECT:
1375  datastore = obj;
1376  uid = datastore->uid;
1377  break;
1378  default:
1379  /* Hash can only work on something with a full key. */
1380  ast_assert(0);
1381  return 0;
1382  }
1383 
1384  return ast_str_hash(uid);
1385 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
Structure for a data store object.
Definition: datastore.h:68
const char * uid
Definition: datastore.h:69
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

◆ explicit_publish_destroy()

static int explicit_publish_destroy ( void *  data)
static

Definition at line 1132 of file res_pjsip_outbound_publish.c.

References ao2_ref, and sip_outbound_publisher::client.

Referenced by cancel_and_unpublish().

1133 {
1134  struct sip_outbound_publisher *publisher = data;
1135 
1136  /*
1137  * If there is no pjsip publishing client then we obviously don't need
1138  * to destroy it. Also, the ref for the Asterisk publishing client that
1139  * pjsip had would not exist or should already be gone as well.
1140  */
1141  if (publisher->client) {
1142  pjsip_publishc_destroy(publisher->client);
1143  ao2_ref(publisher, -1);
1144  }
1145 
1146  ao2_ref(publisher, -1);
1147 
1148  return 0;
1149 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_publishc * client
Underlying publish client.

◆ find_publisher_handler_for_event_name()

static struct ast_sip_event_publisher_handler* find_publisher_handler_for_event_name ( const char *  event_name)
static

Definition at line 350 of file res_pjsip_outbound_publish.c.

References AST_RWLIST_TRAVERSE, ast_sip_event_publisher_handler::event_name, and sip_outbound_publish_message::next.

Referenced by ast_sip_register_event_publisher_handler(), sip_outbound_publish_synchronize(), and stop_publishing().

351 {
352  struct ast_sip_event_publisher_handler *iter;
353 
355  if (!strcmp(iter->event_name, event_name)) {
356  break;
357  }
358  }
359  return iter;
360 }
Callbacks that event publisher handlers will define.
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char * event_name
The name of the event this handler deals with.
struct ast_sip_event_publisher_handler * next

◆ get_publishes_and_update_state()

static struct ao2_container* get_publishes_and_update_state ( void  )
static

Definition at line 323 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ao2_global_obj_replace_unref, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), container, load_lock, lock, NULL, and SCOPED_WRLOCK.

Referenced by sip_outbound_publish_synchronize().

324 {
325  struct ao2_container *container;
327 
328  container = ast_sorcery_retrieve_by_fields(
329  ast_sip_get_sorcery(), "outbound-publish",
331 
332  if (!new_states) {
333  return container;
334  }
335 
336  ao2_global_obj_replace_unref(current_states, new_states);
338  new_states = NULL;
339 
340  return container;
341 }
static ast_rwlock_t load_lock
Used for locking while loading/reloading.
#define SCOPED_WRLOCK(varname, lock)
scoped lock specialization for write locks
Definition: lock.h:597
Perform no matching, return all objects.
Definition: sorcery.h:123
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
ast_mutex_t lock
Definition: app_meetme.c:1091
struct ao2_container * container
Definition: res_fax.c:502
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
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * new_states
Used on [re]loads to hold new state data.
Generic container type.

◆ load_module()

static int load_module ( void  )
static

Definition at line 1647 of file res_pjsip_outbound_publish.c.

References ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_pjproject_get_buildopt(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_serializer_shutdown_group_alloc(), ast_sip_get_pjsip_endpoint(), ast_sip_get_sorcery(), ast_sorcery_apply_config, ast_sorcery_apply_default, ast_sorcery_object_field_register, ast_sorcery_object_field_register_custom, ast_sorcery_object_register, ast_sorcery_reload_object(), ast_sip_outbound_publish::expiration, FLDSET, ast_sip_outbound_publish::from_uri, LOG_ERROR, ast_sip_outbound_publish::max_auth_attempts, ast_sip_outbound_publish::multi_user, NULL, OPT_BOOL_T, OPT_NOOP_T, OPT_STRINGFIELD_T, OPT_UINT_T, outbound_auth_handler(), ast_sip_outbound_publish::outbound_proxy, pjsip_max_url_size, server_uri, sip_outbound_publish_alloc(), sip_outbound_publish_apply(), sip_outbound_publish_synchronize(), STRFLDSET, ast_sip_outbound_publish::to_uri, ast_sip_outbound_publish::transport, and unload_module().

Referenced by reload_module().

1648 {
1649  /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1650  ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1651 
1653  if (!shutdown_group) {
1654  return AST_MODULE_LOAD_DECLINE;
1655  }
1656 
1657  ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_publish");
1658  ast_sorcery_apply_default(ast_sip_get_sorcery(), "outbound-publish", "config", "pjsip.conf,criteria=type=outbound-publish");
1659 
1662  ast_log(LOG_ERROR, "Unable to register 'outbound-publish' type with sorcery\n");
1663  unload_module();
1664  return AST_MODULE_LOAD_DECLINE;
1665  }
1666 
1667  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "type", "", OPT_NOOP_T, 0, 0);
1669  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "from_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, from_uri));
1671  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "to_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, to_uri));
1672  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, outbound_proxy));
1673  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_outbound_publish, expiration));
1674  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "max_auth_attempts", "5", OPT_UINT_T, 0, FLDSET(struct ast_sip_outbound_publish, max_auth_attempts));
1675  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, transport));
1676  ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "outbound-publish", "outbound_auth", "", outbound_auth_handler, NULL, NULL, 0, 0);
1677  ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "multi_user", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_outbound_publish, multi_user));
1678 
1679  ast_sorcery_reload_object(ast_sip_get_sorcery(), "outbound-publish");
1680 
1684 
1685  pjsip_publishc_init_module(ast_sip_get_pjsip_endpoint());
1686 
1687  return AST_MODULE_LOAD_SUCCESS;
1688 }
static int unload_module(void)
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Type for a default handler that should do nothing.
Definition: astman.c:222
#define ast_sorcery_apply_config(sorcery, name)
Definition: sorcery.h:456
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#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.
Type for default option handler for unsigned integers.
static void * sip_outbound_publish_alloc(const char *name)
Allocator function for publish information.
static int pjsip_max_url_size
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:838
static struct ast_serializer_shutdown_group * shutdown_group
#define LOG_ERROR
Definition: logger.h:285
static int sip_outbound_publish_apply(const struct ast_sorcery *sorcery, void *obj)
Apply function which finds or allocates a state structure.
static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Type for default option handler for bools (ast_true/ast_false)
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:477
Outbound publish information.
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
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
static void sip_outbound_publish_synchronize(struct ast_sip_event_publisher_handler *removed)
Helper function which starts or stops publish clients when applicable.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
Type for default option handler for stringfields.
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

◆ outbound_auth_handler()

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

Definition at line 1614 of file res_pjsip_outbound_publish.c.

References ast_sip_auth_vector_init(), ast_sip_outbound_publish::outbound_auths, publish, and ast_variable::value.

Referenced by load_module().

1615 {
1616  struct ast_sip_outbound_publish *publish = obj;
1617 
1618  return ast_sip_auth_vector_init(&publish->outbound_auths, var->value);
1619 }
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.
unsigned char publish
Definition: res_corosync.c:241
Outbound publish information.

◆ outbound_publish_state_cmp()

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

comparator function for client objects

Definition at line 295 of file res_pjsip_outbound_publish.c.

References ast_assert, CMP_MATCH, ast_sip_outbound_publish_state::id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by sip_outbound_publish_apply().

296 {
297  const struct ast_sip_outbound_publish_state *object_left = obj;
298  const struct ast_sip_outbound_publish_state *object_right = arg;
299  const char *right_key = arg;
300  int cmp;
301 
302  switch (flags & OBJ_SEARCH_MASK) {
303  case OBJ_SEARCH_OBJECT:
304  right_key = object_right->id;
305  /* Fall through */
306  case OBJ_SEARCH_KEY:
307  cmp = strcmp(object_left->id, right_key);
308  break;
310  /* Not supported by container. */
311  ast_assert(0);
312  return 0;
313  default:
314  cmp = 0;
315  break;
316  }
317  if (cmp) {
318  return 0;
319  }
320  return CMP_MATCH;
321 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
Outbound publish state information (persists for lifetime of a publish)
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ outbound_publish_state_hash()

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

hashing function for state objects

Definition at line 274 of file res_pjsip_outbound_publish.c.

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by sip_outbound_publish_apply().

275 {
276  const struct ast_sip_outbound_publish_state *object;
277  const char *key;
278 
279  switch (flags & OBJ_SEARCH_MASK) {
280  case OBJ_SEARCH_KEY:
281  key = obj;
282  break;
283  case OBJ_SEARCH_OBJECT:
284  object = obj;
285  key = object->id;
286  break;
287  default:
288  ast_assert(0);
289  return 0;
290  }
291  return ast_str_hash(key);
292 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
Outbound publish state information (persists for lifetime of a publish)
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

◆ publisher_client_send()

static int publisher_client_send ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 796 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_ref, ast_calloc, AST_LIST_INSERT_TAIL, ast_sip_push_task(), sip_outbound_publish_message::body, sip_outbound_publish_message::body_contents, ast_sip_body::body_text, sip_outbound_publisher::client, lock, sip_outbound_publisher::queue, SCOPED_AO2LOCK, sip_outbound_publisher::serializer, sip_publisher_service_queue(), ast_sip_body::subtype, and ast_sip_body::type.

Referenced by ast_sip_publish_client_send(), ast_sip_publish_client_user_send(), schedule_publish_refresh(), and sip_outbound_publish_timer_cb().

797 {
798  struct sip_outbound_publisher *publisher = obj;
799  const struct ast_sip_body *body = arg;
801  size_t type_len = 0, subtype_len = 0, body_text_len = 0;
802  int *res = data;
803  SCOPED_AO2LOCK(lock, publisher);
804 
805  *res = -1;
806  if (!publisher->client) {
807  return -1;
808  }
809 
810  /* If a body is present we need more space for the contents of it */
811  if (body) {
812  type_len = strlen(body->type) + 1;
813  subtype_len = strlen(body->subtype) + 1;
814  body_text_len = strlen(body->body_text) + 1;
815  }
816 
817  message = ast_calloc(1, sizeof(*message) + type_len + subtype_len + body_text_len);
818  if (!message) {
819  return -1;
820  }
821 
822  if (body) {
823  char *dst = message->body_contents;
824 
825  message->body.type = strcpy(dst, body->type);
826  dst += type_len;
827  message->body.subtype = strcpy(dst, body->subtype);
828  dst += subtype_len;
829  message->body.body_text = strcpy(dst, body->body_text);
830  }
831 
832  AST_LIST_INSERT_TAIL(&publisher->queue, message, entry);
833 
834  *res = ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher));
835  if (*res) {
836  ao2_ref(publisher, -1);
837  }
838 
839  return *res;
840 }
const char * body_text
Definition: res_pjsip.h:2033
struct sip_outbound_publisher::@485 queue
Queue of outgoing publish messages to send.
struct ast_sip_body body
Optional body.
static int sip_publisher_service_queue(void *data)
#define ao2_bump(obj)
Definition: astobj2.h:491
char body_contents[0]
Extra space for body contents.
const char * type
Definition: res_pjsip.h:2029
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_taskprocessor * serializer
Serializer for stuff and things.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
pjsip_publishc * client
Underlying publish client.
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
const char * subtype
Definition: res_pjsip.h:2031
Queued outbound publish message.
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Definition: search.h:40
SIP body description.
Definition: res_pjsip.h:2027

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1690 of file res_pjsip_outbound_publish.c.

References AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_sip_get_sorcery(), ast_sorcery_reload_object(), ASTERISK_GPL_KEY, load_module(), NULL, reload(), sip_outbound_publish_synchronize(), and unload_module().

1691 {
1692  ast_sorcery_reload_object(ast_sip_get_sorcery(), "outbound-publish");
1693 
1697  return 0;
1698 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static void sip_outbound_publish_synchronize(struct ast_sip_event_publisher_handler *removed)
Helper function which starts or stops publish clients when applicable.
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

◆ schedule_publish_refresh()

static void schedule_publish_refresh ( struct sip_outbound_publisher publisher,
int  expiration 
)
static

Helper function which sets up the timer to send publication.

Definition at line 373 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_ref, ast_log, ast_sip_get_pjsip_endpoint(), cancel_publish_refresh(), ast_sip_outbound_publish::expiration, LOG_WARNING, sip_outbound_publisher::owner, ast_sip_outbound_publish_client::publish, publish, publisher_client_send(), and sip_outbound_publisher::timer.

Referenced by sip_outbound_publish_callback().

374 {
375  struct ast_sip_outbound_publish *publish = ao2_bump(publisher->owner->publish);
376  pj_time_val delay = { .sec = 0, };
377 
378  cancel_publish_refresh(publisher);
379 
380  if (expiration > 0) {
381  delay.sec = expiration - PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH;
382  }
383  if (publish->expiration && ((delay.sec > publish->expiration) || !delay.sec)) {
384  delay.sec = publish->expiration;
385  }
386  if (delay.sec < PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH) {
387  delay.sec = PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH;
388  }
389 
390  ao2_ref(publisher, +1);
391  if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &publisher->timer, &delay) != PJ_SUCCESS) {
392  ast_log(LOG_WARNING, "Failed to pass timed publish refresh to scheduler\n");
393  ao2_ref(publisher, -1);
394  }
395  ao2_ref(publish, -1);
396 }
#define LOG_WARNING
Definition: logger.h:274
unsigned char publish
Definition: res_corosync.c:241
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pj_timer_entry timer
Timer entry for refreshing publish.
static void cancel_publish_refresh(struct sip_outbound_publisher *publisher)
Helper function which cancels the refresh timer on a publisher.
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
Outbound publish information.
struct ast_sip_outbound_publish * publish
Outbound publish information.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
unsigned int expiration
Requested expiration time.

◆ send_unpublish_task()

static int send_unpublish_task ( void *  data)
static

Task for sending an unpublish.

Definition at line 440 of file res_pjsip_outbound_publish.c.

References ao2_ref, sip_outbound_publisher::client, and set_transport().

Referenced by cancel_and_unpublish(), and sip_outbound_publish_callback().

441 {
442  struct sip_outbound_publisher *publisher = data;
443  pjsip_tx_data *tdata;
444 
445  if (pjsip_publishc_unpublish(publisher->client, &tdata) == PJ_SUCCESS) {
446  set_transport(publisher, tdata);
447  pjsip_publishc_send(publisher->client, tdata);
448  }
449 
450  ao2_ref(publisher, -1);
451 
452  return 0;
453 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pjsip_publishc * client
Underlying publish client.
static void set_transport(struct sip_outbound_publisher *publisher, pjsip_tx_data *tdata)

◆ set_transport()

static void set_transport ( struct sip_outbound_publisher publisher,
pjsip_tx_data *  tdata 
)
static

Definition at line 427 of file res_pjsip_outbound_publish.c.

References ast_sip_set_tpselector_from_transport_name(), ast_sip_tpselector_unref(), ast_strlen_zero, sip_outbound_publisher::owner, ast_sip_outbound_publish_client::publish, and ast_sip_outbound_publish::transport.

Referenced by send_unpublish_task(), sip_outbound_publish_callback(), and sip_publisher_service_queue().

428 {
429  if (!ast_strlen_zero(publisher->owner->publish->transport)) {
430  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
431 
433  publisher->owner->publish->transport, &selector);
434  pjsip_tx_data_set_transport(tdata, &selector);
435  ast_sip_tpselector_unref(&selector);
436  }
437 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
const ast_string_field transport
Explicit transport to use for publish.
struct ast_sip_outbound_publish * publish
Outbound publish information.
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
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

◆ sip_outbound_publish_alloc()

static void* sip_outbound_publish_alloc ( const char *  name)
static

Allocator function for publish information.

Definition at line 667 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ast_sorcery_generic_alloc(), ast_string_field_init, NULL, publish, and sip_outbound_publish_destroy().

Referenced by load_module().

668 {
671 
672  if (!publish || ast_string_field_init(publish, 256)) {
673  ao2_cleanup(publish);
674  return NULL;
675  }
676 
677  return publish;
678 }
#define NULL
Definition: resample.c:96
unsigned char publish
Definition: res_corosync.c:241
static void sip_outbound_publish_destroy(void *obj)
Destructor function for publish information.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
Outbound publish 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_publish_apply()

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

Apply function which finds or allocates a state structure.

Definition at line 1545 of file res_pjsip_outbound_publish.c.

References ADD_TO_NEW_STATES, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_cleanup, ao2_container_alloc_hash, ao2_ref, ast_log, ast_sorcery_object_get_id(), ast_sip_outbound_publish_state::client, current_state_reusable(), DEFAULT_STATE_BUCKETS, LOG_ERROR, ast_sip_outbound_publish::multi_user, NULL, outbound_publish_state_cmp(), outbound_publish_state_hash(), sip_outbound_publish_state_alloc(), sip_publish_state_get(), and validate_publish_config().

Referenced by load_module().

1546 {
1547 #define ADD_TO_NEW_STATES(__obj) \
1548  do { if (__obj) { \
1549  ao2_link(new_states, __obj); \
1550  ao2_ref(__obj, -1); } } while (0)
1551 
1552  struct ast_sip_outbound_publish *applied = obj;
1553  struct ast_sip_outbound_publish_state *current_state, *new_state;
1554  struct sip_outbound_publisher *publisher = NULL;
1555  int res;
1556 
1557  /*
1558  * New states are being loaded or reloaded. We'll need to add the new
1559  * object if created/updated, or keep the old object if an error occurs.
1560  */
1561  if (!new_states) {
1565 
1566  if (!new_states) {
1567  ast_log(LOG_ERROR, "Unable to allocate new states container\n");
1568  return -1;
1569  }
1570  }
1571 
1572  /* If there is current state we'll want to maintain it if any errors occur */
1573  current_state = sip_publish_state_get(ast_sorcery_object_get_id(applied));
1574 
1575  if ((res = validate_publish_config(applied))) {
1576  ADD_TO_NEW_STATES(current_state);
1577  return res;
1578  }
1579 
1580  if (current_state && (res = current_state_reusable(applied, current_state))) {
1581  /*
1582  * The current state object was able to be reused, or an error
1583  * occurred. Either way we keep the current state and be done.
1584  */
1585  ADD_TO_NEW_STATES(current_state);
1586  return res == 1 ? 0 : -1;
1587  }
1588 
1589  /*
1590  * No current state was found or it was unable to be reused. Either way
1591  * we'll need to create a new state object.
1592  */
1593  new_state = sip_outbound_publish_state_alloc(applied);
1594  if (!new_state) {
1595  ast_log(LOG_ERROR, "Unable to create state for outbound publish '%s'\n",
1596  ast_sorcery_object_get_id(applied));
1597  ADD_TO_NEW_STATES(current_state);
1598  return -1;
1599  };
1600 
1601  if (!applied->multi_user &&
1602  !(publisher = sip_outbound_publish_client_add_publisher(new_state->client, NULL))) {
1603  ADD_TO_NEW_STATES(current_state);
1604  ao2_ref(new_state, -1);
1605  return -1;
1606  }
1607  ao2_cleanup(publisher);
1608 
1609  ADD_TO_NEW_STATES(new_state);
1610  ao2_cleanup(current_state);
1611  return res;
1612 }
#define DEFAULT_STATE_BUCKETS
Default number of client state container buckets.
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#define NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
static struct ast_sip_outbound_publish_state * sip_outbound_publish_state_alloc(struct ast_sip_outbound_publish *publish)
Allocator function for publish client.
unsigned int multi_user
The publishing client is used for multiple users when true.
static int current_state_reusable(struct ast_sip_outbound_publish *publish, struct ast_sip_outbound_publish_state *current_state)
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ADD_TO_NEW_STATES(__obj)
static struct sip_outbound_publisher * sip_outbound_publish_client_add_publisher(struct ast_sip_outbound_publish_client *client, const char *user)
#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
static int outbound_publish_state_hash(const void *obj, const int flags)
hashing function for state objects
Outbound publish information.
static struct ast_sip_outbound_publish_state * sip_publish_state_get(const char *id)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * new_states
Used on [re]loads to hold new state data.
static int validate_publish_config(struct ast_sip_outbound_publish *publish)
static int outbound_publish_state_cmp(void *obj, void *arg, int flags)
comparator function for client objects

◆ sip_outbound_publish_callback()

static void sip_outbound_publish_callback ( struct pjsip_publishc_cbparam *  param)
static

Callback function for publish client responses.

Definition at line 1260 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_cleanup, ao2_ref, ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_log, ast_sip_create_request_with_auth(), ast_sip_push_task(), ast_sorcery_object_get_id(), DESTROY_CLIENT, end, lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, publish, RAII_VAR, schedule_publish_refresh(), SCOPED_AO2LOCK, send_unpublish_task(), set_transport(), sip_outbound_publisher_init(), and sip_publisher_service_queue().

Referenced by sip_outbound_publisher_init(), and sip_outbound_publisher_set_uris().

1261 {
1262 #define DESTROY_CLIENT() do { \
1263  pjsip_publishc_destroy(publisher->client); \
1264  publisher->client = NULL; \
1265  ao2_ref(publisher, -1); } while (0)
1266 
1267  RAII_VAR(struct sip_outbound_publisher *, publisher, ao2_bump(param->token), ao2_cleanup);
1268  RAII_VAR(struct ast_sip_outbound_publish *, publish, ao2_bump(publisher->owner->publish), ao2_cleanup);
1269  SCOPED_AO2LOCK(lock, publisher);
1270  pjsip_tx_data *tdata;
1271 
1272  if (publisher->destroy) {
1273  if (publisher->sending) {
1274  publisher->sending = NULL;
1275 
1276  if (!ast_sip_push_task(publisher->serializer, send_unpublish_task, ao2_bump(publisher))) {
1277  return;
1278  }
1279  ast_log(LOG_WARNING, "Could not send unpublish message on outbound publish '%s'\n",
1281  ao2_ref(publisher, -1);
1282  }
1283  /* Once the destroy is called this callback will not get called any longer, so drop the publisher ref */
1284  DESTROY_CLIENT();
1285  return;
1286  }
1287 
1288  if (param->code == 401 || param->code == 407) {
1289  pjsip_transaction *tsx = pjsip_rdata_get_tsx(param->rdata);
1290 
1291  if (!ast_sip_create_request_with_auth(&publish->outbound_auths,
1292  param->rdata, tsx->last_tx, &tdata)) {
1293  set_transport(publisher, tdata);
1294  pjsip_publishc_send(publisher->client, tdata);
1295  }
1296  publisher->auth_attempts++;
1297 
1298  if (publisher->auth_attempts == publish->max_auth_attempts) {
1299  DESTROY_CLIENT();
1300  ast_log(LOG_ERROR, "Reached maximum number of PUBLISH authentication attempts on outbound publish '%s'\n",
1302 
1303  goto end;
1304  }
1305  return;
1306  }
1307 
1308  publisher->auth_attempts = 0;
1309 
1310  if (param->code == 412) {
1311  DESTROY_CLIENT();
1312  if (sip_outbound_publisher_init(publisher)) {
1313  ast_log(LOG_ERROR, "Failed to create a new outbound publish client for '%s' on 412 response\n",
1315  goto end;
1316  }
1317 
1318  /* Setting this to NULL will cause a new PUBLISH to get created and sent for the same underlying body */
1319  publisher->sending = NULL;
1320  } else if (param->code == 423) {
1321  /* Update the expiration with the new expiration time if available */
1322  pjsip_expires_hdr *expires;
1323 
1324  expires = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_MIN_EXPIRES, NULL);
1325  if (!expires || !expires->ivalue) {
1326  DESTROY_CLIENT();
1327  ast_log(LOG_ERROR, "Received 423 response on outbound publish '%s' without a Min-Expires header\n",
1329  goto end;
1330  }
1331 
1332  pjsip_publishc_update_expires(publisher->client, expires->ivalue);
1333  publisher->sending = NULL;
1334  } else if (publisher->sending) {
1335  /* Remove the message currently being sent so that when the queue is serviced another will get sent */
1336  AST_LIST_REMOVE_HEAD(&publisher->queue, entry);
1337  ast_free(publisher->sending);
1338  publisher->sending = NULL;
1339  if (!param->rdata) {
1340  ast_log(LOG_NOTICE, "No response received for outbound publish '%s'\n",
1342  }
1343  }
1344 
1345  if (AST_LIST_EMPTY(&publisher->queue)) {
1346  schedule_publish_refresh(publisher, param->expiration);
1347  }
1348 
1349 end:
1350  if (!publisher->client) {
1352 
1353  while ((message = AST_LIST_REMOVE_HEAD(&publisher->queue, entry))) {
1354  ast_free(message);
1355  }
1356  } else {
1357  if (ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher))) {
1358  ao2_ref(publisher, -1);
1359  }
1360  }
1361 }
#define LOG_WARNING
Definition: logger.h:274
#define DESTROY_CLIENT()
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
static int sip_publisher_service_queue(void *data)
unsigned char publish
Definition: res_corosync.c:241
#define ao2_bump(obj)
Definition: astobj2.h:491
#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 send_unpublish_task(void *data)
Task for sending an unpublish.
ast_mutex_t lock
Definition: app_meetme.c:1091
#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
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
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static int sip_outbound_publisher_init(void *data)
Helper function that allocates a pjsip publish client and configures it.
#define LOG_ERROR
Definition: logger.h:285
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
Outbound publish information.
Queued outbound publish message.
#define LOG_NOTICE
Definition: logger.h:263
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ast_free(a)
Definition: astmm.h:182
static void schedule_publish_refresh(struct sip_outbound_publisher *publisher, int expiration)
Helper function which sets up the timer to send publication.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Definition: search.h:40
static void set_transport(struct sip_outbound_publisher *publisher, pjsip_tx_data *tdata)

◆ sip_outbound_publish_client_add_publisher()

static struct sip_outbound_publisher * sip_outbound_publish_client_add_publisher ( struct ast_sip_outbound_publish_client client,
const char *  user 
)
static

Definition at line 1085 of file res_pjsip_outbound_publish.c.

References ao2_link, ao2_ref, ast_sip_push_task(), cancel_refresh_timer_task(), NULL, ast_sip_outbound_publish_client::publishers, sip_outbound_publisher::serializer, and sip_outbound_publisher_alloc().

Referenced by ast_sip_publish_client_get_from_uri(), and sip_outbound_publish_client_get_publisher().

1087 {
1088  struct sip_outbound_publisher *publisher =
1090 
1091  if (!publisher) {
1092  return NULL;
1093  }
1094 
1095  if (!ao2_link(client->publishers, publisher)) {
1096  /*
1097  * No need to bump the reference here. The task will take care of
1098  * removing the reference.
1099  */
1100  if (ast_sip_push_task(publisher->serializer, cancel_refresh_timer_task, publisher)) {
1101  ao2_ref(publisher, -1);
1102  }
1103  return NULL;
1104  }
1105 
1106  return publisher;
1107 }
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_taskprocessor * serializer
Serializer for stuff and things.
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_publisher * sip_outbound_publisher_alloc(struct ast_sip_outbound_publish_client *client, const char *user)
structure to hold users read from users.conf
struct ao2_container * publishers
Container of all the client publishing objects.
static int cancel_refresh_timer_task(void *data)
Task for cancelling a refresh timer.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ sip_outbound_publish_client_destroy()

static void sip_outbound_publish_client_destroy ( void *  obj)
static

Destructor function for publish client.

Definition at line 1188 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ast_sip_outbound_publish_client::datastores, and ast_sip_outbound_publish_client::publish.

Referenced by sip_outbound_publish_state_alloc().

1189 {
1190  struct ast_sip_outbound_publish_client *client = obj;
1191 
1192  ao2_cleanup(client->datastores);
1193 
1194  /*
1195  * The client's publishers have already been unpublished and destroyed
1196  * by this point, so it is safe to finally remove the reference to the
1197  * publish object. The client needed to hold a reference to it until
1198  * the publishers were done with it.
1199  */
1200  ao2_cleanup(client->publish);
1201 }
Outbound publish client state information (persists for lifetime of a publish)
struct ao2_container * datastores
Publisher datastores set up by handlers.
struct ast_sip_outbound_publish * publish
Outbound publish information.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ sip_outbound_publish_client_get_publisher()

static struct sip_outbound_publisher* sip_outbound_publish_client_get_publisher ( struct ast_sip_outbound_publish_client client,
const char *  user 
)
static

Definition at line 551 of file res_pjsip_outbound_publish.c.

References ao2_find, ast_rwlock_unlock, ast_rwlock_wrlock, load_lock, NULL, OBJ_SEARCH_KEY, ast_sip_outbound_publish_client::publishers, and sip_outbound_publish_client_add_publisher().

Referenced by ast_sip_publish_client_get_user_from_uri(), ast_sip_publish_client_get_user_to_uri(), and ast_sip_publish_client_user_send().

553 {
554  struct sip_outbound_publisher *publisher;
555 
556  /*
557  * Lock before searching since there could be a race between searching and adding.
558  * Just use the load_lock since we might need to lock it anyway (if adding) and
559  * also it simplifies the code (otherwise we'd have to lock the publishers, no-
560  * lock the search and pass a flag to 'add publisher to no-lock the potential link).
561  */
563  publisher = ao2_find(client->publishers, user, OBJ_SEARCH_KEY);
564  if (!publisher) {
565  if (!(publisher = sip_outbound_publish_client_add_publisher(client, user))) {
567  return NULL;
568  }
569  }
571 
572  return publisher;
573 }
static ast_rwlock_t load_lock
Used for locking while loading/reloading.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define NULL
Definition: resample.c:96
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static struct sip_outbound_publisher * sip_outbound_publish_client_add_publisher(struct ast_sip_outbound_publish_client *client, const char *user)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
structure to hold users read from users.conf
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
struct ao2_container * publishers
Container of all the client publishing objects.

◆ sip_outbound_publish_datastore_destroy()

static void sip_outbound_publish_datastore_destroy ( void *  obj)
static

Definition at line 680 of file res_pjsip_outbound_publish.c.

References ast_free, ast_datastore::data, ast_datastore_info::destroy, ast_datastore::info, NULL, and ast_datastore::uid.

Referenced by ast_sip_publish_client_alloc_datastore().

681 {
682  struct ast_datastore *datastore = obj;
683 
684  /* Using the destroy function (if present) destroy the data */
685  if (datastore->info->destroy != NULL && datastore->data != NULL) {
686  datastore->info->destroy(datastore->data);
687  datastore->data = NULL;
688  }
689 
690  ast_free((void *) datastore->uid);
691  datastore->uid = NULL;
692 }
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
const char * uid
Definition: datastore.h:69
const struct ast_datastore_info * info
Definition: datastore.h:71
void(* destroy)(void *data)
Definition: datastore.h:34
#define ast_free(a)
Definition: astmm.h:182
void * data
Definition: datastore.h:70

◆ sip_outbound_publish_destroy()

static void sip_outbound_publish_destroy ( void *  obj)
static

Destructor function for publish information.

Definition at line 657 of file res_pjsip_outbound_publish.c.

References ast_sip_auth_vector_destroy(), ast_string_field_free_memory, ast_sip_outbound_publish::outbound_auths, and publish.

Referenced by sip_outbound_publish_alloc().

658 {
659  struct ast_sip_outbound_publish *publish = obj;
660 
662 
664 }
struct ast_sip_auth_vector outbound_auths
Configured authentication credentials.
void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector)
Free contents of an auth vector.
unsigned char publish
Definition: res_corosync.c:241
Outbound publish information.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ sip_outbound_publish_state_alloc()

static struct ast_sip_outbound_publish_state* sip_outbound_publish_state_alloc ( struct ast_sip_outbound_publish publish)
static

Allocator function for publish client.

Definition at line 1423 of file res_pjsip_outbound_publish.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_bump, ao2_container_alloc_hash, ao2_ref, ast_sorcery_object_get_id(), ast_sip_outbound_publish_state::client, DATASTORE_BUCKETS, datastore_cmp(), datastore_hash(), ast_sip_outbound_publish_client::datastores, ast_sip_outbound_publish_state::id, NULL, ast_sip_outbound_publish_client::publish, ast_sip_outbound_publish_client::publishers, sip_outbound_publish_client_destroy(), sip_outbound_publish_state_destroy(), and state.

Referenced by sip_outbound_publish_apply().

1425 {
1426  const char *id = ast_sorcery_object_get_id(publish);
1428  ao2_alloc(sizeof(*state) + strlen(id) + 1, sip_outbound_publish_state_destroy);
1429 
1430  if (!state) {
1431  return NULL;
1432  }
1433 
1434  state->client = ao2_alloc(sizeof(*state->client), sip_outbound_publish_client_destroy);
1435  if (!state->client) {
1436  ao2_ref(state, -1);
1437  return NULL;
1438  }
1439 
1442  if (!state->client->datastores) {
1443  ao2_ref(state, -1);
1444  return NULL;
1445  }
1446 
1449  sip_outbound_publisher_hash_fn, NULL, sip_outbound_publisher_cmp_fn);
1450  if (!state->client->publishers) {
1451  ao2_ref(state, -1);
1452  return NULL;
1453  }
1454 
1455  state->client->publish = ao2_bump(publish);
1456 
1457  strcpy(state->id, id);
1458  return state;
1459 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static int datastore_hash(const void *obj, int flags)
static void sip_outbound_publish_state_destroy(void *obj)
Destructor function for publish state.
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#define NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
#define ao2_bump(obj)
Definition: astobj2.h:491
static int datastore_cmp(void *obj, void *arg, int flags)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define DATASTORE_BUCKETS
struct ao2_container * datastores
Publisher datastores set up by handlers.
static void sip_outbound_publish_client_destroy(void *obj)
Destructor function for publish client.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_sip_outbound_publish * publish
Outbound publish information.
struct ao2_container * publishers
Container of all the client publishing objects.

◆ sip_outbound_publish_state_destroy()

static void sip_outbound_publish_state_destroy ( void *  obj)
static

Destructor function for publish state.

Definition at line 1204 of file res_pjsip_outbound_publish.c.

References ao2_callback, ao2_cleanup, cancel_and_unpublish(), ast_sip_outbound_publish_state::client, NULL, OBJ_NODATA, OBJ_UNLINK, ast_sip_outbound_publish_client::publishers, ast_sip_outbound_publish_client::started, and stop_publishing().

Referenced by sip_outbound_publish_state_alloc().

1205 {
1206  struct ast_sip_outbound_publish_state *state = obj;
1207 
1208  stop_publishing(state->client, NULL);
1209  /*
1210  * Since the state is being destroyed the associated client needs to also
1211  * be destroyed. However simply removing the reference to the client will
1212  * not initiate client destruction since the client's publisher(s) hold a
1213  * reference to the client object as well. So we need to unpublish the
1214  * the client's publishers here, which will remove the publisher's client
1215  * reference during that process.
1216  *
1217  * That being said we don't want to remove the client's reference to the
1218  * publish object just yet. We'll hold off on that until client destruction
1219  * itself. This is because the publishers need access to the client's
1220  * publish object while they are unpublishing.
1221  */
1223  ao2_cleanup(state->client->publishers);
1224 
1225  state->client->started = 0;
1226  ao2_cleanup(state->client);
1227 }
unsigned int started
Publishing has been fully started and event type informed.
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static void stop_publishing(struct ast_sip_outbound_publish_client *client, struct ast_sip_event_publisher_handler *handler)
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#define NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
static int cancel_and_unpublish(void *obj, void *arg, int flags)
Helper function which cancels and un-publishes a no longer used client.
struct ao2_container * publishers
Container of all the client publishing objects.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ sip_outbound_publish_synchronize()

static void sip_outbound_publish_synchronize ( struct ast_sip_event_publisher_handler removed)
static

Helper function which starts or stops publish clients when applicable.

Definition at line 470 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_callback, ao2_cleanup, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_debug, ast_log, ast_sorcery_object_get_id(), cancel_and_unpublish(), ast_sip_outbound_publish_state::client, ast_sip_outbound_publish::event, ast_sip_event_publisher_handler::event_name, find_publisher_handler_for_event_name(), get_publishes_and_update_state(), handler(), LOG_ERROR, NULL, OBJ_NODATA, ast_sip_outbound_publish_client::publish, publish, ast_sip_outbound_publish_client::publishers, RAII_VAR, ast_sip_event_publisher_handler::start_publishing, ast_sip_outbound_publish_client::started, state, and stop_publishing().

Referenced by ast_sip_register_event_publisher_handler(), ast_sip_unregister_event_publisher_handler(), load_module(), and reload_module().

471 {
473  struct ao2_container *states;
474  struct ao2_iterator i;
476 
477  if (!publishes) {
478  return;
479  }
480 
481  states = ao2_global_obj_ref(current_states);
482  if (!states) {
483  return;
484  }
485 
486  i = ao2_iterator_init(states, 0);
487  while ((state = ao2_iterator_next(&i))) {
490 
491  if (!state->client->started) {
492  /* If the publisher client has not yet been started try to start it */
493  if (!handler) {
494  ast_debug(2, "Could not find handler for event '%s' for outbound publish client '%s'\n",
495  publish->event, ast_sorcery_object_get_id(publish));
496  } else if (handler->start_publishing(publish, state->client)) {
497  ast_log(LOG_ERROR, "Failed to start outbound publish with event '%s' for client '%s'\n",
498  publish->event, ast_sorcery_object_get_id(publish));
499  } else {
500  state->client->started = 1;
501  }
502  } else if (state->client->started && !handler && removed && !strcmp(publish->event, removed->event_name)) {
503  stop_publishing(state->client, removed);
505  state->client->started = 0;
506  }
507  ao2_ref(publish, -1);
508  ao2_ref(state, -1);
509  }
511  ao2_ref(states, -1);
512 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
unsigned int started
Publishing has been fully started and event type informed.
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
int(* start_publishing)(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
Called when a publisher should start publishing.
static void stop_publishing(struct ast_sip_outbound_publish_client *client, struct ast_sip_event_publisher_handler *handler)
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ast_sip_outbound_publish_client * client
Outbound publish client.
#define NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
unsigned char publish
Definition: res_corosync.c:241
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
Callbacks that event publisher handlers will define.
const char * event_name
The name of the event this handler deals with.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static struct ast_sip_event_publisher_handler * find_publisher_handler_for_event_name(const char *event_name)
static int cancel_and_unpublish(void *obj, void *arg, int flags)
Helper function which cancels and un-publishes a no longer used client.
#define LOG_ERROR
Definition: logger.h:285
Outbound publish information.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ast_sip_outbound_publish * publish
Outbound publish information.
static struct ao2_container * get_publishes_and_update_state(void)
const ast_string_field event
The event type to publish.
struct ao2_container * publishers
Container of all the client publishing objects.
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
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
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.

◆ sip_outbound_publish_timer_cb()

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

Publish client timer callback function.

Definition at line 401 of file res_pjsip_outbound_publish.c.

References ao2_lock, ao2_ref, ao2_unlock, AST_LIST_EMPTY, NULL, publisher_client_send(), and sip_outbound_publisher::queue.

Referenced by sip_outbound_publisher_alloc().

402 {
403  struct sip_outbound_publisher *publisher = entry->user_data;
404 
405  ao2_lock(publisher);
406  if (AST_LIST_EMPTY(&publisher->queue)) {
407  int res;
408  /* If there are no outstanding messages send an empty PUBLISH message so our publication doesn't expire */
409  publisher_client_send(publisher, NULL, &res, 0);
410  }
411  ao2_unlock(publisher);
412 
413  ao2_ref(publisher, -1);
414 }
static int publisher_client_send(void *obj, void *arg, void *data, int flags)
struct sip_outbound_publisher::@485 queue
Queue of outgoing publish messages to send.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
Definition: search.h:40

◆ sip_outbound_publisher_alloc()

static struct sip_outbound_publisher* sip_outbound_publisher_alloc ( struct ast_sip_outbound_publish_client client,
const char *  user 
)
static

Definition at line 1033 of file res_pjsip_outbound_publish.c.

References ao2_alloc, ao2_bump, ao2_ref, ast_log, ast_sip_create_serializer_group(), ast_sip_push_task_wait_servant(), ast_sorcery_object_get_id(), ast_taskprocessor_build_name(), AST_TASKPROCESSOR_MAX_NAME, LOG_ERROR, NULL, sip_outbound_publisher::owner, ast_sip_outbound_publish_client::publish, sip_outbound_publisher::serializer, sip_outbound_publish_timer_cb(), sip_outbound_publisher_destroy(), sip_outbound_publisher_init(), sip_outbound_publisher::timer, and sip_outbound_publisher::user.

Referenced by sip_outbound_publish_client_add_publisher().

1035 {
1036  struct sip_outbound_publisher *publisher;
1037  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1038 
1039  publisher = ao2_alloc(sizeof(*publisher) + (user ? strlen(user) : 0) + 1,
1041  if (!publisher) {
1042  return NULL;
1043  }
1044 
1045  /*
1046  * Bump the ref to the client. This essentially creates a circular reference,
1047  * but it is needed in order to make sure the client object doesn't get pulled
1048  * out from under us when the publisher stops publishing.
1049  *
1050  * The circular reference is alleviated by calling cancel_and_unpublish for
1051  * each client, from the state's destructor. By calling it there all references
1052  * to the publishers should go to zero, thus calling the publisher's destructor.
1053  * This in turn removes the client reference we added here. The state then removes
1054  * its reference to the client, which should take it to zero.
1055  */
1056  publisher->owner = ao2_bump(client);
1057  publisher->timer.user_data = publisher;
1058  publisher->timer.cb = sip_outbound_publish_timer_cb;
1059  if (user) {
1060  strcpy(publisher->user, user);
1061  } else {
1062  *publisher->user = '\0';
1063  }
1064 
1065  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outpub/%s",
1067 
1068  publisher->serializer = ast_sip_create_serializer_group(tps_name,
1069  shutdown_group);
1070  if (!publisher->serializer) {
1071  ao2_ref(publisher, -1);
1072  return NULL;
1073  }
1074 
1076  ast_log(LOG_ERROR, "Unable to create publisher for outbound publish '%s'\n",
1078  ao2_ref(publisher, -1);
1079  return NULL;
1080  }
1081 
1082  return publisher;
1083 }
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
char user[0]
User, if any, associated with the publisher.
#define NULL
Definition: resample.c:96
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:60
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
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
#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 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
pj_timer_entry timer
Timer entry for refreshing publish.
struct ast_taskprocessor * serializer
Serializer for stuff and things.
static void sip_outbound_publish_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
Publish client timer callback function.
static struct ast_serializer_shutdown_group * shutdown_group
static int sip_outbound_publisher_init(void *data)
Helper function that allocates a pjsip publish client and configures it.
#define LOG_ERROR
Definition: logger.h:285
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_sip_outbound_publish * publish
Outbound publish information.
structure to hold users read from users.conf
static void sip_outbound_publisher_destroy(void *obj)
Destructor function for publish client.

◆ sip_outbound_publisher_destroy()

static void sip_outbound_publisher_destroy ( void *  obj)
static

Destructor function for publish client.

Definition at line 1015 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ast_free, AST_LIST_REMOVE_HEAD, ast_taskprocessor_unreference(), sip_outbound_publisher::from_uri, sip_outbound_publisher::owner, sip_outbound_publisher::queue, sip_outbound_publisher::serializer, and sip_outbound_publisher::to_uri.

Referenced by sip_outbound_publisher_alloc().

1016 {
1017  struct sip_outbound_publisher *publisher = obj;
1019 
1020  /* You might be tempted to think "the publish client isn't being destroyed" but it actually is - just elsewhere */
1021 
1022  while ((message = AST_LIST_REMOVE_HEAD(&publisher->queue, entry))) {
1023  ast_free(message);
1024  }
1025 
1026  ao2_cleanup(publisher->owner);
1027  ast_free(publisher->from_uri);
1028  ast_free(publisher->to_uri);
1029 
1031 }
struct sip_outbound_publisher::@485 queue
Queue of outgoing publish messages to send.
char * to_uri
The To URI for this specific publisher.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct ast_taskprocessor * serializer
Serializer for stuff and things.
char * from_uri
The From URI for this specific publisher.
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
Queued outbound publish message.
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
Definition: search.h:40

◆ sip_outbound_publisher_init()

static int sip_outbound_publisher_init ( void *  data)
static

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

Definition at line 935 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_cleanup, ao2_ref, ast_log, ast_sip_get_pjsip_endpoint(), ast_sorcery_object_get_id(), ast_strlen_zero, sip_outbound_publisher::client, sip_outbound_publisher::from_uri, LOG_ERROR, NULL, sip_outbound_publisher::owner, pjsip_max_url_size, pool, ast_sip_outbound_publish_client::publish, publish, RAII_VAR, server_uri, sip_outbound_publish_callback(), sip_outbound_publisher_set_uris(), and sip_outbound_publisher::to_uri.

Referenced by sip_outbound_publish_callback(), sip_outbound_publisher_alloc(), and sip_outbound_publisher_reinit().

936 {
937  struct sip_outbound_publisher *publisher = data;
939  pjsip_publishc_opt opt = {
940  .queue_request = PJ_FALSE,
941  };
942  pj_pool_t *pool;
943  pj_str_t event, server_uri, to_uri, from_uri;
944 
945  if (publisher->client) {
946  return 0;
947  }
948 
949  if (pjsip_publishc_create(ast_sip_get_pjsip_endpoint(), &opt,
951  &publisher->client) != PJ_SUCCESS) {
952  ao2_ref(publisher, -1);
953  return -1;
954  }
955 
956  publish = ao2_bump(publisher->owner->publish);
957 
958  if (!ast_strlen_zero(publish->outbound_proxy)) {
959  pjsip_route_hdr route_set, *route;
960  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
961 
962  pj_list_init(&route_set);
963 
964  if (!(route = pjsip_parse_hdr(pjsip_publishc_get_pool(publisher->client), &ROUTE_HNAME,
965  (char*)publish->outbound_proxy, strlen(publish->outbound_proxy), NULL))) {
966  pjsip_publishc_destroy(publisher->client);
967  return -1;
968  }
969  pj_list_insert_nodes_before(&route_set, route);
970 
971  pjsip_publishc_set_route_set(publisher->client, &route_set);
972  }
973 
974  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation",
976  if (!pool) {
977  ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound publish '%s'\n",
979  pjsip_publishc_destroy(publisher->client);
980  return -1;
981  }
982 
983  if (sip_outbound_publisher_set_uris(pool, publisher, &server_uri, &from_uri, &to_uri)) {
984  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
985  pjsip_publishc_destroy(publisher->client);
986  return -1;
987  }
988 
989  pj_cstr(&event, publish->event);
990  if (pjsip_publishc_init(publisher->client, &event, &server_uri, &from_uri, &to_uri,
991  publish->expiration) != PJ_SUCCESS) {
992  ast_log(LOG_ERROR, "Failed to initialize publishing client on outbound publish '%s'\n",
994  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
995  pjsip_publishc_destroy(publisher->client);
996  return -1;
997  }
998 
999  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1000  return 0;
1001 }
static int sip_outbound_publisher_set_uris(pj_pool_t *pool, struct sip_outbound_publisher *publisher, pj_str_t *server_uri, pj_str_t *to_uri, pj_str_t *from_uri)
static pj_pool_t * pool
Global memory pool for configuration and timers.
Definition: astman.c:222
#define NULL
Definition: resample.c:96
char * to_uri
The To URI for this specific publisher.
unsigned char publish
Definition: res_corosync.c:241
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static int pjsip_max_url_size
char * from_uri
The From URI for this specific publisher.
#define LOG_ERROR
Definition: logger.h:285
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
pjsip_publishc * client
Underlying publish client.
Outbound publish information.
struct ast_sip_outbound_publish * publish
Outbound publish information.
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
static void sip_outbound_publish_callback(struct pjsip_publishc_cbparam *param)
Callback function for publish client responses.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ sip_outbound_publisher_reinit()

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

Definition at line 1003 of file res_pjsip_outbound_publish.c.

References sip_outbound_publisher_init().

Referenced by sip_outbound_publisher_reinit_all().

1004 {
1005  return sip_outbound_publisher_init(obj);
1006 }
static int sip_outbound_publisher_init(void *data)
Helper function that allocates a pjsip publish client and configures it.

◆ sip_outbound_publisher_reinit_all()

static int sip_outbound_publisher_reinit_all ( void *  data)
static

Definition at line 1008 of file res_pjsip_outbound_publish.c.

References ao2_callback, NULL, OBJ_NODATA, and sip_outbound_publisher_reinit().

Referenced by current_state_reusable().

1009 {
1011  return 0;
1012 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
static int sip_outbound_publisher_reinit(void *obj, void *arg, int flags)

◆ sip_outbound_publisher_set_uri()

static int sip_outbound_publisher_set_uri ( pj_pool_t *  pool,
const char *  uri,
const char *  user,
pj_str_t *  res_uri 
)
static

Definition at line 853 of file res_pjsip_outbound_publish.c.

References ast_strlen_zero, pjsip_max_url_size, and tmp().

Referenced by sip_outbound_publisher_set_uris().

855 {
856  pj_str_t tmp;
857  pjsip_uri *parsed;
858  pjsip_sip_uri *parsed_uri;
859  int size;
860 
861  pj_strdup2_with_null(pool, &tmp, uri);
862  if (!(parsed = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0))) {
863  return -1;
864  }
865 
866  if (!(parsed_uri = pjsip_uri_get_uri(parsed))) {
867  return -1;
868  }
869 
870  if (!ast_strlen_zero(user)) {
871  pj_strdup2(pool, &parsed_uri->user, user);
872  }
873 
874  res_uri->ptr = (char*) pj_pool_alloc(pool, pjsip_max_url_size);
875  if (!res_uri->ptr) {
876  return -1;
877  }
878 
879  if ((size = pjsip_uri_print(PJSIP_URI_IN_OTHER, parsed_uri, res_uri->ptr,
880  pjsip_max_url_size - 1)) <= 0) {
881  return -1;
882  }
883  res_uri->ptr[size] = '\0';
884  res_uri->slen = size;
885 
886  return 0;
887 }
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
static int pjsip_max_url_size
structure to hold users read from users.conf

◆ sip_outbound_publisher_set_uris()

static int sip_outbound_publisher_set_uris ( pj_pool_t *  pool,
struct sip_outbound_publisher publisher,
pj_str_t *  server_uri,
pj_str_t *  to_uri,
pj_str_t *  from_uri 
)
static

Definition at line 889 of file res_pjsip_outbound_publish.c.

References ast_log, ast_sorcery_object_get_id(), ast_strdup, ast_strlen_zero, ast_sip_outbound_publish::from_uri, sip_outbound_publisher::from_uri, LOG_ERROR, sip_outbound_publisher::owner, ast_sip_outbound_publish_client::publish, publish, ast_sip_outbound_publish::server_uri, sip_outbound_publish_callback(), sip_outbound_publisher_set_uri(), ast_sip_outbound_publish::to_uri, sip_outbound_publisher::to_uri, and sip_outbound_publisher::user.

Referenced by sip_outbound_publisher_init().

892 {
893  struct ast_sip_outbound_publish *publish = publisher->owner->publish;
894 
895  if (sip_outbound_publisher_set_uri(pool, publish->server_uri, publisher->user, server_uri)) {
896  ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound publish '%s'\n",
897  publish->server_uri, ast_sorcery_object_get_id(publish));
898  return -1;
899  }
900 
901  if (ast_strlen_zero(publish->to_uri)) {
902  to_uri->ptr = server_uri->ptr;
903  to_uri->slen = server_uri->slen;
904  } else if (sip_outbound_publisher_set_uri(pool, publish->to_uri, publisher->user, to_uri)) {
905  ast_log(LOG_ERROR, "Invalid to URI '%s' specified on outbound publish '%s'\n",
906  publish->to_uri, ast_sorcery_object_get_id(publish));
907  return -1;
908  }
909 
910  publisher->to_uri = ast_strdup(to_uri->ptr);
911  if (!publisher->to_uri) {
912  return -1;
913  }
914 
915  if (ast_strlen_zero(publish->from_uri)) {
916  from_uri->ptr = server_uri->ptr;
917  from_uri->slen = server_uri->slen;
918  } else if (sip_outbound_publisher_set_uri(pool, publish->from_uri, publisher->user, from_uri)) {
919  ast_log(LOG_ERROR, "Invalid from URI '%s' specified on outbound publish '%s'\n",
920  publish->from_uri, ast_sorcery_object_get_id(publish));
921  return -1;
922  }
923 
924  publisher->from_uri = ast_strdup(from_uri->ptr);
925  if (!publisher->from_uri) {
926  return -1;
927  }
928 
929  return 0;
930 }
static pj_pool_t * pool
Global memory pool for configuration and timers.
char user[0]
User, if any, associated with the publisher.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int sip_outbound_publisher_set_uri(pj_pool_t *pool, const char *uri, const char *user, pj_str_t *res_uri)
char * to_uri
The To URI for this specific publisher.
unsigned char publish
Definition: res_corosync.c:241
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
char * from_uri
The From URI for this specific publisher.
#define LOG_ERROR
Definition: logger.h:285
struct ast_sip_outbound_publish_client * owner
The client object that &#39;owns&#39; this client.
Outbound publish information.
const ast_string_field server_uri
URI for the entity and server.
struct ast_sip_outbound_publish * publish
Outbound publish information.
static char server_uri[512]
const ast_string_field from_uri
URI for the From header.
const ast_string_field to_uri
URI for the To header.

◆ sip_publish_state_get()

static struct ast_sip_outbound_publish_state* sip_publish_state_get ( const char *  id)
static

Definition at line 514 of file res_pjsip_outbound_publish.c.

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

Referenced by ast_sip_publish_client_get(), and sip_outbound_publish_apply().

515 {
516  struct ao2_container *states = ao2_global_obj_ref(current_states);
517  struct ast_sip_outbound_publish_state *res;
518 
519  if (!states) {
520  return NULL;
521  }
522 
523  res = ao2_find(states, id, OBJ_SEARCH_KEY);
524  ao2_ref(states, -1);
525  return res;
526 }
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 NULL
Definition: resample.c:96
Outbound publish state information (persists for lifetime of a publish)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Generic container type.

◆ sip_publisher_service_queue()

static int sip_publisher_service_queue ( void *  data)
static

Definition at line 749 of file res_pjsip_outbound_publish.c.

References ao2_bump, ao2_cleanup, ao2_ref, ast_free, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, ast_sip_add_body(), ast_sip_push_task(), ast_strlen_zero, sip_outbound_publish_message::body, lock, RAII_VAR, SCOPED_AO2LOCK, service, set_transport(), status, ast_sip_body::subtype, and ast_sip_body::type.

Referenced by publisher_client_send(), and sip_outbound_publish_callback().

750 {
751  RAII_VAR(struct sip_outbound_publisher *, publisher, data, ao2_cleanup);
752  SCOPED_AO2LOCK(lock, publisher);
754  pjsip_tx_data *tdata;
755  pj_status_t status;
756 
757  if (publisher->destroy || publisher->sending || !(message = AST_LIST_FIRST(&publisher->queue))) {
758  return 0;
759  }
760 
761  if (pjsip_publishc_publish(publisher->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
762  goto fatal;
763  }
764 
765  if (!ast_strlen_zero(message->body.type) && !ast_strlen_zero(message->body.subtype) &&
766  ast_sip_add_body(tdata, &message->body)) {
767  pjsip_tx_data_dec_ref(tdata);
768  goto fatal;
769  }
770 
771  set_transport(publisher, tdata);
772 
773  status = pjsip_publishc_send(publisher->client, tdata);
774  if (status == PJ_EBUSY) {
775  /* We attempted to send the message but something else got there first */
776  goto service;
777  } else if (status != PJ_SUCCESS) {
778  goto fatal;
779  }
780 
781  publisher->sending = message;
782 
783  return 0;
784 
785 fatal:
786  AST_LIST_REMOVE_HEAD(&publisher->queue, entry);
787  ast_free(message);
788 
789 service:
790  if (ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher))) {
791  ao2_ref(publisher, -1);
792  }
793  return -1;
794 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
enum ast_cc_service_type service
Definition: chan_sip.c:949
struct ast_sip_body body
Optional body.
static int sip_publisher_service_queue(void *data)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
Definition: res_pjsip.c:5091
#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 * type
Definition: res_pjsip.h:2029
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
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
const char * subtype
Definition: res_pjsip.h:2031
Queued outbound publish message.
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Definition: search.h:40
static void set_transport(struct sip_outbound_publisher *publisher, pjsip_tx_data *tdata)
jack_status_t status
Definition: app_jack.c:146

◆ stop_publishing()

static void stop_publishing ( struct ast_sip_outbound_publish_client client,
struct ast_sip_event_publisher_handler handler 
)
static

Definition at line 455 of file res_pjsip_outbound_publish.c.

References cancel_and_unpublish(), ast_sip_outbound_publish::event, find_publisher_handler_for_event_name(), ast_sip_outbound_publish_client::publish, and ast_sip_event_publisher_handler::stop_publishing.

Referenced by sip_outbound_publish_state_destroy(), and sip_outbound_publish_synchronize().

457 {
458  if (!handler) {
460  }
461 
462  if (handler) {
463  handler->stop_publishing(client);
464  }
465 }
int(* stop_publishing)(struct ast_sip_outbound_publish_client *client)
Called when a publisher should stop publishing.
static struct ast_sip_event_publisher_handler * find_publisher_handler_for_event_name(const char *event_name)
struct ast_sip_outbound_publish * publish
Outbound publish information.
const ast_string_field event
The event type to publish.

◆ sub_add_handler()

static void sub_add_handler ( struct ast_sip_event_publisher_handler handler)
static

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1622 of file res_pjsip_outbound_publish.c.

References ao2_cleanup, ao2_global_obj_release, ast_debug, ast_log, ast_serializer_shutdown_group_join(), ast_sip_get_sorcery(), ast_sorcery_object_unregister(), LOG_WARNING, MAX_UNLOAD_TIMEOUT_TIME, and NULL.

Referenced by load_module(), and reload_module().

1623 {
1624  int remaining;
1625 
1626  ast_sorcery_object_unregister(ast_sip_get_sorcery(), "outbound-publish");
1627 
1628  ao2_global_obj_release(current_states);
1629 
1630  /* Wait for publication serializers to get destroyed. */
1631  ast_debug(2, "Waiting for publication to complete for unload.\n");
1633  if (remaining) {
1634  ast_log(LOG_WARNING, "Unload incomplete. Could not stop %d outbound publications. Try again later.\n",
1635  remaining);
1636  return -1;
1637  }
1638 
1639  ast_debug(2, "Successful shutdown.\n");
1640 
1642  shutdown_group = NULL;
1643 
1644  return 0;
1645 }
#define LOG_WARNING
Definition: logger.h:274
#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
#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
static struct ast_serializer_shutdown_group * shutdown_group
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define MAX_UNLOAD_TIMEOUT_TIME

◆ validate_publish_config()

static int validate_publish_config ( struct ast_sip_outbound_publish publish)
static

Definition at line 1461 of file res_pjsip_outbound_publish.c.

References ast_log, ast_sip_validate_uri_length(), ast_sorcery_object_get_id(), ast_strlen_zero, ast_sip_outbound_publish::event, ast_sip_outbound_publish::from_uri, LOG_ERROR, ast_sip_outbound_publish::server_uri, and ast_sip_outbound_publish::to_uri.

Referenced by sip_outbound_publish_apply().

1462 {
1463  if (ast_strlen_zero(publish->server_uri)) {
1464  ast_log(LOG_ERROR, "No server URI specified on outbound publish '%s'\n",
1465  ast_sorcery_object_get_id(publish));
1466  return -1;
1467  } else if (ast_sip_validate_uri_length(publish->server_uri)) {
1468  ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1469  publish->server_uri,
1470  ast_sorcery_object_get_id(publish));
1471  return -1;
1472  } else if (ast_strlen_zero(publish->event)) {
1473  ast_log(LOG_ERROR, "No event type specified for outbound publish '%s'\n",
1474  ast_sorcery_object_get_id(publish));
1475  return -1;
1476  } else if (!ast_strlen_zero(publish->from_uri)
1477  && ast_sip_validate_uri_length(publish->from_uri)) {
1478  ast_log(LOG_ERROR, "From URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1479  publish->from_uri,
1480  ast_sorcery_object_get_id(publish));
1481  return -1;
1482  } else if (!ast_strlen_zero(publish->to_uri)
1483  && ast_sip_validate_uri_length(publish->to_uri)) {
1484  ast_log(LOG_ERROR, "To URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1485  publish->to_uri,
1486  ast_sorcery_object_get_id(publish));
1487  return -1;
1488  }
1489  return 0;
1490 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field server_uri
URI for the entity and server.
const ast_string_field event
The event type to publish.
int ast_sip_validate_uri_length(const char *uri)
Definition: location.c:525
const ast_string_field from_uri
URI for the From header.
const ast_string_field to_uri
URI for the To header.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Outbound Publish 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_CHANNEL_DEPEND, .requires = "res_pjproject,res_pjsip", }
static

Definition at line 1707 of file res_pjsip_outbound_publish.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1707 of file res_pjsip_outbound_publish.c.

◆ load_lock

ast_rwlock_t load_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
static

Used for locking while loading/reloading.

Mutli-user configurations make it so publishers can be dynamically added and removed. Publishers should not be added or removed during a [re]load since it could cause the current_clients container to be out of sync. Thus the reason for this lock.

Definition at line 255 of file res_pjsip_outbound_publish.c.

Referenced by ast_sip_publish_client_remove(), get_publishes_and_update_state(), and sip_outbound_publish_client_get_publisher().

◆ new_states

struct ao2_container* new_states
static

Used on [re]loads to hold new state data.

Definition at line 271 of file res_pjsip_outbound_publish.c.

Referenced by load_module().

◆ pjsip_max_url_size

int pjsip_max_url_size = PJSIP_MAX_URL_SIZE
static

◆ publisher_handlers

struct publisher_handlers publisher_handlers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ shutdown_group

struct ast_serializer_shutdown_group* shutdown_group
static

Shutdown group to monitor sip_outbound_registration_client_state serializers.

Definition at line 265 of file res_pjsip_outbound_publish.c.