Asterisk - The Open Source Telephony Project GIT-master-a358458
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_solicited)
 
 AO2_GLOBAL_OBJ_STATIC (mwi_unsolicited)
 
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 = AST_BUILDOPT_SUM, .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.

◆ MWI_BUCKETS

#define MWI_BUCKETS   53

Definition at line 52 of file res_pjsip_mwi.c.

◆ MWI_DATASTORE

#define MWI_DATASTORE   "MWI datastore"

Definition at line 57 of file res_pjsip_mwi.c.

◆ 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.

◆ MWI_SUBTYPE

#define MWI_SUBTYPE   "simple-message-summary"

Definition at line 55 of file res_pjsip_mwi.c.

◆ MWI_TYPE

#define MWI_TYPE   "application"

Definition at line 54 of file res_pjsip_mwi.c.

◆ STASIS_BUCKETS

#define STASIS_BUCKETS   13

Definition at line 51 of file res_pjsip_mwi.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1637 of file res_pjsip_mwi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1637 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.

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}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct stasis_forward * sub
Definition: res_corosync.c:240
static struct ast_datastore_info mwi_ds_info
#define MWI_DATASTORE
Definition: res_pjsip_mwi.c:57
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

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

Referenced by mwi_create_subscription().

◆ 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.

731{
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}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ast_debug(level,...)
Log a DEBUG message.
static struct stasis_subscription * mwi_sub
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 unsubscribe_stasis(void *obj, void *arg, int flags)
#define NULL
Definition: resample.c:96
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_sip_mwi_configuration mwi
Definition: res_pjsip.h:751
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:998
unsigned int aggregate
Definition: res_pjsip.h:735
unsigned int subscribe_replaces_unsolicited
Definition: res_pjsip.h:737
Wrapper for stasis subscription.
Definition: res_pjsip_mwi.c:97
A subscription for MWI.

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

Referenced by mwi_validate_for_aor().

◆ AO2_GLOBAL_OBJ_STATIC() [1/2]

AO2_GLOBAL_OBJ_STATIC ( mwi_solicited  )

◆ AO2_GLOBAL_OBJ_STATIC() [2/2]

AO2_GLOBAL_OBJ_STATIC ( mwi_unsolicited  )

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1637 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.

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
1317
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);
1335 ao2_unlock(unsolicited_mwi);
1336
1337 ao2_ref(endpoints, -1);
1338 ao2_cleanup(solicited_mwi);
1339 ao2_ref(unsolicited_mwi, -1);
1340}
#define var
Definition: ast_expr2f.c:605
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1723
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ast_variable_new(name, value, filename)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
static struct ao2_container * endpoints
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static int unsubscribe(void *obj, void *arg, int flags)
static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, void *data, int flags)
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
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
Generic container type.
Structure for variables, used for configurations and for channel variables.

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

◆ 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.

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)

References create_unsolicited_mwi_subscriptions().

Referenced by create_mwi_subscriptions().

◆ 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.

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
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}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
char * strsep(char **str, const char *delims)
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
static int send_notify(void *obj, void *arg, int flags)
static struct mwi_subscription * mwi_subscription_alloc(struct ast_sip_endpoint *endpoint, unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
static struct mwi_stasis_subscription * mwi_stasis_subscription_alloc(const char *mailbox, struct mwi_subscription *mwi_sub)
static int is_unsolicited_allowed(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
const ast_string_field mailboxes
Definition: res_pjsip.h:733
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References 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(), voicemailpwcheck::mailbox, ast_sip_mwi_configuration::mailboxes, mailboxes, ast_sip_endpoint_subscription_configuration::mwi, mwi_stasis_subscription_alloc(), mwi_subscription_alloc(), NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, RAII_VAR, send_notify(), strsep(), sub, and ast_sip_endpoint::subscription.

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

◆ 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.

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}
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
A SIP address of record.
Definition: res_pjsip.h:478
char * voicemail_extension
Definition: res_pjsip.h:508
const ast_string_field aors
Definition: res_pjsip.h:992

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

◆ 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.

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_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
Definition: mwi.c:269
The structure that contains MWI state.
Definition: mwi.h:455
int old_msgs
Definition: mwi.h:460
int new_msgs
Definition: mwi.h:459
Message counter used for message-summary XML bodies.
struct ast_mwi_subscriber * mwi_subscriber
Definition: res_pjsip_mwi.c:99

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

Referenced by mwi_get_notify_data(), and send_mwi_notify().

◆ global_loaded()

static void global_loaded ( const char *  object_type)
static

Definition at line 1505 of file res_pjsip_mwi.c.

1506{
1511}
#define ast_free(a)
Definition: astmm.h:180
char * ast_sip_get_default_voicemail_extension(void)
Retrieve the default voicemail extension.
int ast_sip_get_mwi_tps_queue_low(void)
Retrieve the global MWI taskprocessor low water clear alert level.
unsigned int ast_sip_get_mwi_tps_queue_high(void)
Retrieve the global MWI taskprocessor high water alert trigger level.
static struct ast_serializer_pool * mwi_serializer_pool
Definition: res_pjsip_mwi.c:66
static char * default_voicemail_extension
Definition: res_pjsip_mwi.c:49
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

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(), default_voicemail_extension, and mwi_serializer_pool.

◆ 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.

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}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * container
Definition: res_fax.c:501
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_find, ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, ast_sorcery_object_get_id(), container, voicemailpwcheck::mailbox, mwi_sub, NULL, OBJ_MULTIPLE, OBJ_NOLOCK, and OBJ_SEARCH_KEY.

Referenced by allow_and_or_replace_unsolicited(), and is_unsolicited_allowed().

◆ 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.

785{
787 struct mwi_stasis_subscription *mwi_stasis;
788
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;
825
826 ao2_ref(mwi_stasis, -1);
827 ao2_ref(mwi_sub, -1);
828
829 return 1;
830}

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

Referenced by create_unsolicited_mwi_subscriptions().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1568 of file res_pjsip_mwi.c.

1569{
1570 struct ao2_container *mwi_container;
1571
1574 }
1575
1578 if (!mwi_serializer_pool) {
1579 ast_log(AST_LOG_WARNING, "Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");
1580 }
1581
1584 if (!mwi_container) {
1585 unload_module();
1587 }
1588 ao2_global_obj_replace_unref(mwi_solicited, mwi_container);
1589 ao2_ref(mwi_container, -1);
1590
1593 if (!mwi_container) {
1594 unload_module();
1596 }
1597 ao2_global_obj_replace_unref(mwi_unsolicited, mwi_container);
1598 ao2_ref(mwi_container, -1);
1599
1603
1609 } else {
1610 struct stasis_subscription *sub;
1611
1615 }
1616 }
1617
1618 if (!mwi_serializer_pool) {
1619 /*
1620 * If the mwi serializer pool was unable to be established then the module will
1621 * use the default serializer pool. If this happens prevent manual unloading
1622 * since there would now exist the potential for a crash on unload.
1623 */
1625 }
1626
1628}
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1872
struct ast_flags ast_options
Definition: options.c:61
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:58
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:2099
#define AST_LOG_WARNING
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
Retrieve the global setting 'disable sending unsolicited mwi on startup'.
struct ast_threadpool * ast_sip_threadpool(void)
Retrieve the SIP threadpool object.
Definition: res_pjsip.c:3462
static struct ast_sorcery_observer global_observer
#define MAX_UNLOAD_TIMEOUT_TIME
Definition: res_pjsip_mwi.c:63
static const struct ast_sorcery_observer mwi_contact_observer
Observer for contacts so unsolicited MWI is sent when a contact changes.
static void create_mwi_subscriptions(void)
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.
static int mwi_sub_cmp(void *obj, void *arg, int flags)
static int unload_module(void)
#define MWI_BUCKETS
Definition: res_pjsip_mwi.c:52
static int mwi_sub_hash(const void *obj, const int flags)
static int send_initial_notify_all(void *obj)
Task invoked to send initial MWI NOTIFY for unsolicited.
#define MWI_SERIALIZER_POOL_SIZE
Definition: res_pjsip_mwi.c:60
static struct ast_sip_subscription_handler mwi_handler
Definition: res_pjsip_mwi.c:82
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
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
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
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
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1023
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1077
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:680
struct ast_module * self
Definition: module.h:342
#define ast_test_flag(p, flag)
Definition: utils.h:63

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_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_module_shutdown_ref, 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, create_mwi_subscriptions(), global_observer, MAX_UNLOAD_TIMEOUT_TIME, MWI_BUCKETS, mwi_contact_observer, mwi_handler, mwi_serializer_pool, MWI_SERIALIZER_POOL_SIZE, mwi_startup_event_cb(), mwi_sub_cmp(), mwi_sub_hash(), NULL, 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().

◆ 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.

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

References mwi_contact_changed().

◆ 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.

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}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
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.
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:424
const ast_string_field endpoint_name
Definition: res_pjsip.h:414
An entity with which Asterisk communicates.
Definition: res_pjsip.h:963

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

◆ 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.

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)) {
1455 }
1456 ao2_iterator_destroy(mwi_subs);
1457 }
1458 ao2_unlock(unsolicited_mwi);
1459 ao2_ref(unsolicited_mwi, -1);
1460}
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:392

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

◆ 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.

1403{
1404 mwi_contact_changed(object);
1405}

References mwi_contact_changed().

◆ 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.

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
static int add_mwi_datastore(struct mwi_subscription *sub)
struct ast_sip_subscription * sip_sub

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

Referenced by mwi_subscribe_all(), and mwi_subscribe_single().

◆ mwi_ds_destroy()

static void mwi_ds_destroy ( void *  data)
static

Definition at line 629 of file res_pjsip_mwi.c.

630{
631 struct mwi_subscription *sub = data;
632
633 ao2_ref(sub, -1);
634}

References ao2_ref, and sub.

◆ 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.

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;
1049
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
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
1073 ao2_callback(mwi_sub->stasis_subs, OBJ_NODATA, get_message_count, counter);
1074 ao2_cleanup(mwi_datastore);
1075 return counter;
1076}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
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 get_message_count(void *obj, void *arg, int flags)
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
pjsip_sip_uri * ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub)
Retrieve the local sip uri for this subscription.
pjsip_dialog * ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub)
Get the pjsip dialog that is associated with this subscription.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.

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(), sub, and ast_sip_aor::voicemail_extension.

◆ 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.

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}
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 'on_aor' handler.
Definition: location.c:687
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.

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.

◆ 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.

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
901 while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
902 struct mwi_stasis_subscription *mwi_stasis_sub;
903
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:486

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

Referenced by mwi_subscribe_all(), and mwi_subscribe_single().

◆ 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.

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
1503}
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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:971
struct ast_json * json
Definition: json.h:1083

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, mwi_serializer_pool, NULL, send_initial_notify_all(), stasis_message_data(), stasis_message_type(), stasis_unsubscribe(), sub, and type.

Referenced by load_module().

◆ 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.

1158{
1159 struct mwi_subscription *mwi_sub = userdata;
1160
1164 ao2_ref(mwi_sub, -1);
1165 }
1166 return;
1167 }
1168
1171 }
1172}
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
static int serialized_cleanup(void *userdata)
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:1174

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

Referenced by mwi_stasis_subscription_alloc().

◆ 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.

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);
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 stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
struct stasis_subscription * ast_mwi_subscriber_subscription(struct ast_mwi_subscriber *sub)
Retrieve the stasis MWI topic subscription if available.
Definition: mwi.c:277
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:235
static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)

References ao2_alloc, ao2_ref, ast_mwi_subscribe_pool(), ast_mwi_subscriber_subscription(), voicemailpwcheck::mailbox, mwi_stasis_subscription::mailbox, mwi_stasis_cb(), mwi_sub, 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().

◆ 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.

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) {
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}
@ CMP_MATCH
Definition: astobj2.h:1027
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072

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

Referenced by load_module().

◆ 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.

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;
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}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259
#define ast_assert(a)
Definition: utils.h:739

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

Referenced by load_module().

◆ 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.

962{
963 struct mwi_subscription *sub;
964
966 if (!sub) {
967 return NULL;
968 }
969
971 return sub;
972}
static struct mwi_subscription * mwi_create_subscription(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
static int mwi_on_aor(void *obj, void *arg, int flags)

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

Referenced by mwi_subscription_established().

◆ 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.

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
952 if (sub) {
953 mwi_on_aor(aor, sub, 0);
954 }
955
956 ao2_ref(aor, -1);
957 return sub;
958}
static const char name[]
Definition: format_mp3.c:68

References ao2_ref, ast_log, find_aor_for_resource(), LOG_WARNING, mwi_create_subscription(), mwi_on_aor(), name, NULL, mwi_subscription::sip_sub, and sub.

Referenced by mwi_subscription_established().

◆ 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.

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) {
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}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
static void mwi_subscription_destructor(void *obj)
static int stasis_sub_hash(const void *obj, const int flags)
static int stasis_sub_cmp(void *obj, void *arg, int flags)
#define STASIS_BUCKETS
Definition: res_pjsip_mwi.c:51
unsigned int is_solicited

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

Referenced by create_unsolicited_mwi_subscriptions(), and mwi_create_subscription().

◆ mwi_subscription_destructor()

static void mwi_subscription_destructor ( void *  obj)
static

Definition at line 219 of file res_pjsip_mwi.c.

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}
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.

References ao2_cleanup, ast_debug, ast_free, ast_sip_subscription_destroy(), and sub.

Referenced by mwi_subscription_alloc().

◆ mwi_subscription_established()

static int mwi_subscription_established ( struct ast_sip_subscription sub)
static

Definition at line 1005 of file res_pjsip_mwi.c.

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
1038 ao2_cleanup(endpoint);
1039 return 0;
1040}
static struct mwi_subscription * mwi_subscribe_all(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
static struct mwi_subscription * mwi_subscribe_single(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.

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::sip_sub, and sub.

◆ 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.

1080{
1081 int is_first = 1;
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}
const char * str
Definition: app_jack.c:147
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
Definition: test_heap.c:38

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_str_append(), and str.

Referenced by mwi_to_ami().

◆ mwi_subscription_shutdown()

static void mwi_subscription_shutdown ( struct ast_sip_subscription sub)
static

Definition at line 587 of file res_pjsip_mwi.c.

588{
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}

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_DATASTORE, mwi_sub, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sub, and unsubscribe_stasis().

◆ 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.

1099{
1100 struct mwi_subscription *mwi_sub;
1101 struct ast_datastore *mwi_datastore;
1102
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}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs, struct ast_str **str)

References ao2_ref, ast_sip_subscription_get_datastore(), ast_str_append(), buf, ast_datastore::data, MWI_DATASTORE, mwi_sub, mwi_subscription_mailboxes_str(), and 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.

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
863 while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
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}
static int allow_and_or_replace_unsolicited(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi)

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(), voicemailpwcheck::mailbox, ast_sip_aor::mailboxes, mailboxes, and strsep().

Referenced by mwi_new_subscribe().

◆ reload()

static int reload ( void  )
static

Definition at line 1517 of file res_pjsip_mwi.c.

1518{
1521 }
1522 return 0;
1523}

References ast_sip_get_mwi_disable_initial_unsolicited(), and create_mwi_subscriptions().

◆ 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.

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
1354 ao2_ref(mwi_sub, -1);
1355 }
1356
1357 return 0;
1358}
static int serialized_notify(void *userdata)

References ao2_bump, ao2_ref, ast_serializer_pool_get(), ast_sip_push_task(), mwi_serializer_pool, mwi_sub, and serialized_notify().

Referenced by mwi_contact_changed().

◆ 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.

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}

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

Referenced by load_module(), and mwi_startup_event_cb().

◆ send_mwi_notify()

static void send_mwi_notify ( struct mwi_subscription sub)
static

Definition at line 538 of file res_pjsip_mwi.c.

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
550 ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
551
552 if (sub->is_solicited) {
553 const char *resource = ast_sip_subscription_get_resource_name(sub->sip_sub);
554 struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(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
571}
static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, struct ast_sip_message_accumulator *counter)
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.
#define AST_SIP_MESSAGE_ACCUMULATOR
Data used to create bodies for NOTIFY/PUBLISH requests.
const char * body_type

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(), OBJ_NODATA, ast_sip_message_accumulator::old_msgs, send_unsolicited_mwi_notify(), set_voicemail_extension(), sub, and ast_sip_aor::voicemail_extension.

Referenced by serialized_notify().

◆ send_notify()

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

Definition at line 1142 of file res_pjsip_mwi.c.

1143{
1144 struct mwi_subscription *mwi_sub = obj;
1145 struct ast_taskprocessor *serializer = mwi_sub->is_solicited
1148
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.
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69

References ao2_bump, ao2_ref, ast_serializer_pool_get(), ast_sip_push_task(), ast_sip_subscription_get_serializer(), mwi_serializer_pool, mwi_sub, and serialized_notify().

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

◆ 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.

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}
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)
struct ast_sip_endpoint * endpoint
struct ast_sip_message_accumulator * counter
struct mwi_subscription * sub

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

◆ 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.

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;
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}
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:1979
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:2052
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:1435
#define MWI_TYPE
Definition: res_pjsip_mwi.c:54
#define MWI_SUBTYPE
Definition: res_pjsip_mwi.c:55
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.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
SIP body description.
Definition: res_pjsip.h:2325
const ast_string_field uri
Definition: res_pjsip.h:414
const ast_string_field fromuser
Definition: res_pjsip.h:733
Support for dynamic strings.
Definition: strings.h:623
Definition: astman.c:222
pjsip_evsub_state state

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_data::body_data, ast_sip_body::body_text, unsolicited_mwi_data::counter, unsolicited_mwi_data::endpoint, ast_sip_mwi_configuration::fromuser, 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().

◆ serialized_cleanup()

static int serialized_cleanup ( void *  userdata)
static

Definition at line 1127 of file res_pjsip_mwi.c.

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 */
1135 /* This is getting rid of the reference held by the
1136 * stasis subscription
1137 */
1139 return 0;
1140}

References ao2_cleanup, and mwi_sub.

Referenced by mwi_stasis_cb().

◆ serialized_notify()

static int serialized_notify ( void *  userdata)
static

Definition at line 1118 of file res_pjsip_mwi.c.

1119{
1120 struct mwi_subscription *mwi_sub = userdata;
1121
1123 ao2_ref(mwi_sub, -1);
1124 return 0;
1125}
static void send_mwi_notify(struct mwi_subscription *sub)

References ao2_ref, mwi_sub, and send_mwi_notify().

Referenced by send_contact_notify(), and send_notify().

◆ 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.

347{
348 pjsip_sip_uri *account_uri;
349 const char *vm_exten;
350
351 if (ast_strlen_zero(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}

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

◆ 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.

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) {
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}

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

◆ 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.

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;
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}

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

Referenced by mwi_subscription_alloc().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1525 of file res_pjsip_mwi.c.

1526{
1527 /*
1528 * pjsip_evsub_register_pkg is called by ast_sip_register_subscription_handler
1529 * but there is no corresponding unregister function, so unloading
1530 * a module does not remove the event package. If this module is ever
1531 * loaded again, then pjproject will assert and cause a crash.
1532 * For that reason, we must only be allowed to unload when
1533 * asterisk is shutting down. If a pjsip_evsub_unregister_pkg
1534 * API is added in the future then we should go back to unloading
1535 * the module as intended.
1536 */
1537
1538 if (ast_shutdown_final()) {
1539 struct ao2_container *unsolicited_mwi;
1540
1543
1544 unsolicited_mwi = ao2_global_obj_replace(mwi_unsolicited, NULL);
1545 if (unsolicited_mwi) {
1547 ao2_ref(unsolicited_mwi, -1);
1548 }
1549
1550 ao2_global_obj_release(mwi_solicited);
1551
1553 ast_log(LOG_WARNING, "Unload incomplete. Try again later\n");
1554 return -1;
1555 }
1557
1559
1562 return 0;
1563 } else {
1564 return -1;
1565 }
1566}
int ast_shutdown_final(void)
Definition: asterisk.c:1867
#define ao2_global_obj_replace(holder, obj)
Replace an ao2 object in the global holder.
Definition: astobj2.h:878
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
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

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

Referenced by load_module().

◆ unsubscribe()

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

◆ unsubscribe_stasis()

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

Definition at line 573 of file res_pjsip_mwi.c.

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}
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:259

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

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

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 = AST_BUILDOPT_SUM, .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 1637 of file res_pjsip_mwi.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1637 of file res_pjsip_mwi.c.

◆ default_voicemail_extension

char* default_voicemail_extension
static

◆ 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.

Referenced by load_module(), and unload_module().

◆ 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_deleted(const void *object)
Function called when a contact is 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.

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

Definition at line 1463 of file res_pjsip_mwi.c.

Referenced by load_module(), and unload_module().

◆ 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.

Referenced by add_mwi_datastore().

◆ mwi_handler

struct ast_sip_subscription_handler mwi_handler
static

Definition at line 82 of file res_pjsip_mwi.c.

Referenced by load_module(), and unload_module().

◆ 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.

Referenced by global_loaded(), load_module(), mwi_startup_event_cb(), mwi_stasis_cb(), send_contact_notify(), send_notify(), and unload_module().