summaryrefslogtreecommitdiff
path: root/res/res_pjsip_mwi.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2015-06-17 07:04:39 -0300
committerJoshua Colp <jcolp@digium.com>2015-06-23 10:12:38 -0300
commit80e82dc97f85ce55bbdb311ea2dce641df388c70 (patch)
tree4e897f3a0d5cdf83b3c236f16a30ac7f390a95bc /res/res_pjsip_mwi.c
parent74616ae43d4e24e914ee612846a464da5b241b9b (diff)
res_pjsip_mwi: Set up unsolicited MWI upon registration.
The res_pjsip_mwi previously required a reload to set up the proper subscriptions to allow unsolicited MWI to work. This change makes it so the act of registering will also cause this to occur. This is particularly useful if realtime is involved as no reload needs to occur within Asterisk to cause the MWI information to get sent. ASTERISK-25180 #close Change-Id: Id847b47de4b8b3ab8858455ccc2f07b0f915f252
Diffstat (limited to 'res/res_pjsip_mwi.c')
-rw-r--r--res/res_pjsip_mwi.c176
1 files changed, 113 insertions, 63 deletions
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index 76e0e4c35..eae029376 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -40,7 +40,7 @@
#include "asterisk/app.h"
struct mwi_subscription;
-AO2_GLOBAL_OBJ_STATIC(unsolicited_mwi);
+static struct ao2_container *unsolicited_mwi;
#define STASIS_BUCKETS 13
#define MWI_BUCKETS 53
@@ -297,7 +297,7 @@ static int mwi_sub_cmp(void *obj, void *arg, int flags)
static int get_message_count(void *obj, void *arg, int flags)
{
- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct stasis_message *msg;
struct mwi_stasis_subscription *mwi_stasis = obj;
struct ast_sip_message_accumulator *counter = arg;
struct ast_mwi_state *mwi_state;
@@ -310,6 +310,9 @@ static int get_message_count(void *obj, void *arg, int flags)
mwi_state = stasis_message_data(msg);
counter->old_msgs += mwi_state->old_msgs;
counter->new_msgs += mwi_state->new_msgs;
+
+ ao2_ref(msg, -1);
+
return 0;
}
@@ -479,22 +482,24 @@ static int unsubscribe_stasis(void *obj, void *arg, int flags)
static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
{
struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, MWI_DATASTORE), ao2_cleanup);
+ struct ast_datastore *mwi_datastore;
+ mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
if (!mwi_datastore) {
return;
}
mwi_sub = mwi_datastore->data;
ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
+
+ ao2_ref(mwi_datastore, -1);
}
static struct ast_datastore_info mwi_ds_info = { };
static int add_mwi_datastore(struct mwi_subscription *sub)
{
- RAII_VAR(struct ast_datastore *, mwi_datastore, NULL, ao2_cleanup);
+ struct ast_datastore *mwi_datastore;
mwi_datastore = ast_sip_subscription_alloc_datastore(&mwi_ds_info, MWI_DATASTORE);
if (!mwi_datastore) {
@@ -503,6 +508,7 @@ static int add_mwi_datastore(struct mwi_subscription *sub)
mwi_datastore->data = sub;
ast_sip_subscription_add_datastore(sub->sip_sub, mwi_datastore);
+ ao2_ref(mwi_datastore, -1);
return 0;
}
@@ -517,18 +523,12 @@ static int add_mwi_datastore(struct mwi_subscription *sub)
static int endpoint_receives_unsolicited_mwi_for_mailbox(struct ast_sip_endpoint *endpoint,
const char *mailbox)
{
- struct ao2_container *unsolicited = ao2_global_obj_ref(unsolicited_mwi);
struct ao2_iterator *mwi_subs;
struct mwi_subscription *mwi_sub;
const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
int ret = 0;
- if (!unsolicited) {
- return 0;
- }
-
- mwi_subs = ao2_find(unsolicited, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
- ao2_cleanup(unsolicited);
+ mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
if (!mwi_subs) {
return 0;
@@ -597,11 +597,15 @@ static int mwi_on_aor(void *obj, void *arg, int flags)
mailboxes = ast_strdupa(aor->mailboxes);
while ((mailbox = strsep(&mailboxes, ","))) {
- RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
- mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
- if (mwi_stasis_sub) {
- ao2_link(sub->stasis_subs, mwi_stasis_sub);
+ struct mwi_stasis_subscription *mwi_stasis_sub;
+
+ mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
+ if (!mwi_stasis_sub) {
+ continue;
}
+
+ ao2_link(sub->stasis_subs, mwi_stasis_sub);
+ ao2_ref(mwi_stasis_sub, -1);
}
return 0;
@@ -768,9 +772,9 @@ static void mwi_to_ami(struct ast_sip_subscription *sub,
struct ast_str **buf)
{
struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, MWI_DATASTORE), ao2_cleanup);
+ struct ast_datastore *mwi_datastore;
+ mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
if (!mwi_datastore) {
return;
}
@@ -781,6 +785,8 @@ static void mwi_to_ami(struct ast_sip_subscription *sub,
ast_str_append(buf, 0, "Mailboxes: ");
mwi_subscription_mailboxes_str(mwi_sub->stasis_subs, buf);
ast_str_append(buf, 0, "\r\n");
+
+ ao2_ref(mwi_datastore, -1);
}
static int serialized_notify(void *userdata)
@@ -840,14 +846,38 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
{
RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup);
struct ast_sip_endpoint *endpoint = obj;
- struct ao2_container *mwi_subscriptions = arg;
- char *mailboxes;
- char *mailbox;
+ char *endpoint_aors, *aor_name, *mailboxes, *mailbox;
+ struct ao2_container *contacts = NULL;
if (ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
return 0;
}
+ endpoint_aors = ast_strdupa(endpoint->aors);
+
+ while ((aor_name = strsep(&endpoint_aors, ","))) {
+ RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
+
+ if (!aor) {
+ continue;
+ }
+
+ contacts = ast_sip_location_retrieve_aor_contacts(aor);
+ if (!contacts || (ao2_container_count(contacts) == 0)) {
+ ao2_cleanup(contacts);
+ contacts = NULL;
+ continue;
+ }
+
+ break;
+ }
+
+ if (!contacts) {
+ return 0;
+ }
+
+ ao2_ref(contacts, -1);
+
if (endpoint->subscription.mwi.aggregate) {
aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
if (!aggregate_sub) {
@@ -859,18 +889,20 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
while ((mailbox = strsep(&mailboxes, ","))) {
struct mwi_subscription *sub = aggregate_sub ?:
mwi_subscription_alloc(endpoint, 0, NULL);
- RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
- mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
+ struct mwi_stasis_subscription *mwi_stasis_sub;
+
+ mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
if (mwi_stasis_sub) {
ao2_link(sub->stasis_subs, mwi_stasis_sub);
+ ao2_ref(mwi_stasis_sub, -1);
}
- if (!aggregate_sub) {
- ao2_link(mwi_subscriptions, sub);
- ao2_cleanup(sub);
+ if (!aggregate_sub && sub) {
+ ao2_link_flags(unsolicited_mwi, sub, OBJ_NOLOCK);
+ ao2_ref(sub, -1);
}
}
if (aggregate_sub) {
- ao2_link(mwi_subscriptions, aggregate_sub);
+ ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
}
return 0;
}
@@ -886,13 +918,11 @@ static int unsubscribe(void *obj, void *arg, int flags)
static void create_mwi_subscriptions(void)
{
- struct ao2_container *mwi_subscriptions = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
- RAII_VAR(struct ao2_container *, old_mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
- RAII_VAR(struct ao2_container *, endpoints, ast_sorcery_retrieve_by_fields(
- ast_sip_get_sorcery(), "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL),
- ao2_cleanup);
+ struct ao2_container *endpoints;
- if (!mwi_subscriptions) {
+ endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ if (!endpoints) {
return;
}
@@ -902,12 +932,12 @@ static void create_mwi_subscriptions(void)
* and resubscribing, up-to-date mailbox state will be sent out to the endpoint when the
* new stasis subscription is established
*/
- if (old_mwi_subscriptions) {
- ao2_callback(old_mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
- }
- ao2_callback(endpoints, OBJ_NODATA, create_mwi_subscriptions_for_endpoint, mwi_subscriptions);
- ao2_global_obj_replace_unref(unsolicited_mwi, mwi_subscriptions);
- ao2_ref(mwi_subscriptions, -1);
+ ao2_lock(unsolicited_mwi);
+ ao2_callback(unsolicited_mwi, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
+ ao2_callback(endpoints, OBJ_NODATA, create_mwi_subscriptions_for_endpoint, NULL);
+ ao2_unlock(unsolicited_mwi);
+
+ ao2_ref(endpoints, -1);
}
/*! \brief Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR */
@@ -927,40 +957,56 @@ static int send_contact_notify(void *obj, void *arg, int flags)
return 0;
}
-
-/*! \brief Function called when a contact is created or updated */
-static void mwi_contact_changed_observer(const void *object)
+/*! \brief Function called when a contact is updated */
+static void mwi_contact_updated(const void *object)
{
char *id = ast_strdupa(ast_sorcery_object_get_id(object)), *aor = NULL;
- struct ao2_container *mwi_subscriptions = ao2_global_obj_ref(unsolicited_mwi);
- if (!mwi_subscriptions) {
+ aor = strsep(&id, ";@");
+
+ ao2_callback(unsolicited_mwi, OBJ_NODATA, send_contact_notify, aor);
+}
+
+/*! \brief Function called when a contact is added */
+static void mwi_contact_added(const void *object)
+{
+ const struct ast_sip_contact *contact = object;
+ struct ao2_iterator *mwi_subs;
+ struct mwi_subscription *mwi_sub;
+ const char *endpoint_id = ast_sorcery_object_get_id(contact->endpoint);
+
+ if (ast_strlen_zero(contact->endpoint->subscription.mwi.mailboxes)) {
return;
}
- aor = strsep(&id, ";@");
+ ao2_lock(unsolicited_mwi);
+
+ mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE | OBJ_NOLOCK | OBJ_UNLINK);
- ao2_callback(mwi_subscriptions, OBJ_NODATA, send_contact_notify, aor);
- ao2_ref(mwi_subscriptions, -1);
+ if (mwi_subs) {
+ for (; (mwi_sub = ao2_iterator_next(mwi_subs)); ao2_cleanup(mwi_sub)) {
+ unsubscribe(mwi_sub, NULL, 0);
+ }
+ ao2_iterator_destroy(mwi_subs);
+ }
+
+ create_mwi_subscriptions_for_endpoint(contact->endpoint, NULL, 0);
+
+ ao2_unlock(unsolicited_mwi);
+
+ mwi_contact_updated(object);
}
/*! \brief Observer for contacts so unsolicited MWI is sent when a contact changes */
static const struct ast_sorcery_observer mwi_contact_observer = {
- .created = mwi_contact_changed_observer,
- .updated = mwi_contact_changed_observer,
+ .created = mwi_contact_added,
+ .updated = mwi_contact_updated,
};
/*! \brief Task invoked to send initial MWI NOTIFY for unsolicited */
static int send_initial_notify_all(void *obj)
{
- struct ao2_container *mwi_subscriptions = ao2_global_obj_ref(unsolicited_mwi);
-
- if (!mwi_subscriptions) {
- return 0;
- }
-
- ao2_callback(mwi_subscriptions, OBJ_NODATA, send_notify, NULL);
- ao2_ref(mwi_subscriptions, -1);
+ ao2_callback(unsolicited_mwi, OBJ_NODATA, send_notify, NULL);
return 0;
}
@@ -1000,6 +1046,13 @@ static int load_module(void)
if (ast_sip_register_subscription_handler(&mwi_handler)) {
return AST_MODULE_LOAD_DECLINE;
}
+
+ unsolicited_mwi = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
+ if (!unsolicited_mwi) {
+ ast_sip_unregister_subscription_handler(&mwi_handler);
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
create_mwi_subscriptions();
ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
@@ -1014,12 +1067,9 @@ static int load_module(void)
static int unload_module(void)
{
- RAII_VAR(struct ao2_container *, mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
- if (mwi_subscriptions) {
- ao2_callback(mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
- ao2_global_obj_release(unsolicited_mwi);
- ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
- }
+ ao2_callback(unsolicited_mwi, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
+ ao2_ref(unsolicited_mwi, -1);
+ ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
ast_sip_unregister_subscription_handler(&mwi_handler);
return 0;
}