Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_pjsip_mwi.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjlib.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_pubsub.h"
#include "asterisk/res_pjsip_body_generator_types.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/astobj2.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/serializer.h"
#include "asterisk/sorcery.h"
#include "asterisk/stasis.h"
#include "asterisk/mwi.h"
Include dependency graph for res_pjsip_mwi.c:

Go to the source code of this file.

Data Structures

struct  mwi_stasis_subscription
 Wrapper for stasis subscription. More...
 
struct  mwi_subscription
 A subscription for MWI. More...
 
struct  unsolicited_mwi_data
 

Macros

#define MAX_UNLOAD_TIMEOUT_TIME   10 /* Seconds */
 
#define MWI_BUCKETS   53
 
#define MWI_DATASTORE   "MWI datastore"
 
#define MWI_SERIALIZER_POOL_SIZE   8
 
#define MWI_SUBTYPE   "simple-message-summary"
 
#define MWI_TYPE   "application"
 
#define STASIS_BUCKETS   13
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_mwi_datastore (struct mwi_subscription *sub)
 
static int allow_and_or_replace_unsolicited (struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi)
 
 AO2_GLOBAL_OBJ_STATIC (mwi_unsolicited)
 
 AO2_GLOBAL_OBJ_STATIC (mwi_solicited)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void create_mwi_subscriptions (void)
 
static int create_mwi_subscriptions_for_endpoint (void *obj, void *arg, void *data, int flags)
 
static int create_unsolicited_mwi_subscriptions (struct ast_sip_endpoint *endpoint, int recreate, int send_now, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
 
static struct ast_sip_aorfind_aor_for_resource (struct ast_sip_endpoint *endpoint, const char *resource)
 
static int get_message_count (void *obj, void *arg, int flags)
 
static void global_loaded (const char *object_type)
 
static int has_mwi_subscription (struct ao2_container *container, struct ast_sip_endpoint *endpoint, const char *mailbox, struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
 
static int is_unsolicited_allowed (struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
 
static int load_module (void)
 
static void mwi_contact_added (const void *object)
 Function called when a contact is added. More...
 
static void mwi_contact_changed (const struct ast_sip_contact *contact)
 Create mwi subscriptions and notify. More...
 
static void mwi_contact_deleted (const void *object)
 Function called when a contact is deleted. More...
 
static void mwi_contact_updated (const void *object)
 Function called when a contact is updated. More...
 
static struct mwi_subscriptionmwi_create_subscription (struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
 
static void mwi_ds_destroy (void *data)
 
static void * mwi_get_notify_data (struct ast_sip_subscription *sub)
 
static int mwi_new_subscribe (struct ast_sip_endpoint *endpoint, const char *resource)
 
static int mwi_on_aor (void *obj, void *arg, int flags)
 
static void mwi_startup_event_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Event callback which fires initial unsolicited MWI NOTIFY messages when we're fully booted. More...
 
static void mwi_stasis_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static struct mwi_stasis_subscriptionmwi_stasis_subscription_alloc (const char *mailbox, struct mwi_subscription *mwi_sub)
 
static int mwi_sub_cmp (void *obj, void *arg, int flags)
 
static int mwi_sub_hash (const void *obj, const int flags)
 
static struct mwi_subscriptionmwi_subscribe_all (struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
 
static struct mwi_subscriptionmwi_subscribe_single (struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
 
static struct mwi_subscriptionmwi_subscription_alloc (struct ast_sip_endpoint *endpoint, unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
 
static void mwi_subscription_destructor (void *obj)
 
static int mwi_subscription_established (struct ast_sip_subscription *sub)
 
static void mwi_subscription_mailboxes_str (struct ao2_container *stasis_subs, struct ast_str **str)
 
static void mwi_subscription_shutdown (struct ast_sip_subscription *sub)
 
static void mwi_to_ami (struct ast_sip_subscription *sub, struct ast_str **buf)
 
static int mwi_validate_for_aor (void *obj, void *arg, int flags)
 Determine if an endpoint is a candidate to be able to subscribe for MWI. More...
 
static int reload (void)
 
static int send_contact_notify (void *obj, void *arg, int flags)
 Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR. More...
 
static int send_initial_notify_all (void *obj)
 Task invoked to send initial MWI NOTIFY for unsolicited. More...
 
static void send_mwi_notify (struct mwi_subscription *sub)
 
static int send_notify (void *obj, void *arg, int flags)
 
static void send_unsolicited_mwi_notify (struct mwi_subscription *sub, struct ast_sip_message_accumulator *counter)
 
static int send_unsolicited_mwi_notify_to_contact (void *obj, void *arg, int flags)
 
static int serialized_cleanup (void *userdata)
 
static int serialized_notify (void *userdata)
 
static void set_voicemail_extension (pj_pool_t *pool, pjsip_sip_uri *local_uri, struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
 
static int stasis_sub_cmp (void *obj, void *arg, int flags)
 
static int stasis_sub_hash (const void *obj, const int flags)
 
static int unload_module (void)
 
static int unsubscribe (void *obj, void *arg, int flags)
 
static int unsubscribe_stasis (void *obj, void *arg, int flags)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP MWI resource" , .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, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5, .requires = "res_pjsip,res_pjsip_pubsub", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static char * default_voicemail_extension
 
static struct ast_sorcery_observer global_observer
 
static const struct ast_sorcery_observer mwi_contact_observer
 Observer for contacts so unsolicited MWI is sent when a contact changes. More...
 
static struct ast_datastore_info mwi_ds_info
 
static struct ast_sip_subscription_handler mwi_handler
 
static struct ast_sip_notifier mwi_notifier
 
static struct ast_serializer_poolmwi_serializer_pool
 

Macro Definition Documentation

◆ MAX_UNLOAD_TIMEOUT_TIME

#define MAX_UNLOAD_TIMEOUT_TIME   10 /* Seconds */

Max timeout for all threads to join during an unload.

Definition at line 63 of file res_pjsip_mwi.c.

Referenced by load_module().

◆ MWI_BUCKETS

#define MWI_BUCKETS   53

Definition at line 52 of file res_pjsip_mwi.c.

Referenced by load_module().

◆ MWI_DATASTORE

#define MWI_DATASTORE   "MWI datastore"

◆ MWI_SERIALIZER_POOL_SIZE

#define MWI_SERIALIZER_POOL_SIZE   8

Number of serializers in pool if one not supplied.

Definition at line 60 of file res_pjsip_mwi.c.

Referenced by load_module().

◆ MWI_SUBTYPE

#define MWI_SUBTYPE   "simple-message-summary"

Definition at line 55 of file res_pjsip_mwi.c.

Referenced by send_unsolicited_mwi_notify_to_contact().

◆ MWI_TYPE

#define MWI_TYPE   "application"

Definition at line 54 of file res_pjsip_mwi.c.

Referenced by send_unsolicited_mwi_notify_to_contact().

◆ STASIS_BUCKETS

#define STASIS_BUCKETS   13

Definition at line 51 of file res_pjsip_mwi.c.

Referenced by mwi_subscription_alloc().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1622 of file res_pjsip_mwi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1622 of file res_pjsip_mwi.c.

◆ add_mwi_datastore()

static int add_mwi_datastore ( struct mwi_subscription sub)
static

Definition at line 640 of file res_pjsip_mwi.c.

References ao2_ref, ast_sip_subscription_add_datastore(), ast_sip_subscription_alloc_datastore(), ast_datastore::data, MWI_DATASTORE, mwi_subscription::sip_sub, and sub.

Referenced by mwi_create_subscription().

641 {
642  struct ast_datastore *mwi_datastore;
643  int res;
644 
646  if (!mwi_datastore) {
647  return -1;
648  }
649  ao2_ref(sub, +1);
650  mwi_datastore->data = sub;
651 
652  /*
653  * NOTE: Adding the datastore to the subscription creates a ref loop
654  * that must be manually broken.
655  */
656  res = ast_sip_subscription_add_datastore(sub->sip_sub, mwi_datastore);
657  ao2_ref(mwi_datastore, -1);
658  return res;
659 }
Structure for a data store object.
Definition: datastore.h:68
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
struct ast_sip_subscription * sip_sub
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_datastore_info mwi_ds_info
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
void * data
Definition: datastore.h:70
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ allow_and_or_replace_unsolicited()

static int allow_and_or_replace_unsolicited ( struct ast_sip_endpoint endpoint,
const char *  mailbox,
struct ao2_container unsolicited_mwi 
)
static

Definition at line 729 of file res_pjsip_mwi.c.

References ast_sip_mwi_configuration::aggregate, ao2_ref, ao2_unlink, ast_debug, ast_sorcery_object_get_id(), has_mwi_subscription(), ast_sip_endpoint_subscription_configuration::mwi, mwi_sub, NULL, send_notify(), mwi_subscription::stasis_subs, ast_sip_mwi_configuration::subscribe_replaces_unsolicited, ast_sip_endpoint::subscription, and unsubscribe_stasis().

Referenced by mwi_validate_for_aor().

731 {
732  struct mwi_subscription *mwi_sub;
733  struct mwi_stasis_subscription *mwi_stasis;
734 
735  if (!has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
736  /* If no unsolicited subscription then allow the solicited one */
737  return 1;
738  }
739 
741  /* Has unsolicited subscription and can't replace, so disallow */
742  ao2_ref(mwi_stasis, -1);
743  ao2_ref(mwi_sub, -1);
744  return 0;
745  }
746 
747  /*
748  * The unsolicited subscription exists, and it is allowed to be replaced.
749  * So, first remove the unsolicited stasis subscription, and if aggregation
750  * is not enabled then also remove the mwi_subscription object as well.
751  */
752  ast_debug(1, "Unsolicited subscription being replaced by solicited for "
753  "endpoint '%s' mailbox '%s'\n", ast_sorcery_object_get_id(endpoint), mailbox);
754 
755  unsubscribe_stasis(mwi_stasis, NULL, 0);
756  ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
757 
758  if (!endpoint->subscription.mwi.aggregate) {
759  ao2_unlink(unsolicited_mwi, mwi_sub);
760  }
761 
762  ao2_ref(mwi_stasis, -1);
763  ao2_ref(mwi_sub, -1);
764 
765  /* This solicited subscription is replacing an unsolicited one, so allow */
766  return 1;
767 }
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
static int unsubscribe_stasis(void *obj, void *arg, int flags)
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
#define NULL
Definition: resample.c:96
struct ao2_container * stasis_subs
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int has_mwi_subscription(struct ao2_container *container, struct ast_sip_endpoint *endpoint, const char *mailbox, struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
unsigned int subscribe_replaces_unsolicited
Definition: res_pjsip.h:594
#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
unsigned int aggregate
Definition: res_pjsip.h:592
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
A subscription for MWI.
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
static struct stasis_subscription * mwi_sub

◆ AO2_GLOBAL_OBJ_STATIC() [1/2]

AO2_GLOBAL_OBJ_STATIC ( mwi_unsolicited  )

◆ AO2_GLOBAL_OBJ_STATIC() [2/2]

AO2_GLOBAL_OBJ_STATIC ( mwi_solicited  )

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1622 of file res_pjsip_mwi.c.

◆ create_mwi_subscriptions()

static void create_mwi_subscriptions ( void  )
static

Definition at line 1301 of file res_pjsip_mwi.c.

References ao2_callback, ao2_callback_data, ao2_cleanup, ao2_global_obj_ref, ao2_lock, ao2_ref, ao2_unlock, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), ast_variable_new, ast_variables_destroy(), create_mwi_subscriptions_for_endpoint(), endpoints, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, OBJ_UNLINK, unsubscribe(), and var.

Referenced by load_module(), and reload().

1302 {
1303  struct ao2_container *unsolicited_mwi;
1304  struct ao2_container *solicited_mwi;
1305  struct ao2_container *endpoints;
1306  struct ast_variable *var;
1307 
1308  unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
1309  if (!unsolicited_mwi) {
1310  return;
1311  }
1312 
1313  var = ast_variable_new("mailboxes !=", "", "");
1314 
1315  endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint",
1317 
1318  ast_variables_destroy(var);
1319  if (!endpoints) {
1320  ao2_ref(unsolicited_mwi, -1);
1321  return;
1322  }
1323 
1324  solicited_mwi = ao2_global_obj_ref(mwi_solicited);
1325 
1326  /* We remove all the old stasis subscriptions first before applying the new configuration. This
1327  * prevents a situation where there might be multiple overlapping stasis subscriptions for an
1328  * endpoint for mailboxes. Though there may be mailbox changes during the gap between unsubscribing
1329  * and resubscribing, up-to-date mailbox state will be sent out to the endpoint when the
1330  * new stasis subscription is established
1331  */
1332  ao2_lock(unsolicited_mwi);
1334  ao2_callback_data(endpoints, OBJ_NODATA, create_mwi_subscriptions_for_endpoint, unsolicited_mwi, solicited_mwi);
1335  ao2_unlock(unsolicited_mwi);
1336 
1337  ao2_ref(endpoints, -1);
1338  ao2_cleanup(solicited_mwi);
1339  ao2_ref(unsolicited_mwi, -1);
1340 }
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
Return all matching objects.
Definition: sorcery.h:120
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_variable_new(name, value, filename)
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
static int unsubscribe(void *obj, void *arg, int flags)
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, void *data, int flags)
Generic container type.

◆ create_mwi_subscriptions_for_endpoint()

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

Definition at line 1287 of file res_pjsip_mwi.c.

References create_unsolicited_mwi_subscriptions().

Referenced by create_mwi_subscriptions().

1288 {
1289  return create_unsolicited_mwi_subscriptions(obj, 0, 0, arg, data);
1290 }
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint, int recreate, int send_now, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)

◆ create_unsolicited_mwi_subscriptions()

static int create_unsolicited_mwi_subscriptions ( struct ast_sip_endpoint endpoint,
int  recreate,
int  send_now,
struct ao2_container unsolicited_mwi,
struct ao2_container solicited_mwi 
)
static

Definition at line 1188 of file res_pjsip_mwi.c.

References ast_sip_mwi_configuration::aggregate, ao2_cleanup, ao2_container_count(), ao2_find, ao2_link, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_sorcery_object_get_id(), ast_strdupa, ast_strip(), ast_strlen_zero, is_unsolicited_allowed(), mwi_stasis_subscription::mailbox, mailboxes, ast_sip_mwi_configuration::mailboxes, ast_sip_endpoint_subscription_configuration::mwi, mwi_stasis_subscription_alloc(), mwi_subscription_alloc(), NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, RAII_VAR, send_notify(), mwi_subscription::stasis_subs, strsep(), sub, and ast_sip_endpoint::subscription.

Referenced by create_mwi_subscriptions_for_endpoint(), mwi_contact_changed(), mwi_subscription_shutdown(), and unsubscribe_stasis().

1190 {
1191  RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup);
1192  char *mailboxes;
1193  char *mailbox;
1194  int sub_added = 0;
1195 
1196  if (ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
1197  return 0;
1198  }
1199 
1200  if (endpoint->subscription.mwi.aggregate) {
1201  const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
1202 
1203  /* Check if aggregate subscription exists */
1204  aggregate_sub = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1205 
1206  /*
1207  * If enabled there should only ever exist a single aggregate subscription object
1208  * for an endpoint. So if it exists just return unless subscriptions are potentially
1209  * being added back in. If that's the case then continue.
1210  */
1211  if (aggregate_sub && !recreate) {
1212  return 0;
1213  }
1214 
1215  if (!aggregate_sub) {
1216  aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
1217  if (!aggregate_sub) {
1218  return 0; /* No MWI aggregation for you */
1219  }
1220 
1221  /*
1222  * Just in case we somehow get in the position of recreating with no previous
1223  * aggregate object, set recreate to false here in order to allow the new
1224  * object to be linked into the container below
1225  */
1226  recreate = 0;
1227  }
1228  }
1229 
1230  /* Lock solicited so we don't potentially add to both containers */
1231  if (solicited_mwi) {
1232  ao2_lock(solicited_mwi);
1233  }
1234 
1235  mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
1236  while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
1237  struct mwi_subscription *sub;
1238  struct mwi_stasis_subscription *mwi_stasis_sub;
1239 
1240  if (!is_unsolicited_allowed(endpoint, mailbox, unsolicited_mwi, solicited_mwi)) {
1241  continue;
1242  }
1243 
1244  sub = aggregate_sub ?: mwi_subscription_alloc(endpoint, 0, NULL);
1245  if (!sub) {
1246  continue;
1247  }
1248 
1249  mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
1250  if (mwi_stasis_sub) {
1251  ao2_link(sub->stasis_subs, mwi_stasis_sub);
1252  ao2_ref(mwi_stasis_sub, -1);
1253  }
1254  if (!aggregate_sub) {
1255  ao2_link_flags(unsolicited_mwi, sub, OBJ_NOLOCK);
1256  if (send_now) {
1257  send_notify(sub, NULL, 0);
1258  }
1259  ao2_ref(sub, -1);
1260  }
1261 
1262  if (aggregate_sub && !sub_added) {
1263  /* If aggregation track if at least one subscription has been added */
1264  sub_added = 1;
1265  }
1266  }
1267 
1268  if (aggregate_sub) {
1269  if (ao2_container_count(aggregate_sub->stasis_subs)) {
1270  /* Only link if we're dealing with a new aggregate object */
1271  if (!recreate) {
1272  ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
1273  }
1274  if (send_now && sub_added) {
1275  send_notify(aggregate_sub, NULL, 0);
1276  }
1277  }
1278  }
1279 
1280  if (solicited_mwi) {
1281  ao2_unlock(solicited_mwi);
1282  }
1283 
1284  return 0;
1285 }
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const ast_string_field mailboxes
Definition: res_pjsip.h:588
static struct mwi_stasis_subscription * mwi_stasis_subscription_alloc(const char *mailbox, struct mwi_subscription *mwi_sub)
struct ao2_container * stasis_subs
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#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
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
unsigned int aggregate
Definition: res_pjsip.h:592
static int send_notify(void *obj, void *arg, int flags)
A subscription for MWI.
static struct mwi_subscription * mwi_subscription_alloc(struct ast_sip_endpoint *endpoint, unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
char * strsep(char **str, const char *delims)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct stasis_forward * sub
Definition: res_corosync.c:240
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
static int is_unsolicited_allowed(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ find_aor_for_resource()

static struct ast_sip_aor* find_aor_for_resource ( struct ast_sip_endpoint endpoint,
const char *  resource 
)
static

Definition at line 450 of file res_pjsip_mwi.c.

References ao2_ref, ast_sip_endpoint::aors, ast_debug, ast_sip_location_retrieve_aor(), ast_strdupa, ast_strip(), ast_strlen_zero, NULL, strsep(), and ast_sip_aor::voicemail_extension.

Referenced by mwi_get_notify_data(), mwi_new_subscribe(), mwi_subscribe_single(), and send_mwi_notify().

451 {
452  struct ast_sip_aor *aor;
453  char *aor_name;
454  char *aors_copy;
455 
456  /* Direct match */
457  if ((aor = ast_sip_location_retrieve_aor(resource))) {
458  return aor;
459  }
460 
461  if (!endpoint) {
462  return NULL;
463  }
464 
465  /*
466  * This may be a subscribe to the voicemail_extension. If so,
467  * look for an aor belonging to this endpoint that has a matching
468  * voicemail_extension.
469  */
470  aors_copy = ast_strdupa(endpoint->aors);
471  while ((aor_name = ast_strip(strsep(&aors_copy, ",")))) {
472  struct ast_sip_aor *check_aor = ast_sip_location_retrieve_aor(aor_name);
473 
474  if (!check_aor) {
475  continue;
476  }
477 
478  if (!ast_strlen_zero(check_aor->voicemail_extension)
479  && !strcasecmp(check_aor->voicemail_extension, resource)) {
480  ast_debug(1, "Found an aor (%s) that matches voicemail_extension %s\n", aor_name, resource);
481  return check_aor;
482  }
483 
484  ao2_ref(check_aor, -1);
485  }
486 
487  return NULL;
488 }
A SIP address of record.
Definition: res_pjsip.h:361
#define NULL
Definition: resample.c:96
char * voicemail_extension
Definition: res_pjsip.h:389
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
char * strsep(char **str, const char *delims)
const ast_string_field aors
Definition: res_pjsip.h:821

◆ get_message_count()

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

Definition at line 326 of file res_pjsip_mwi.c.

References ao2_ref, ast_mwi_subscriber_data(), mwi_stasis_subscription::mwi_subscriber, ast_sip_message_accumulator::new_msgs, ast_mwi_state::new_msgs, ast_sip_message_accumulator::old_msgs, and ast_mwi_state::old_msgs.

Referenced by mwi_get_notify_data(), and send_mwi_notify().

327 {
328  struct mwi_stasis_subscription *mwi_stasis = obj;
329  struct ast_sip_message_accumulator *counter = arg;
330  struct ast_mwi_state *mwi_state;
331 
332  mwi_state = ast_mwi_subscriber_data(mwi_stasis->mwi_subscriber);
333  if (!mwi_state) {
334  return 0;
335  }
336 
337  counter->old_msgs += mwi_state->old_msgs;
338  counter->new_msgs += mwi_state->new_msgs;
339 
340  ao2_ref(mwi_state, -1);
341 
342  return 0;
343 }
struct ast_mwi_subscriber * mwi_subscriber
Definition: res_pjsip_mwi.c:99
Message counter used for message-summary XML bodies.
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
Definition: mwi.c:264
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int old_msgs
Definition: mwi.h:462
int new_msgs
Definition: mwi.h:461
The structure that contains MWI state.
Definition: mwi.h:457
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97

◆ global_loaded()

static void global_loaded ( const char *  object_type)
static

Definition at line 1505 of file res_pjsip_mwi.c.

References ast_free, ast_serializer_pool_set_alerts(), ast_sip_get_default_voicemail_extension(), ast_sip_get_mwi_tps_queue_high(), ast_sip_get_mwi_tps_queue_low(), and default_voicemail_extension.

1506 {
1511 }
unsigned int ast_sip_get_mwi_tps_queue_high(void)
Retrieve the global MWI taskprocessor high water alert trigger level.
int ast_sip_get_mwi_tps_queue_low(void)
Retrieve the global MWI taskprocessor low water clear alert level.
char * ast_sip_get_default_voicemail_extension(void)
Retrieve the default voicemail extension.
static char * default_voicemail_extension
Definition: res_pjsip_mwi.c:49
#define ast_free(a)
Definition: astmm.h:182
int ast_serializer_pool_set_alerts(struct ast_serializer_pool *pool, long high, long low)
Set taskprocessor alert levels for the serializers in the pool.
Definition: serializer.c:156
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ has_mwi_subscription()

static int has_mwi_subscription ( struct ao2_container container,
struct ast_sip_endpoint endpoint,
const char *  mailbox,
struct mwi_subscription **  mwi_sub,
struct mwi_stasis_subscription **  mwi_stasis 
)
static

Definition at line 682 of file res_pjsip_mwi.c.

References ao2_find, ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, ast_sorcery_object_get_id(), NULL, OBJ_MULTIPLE, OBJ_NOLOCK, and OBJ_SEARCH_KEY.

Referenced by allow_and_or_replace_unsolicited(), and is_unsolicited_allowed().

685 {
686  struct ao2_iterator *mwi_subs;
687 
688  *mwi_sub = NULL;
689  *mwi_stasis = NULL;
690 
691  if (!container) {
692  return 0;
693  }
694 
695  mwi_subs = ao2_find(container, ast_sorcery_object_get_id(endpoint),
697  if (!mwi_subs) {
698  return 0;
699  }
700 
701  while ((*mwi_sub = ao2_iterator_next(mwi_subs))) {
702  *mwi_stasis = ao2_find((*mwi_sub)->stasis_subs, mailbox, OBJ_SEARCH_KEY);
703  if (*mwi_stasis) {
704  /* If found then caller is responsible for unrefs of passed back objects */
705  break;
706  }
707  ao2_ref(*mwi_sub, -1);
708  }
709 
710  ao2_iterator_destroy(mwi_subs);
711  return *mwi_stasis ? 1 : 0;
712 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define NULL
Definition: resample.c:96
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#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 ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841

◆ is_unsolicited_allowed()

static int is_unsolicited_allowed ( struct ast_sip_endpoint endpoint,
const char *  mailbox,
struct ao2_container unsolicited_mwi,
struct ao2_container solicited_mwi 
)
static

Definition at line 783 of file res_pjsip_mwi.c.

References ao2_ref, ast_strlen_zero, has_mwi_subscription(), ast_sip_endpoint_subscription_configuration::mwi, mwi_sub, NULL, send_notify(), ast_sip_mwi_configuration::subscribe_replaces_unsolicited, ast_sip_endpoint::subscription, and mwi_subscription::terminate.

Referenced by create_unsolicited_mwi_subscriptions().

785 {
786  struct mwi_subscription *mwi_sub;
787  struct mwi_stasis_subscription *mwi_stasis;
788 
789  if (ast_strlen_zero(mailbox)) {
790  return 0;
791  }
792 
793  /*
794  * First check if an unsolicited subscription exists. If it does then we don't
795  * want to add another one.
796  */
797  if (has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
798  ao2_ref(mwi_stasis, -1);
799  ao2_ref(mwi_sub, -1);
800  return 0;
801  }
802 
803  /*
804  * If there is no unsolicited subscription, next check to see if a solicited
805  * subscription exists for the endpoint/mailbox. If not, then allow.
806  */
807  if (!has_mwi_subscription(solicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
808  return 1;
809  }
810 
811  /*
812  * If however, a solicited subscription does exist then we'll need to see if that
813  * subscription is allowed to replace the unsolicited one. If is allowed to replace
814  * then disallow the unsolicited one.
815  */
817  ao2_ref(mwi_stasis, -1);
818  ao2_ref(mwi_sub, -1);
819  return 0;
820  }
821 
822  /* Otherwise, shutdown the solicited subscription and allow the unsolicited */
823  mwi_sub->terminate = 1;
824  send_notify(mwi_sub, NULL, 0);
825 
826  ao2_ref(mwi_stasis, -1);
827  ao2_ref(mwi_sub, -1);
828 
829  return 1;
830 }
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
unsigned int terminate
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int has_mwi_subscription(struct ao2_container *container, struct ast_sip_endpoint *endpoint, const char *mailbox, struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
unsigned int subscribe_replaces_unsolicited
Definition: res_pjsip.h:594
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int send_notify(void *obj, void *arg, int flags)
A subscription for MWI.
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
static struct stasis_subscription * mwi_sub

◆ load_module()

static int load_module ( void  )
static

Definition at line 1553 of file res_pjsip_mwi.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_global_obj_replace_unref, ao2_ref, ast_log, AST_LOG_WARNING, ast_manager_get_generic_type(), ast_manager_get_topic(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_module_shutdown_ref, AST_MODULE_SUPPORT_CORE, AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_serializer_pool_create(), ast_serializer_pool_get(), ast_sip_get_mwi_disable_initial_unsolicited(), ast_sip_get_sorcery(), ast_sip_push_task(), ast_sip_register_subscription_handler(), ast_sip_threadpool(), ast_sorcery_observer_add(), ast_sorcery_reload_object(), ast_test_flag, ASTERISK_GPL_KEY, create_mwi_subscriptions(), MAX_UNLOAD_TIMEOUT_TIME, MWI_BUCKETS, MWI_SERIALIZER_POOL_SIZE, mwi_startup_event_cb(), mwi_sub_cmp(), mwi_sub_hash(), NULL, reload(), ast_module_info::self, send_initial_notify_all(), stasis_subscribe_pool, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), sub, and unload_module().

1554 {
1555  struct ao2_container *mwi_container;
1556 
1558  return AST_MODULE_LOAD_DECLINE;
1559  }
1560 
1563  if (!mwi_serializer_pool) {
1564  ast_log(AST_LOG_WARNING, "Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");
1565  }
1566 
1569  if (!mwi_container) {
1570  unload_module();
1571  return AST_MODULE_LOAD_DECLINE;
1572  }
1573  ao2_global_obj_replace_unref(mwi_solicited, mwi_container);
1574  ao2_ref(mwi_container, -1);
1575 
1578  if (!mwi_container) {
1579  unload_module();
1580  return AST_MODULE_LOAD_DECLINE;
1581  }
1582  ao2_global_obj_replace_unref(mwi_unsolicited, mwi_container);
1583  ao2_ref(mwi_container, -1);
1584 
1588 
1594  } else {
1595  struct stasis_subscription *sub;
1596 
1600  }
1601  }
1602 
1603  if (!mwi_serializer_pool) {
1604  /*
1605  * If the mwi serializer pool was unable to be established then the module will
1606  * use the default serializer pool. If this happens prevent manual unloading
1607  * since there would now exist the potential for a crash on unload.
1608  */
1610  }
1611 
1612  return AST_MODULE_LOAD_SUCCESS;
1613 }
static struct ast_sorcery_observer global_observer
static void mwi_startup_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Event callback which fires initial unsolicited MWI NOTIFY messages when we&#39;re fully booted...
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_LOG_WARNING
Definition: logger.h:279
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
static int unload_module(void)
static struct ast_sip_subscription_handler mwi_handler
Definition: res_pjsip_mwi.c:82
#define NULL
Definition: resample.c:96
struct ast_threadpool * ast_sip_threadpool(void)
Retrieve the SIP threadpool object.
Definition: res_pjsip.c:5630
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
#define ast_log
Definition: astobj2.c:42
static int mwi_sub_cmp(void *obj, void *arg, int flags)
struct ast_module * self
Definition: module.h:342
#define MAX_UNLOAD_TIMEOUT_TIME
Definition: res_pjsip_mwi.c:63
#define ao2_ref(o, delta)
Definition: astobj2.h:464
unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
Retrieve the global setting &#39;disable sending unsolicited mwi on startup&#39;.
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static int mwi_sub_hash(const void *obj, const int flags)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:682
static const struct ast_sorcery_observer mwi_contact_observer
Observer for contacts so unsolicited MWI is sent when a contact changes.
#define MWI_SERIALIZER_POOL_SIZE
Definition: res_pjsip_mwi.c:60
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1720
struct ast_serializer_pool * ast_serializer_pool_create(const char *name, unsigned int size, struct ast_threadpool *threadpool, int timeout)
Create a serializer pool.
Definition: serializer.c:76
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
struct ast_flags ast_options
Definition: options.c:61
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static void create_mwi_subscriptions(void)
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
struct stasis_forward * sub
Definition: res_corosync.c:240
static int send_initial_notify_all(void *obj)
Task invoked to send initial MWI NOTIFY for unsolicited.
Generic container type.
#define MWI_BUCKETS
Definition: res_pjsip_mwi.c:52
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
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
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ mwi_contact_added()

static void mwi_contact_added ( const void *  object)
static

Function called when a contact is added.

Definition at line 1408 of file res_pjsip_mwi.c.

References mwi_contact_changed().

1409 {
1410  mwi_contact_changed(object);
1411 }
static void mwi_contact_changed(const struct ast_sip_contact *contact)
Create mwi subscriptions and notify.

◆ mwi_contact_changed()

static void mwi_contact_changed ( const struct ast_sip_contact contact)
static

Create mwi subscriptions and notify.

Definition at line 1361 of file res_pjsip_mwi.c.

References ao2_bump, ao2_callback, ao2_cleanup, ao2_global_obj_ref, ao2_lock, ao2_ref, ao2_unlock, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strlen_zero, create_unsolicited_mwi_subscriptions(), ast_sip_contact::endpoint, ast_sip_contact::endpoint_name, ast_sip_mwi_configuration::mailboxes, ast_sip_endpoint_subscription_configuration::mwi, NULL, OBJ_NODATA, send_contact_notify(), strsep(), and ast_sip_endpoint::subscription.

Referenced by mwi_contact_added(), and mwi_contact_updated().

1362 {
1363  char *id = ast_strdupa(ast_sorcery_object_get_id(contact));
1364  char *aor = NULL;
1365  struct ast_sip_endpoint *endpoint = NULL;
1366  struct ao2_container *unsolicited_mwi;
1367  struct ao2_container *solicited_mwi;
1368 
1369  if (contact->endpoint) {
1370  endpoint = ao2_bump(contact->endpoint);
1371  } else {
1372  if (!ast_strlen_zero(contact->endpoint_name)) {
1373  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", contact->endpoint_name);
1374  }
1375  }
1376 
1377  if (!endpoint || ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
1378  ao2_cleanup(endpoint);
1379  return;
1380  }
1381 
1382  unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
1383  if (!unsolicited_mwi) {
1384  ao2_cleanup(endpoint);
1385  return;
1386  }
1387 
1388  solicited_mwi = ao2_global_obj_ref(mwi_solicited);
1389 
1390  ao2_lock(unsolicited_mwi);
1391  create_unsolicited_mwi_subscriptions(endpoint, 0, 0, unsolicited_mwi, solicited_mwi);
1392  ao2_unlock(unsolicited_mwi);
1393  ao2_cleanup(endpoint);
1394  ao2_cleanup(solicited_mwi);
1395  ao2_ref(unsolicited_mwi, -1);
1396 
1397  aor = strsep(&id, ";@");
1398  ao2_callback(unsolicited_mwi, OBJ_NODATA, send_contact_notify, aor);
1399 }
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint, int recreate, int send_now, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const ast_string_field mailboxes
Definition: res_pjsip.h:588
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
#define ao2_bump(obj)
Definition: astobj2.h:491
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
char * strsep(char **str, const char *delims)
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 int send_contact_notify(void *obj, void *arg, int flags)
Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR.
Generic container type.

◆ mwi_contact_deleted()

static void mwi_contact_deleted ( const void *  object)
static

Function called when a contact is deleted.

Definition at line 1414 of file res_pjsip_mwi.c.

References ao2_bump, ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_sip_endpoint::aors, ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sorcery_retrieve_by_id(), ast_strlen_zero, ast_sip_contact::endpoint, ast_sip_contact::endpoint_name, ast_sip_mwi_configuration::mailboxes, ast_sip_endpoint_subscription_configuration::mwi, mwi_sub, NULL, OBJ_MULTIPLE, OBJ_NOLOCK, OBJ_SEARCH_KEY, OBJ_UNLINK, ast_sip_endpoint::subscription, and unsubscribe().

1415 {
1416  const struct ast_sip_contact *contact = object;
1417  struct ao2_iterator *mwi_subs;
1418  struct mwi_subscription *mwi_sub;
1419  struct ast_sip_endpoint *endpoint = NULL;
1420  struct ast_sip_contact *found_contact;
1421  struct ao2_container *unsolicited_mwi;
1422 
1423  if (contact->endpoint) {
1424  endpoint = ao2_bump(contact->endpoint);
1425  } else {
1426  if (!ast_strlen_zero(contact->endpoint_name)) {
1427  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", contact->endpoint_name);
1428  }
1429  }
1430 
1431  if (!endpoint || ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
1432  ao2_cleanup(endpoint);
1433  return;
1434  }
1435 
1436  /* Check if there is another contact */
1437  found_contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
1438  ao2_cleanup(endpoint);
1439  if (found_contact) {
1440  ao2_cleanup(found_contact);
1441  return;
1442  }
1443 
1444  unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
1445  if (!unsolicited_mwi) {
1446  return;
1447  }
1448 
1449  ao2_lock(unsolicited_mwi);
1450  mwi_subs = ao2_find(unsolicited_mwi, contact->endpoint_name,
1452  if (mwi_subs) {
1453  for (; (mwi_sub = ao2_iterator_next(mwi_subs)); ao2_cleanup(mwi_sub)) {
1454  unsubscribe(mwi_sub, NULL, 0);
1455  }
1456  ao2_iterator_destroy(mwi_subs);
1457  }
1458  ao2_unlock(unsolicited_mwi);
1459  ao2_ref(unsolicited_mwi, -1);
1460 }
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const ast_string_field mailboxes
Definition: res_pjsip.h:588
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:313
#define ao2_bump(obj)
Definition: astobj2.h:491
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
Definition: location.c:304
Contact associated with an address of record.
Definition: res_pjsip.h:281
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
A subscription for MWI.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int unsubscribe(void *obj, void *arg, int flags)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.
const ast_string_field aors
Definition: res_pjsip.h:821
static struct stasis_subscription * mwi_sub

◆ mwi_contact_updated()

static void mwi_contact_updated ( const void *  object)
static

Function called when a contact is updated.

Definition at line 1402 of file res_pjsip_mwi.c.

References mwi_contact_changed().

1403 {
1404  mwi_contact_changed(object);
1405 }
static void mwi_contact_changed(const struct ast_sip_contact *contact)
Create mwi subscriptions and notify.

◆ mwi_create_subscription()

static struct mwi_subscription* mwi_create_subscription ( struct ast_sip_endpoint endpoint,
struct ast_sip_subscription sip_sub 
)
static

Definition at line 920 of file res_pjsip_mwi.c.

References add_mwi_datastore(), ao2_ref, ast_log, mwi_subscription::id, LOG_WARNING, mwi_subscription_alloc(), NULL, and sub.

Referenced by mwi_subscribe_all(), and mwi_subscribe_single().

922 {
923  struct mwi_subscription *sub = mwi_subscription_alloc(endpoint, 1, sip_sub);
924 
925  if (!sub) {
926  return NULL;
927  }
928 
929  if (add_mwi_datastore(sub)) {
930  ast_log(LOG_WARNING, "Unable to add datastore for MWI subscription to %s\n",
931  sub->id);
932  ao2_ref(sub, -1);
933  return NULL;
934  }
935 
936  return sub;
937 }
#define LOG_WARNING
Definition: logger.h:274
static int add_mwi_datastore(struct mwi_subscription *sub)
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
A subscription for MWI.
static struct mwi_subscription * mwi_subscription_alloc(struct ast_sip_endpoint *endpoint, unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mwi_ds_destroy()

static void mwi_ds_destroy ( void *  data)
static

Definition at line 629 of file res_pjsip_mwi.c.

References ao2_ref, and sub.

630 {
631  struct mwi_subscription *sub = data;
632 
633  ao2_ref(sub, -1);
634 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
A subscription for MWI.
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mwi_get_notify_data()

static void * mwi_get_notify_data ( struct ast_sip_subscription sub)
static

Definition at line 1042 of file res_pjsip_mwi.c.

References ao2_alloc, ao2_callback, ao2_cleanup, ao2_ref, ast_sip_subscription_get_datastore(), ast_sip_subscription_get_dialog(), ast_sip_subscription_get_endpoint(), ast_sip_subscription_get_resource_name(), ast_sip_subscription_get_sip_uri(), ast_datastore::data, find_aor_for_resource(), get_message_count(), MWI_DATASTORE, mwi_sub, NULL, OBJ_NODATA, set_voicemail_extension(), mwi_subscription::stasis_subs, and ast_sip_aor::voicemail_extension.

1043 {
1044  struct ast_sip_message_accumulator *counter;
1045  struct mwi_subscription *mwi_sub;
1046  struct ast_datastore *mwi_datastore;
1047  struct ast_sip_aor *aor;
1048  struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sub);
1049 
1050  mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
1051  if (!mwi_datastore) {
1052  return NULL;
1053  }
1054  mwi_sub = mwi_datastore->data;
1055 
1056  counter = ao2_alloc(sizeof(*counter), NULL);
1057  if (!counter) {
1058  ao2_cleanup(mwi_datastore);
1059  return NULL;
1060  }
1061 
1062  if ((aor = find_aor_for_resource(endpoint, ast_sip_subscription_get_resource_name(sub)))) {
1063  pjsip_dialog *dlg = ast_sip_subscription_get_dialog(sub);
1064  pjsip_sip_uri *sip_uri = ast_sip_subscription_get_sip_uri(sub);
1065 
1066  if (dlg && sip_uri) {
1067  set_voicemail_extension(dlg->pool, sip_uri, counter, aor->voicemail_extension);
1068  }
1069  ao2_ref(aor, -1);
1070  }
1071  ao2_cleanup(endpoint);
1072 
1074  ao2_cleanup(mwi_datastore);
1075  return counter;
1076 }
A SIP address of record.
Definition: res_pjsip.h:361
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Message counter used for message-summary XML bodies.
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
struct ao2_container * stasis_subs
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
char * voicemail_extension
Definition: res_pjsip.h:389
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
pjsip_sip_uri * ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub)
Retrieve the local sip uri for this subscription.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void set_voicemail_extension(pj_pool_t *pool, pjsip_sip_uri *local_uri, struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
A subscription for MWI.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
pjsip_dialog * ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub)
Get the pjsip dialog that is associated with this subscription.
void * data
Definition: datastore.h:70
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int get_message_count(void *obj, void *arg, int flags)
static struct stasis_subscription * mwi_sub

◆ mwi_new_subscribe()

static int mwi_new_subscribe ( struct ast_sip_endpoint endpoint,
const char *  resource 
)
static

Definition at line 974 of file res_pjsip_mwi.c.

References ao2_cleanup, ast_sip_endpoint::aors, ast_debug, ast_sip_for_each_aor(), ast_strlen_zero, find_aor_for_resource(), mwi_validate_for_aor(), NULL, and RAII_VAR.

976 {
977  RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
978 
979  if (ast_strlen_zero(resource)) {
980  if (ast_sip_for_each_aor(endpoint->aors, mwi_validate_for_aor, endpoint)) {
981  return 500;
982  }
983  return 200;
984  }
985 
986  aor = find_aor_for_resource(endpoint, resource);
987  if (!aor) {
988  ast_debug(1, "Unable to locate aor %s. MWI subscription failed.\n", resource);
989  return 404;
990  }
991 
992  if (ast_strlen_zero(aor->mailboxes)) {
993  ast_debug(1, "AOR %s has no configured mailboxes. MWI subscription failed.\n",
994  resource);
995  return 404;
996  }
997 
998  if (mwi_validate_for_aor(aor, endpoint, 0)) {
999  return 500;
1000  }
1001 
1002  return 200;
1003 }
A SIP address of record.
Definition: res_pjsip.h:361
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given &#39;on_aor&#39; handler. ...
Definition: location.c:684
static int mwi_validate_for_aor(void *obj, void *arg, int flags)
Determine if an endpoint is a candidate to be able to subscribe for MWI.
#define NULL
Definition: resample.c:96
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field aors
Definition: res_pjsip.h:821

◆ mwi_on_aor()

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

Definition at line 889 of file res_pjsip_mwi.c.

References ao2_link, ao2_ref, ast_strdupa, ast_strip(), ast_strlen_zero, mwi_stasis_subscription::mailbox, mailboxes, ast_sip_aor::mailboxes, mwi_stasis_subscription_alloc(), mwi_subscription::stasis_subs, strsep(), and sub.

Referenced by mwi_subscribe_all(), and mwi_subscribe_single().

890 {
891  struct ast_sip_aor *aor = obj;
892  struct mwi_subscription *sub = arg;
893  char *mailboxes;
894  char *mailbox;
895 
896  if (ast_strlen_zero(aor->mailboxes)) {
897  return 0;
898  }
899 
900  mailboxes = ast_strdupa(aor->mailboxes);
901  while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
902  struct mwi_stasis_subscription *mwi_stasis_sub;
903 
904  if (ast_strlen_zero(mailbox)) {
905  continue;
906  }
907 
908  mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
909  if (!mwi_stasis_sub) {
910  continue;
911  }
912 
913  ao2_link(sub->stasis_subs, mwi_stasis_sub);
914  ao2_ref(mwi_stasis_sub, -1);
915  }
916 
917  return 0;
918 }
const ast_string_field mailboxes
Definition: res_pjsip.h:365
A SIP address of record.
Definition: res_pjsip.h:361
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
static struct mwi_stasis_subscription * mwi_stasis_subscription_alloc(const char *mailbox, struct mwi_subscription *mwi_sub)
struct ao2_container * stasis_subs
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
A subscription for MWI.
char * strsep(char **str, const char *delims)
struct stasis_forward * sub
Definition: res_corosync.c:240
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ mwi_startup_event_cb()

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

Event callback which fires initial unsolicited MWI NOTIFY messages when we're fully booted.

Definition at line 1483 of file res_pjsip_mwi.c.

References ast_json_object_get(), ast_json_string_get(), ast_manager_get_generic_type(), ast_serializer_pool_get(), ast_sip_push_task(), ast_json_payload::json, NULL, send_initial_notify_all(), stasis_message_data(), stasis_message_type(), stasis_unsubscribe(), and type.

Referenced by load_module().

1484 {
1485  struct ast_json_payload *payload;
1486  const char *type;
1487 
1489  return;
1490  }
1491 
1492  payload = stasis_message_data(message);
1493  type = ast_json_string_get(ast_json_object_get(payload->json, "type"));
1494 
1495  if (strcmp(type, "FullyBooted")) {
1496  return;
1497  }
1498 
1501 
1502  stasis_unsubscribe(sub);
1503 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_json * json
Definition: json.h:1025
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
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
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
static int send_initial_notify_all(void *obj)
Task invoked to send initial MWI NOTIFY for unsolicited.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ mwi_stasis_cb()

static void mwi_stasis_cb ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 1156 of file res_pjsip_mwi.c.

References ao2_bump, ao2_ref, ast_mwi_state_type(), ast_serializer_pool_get(), ast_sip_push_task(), mwi_sub, NULL, send_notify(), serialized_cleanup(), stasis_message_type(), and stasis_subscription_final_message().

Referenced by mwi_stasis_subscription_alloc().

1158 {
1159  struct mwi_subscription *mwi_sub = userdata;
1160 
1161  if (stasis_subscription_final_message(sub, msg)) {
1163  serialized_cleanup, ao2_bump(mwi_sub))) {
1164  ao2_ref(mwi_sub, -1);
1165  }
1166  return;
1167  }
1168 
1169  if (ast_mwi_state_type() == stasis_message_type(msg)) {
1170  send_notify(mwi_sub, NULL, 0);
1171  }
1172 }
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
static int send_notify(void *obj, void *arg, int flags)
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition: stasis.c:1176
A subscription for MWI.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
static struct stasis_subscription * mwi_sub
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66
static int serialized_cleanup(void *userdata)

◆ mwi_stasis_subscription_alloc()

static struct mwi_stasis_subscription* mwi_stasis_subscription_alloc ( const char *  mailbox,
struct mwi_subscription mwi_sub 
)
static

Definition at line 140 of file res_pjsip_mwi.c.

References ao2_alloc, ao2_ref, ast_mwi_subscribe_pool(), ast_mwi_subscriber_subscription(), mwi_stasis_subscription::mailbox, mwi_stasis_cb(), mwi_stasis_subscription::mwi_subscriber, NULL, stasis_subscription_accept_message_type(), and stasis_subscription_change_type().

Referenced by create_unsolicited_mwi_subscriptions(), and mwi_on_aor().

141 {
142  struct mwi_stasis_subscription *mwi_stasis_sub;
143 
144  if (!mwi_sub) {
145  return NULL;
146  }
147 
148  mwi_stasis_sub = ao2_alloc(sizeof(*mwi_stasis_sub) + strlen(mailbox), NULL);
149  if (!mwi_stasis_sub) {
150  return NULL;
151  }
152 
153  /* Safe strcpy */
154  strcpy(mwi_stasis_sub->mailbox, mailbox);
155 
156  ao2_ref(mwi_sub, +1);
157  mwi_stasis_sub->mwi_subscriber = ast_mwi_subscribe_pool(mailbox, mwi_stasis_cb, mwi_sub);
158  if (!mwi_stasis_sub->mwi_subscriber) {
159  /* Failed to subscribe. */
160  ao2_ref(mwi_stasis_sub, -1);
161  ao2_ref(mwi_sub, -1);
162  return NULL;
163  }
164 
168 
169  return mwi_stasis_sub;
170 }
struct ast_mwi_subscriber * mwi_subscriber
Definition: res_pjsip_mwi.c:99
struct stasis_subscription * ast_mwi_subscriber_subscription(struct ast_mwi_subscriber *sub)
Retrieve the stasis MWI topic subscription if available.
Definition: mwi.c:272
#define NULL
Definition: resample.c:96
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
Definition: mwi.c:230
static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)

◆ mwi_sub_cmp()

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

Definition at line 299 of file res_pjsip_mwi.c.

References CMP_MATCH, mwi_subscription::id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by load_module().

300 {
301  const struct mwi_subscription *sub_left = obj;
302  const struct mwi_subscription *sub_right = arg;
303  const char *right_key = arg;
304  int cmp;
305 
306  switch (flags & OBJ_SEARCH_MASK) {
307  case OBJ_SEARCH_OBJECT:
308  right_key = sub_right->id;
309  /* Fall through */
310  case OBJ_SEARCH_KEY:
311  cmp = strcmp(sub_left->id, right_key);
312  break;
314  cmp = strncmp(sub_left->id, right_key, strlen(right_key));
315  break;
316  default:
317  cmp = 0;
318  break;
319  }
320  if (cmp) {
321  return 0;
322  }
323  return CMP_MATCH;
324 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
A subscription for MWI.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ mwi_sub_hash()

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

Definition at line 279 of file res_pjsip_mwi.c.

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

Referenced by load_module().

280 {
281  const struct mwi_subscription *object;
282  const char *key;
283 
284  switch (flags & OBJ_SEARCH_MASK) {
285  case OBJ_SEARCH_KEY:
286  key = obj;
287  break;
288  case OBJ_SEARCH_OBJECT:
289  object = obj;
290  key = object->id;
291  break;
292  default:
293  ast_assert(0);
294  return 0;
295  }
296  return ast_str_hash(key);
297 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
A subscription for MWI.
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

◆ mwi_subscribe_all()

static struct mwi_subscription* mwi_subscribe_all ( struct ast_sip_endpoint endpoint,
struct ast_sip_subscription sip_sub 
)
static

Definition at line 960 of file res_pjsip_mwi.c.

References ast_sip_endpoint::aors, ast_sip_for_each_aor(), mwi_create_subscription(), mwi_on_aor(), NULL, and sub.

Referenced by mwi_subscription_established().

962 {
963  struct mwi_subscription *sub;
964 
965  sub = mwi_create_subscription(endpoint, sip_sub);
966  if (!sub) {
967  return NULL;
968  }
969 
970  ast_sip_for_each_aor(endpoint->aors, mwi_on_aor, sub);
971  return sub;
972 }
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given &#39;on_aor&#39; handler. ...
Definition: location.c:684
#define NULL
Definition: resample.c:96
static int mwi_on_aor(void *obj, void *arg, int flags)
static struct mwi_subscription * mwi_create_subscription(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
A subscription for MWI.
struct stasis_forward * sub
Definition: res_corosync.c:240
const ast_string_field aors
Definition: res_pjsip.h:821

◆ mwi_subscribe_single()

static struct mwi_subscription* mwi_subscribe_single ( struct ast_sip_endpoint endpoint,
struct ast_sip_subscription sip_sub,
const char *  name 
)
static

Definition at line 939 of file res_pjsip_mwi.c.

References ao2_ref, ast_log, find_aor_for_resource(), LOG_WARNING, mwi_create_subscription(), mwi_on_aor(), NULL, and sub.

Referenced by mwi_subscription_established().

941 {
942  struct ast_sip_aor *aor;
943  struct mwi_subscription *sub;
944 
945  aor = find_aor_for_resource(endpoint, name);
946  if (!aor) {
947  ast_log(LOG_WARNING, "Unable to locate aor %s. MWI subscription failed.\n", name);
948  return NULL;
949  }
950 
951  sub = mwi_create_subscription(endpoint, sip_sub);
952  if (sub) {
953  mwi_on_aor(aor, sub, 0);
954  }
955 
956  ao2_ref(aor, -1);
957  return sub;
958 }
A SIP address of record.
Definition: res_pjsip.h:361
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
static int mwi_on_aor(void *obj, void *arg, int flags)
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct mwi_subscription * mwi_create_subscription(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
static const char name[]
Definition: cdr_mysql.c:74
A subscription for MWI.
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mwi_subscription_alloc()

static struct mwi_subscription* mwi_subscription_alloc ( struct ast_sip_endpoint endpoint,
unsigned int  is_solicited,
struct ast_sip_subscription sip_sub 
)
static

Definition at line 231 of file res_pjsip_mwi.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_container_alloc_hash, ao2_ref, mwi_subscription::aors, ast_sip_endpoint::aors, ast_debug, ast_sorcery_object_get_id(), ast_strdup, ast_strlen_zero, mwi_subscription::id, mwi_subscription::is_solicited, mwi_subscription_destructor(), NULL, mwi_subscription::sip_sub, STASIS_BUCKETS, stasis_sub_cmp(), stasis_sub_hash(), mwi_subscription::stasis_subs, and sub.

Referenced by create_unsolicited_mwi_subscriptions(), and mwi_create_subscription().

233 {
234  struct mwi_subscription *sub;
235  const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
236 
237  sub = ao2_alloc(sizeof(*sub) + strlen(endpoint_id),
239 
240  if (!sub) {
241  return NULL;
242  }
243 
244  /* Safe strcpy */
245  strcpy(sub->id, endpoint_id);
246 
247  /* Unsolicited MWI doesn't actually result in a SIP subscription being
248  * created. This is because a SIP subscription associates with a dialog.
249  * Most devices expect unsolicited MWI NOTIFYs to appear out of dialog. If
250  * they receive an in-dialog MWI NOTIFY (i.e. with a to-tag), then they
251  * will reject the NOTIFY with a 481, thus resulting in message-waiting
252  * state not being updated on the device
253  */
254  if (is_solicited) {
255  sub->sip_sub = sip_sub;
256  }
257 
260  if (!sub->stasis_subs) {
261  ao2_cleanup(sub);
262  return NULL;
263  }
264  sub->is_solicited = is_solicited;
265 
266  if (!is_solicited && !ast_strlen_zero(endpoint->aors)) {
267  sub->aors = ast_strdup(endpoint->aors);
268  if (!sub->aors) {
269  ao2_ref(sub, -1);
270  return NULL;
271  }
272  }
273 
274  ast_debug(3, "Created %s MWI subscription for endpoint %s\n", is_solicited ? "solicited" : "unsolicited", sub->id);
275 
276  return sub;
277 }
unsigned int is_solicited
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
static void mwi_subscription_destructor(void *obj)
struct ao2_container * stasis_subs
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int stasis_sub_hash(const void *obj, const int flags)
static int stasis_sub_cmp(void *obj, void *arg, int flags)
struct ast_sip_subscription * sip_sub
#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 ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define STASIS_BUCKETS
Definition: res_pjsip_mwi.c:51
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
A subscription for MWI.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct stasis_forward * sub
Definition: res_corosync.c:240
const ast_string_field aors
Definition: res_pjsip.h:821

◆ mwi_subscription_destructor()

static void mwi_subscription_destructor ( void *  obj)
static

Definition at line 219 of file res_pjsip_mwi.c.

References ao2_cleanup, mwi_subscription::aors, ast_debug, ast_free, ast_sip_subscription_destroy(), mwi_subscription::id, mwi_subscription::is_solicited, mwi_subscription::sip_sub, mwi_subscription::stasis_subs, and sub.

Referenced by mwi_subscription_alloc().

220 {
221  struct mwi_subscription *sub = obj;
222 
223  ast_debug(3, "Destroying MWI subscription for endpoint %s\n", sub->id);
224  if (sub->is_solicited) {
226  }
227  ao2_cleanup(sub->stasis_subs);
228  ast_free(sub->aors);
229 }
unsigned int is_solicited
struct ao2_container * stasis_subs
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_sip_subscription * sip_sub
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.
#define ast_free(a)
Definition: astmm.h:182
A subscription for MWI.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mwi_subscription_established()

static int mwi_subscription_established ( struct ast_sip_subscription sub)
static

Definition at line 1005 of file res_pjsip_mwi.c.

References ao2_cleanup, ao2_container_count(), ao2_global_obj_ref, ao2_link, ao2_ref, ast_sip_subscription_get_endpoint(), ast_sip_subscription_get_resource_name(), ast_sip_subscription_remove_datastore(), ast_strlen_zero, MWI_DATASTORE, mwi_subscribe_all(), mwi_subscribe_single(), mwi_subscription::stasis_subs, and sub.

1006 {
1007  const char *resource = ast_sip_subscription_get_resource_name(sip_sub);
1008  struct mwi_subscription *sub;
1009  struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
1010  struct ao2_container *solicited_mwi;
1011 
1012  /* no aor in uri? subscribe to all on endpoint */
1013  if (ast_strlen_zero(resource)) {
1014  sub = mwi_subscribe_all(endpoint, sip_sub);
1015  } else {
1016  sub = mwi_subscribe_single(endpoint, sip_sub, resource);
1017  }
1018  if (!sub) {
1019  ao2_cleanup(endpoint);
1020  return -1;
1021  }
1022 
1023  if (!ao2_container_count(sub->stasis_subs)) {
1024  /*
1025  * We setup no MWI subscriptions so remove the MWI datastore
1026  * to break the ref loop.
1027  */
1029  }
1030 
1031  solicited_mwi = ao2_global_obj_ref(mwi_solicited);
1032  if (solicited_mwi) {
1033  ao2_link(solicited_mwi, sub);
1034  ao2_ref(solicited_mwi, -1);
1035  }
1036 
1037  ao2_cleanup(sub);
1038  ao2_cleanup(endpoint);
1039  return 0;
1040 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
struct ao2_container * stasis_subs
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
struct ast_sip_subscription * sip_sub
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static struct mwi_subscription * mwi_subscribe_single(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
A subscription for MWI.
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
struct stasis_forward * sub
Definition: res_corosync.c:240
static struct mwi_subscription * mwi_subscribe_all(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
Generic container type.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ mwi_subscription_mailboxes_str()

static void mwi_subscription_mailboxes_str ( struct ao2_container stasis_subs,
struct ast_str **  str 
)
static

Definition at line 1078 of file res_pjsip_mwi.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_str_append(), and mwi_stasis_subscription::mailbox.

Referenced by mwi_to_ami().

1080 {
1081  int is_first = 1;
1082  struct mwi_stasis_subscription *node;
1083  struct ao2_iterator i = ao2_iterator_init(stasis_subs, 0);
1084 
1085  while ((node = ao2_iterator_next(&i))) {
1086  if (is_first) {
1087  is_first = 0;
1088  ast_str_append(str, 0, "%s", node->mailbox);
1089  } else {
1090  ast_str_append(str, 0, ",%s", node->mailbox);
1091  }
1092  ao2_ref(node, -1);
1093  }
1095 }
Definition: test_heap.c:38
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ mwi_subscription_shutdown()

static void mwi_subscription_shutdown ( struct ast_sip_subscription sub)
static

Definition at line 587 of file res_pjsip_mwi.c.

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_sip_get_sorcery(), ast_sip_subscription_get_datastore(), ast_sip_subscription_remove_datastore(), ast_sorcery_retrieve_by_id(), create_unsolicited_mwi_subscriptions(), ast_datastore::data, mwi_subscription::id, MWI_DATASTORE, mwi_sub, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, mwi_subscription::stasis_subs, and unsubscribe_stasis().

588 {
589  struct mwi_subscription *mwi_sub;
590  struct ast_datastore *mwi_datastore;
591  struct ast_sip_endpoint *endpoint = NULL;
592  struct ao2_container *unsolicited_mwi;
593  struct ao2_container *solicited_mwi;
594 
596  if (!mwi_datastore) {
597  return;
598  }
599 
600  mwi_sub = mwi_datastore->data;
601 
604  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", mwi_sub->id);
605 
606  ao2_ref(mwi_datastore, -1);
607 
608  solicited_mwi = ao2_global_obj_ref(mwi_solicited);
609  if (solicited_mwi) {
610  ao2_unlink(solicited_mwi, mwi_sub);
611  }
612 
613  /*
614  * When a solicited subscription is removed it's possible an unsolicited one
615  * needs to be [re-]created. Attempt to establish unsolicited MWI.
616  */
617  unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
618  if (unsolicited_mwi && endpoint) {
619  ao2_lock(unsolicited_mwi);
620  create_unsolicited_mwi_subscriptions(endpoint, 1, 1, unsolicited_mwi, solicited_mwi);
621  ao2_unlock(unsolicited_mwi);
622  ao2_ref(unsolicited_mwi, -1);
623  }
624 
625  ao2_cleanup(solicited_mwi);
626  ao2_cleanup(endpoint);
627 }
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint, int recreate, int send_now, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static int unsubscribe_stasis(void *obj, void *arg, int flags)
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ao2_unlock(a)
Definition: astobj2.h:730
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
struct ao2_container * stasis_subs
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
A subscription for MWI.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
void * data
Definition: datastore.h:70
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
Generic container type.
static struct stasis_subscription * mwi_sub

◆ mwi_to_ami()

static void mwi_to_ami ( struct ast_sip_subscription sub,
struct ast_str **  buf 
)
static

Definition at line 1097 of file res_pjsip_mwi.c.

References ao2_ref, ast_sip_subscription_get_datastore(), ast_str_append(), ast_datastore::data, MWI_DATASTORE, mwi_sub, mwi_subscription_mailboxes_str(), and mwi_subscription::stasis_subs.

1099 {
1100  struct mwi_subscription *mwi_sub;
1101  struct ast_datastore *mwi_datastore;
1102 
1103  mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
1104  if (!mwi_datastore) {
1105  return;
1106  }
1107 
1108  mwi_sub = mwi_datastore->data;
1109 
1110  ast_str_append(buf, 0, "SubscriptionType: mwi\r\n");
1111  ast_str_append(buf, 0, "Mailboxes: ");
1113  ast_str_append(buf, 0, "\r\n");
1114 
1115  ao2_ref(mwi_datastore, -1);
1116 }
static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs, struct ast_str **str)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
Structure for a data store object.
Definition: datastore.h:68
struct ao2_container * stasis_subs
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
#define ao2_ref(o, delta)
Definition: astobj2.h:464
A subscription for MWI.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
void * data
Definition: datastore.h:70
static struct stasis_subscription * mwi_sub

◆ mwi_validate_for_aor()

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

Determine if an endpoint is a candidate to be able to subscribe for MWI.

Currently, this just makes sure that the endpoint is not already receiving unsolicted MWI for any of an AOR's configured mailboxes.

Parameters
objThe AOR to which the endpoint is subscribing.
argThe endpoint that is attempting to subscribe.
flagsUnused.
Return values
0Endpoint is a candidate to subscribe to MWI on the AOR.
-1The endpoint cannot subscribe to MWI on the AOR.

Definition at line 844 of file res_pjsip_mwi.c.

References allow_and_or_replace_unsolicited(), ao2_global_obj_ref, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_sorcery_object_get_id(), ast_strdupa, ast_strip(), ast_strlen_zero, mwi_stasis_subscription::mailbox, mailboxes, ast_sip_aor::mailboxes, and strsep().

Referenced by mwi_new_subscribe().

845 {
846  struct ast_sip_aor *aor = obj;
847  struct ast_sip_endpoint *endpoint = arg;
848  char *mailboxes;
849  char *mailbox;
850  struct ao2_container *unsolicited_mwi;
851 
852  if (ast_strlen_zero(aor->mailboxes)) {
853  return 0;
854  }
855 
856  /* A reload could be taking place so lock while checking if allowed */
857  unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
858  if (unsolicited_mwi) {
859  ao2_lock(unsolicited_mwi);
860  }
861 
862  mailboxes = ast_strdupa(aor->mailboxes);
863  while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
864  if (ast_strlen_zero(mailbox)) {
865  continue;
866  }
867 
868  if (!allow_and_or_replace_unsolicited(endpoint, mailbox, unsolicited_mwi)) {
869  ast_debug(1, "Endpoint '%s' already configured for unsolicited MWI for mailbox '%s'. "
870  "Denying MWI subscription to %s\n", ast_sorcery_object_get_id(endpoint), mailbox,
872 
873  if (unsolicited_mwi) {
874  ao2_unlock(unsolicited_mwi);
875  ao2_ref(unsolicited_mwi, -1);
876  }
877  return -1;
878  }
879  }
880 
881  if (unsolicited_mwi) {
882  ao2_unlock(unsolicited_mwi);
883  ao2_ref(unsolicited_mwi, -1);
884  }
885 
886  return 0;
887 }
const ast_string_field mailboxes
Definition: res_pjsip.h:365
A SIP address of record.
Definition: res_pjsip.h:361
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static int allow_and_or_replace_unsolicited(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi)
char * strsep(char **str, const char *delims)
Generic container type.

◆ reload()

static int reload ( void  )
static

Definition at line 1517 of file res_pjsip_mwi.c.

References ast_sip_get_mwi_disable_initial_unsolicited(), and create_mwi_subscriptions().

Referenced by load_module().

1518 {
1521  }
1522  return 0;
1523 }
unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
Retrieve the global setting &#39;disable sending unsolicited mwi on startup&#39;.
static void create_mwi_subscriptions(void)

◆ send_contact_notify()

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

Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR.

Definition at line 1343 of file res_pjsip_mwi.c.

References ao2_bump, ao2_ref, mwi_subscription::aors, ast_serializer_pool_get(), ast_sip_push_task(), mwi_sub, and serialized_notify().

Referenced by mwi_contact_changed().

1344 {
1345  struct mwi_subscription *mwi_sub = obj;
1346  const char *aor = arg;
1347 
1348  if (!mwi_sub->aors || !strstr(mwi_sub->aors, aor)) {
1349  return 0;
1350  }
1351 
1353  serialized_notify, ao2_bump(mwi_sub))) {
1354  ao2_ref(mwi_sub, -1);
1355  }
1356 
1357  return 0;
1358 }
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int serialized_notify(void *userdata)
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
A subscription for MWI.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
static struct stasis_subscription * mwi_sub
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ send_initial_notify_all()

static int send_initial_notify_all ( void *  obj)
static

Task invoked to send initial MWI NOTIFY for unsolicited.

Definition at line 1470 of file res_pjsip_mwi.c.

References ao2_callback, ao2_global_obj_ref, ao2_ref, NULL, OBJ_NODATA, and send_notify().

Referenced by load_module(), and mwi_startup_event_cb().

1471 {
1472  struct ao2_container *unsolicited_mwi = ao2_global_obj_ref(mwi_unsolicited);
1473 
1474  if (unsolicited_mwi) {
1475  ao2_callback(unsolicited_mwi, OBJ_NODATA, send_notify, NULL);
1476  ao2_ref(unsolicited_mwi, -1);
1477  }
1478 
1479  return 0;
1480 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int send_notify(void *obj, void *arg, int flags)
Generic container type.

◆ send_mwi_notify()

static void send_mwi_notify ( struct mwi_subscription sub)
static

Definition at line 538 of file res_pjsip_mwi.c.

References ao2_callback, ao2_cleanup, AST_SIP_MESSAGE_ACCUMULATOR, ast_sip_subscription_get_dialog(), ast_sip_subscription_get_endpoint(), ast_sip_subscription_get_resource_name(), ast_sip_subscription_get_sip_uri(), ast_sip_subscription_notify(), ast_sip_body_data::body_type, find_aor_for_resource(), get_message_count(), mwi_subscription::is_solicited, OBJ_NODATA, ast_sip_message_accumulator::old_msgs, send_unsolicited_mwi_notify(), set_voicemail_extension(), mwi_subscription::sip_sub, mwi_subscription::stasis_subs, mwi_subscription::terminate, and ast_sip_aor::voicemail_extension.

Referenced by serialized_notify().

539 {
540  struct ast_sip_message_accumulator counter = {
541  .old_msgs = 0,
542  .new_msgs = 0,
543  .message_account[0] = '\0',
544  };
545  struct ast_sip_body_data data = {
547  .body_data = &counter,
548  };
549 
551 
552  if (sub->is_solicited) {
553  const char *resource = ast_sip_subscription_get_resource_name(sub->sip_sub);
555  struct ast_sip_aor *aor = find_aor_for_resource(endpoint, resource);
556  pjsip_dialog *dlg = ast_sip_subscription_get_dialog(sub->sip_sub);
557  pjsip_sip_uri *sip_uri = ast_sip_subscription_get_sip_uri(sub->sip_sub);
558 
559  if (aor && dlg && sip_uri) {
560  set_voicemail_extension(dlg->pool, sip_uri, &counter, aor->voicemail_extension);
561  }
562 
563  ao2_cleanup(aor);
564  ao2_cleanup(endpoint);
565  ast_sip_subscription_notify(sub->sip_sub, &data, sub->terminate);
566 
567  return;
568  }
569 
570  send_unsolicited_mwi_notify(sub, &counter);
571 }
#define AST_SIP_MESSAGE_ACCUMULATOR
unsigned int terminate
A SIP address of record.
Definition: res_pjsip.h:361
unsigned int is_solicited
const char * body_type
Data used to create bodies for NOTIFY/PUBLISH requests.
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
Message counter used for message-summary XML bodies.
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
struct ao2_container * stasis_subs
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
char * voicemail_extension
Definition: res_pjsip.h:389
pjsip_sip_uri * ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub)
Retrieve the local sip uri for this subscription.
struct ast_sip_subscription * sip_sub
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, struct ast_sip_message_accumulator *counter)
static void set_voicemail_extension(pj_pool_t *pool, pjsip_sip_uri *local_uri, struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
pjsip_dialog * ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub)
Get the pjsip dialog that is associated with this subscription.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate)
Notify a SIP subscription of a state change.
static int get_message_count(void *obj, void *arg, int flags)

◆ send_notify()

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

Definition at line 1142 of file res_pjsip_mwi.c.

References ao2_bump, ao2_ref, ast_serializer_pool_get(), ast_sip_push_task(), ast_sip_subscription_get_serializer(), mwi_subscription::is_solicited, mwi_sub, serialized_notify(), and mwi_subscription::sip_sub.

Referenced by allow_and_or_replace_unsolicited(), create_unsolicited_mwi_subscriptions(), is_unsolicited_allowed(), mwi_stasis_cb(), and send_initial_notify_all().

1143 {
1144  struct mwi_subscription *mwi_sub = obj;
1145  struct ast_taskprocessor *serializer = mwi_sub->is_solicited
1148 
1149  if (ast_sip_push_task(serializer, serialized_notify, ao2_bump(mwi_sub))) {
1150  ao2_ref(mwi_sub, -1);
1151  }
1152 
1153  return 0;
1154 }
struct ast_taskprocessor * ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
Get the serializer for the subscription.
unsigned int is_solicited
#define ao2_bump(obj)
Definition: astobj2.h:491
struct ast_sip_subscription * sip_sub
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int serialized_notify(void *userdata)
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
A subscription for MWI.
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
static struct stasis_subscription * mwi_sub
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ send_unsolicited_mwi_notify()

static void send_unsolicited_mwi_notify ( struct mwi_subscription sub,
struct ast_sip_message_accumulator counter 
)
static

Definition at line 490 of file res_pjsip_mwi.c.

References ao2_callback, ao2_cleanup, ao2_container_count(), ast_debug, ast_log, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_location_retrieve_aor_contacts(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strip(), ast_strlen_zero, unsolicited_mwi_data::counter, unsolicited_mwi_data::endpoint, mwi_subscription::id, LOG_WARNING, ast_sip_message_accumulator::new_msgs, NULL, OBJ_NODATA, ast_sip_message_accumulator::old_msgs, RAII_VAR, send_unsolicited_mwi_notify_to_contact(), strsep(), sub, and unsolicited_mwi_data::sub.

Referenced by send_mwi_notify().

492 {
494  "endpoint", sub->id), ao2_cleanup);
495  char *endpoint_aors;
496  char *aor_name;
497 
498  if (!endpoint) {
499  ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because endpoint does not exist\n",
500  sub->id);
501  return;
502  }
503  if (ast_strlen_zero(endpoint->aors)) {
504  ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because the endpoint has no"
505  " configured AORs\n", sub->id);
506  return;
507  }
508 
509  endpoint_aors = ast_strdupa(endpoint->aors);
510 
511  ast_debug(5, "Sending unsolicited MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
512  sub->id, counter->new_msgs, counter->old_msgs);
513 
514  while ((aor_name = ast_strip(strsep(&endpoint_aors, ",")))) {
516  RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
517  struct unsolicited_mwi_data mwi_data = {
518  .sub = sub,
519  .endpoint = endpoint,
520  .counter = counter,
521  };
522 
523  if (!aor) {
524  ast_log(LOG_WARNING, "Unable to locate AOR %s for unsolicited MWI\n", aor_name);
525  continue;
526  }
527 
529  if (!contacts || (ao2_container_count(contacts) == 0)) {
530  ast_debug(1, "No contacts bound to AOR %s. Cannot send unsolicited MWI until a contact registers.\n", aor_name);
531  continue;
532  }
533 
535  }
536 }
A SIP address of record.
Definition: res_pjsip.h:361
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ast_sip_message_accumulator * counter
struct mwi_subscription * sub
#define LOG_WARNING
Definition: logger.h:274
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
struct ao2_container * ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR.
Definition: location.c:247
static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flags)
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define 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
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
char * strsep(char **str, const char *delims)
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct stasis_forward * sub
Definition: res_corosync.c:240
Generic container type.
struct ast_sip_endpoint * endpoint

◆ send_unsolicited_mwi_notify_to_contact()

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

Definition at line 371 of file res_pjsip_mwi.c.

References ast_free, ast_log, ast_sip_add_body(), ast_sip_create_request(), AST_SIP_MESSAGE_ACCUMULATOR, ast_sip_pubsub_generate_body_content(), ast_sip_send_request(), ast_str_buffer(), ast_str_create, ast_strlen_zero, ast_sip_body::body_text, ast_sip_body_data::body_type, unsolicited_mwi_data::counter, unsolicited_mwi_data::endpoint, ast_sip_mwi_configuration::fromuser, mwi_subscription::id, LOG_WARNING, ast_sip_endpoint_subscription_configuration::mwi, MWI_SUBTYPE, MWI_TYPE, NULL, set_voicemail_extension(), unsolicited_mwi_data::state, sub, unsolicited_mwi_data::sub, ast_sip_endpoint::subscription, ast_sip_body::subtype, ast_sip_body::type, ast_sip_contact::uri, and ast_sip_mwi_configuration::voicemail_extension.

Referenced by send_unsolicited_mwi_notify().

372 {
373  struct unsolicited_mwi_data *mwi_data = arg;
374  struct mwi_subscription *sub = mwi_data->sub;
375  struct ast_sip_endpoint *endpoint = mwi_data->endpoint;
376  pjsip_evsub_state state = mwi_data->state;
377  struct ast_sip_contact *contact = obj;
378  const char *state_name;
379  pjsip_tx_data *tdata;
380  pjsip_sub_state_hdr *sub_state;
381  pjsip_event_hdr *event;
382  pjsip_from_hdr *from;
383  pjsip_sip_uri *from_uri;
384  const pjsip_hdr *allow_events = pjsip_evsub_get_allow_events_hdr(NULL);
385  struct ast_sip_body body;
386  struct ast_str *body_text;
387  struct ast_sip_body_data body_data = {
388  .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
389  .body_data = mwi_data->counter,
390  };
391 
392  if (ast_sip_create_request("NOTIFY", NULL, endpoint, NULL, contact, &tdata)) {
393  ast_log(LOG_WARNING, "Unable to create unsolicited NOTIFY request to endpoint %s URI %s\n", sub->id, contact->uri);
394  return 0;
395  }
396 
397  body.type = MWI_TYPE;
398  body.subtype = MWI_SUBTYPE;
399  body_text = ast_str_create(64);
400  if (!body_text) {
401  pjsip_tx_data_dec_ref(tdata);
402  return 0;
403  }
404 
405  from = PJSIP_MSG_FROM_HDR(tdata->msg);
406  from_uri = pjsip_uri_get_uri(from->uri);
407 
408  if (!ast_strlen_zero(endpoint->subscription.mwi.fromuser)) {
409  pj_strdup2(tdata->pool, &from_uri->user, endpoint->subscription.mwi.fromuser);
410  }
411 
412  set_voicemail_extension(tdata->pool, from_uri, mwi_data->counter, endpoint->subscription.mwi.voicemail_extension);
413 
414  if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, &body_data, &body_text)) {
415  ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
416  ast_free(body_text);
417  pjsip_tx_data_dec_ref(tdata);
418  return 0;
419  }
420 
421  body.body_text = ast_str_buffer(body_text);
422 
423  switch (state) {
424  case PJSIP_EVSUB_STATE_ACTIVE:
425  state_name = "active";
426  break;
427  case PJSIP_EVSUB_STATE_TERMINATED:
428  default:
429  state_name = "terminated";
430  break;
431  }
432 
433  sub_state = pjsip_sub_state_hdr_create(tdata->pool);
434  pj_cstr(&sub_state->sub_state, state_name);
435  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state);
436 
437  event = pjsip_event_hdr_create(tdata->pool);
438  pj_cstr(&event->event_type, "message-summary");
439  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
440 
441  pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, allow_events));
442  ast_sip_add_body(tdata, &body);
443  ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL);
444 
445  ast_free(body_text);
446 
447  return 0;
448 }
#define AST_SIP_MESSAGE_ACCUMULATOR
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:608
#define MWI_TYPE
Definition: res_pjsip_mwi.c:54
pjsip_evsub_state state
struct ast_sip_message_accumulator * counter
struct mwi_subscription * sub
Data used to create bodies for NOTIFY/PUBLISH requests.
#define MWI_SUBTYPE
Definition: res_pjsip_mwi.c:55
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
Definition: astman.c:222
#define NULL
Definition: resample.c:96
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
Definition: res_pjsip.c:5034
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
int ast_sip_pubsub_generate_body_content(const char *content_type, const char *content_subtype, struct ast_sip_body_data *data, struct ast_str **str)
Generate body content for a PUBLISH or NOTIFY.
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
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Contact associated with an address of record.
Definition: res_pjsip.h:281
static void set_voicemail_extension(pj_pool_t *pool, pjsip_sip_uri *local_uri, struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
#define ast_free(a)
Definition: astmm.h:182
A subscription for MWI.
const ast_string_field fromuser
Definition: res_pjsip.h:590
struct stasis_forward * sub
Definition: res_corosync.c:240
const ast_string_field uri
Definition: res_pjsip.h:303
struct ast_sip_endpoint * endpoint
SIP body description.
Definition: res_pjsip.h:2027
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition: res_pjsip.c:4490

◆ serialized_cleanup()

static int serialized_cleanup ( void *  userdata)
static

Definition at line 1127 of file res_pjsip_mwi.c.

References ao2_cleanup, and mwi_sub.

Referenced by mwi_stasis_cb().

1128 {
1129  struct mwi_subscription *mwi_sub = userdata;
1130 
1131  /* This is getting rid of the reference that was added
1132  * just before this serialized task was pushed.
1133  */
1134  ao2_cleanup(mwi_sub);
1135  /* This is getting rid of the reference held by the
1136  * stasis subscription
1137  */
1138  ao2_cleanup(mwi_sub);
1139  return 0;
1140 }
A subscription for MWI.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct stasis_subscription * mwi_sub

◆ serialized_notify()

static int serialized_notify ( void *  userdata)
static

Definition at line 1118 of file res_pjsip_mwi.c.

References ao2_ref, mwi_sub, and send_mwi_notify().

Referenced by send_contact_notify(), and send_notify().

1119 {
1120  struct mwi_subscription *mwi_sub = userdata;
1121 
1122  send_mwi_notify(mwi_sub);
1123  ao2_ref(mwi_sub, -1);
1124  return 0;
1125 }
static void send_mwi_notify(struct mwi_subscription *sub)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
A subscription for MWI.
static struct stasis_subscription * mwi_sub

◆ set_voicemail_extension()

static void set_voicemail_extension ( pj_pool_t *  pool,
pjsip_sip_uri *  local_uri,
struct ast_sip_message_accumulator counter,
const char *  voicemail_extension 
)
static

Definition at line 345 of file res_pjsip_mwi.c.

References ast_strlen_zero, default_voicemail_extension, and ast_sip_message_accumulator::message_account.

Referenced by mwi_get_notify_data(), send_mwi_notify(), and send_unsolicited_mwi_notify_to_contact().

347 {
348  pjsip_sip_uri *account_uri;
349  const char *vm_exten;
350 
351  if (ast_strlen_zero(voicemail_extension)) {
352  vm_exten = default_voicemail_extension;
353  } else {
354  vm_exten = voicemail_extension;
355  }
356 
357  if (!ast_strlen_zero(vm_exten)) {
358  account_uri = pjsip_uri_clone(pool, local_uri);
359  pj_strdup2(pool, &account_uri->user, vm_exten);
360  pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, account_uri, counter->message_account, sizeof(counter->message_account));
361  }
362 }
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char * default_voicemail_extension
Definition: res_pjsip_mwi.c:49

◆ stasis_sub_cmp()

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

Definition at line 192 of file res_pjsip_mwi.c.

References CMP_MATCH, mwi_stasis_subscription::mailbox, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by mwi_subscription_alloc().

193 {
194  const struct mwi_stasis_subscription *sub_left = obj;
195  const struct mwi_stasis_subscription *sub_right = arg;
196  const char *right_key = arg;
197  int cmp;
198 
199  switch (flags & OBJ_SEARCH_MASK) {
200  case OBJ_SEARCH_OBJECT:
201  right_key = sub_right->mailbox;
202  /* Fall through */
203  case OBJ_SEARCH_KEY:
204  cmp = strcmp(sub_left->mailbox, right_key);
205  break;
207  cmp = strncmp(sub_left->mailbox, right_key, strlen(right_key));
208  break;
209  default:
210  cmp = 0;
211  break;
212  }
213  if (cmp) {
214  return 0;
215  }
216  return CMP_MATCH;
217 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
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
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97

◆ stasis_sub_hash()

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

Definition at line 172 of file res_pjsip_mwi.c.

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

Referenced by mwi_subscription_alloc().

173 {
174  const struct mwi_stasis_subscription *object;
175  const char *key;
176 
177  switch (flags & OBJ_SEARCH_MASK) {
178  case OBJ_SEARCH_KEY:
179  key = obj;
180  break;
181  case OBJ_SEARCH_OBJECT:
182  object = obj;
183  key = object->mailbox;
184  break;
185  default:
186  ast_assert(0);
187  return 0;
188  }
189  return ast_str_hash(key);
190 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1525 of file res_pjsip_mwi.c.

References ao2_callback, ao2_global_obj_release, ao2_global_obj_replace, ao2_ref, ast_free, ast_log, ast_serializer_pool_destroy(), ast_sip_get_sorcery(), ast_sip_unregister_subscription_handler(), ast_sorcery_observer_remove(), default_voicemail_extension, LOG_WARNING, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and unsubscribe().

Referenced by load_module().

1526 {
1527  struct ao2_container *unsolicited_mwi;
1528 
1531 
1532  unsolicited_mwi = ao2_global_obj_replace(mwi_unsolicited, NULL);
1533  if (unsolicited_mwi) {
1535  ao2_ref(unsolicited_mwi, -1);
1536  }
1537 
1538  ao2_global_obj_release(mwi_solicited);
1539 
1541  ast_log(LOG_WARNING, "Unload incomplete. Try again later\n");
1542  return -1;
1543  }
1545 
1547 
1550  return 0;
1551 }
static struct ast_sorcery_observer global_observer
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
#define LOG_WARNING
Definition: logger.h:274
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static struct ast_sip_subscription_handler mwi_handler
Definition: res_pjsip_mwi.c:82
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
static char * default_voicemail_extension
Definition: res_pjsip_mwi.c:49
#define ast_free(a)
Definition: astmm.h:182
static const struct ast_sorcery_observer mwi_contact_observer
Observer for contacts so unsolicited MWI is sent when a contact changes.
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
static int unsubscribe(void *obj, void *arg, int flags)
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
Generic container type.
#define ao2_global_obj_replace(holder, obj)
Definition: astobj2.h:885
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66

◆ unsubscribe()

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

Definition at line 1292 of file res_pjsip_mwi.c.

References ao2_callback, CMP_MATCH, mwi_sub, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, mwi_subscription::stasis_subs, and unsubscribe_stasis().

Referenced by create_mwi_subscriptions(), mwi_contact_deleted(), unload_module(), and xmpp_pubsub_unsubscribe().

1293 {
1294  struct mwi_subscription *mwi_sub = obj;
1295 
1297 
1298  return CMP_MATCH;
1299 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static int unsubscribe_stasis(void *obj, void *arg, int flags)
#define NULL
Definition: resample.c:96
struct ao2_container * stasis_subs
A subscription for MWI.
static struct stasis_subscription * mwi_sub

◆ unsubscribe_stasis()

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

Definition at line 573 of file res_pjsip_mwi.c.

References ast_debug, ast_mwi_unsubscribe_and_join(), CMP_MATCH, create_unsolicited_mwi_subscriptions(), mwi_stasis_subscription::mailbox, and mwi_stasis_subscription::mwi_subscriber.

Referenced by allow_and_or_replace_unsolicited(), mwi_subscription_shutdown(), and unsubscribe().

574 {
575  struct mwi_stasis_subscription *mwi_stasis = obj;
576 
577  if (mwi_stasis->mwi_subscriber) {
578  ast_debug(3, "Removing stasis subscription to mailbox %s\n", mwi_stasis->mailbox);
580  }
581  return CMP_MATCH;
582 }
struct ast_mwi_subscriber * mwi_subscriber
Definition: res_pjsip_mwi.c:99
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
void * ast_mwi_unsubscribe_and_join(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic, block until the final message is received, and then unsubscribe fr...
Definition: mwi.c:254
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP MWI resource" , .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, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5, .requires = "res_pjsip,res_pjsip_pubsub", }
static

Definition at line 1622 of file res_pjsip_mwi.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1622 of file res_pjsip_mwi.c.

◆ default_voicemail_extension

char* default_voicemail_extension
static

Definition at line 49 of file res_pjsip_mwi.c.

Referenced by global_loaded(), set_voicemail_extension(), and unload_module().

◆ global_observer

struct ast_sorcery_observer global_observer
static
Initial value:
= {
.loaded = global_loaded,
}
static void global_loaded(const char *object_type)

Definition at line 1513 of file res_pjsip_mwi.c.

◆ mwi_contact_observer

const struct ast_sorcery_observer mwi_contact_observer
static
Initial value:
= {
.created = mwi_contact_added,
.updated = mwi_contact_updated,
.deleted = mwi_contact_deleted,
}
static void mwi_contact_added(const void *object)
Function called when a contact is added.
static void mwi_contact_updated(const void *object)
Function called when a contact is updated.
static void mwi_contact_deleted(const void *object)
Function called when a contact is deleted.

Observer for contacts so unsolicited MWI is sent when a contact changes.

Definition at line 1463 of file res_pjsip_mwi.c.

◆ mwi_ds_info

struct ast_datastore_info mwi_ds_info
static
Initial value:
= {
.destroy = mwi_ds_destroy,
}
static void mwi_ds_destroy(void *data)

Definition at line 636 of file res_pjsip_mwi.c.

◆ mwi_handler

struct ast_sip_subscription_handler mwi_handler
static

Definition at line 82 of file res_pjsip_mwi.c.

◆ mwi_notifier

struct ast_sip_notifier mwi_notifier
static

Definition at line 75 of file res_pjsip_mwi.c.

◆ mwi_serializer_pool

struct ast_serializer_pool* mwi_serializer_pool
static

Pool of serializers to use if not supplied.

Definition at line 66 of file res_pjsip_mwi.c.