diff options
Diffstat (limited to 'res/res_pjsip_mwi.c')
-rw-r--r-- | res/res_pjsip_mwi.c | 86 |
1 files changed, 59 insertions, 27 deletions
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c index eae029376..06587daf7 100644 --- a/res/res_pjsip_mwi.c +++ b/res/res_pjsip_mwi.c @@ -138,9 +138,17 @@ static struct mwi_stasis_subscription *mwi_stasis_subscription_alloc(const char /* Safe strcpy */ strcpy(mwi_stasis_sub->mailbox, mailbox); + + ast_debug(3, "Creating stasis MWI subscription to mailbox %s for endpoint %s\n", + mailbox, mwi_sub->id); ao2_ref(mwi_sub, +1); - ast_debug(3, "Creating stasis MWI subscription to mailbox %s for endpoint %s\n", mailbox, mwi_sub->id); mwi_stasis_sub->stasis_sub = stasis_subscribe_pool(topic, mwi_stasis_cb, mwi_sub); + if (!mwi_stasis_sub->stasis_sub) { + /* Failed to subscribe. */ + ao2_ref(mwi_stasis_sub, -1); + ao2_ref(mwi_sub, -1); + mwi_stasis_sub = NULL; + } return mwi_stasis_sub; } @@ -491,25 +499,41 @@ static void mwi_subscription_shutdown(struct ast_sip_subscription *sub) mwi_sub = mwi_datastore->data; ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL); + ast_sip_subscription_remove_datastore(sub, MWI_DATASTORE); ao2_ref(mwi_datastore, -1); } -static struct ast_datastore_info mwi_ds_info = { }; +static void mwi_ds_destroy(void *data) +{ + struct mwi_subscription *sub = data; + + ao2_ref(sub, -1); +} + +static struct ast_datastore_info mwi_ds_info = { + .destroy = mwi_ds_destroy, +}; static int add_mwi_datastore(struct mwi_subscription *sub) { struct ast_datastore *mwi_datastore; + int res; mwi_datastore = ast_sip_subscription_alloc_datastore(&mwi_ds_info, MWI_DATASTORE); if (!mwi_datastore) { return -1; } + ao2_ref(sub, +1); mwi_datastore->data = sub; - ast_sip_subscription_add_datastore(sub->sip_sub, mwi_datastore); + /* + * NOTE: Adding the datastore to the subscription creates a ref loop + * that must be manually broken. + */ + res = ast_sip_subscription_add_datastore(sub->sip_sub, mwi_datastore); ao2_ref(mwi_datastore, -1); - return 0; + return res; } /*! @@ -621,8 +645,8 @@ static struct mwi_subscription *mwi_create_subscription( } if (add_mwi_datastore(sub)) { - ast_log(LOG_WARNING, "Unable to allocate datastore on MWI " - "subscription from %s\n", sub->id); + ast_log(LOG_WARNING, "Unable to add datastore for MWI subscription to %s\n", + sub->id); ao2_ref(sub, -1); return NULL; } @@ -633,25 +657,26 @@ static struct mwi_subscription *mwi_create_subscription( static struct mwi_subscription *mwi_subscribe_single( struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name) { - RAII_VAR(struct ast_sip_aor *, aor, - ast_sip_location_retrieve_aor(name), ao2_cleanup); + struct ast_sip_aor *aor; struct mwi_subscription *sub; + aor = ast_sip_location_retrieve_aor(name); if (!aor) { /*! I suppose it's possible for the AOR to disappear on us * between accepting the subscription and sending the first * NOTIFY... */ - ast_log(LOG_WARNING, "Unable to locate aor %s. MWI " - "subscription failed.\n", name); + ast_log(LOG_WARNING, "Unable to locate aor %s. MWI subscription failed.\n", + name); return NULL; } - if (!(sub = mwi_create_subscription(endpoint, sip_sub))) { - return NULL; + sub = mwi_create_subscription(endpoint, sip_sub); + if (sub) { + mwi_on_aor(aor, sub, 0); } - mwi_on_aor(aor, sub, 0); + ao2_ref(aor, -1); return sub; } @@ -661,7 +686,6 @@ static struct mwi_subscription *mwi_subscribe_all( struct mwi_subscription *sub; sub = mwi_create_subscription(endpoint, sip_sub); - if (!sub) { return NULL; } @@ -683,16 +707,15 @@ static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint, } aor = ast_sip_location_retrieve_aor(resource); - if (!aor) { - ast_log(LOG_WARNING, "Unable to locate aor %s. MWI " - "subscription failed.\n", resource); + ast_log(LOG_WARNING, "Unable to locate aor %s. MWI subscription failed.\n", + resource); return 404; } if (ast_strlen_zero(aor->mailboxes)) { - ast_log(LOG_NOTICE, "AOR %s has no configured mailboxes. " - "MWI subscription failed\n", resource); + ast_log(LOG_NOTICE, "AOR %s has no configured mailboxes. MWI subscription failed.\n", + resource); return 404; } @@ -715,12 +738,19 @@ static int mwi_subscription_established(struct ast_sip_subscription *sip_sub) } else { sub = mwi_subscribe_single(endpoint, sip_sub, resource); } - if (!sub) { ao2_cleanup(endpoint); return -1; } + if (!ao2_container_count(sub->stasis_subs)) { + /* + * We setup no MWI subscriptions so remove the MWI datastore + * to break the ref loop. + */ + ast_sip_subscription_remove_datastore(sip_sub, MWI_DATASTORE); + } + ao2_cleanup(sub); ao2_cleanup(endpoint); return 0; @@ -752,16 +782,16 @@ static void *mwi_get_notify_data(struct ast_sip_subscription *sub) static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs, struct ast_str **str) { - int num = ao2_container_count(stasis_subs); - + int is_first = 1; struct mwi_stasis_subscription *node; struct ao2_iterator i = ao2_iterator_init(stasis_subs, 0); while ((node = ao2_iterator_next(&i))) { - if (--num) { - ast_str_append(str, 0, "%s,", node->mailbox); - } else { + if (is_first) { + is_first = 0; ast_str_append(str, 0, "%s", node->mailbox); + } else { + ast_str_append(str, 0, ",%s", node->mailbox); } ao2_ref(node, -1); } @@ -816,7 +846,9 @@ static int serialized_cleanup(void *userdata) static int send_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; + 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); @@ -842,6 +874,7 @@ static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub, } } +/*! \note Called with the unsolicited_mwi conainer lock held. */ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags) { RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup); @@ -982,7 +1015,6 @@ static void mwi_contact_added(const void *object) ao2_lock(unsolicited_mwi); mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE | OBJ_NOLOCK | OBJ_UNLINK); - if (mwi_subs) { for (; (mwi_sub = ao2_iterator_next(mwi_subs)); ao2_cleanup(mwi_sub)) { unsubscribe(mwi_sub, NULL, 0); |