[Asterisk-code-review] res pjsip mwi: Send unsolicited MWI NOTIFY on startup and wh... (asterisk[master])
Joshua Colp
asteriskteam at digium.com
Tue Apr 21 04:54:35 CDT 2015
Joshua Colp has uploaded a new change for review.
https://gerrit.asterisk.org/176
Change subject: res_pjsip_mwi: Send unsolicited MWI NOTIFY on startup and when endpoint registers.
......................................................................
res_pjsip_mwi: Send unsolicited MWI NOTIFY on startup and when endpoint registers.
Currently the res_pjsip_mwi module only sends an unsolicited MWI NOTIFY upon
a mailbox state change (such as a new message being left, or one being deleted).
In practice this is not sufficient to keep clients aware of the current MWI status.
This change makes the module send unsolicited MWI NOTIFY on startup so that
clients are guaranteed to have the most up to date MWI information. It also makes
clients receive an unsolicited MWI NOTIFY upon registration so if they are unaware
of the current MWI status they receive it.
ASTERISK-24982 #close
Reported by: Joshua Colp
Change-Id: I043f20230227e91218f18a82c7d5bb2aa62b1d58
---
M res/res_pjsip_mwi.c
1 file changed, 115 insertions(+), 5 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/76/176/1
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index 9c275af..4ecad03 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -100,12 +100,14 @@
*/
struct mwi_subscription {
/*! Container of \ref mwi_stasis_subscription structures.
- * A single MWI subscription may be fore multiple mailboxes, thus
+ * A single MWI subscription may be for multiple mailboxes, thus
* requiring multiple stasis subscriptions
*/
struct ao2_container *stasis_subs;
/*! The SIP subscription. Unsolicited MWI does not use this */
struct ast_sip_subscription *sip_sub;
+ /*! AORs we should react to for unsolicited MWI NOTIFY */
+ char *aors;
/*! Is the MWI solicited (i.e. Initiated with an external SUBSCRIBE) ? */
unsigned int is_solicited;
/*! Identifier for the subscription.
@@ -231,6 +233,14 @@
return NULL;
}
sub->is_solicited = is_solicited;
+
+ if (!is_solicited && !ast_strlen_zero(endpoint->aors)) {
+ sub->aors = ast_strdup(endpoint->aors);
+ if (!sub->aors) {
+ ao2_ref(sub, -1);
+ return NULL;
+ }
+ }
ast_debug(3, "Created %s MWI subscription for endpoint %s\n", is_solicited ? "solicited" : "unsolicited", sub->id);
@@ -802,15 +812,18 @@
struct mwi_subscription *mwi_sub = userdata;
if (stasis_subscription_final_message(sub, msg)) {
- ao2_ref(mwi_sub, +1);
- ast_sip_push_task(NULL, serialized_cleanup, mwi_sub);
+ if (ast_sip_push_task(NULL, serialized_cleanup, ao2_bump(mwi_sub))) {
+ ao2_ref(mwi_sub, -1);
+ }
return;
}
if (ast_mwi_state_type() == stasis_message_type(msg)) {
struct ast_taskprocessor *serializer = mwi_sub->is_solicited ? ast_sip_subscription_get_serializer(mwi_sub->sip_sub) : NULL;
- ao2_ref(mwi_sub, +1);
- ast_sip_push_task(serializer, serialized_notify, mwi_sub);
+
+ if (ast_sip_push_task(serializer, serialized_notify, ao2_bump(mwi_sub))) {
+ ao2_ref(mwi_sub, -1);
+ }
}
}
@@ -858,7 +871,20 @@
struct mwi_subscription *mwi_sub = obj;
ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
+
return CMP_MATCH;
+}
+
+static int send_initial_notify(void *obj, void *arg, int flags)
+{
+ struct mwi_subscription *mwi_sub = obj;
+ struct ast_taskprocessor *serializer = mwi_sub->is_solicited ? ast_sip_subscription_get_serializer(mwi_sub->sip_sub) : NULL;
+
+ if (ast_sip_push_task(serializer, serialized_notify, ao2_bump(mwi_sub))) {
+ ao2_ref(mwi_sub, -1);
+ }
+
+ return 0;
}
static void create_mwi_subscriptions(void)
@@ -887,6 +913,81 @@
ao2_ref(mwi_subscriptions, -1);
}
+/*! \brief Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR */
+static int send_contact_notify(void *obj, void *arg, int flags)
+{
+ struct mwi_subscription *mwi_sub = obj;
+ const char *aor = arg;
+
+ if (!mwi_sub->aors || !strstr(mwi_sub->aors, aor)) {
+ return 0;
+ }
+
+ if (ast_sip_push_task(NULL, serialized_notify, ao2_bump(mwi_sub))) {
+ ao2_ref(mwi_sub, -1);
+ }
+
+ return 0;
+}
+
+
+/*! \brief Function called when a contact is created or updated */
+static void mwi_contact_changed_observer(const void *object)
+{
+ char *id = ast_strdupa(ast_sorcery_object_get_id(object)), *aor = NULL;
+ RAII_VAR(struct ao2_container *, mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
+
+ if (!mwi_subscriptions) {
+ return;
+ }
+
+ aor = strsep(&id, ";@");
+
+ ao2_callback(mwi_subscriptions, OBJ_NODATA, send_contact_notify, aor);
+}
+
+/*! \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,
+};
+
+/*! \brief Task invoked to send initial MWI NOTIFY for unsolicited */
+static int send_initial_notify_all(void *obj)
+{
+ RAII_VAR(struct ao2_container *, mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
+
+ if (!mwi_subscriptions) {
+ return 0;
+ }
+
+ ao2_callback(mwi_subscriptions, OBJ_NODATA, send_initial_notify, NULL);
+
+ return 0;
+}
+
+/*! \brief Event callback which fires initial unsolicited MWI NOTIFY messages when we're fully booted */
+static void mwi_startup_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+ struct ast_json_payload *payload;
+ const char *type;
+
+ if (stasis_message_type(message) != ast_manager_get_generic_type()) {
+ return;
+ }
+
+ payload = stasis_message_data(message);
+ type = ast_json_string_get(ast_json_object_get(payload->json, "type"));
+
+ if (strcmp(type, "FullyBooted")) {
+ return;
+ }
+
+ ast_sip_push_task(NULL, send_initial_notify_all, NULL);
+
+ stasis_unsubscribe(sub);
+}
+
static int reload(void)
{
create_mwi_subscriptions();
@@ -901,6 +1002,14 @@
return AST_MODULE_LOAD_DECLINE;
}
create_mwi_subscriptions();
+ ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
+
+ if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
+ ast_sip_push_task(NULL, send_initial_notify_all, NULL);
+ } else {
+ stasis_subscribe_pool(ast_manager_get_topic(), mwi_startup_event_cb, NULL);
+ }
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -910,6 +1019,7 @@
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);
}
ast_sip_unregister_subscription_handler(&mwi_handler);
return 0;
--
To view, visit https://gerrit.asterisk.org/176
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I043f20230227e91218f18a82c7d5bb2aa62b1d58
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Joshua Colp <jcolp at digium.com>
More information about the asterisk-code-review
mailing list