summaryrefslogtreecommitdiff
path: root/res/res_pjsip_pubsub.c
diff options
context:
space:
mode:
authorGeorge Joseph <gjoseph@digium.com>2018-01-28 09:10:00 -0700
committerGeorge Joseph <gjoseph@digium.com>2018-01-30 09:29:51 -0600
commit2b9aa6b5bbe8d3ada6e4a9b0bc614f2f77470cd0 (patch)
treea9dff42e45491c719a4a08fc402472b9a82885cc /res/res_pjsip_pubsub.c
parent81db0aca0fb8d288a780ca664817ef231a9a4ac0 (diff)
res_pjsip_pubsub: Prune subs with reliable transports at startup
In an earlier release, inbound registrations on a reliable transport were pruned on Asterisk restart since the TCP connection would have been torn down and become unusable when Asterisk stopped. This same process is now also applied to inbound subscriptions. Also fixed issues in res_pjsip_registrar where it wasn't handling the monitoring correctly when multiple registrations came in over the same transport. To accomplish this, the pjsip_transport_event feature needed to be refactored to allow multiple monitors (multiple subcriptions or registrations from the same endpoint) to exist on the same transport. Since this changed the API, any external modules that may have used the transport monitor feature (highly unlikey) will need to be changed. ASTERISK-27612 Reported by: Ross Beer Change-Id: Iee87cf4eb9b7b2b93d5739a72af52d6ca8fbbe36
Diffstat (limited to 'res/res_pjsip_pubsub.c')
-rw-r--r--res/res_pjsip_pubsub.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 369e06d4c..c78f20c2b 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -127,6 +127,11 @@
<configOption name="contact_uri">
<synopsis>The Contact URI of the dialog for the subscription</synopsis>
</configOption>
+ <configOption name="prune_on_boot">
+ <synopsis>If set, indicates that the contact used a reliable transport
+ and therefore the subscription must be deleted after an asterisk restart.
+ </synopsis>
+ </configOption>
</configObject>
<configObject name="resource_list">
<synopsis>Resource list configuration parameters.</synopsis>
@@ -382,6 +387,8 @@ struct subscription_persistence {
struct timeval expires;
/*! Contact URI */
char contact_uri[PJSIP_MAX_URL_SIZE];
+ /*! Prune subscription on restart */
+ int prune_on_boot;
};
/*!
@@ -446,6 +453,10 @@ struct sip_subscription_tree {
* capable of restarting the timer.
*/
struct ast_sip_sched_task *expiration_task;
+ /*! The transport the subscription was received on.
+ * Only used for reliable transports.
+ */
+ pjsip_transport *transport;
};
/*!
@@ -549,6 +560,17 @@ static void *publication_resource_alloc(const char *name)
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy);
}
+static void sub_tree_transport_cb(void *data) {
+ struct sip_subscription_tree *sub_tree = data;
+
+ ast_debug(3, "Transport destroyed. Removing subscription '%s->%s' prune on restart: %d\n",
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot);
+
+ sub_tree->state = SIP_SUB_TREE_TERMINATE_IN_PROGRESS;
+ pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
+}
+
/*! \brief Destructor for subscription persistence */
static void subscription_persistence_destroy(void *obj)
{
@@ -599,8 +621,9 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
return;
}
- ast_debug(3, "Updating persistence for '%s->%s'\n", sub_tree->persistence->endpoint,
- sub_tree->root->resource);
+ ast_debug(3, "Updating persistence for '%s->%s' prune on restart: %s\n",
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot ? "yes" : "no");
dlg = sub_tree->dlg;
sub_tree->persistence->cseq = dlg->local.cseq;
@@ -614,6 +637,28 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
sub_tree->persistence->expires = ast_tvadd(ast_tvnow(), ast_samp2tv(expires, 1));
if (contact_hdr) {
+ if (contact_hdr) {
+ if (type == SUBSCRIPTION_PERSISTENCE_CREATED) {
+ sub_tree->persistence->prune_on_boot =
+ !ast_sip_will_uri_survive_restart(
+ (pjsip_sip_uri *)pjsip_uri_get_uri(contact_hdr->uri),
+ sub_tree->endpoint, rdata);
+
+ if (sub_tree->persistence->prune_on_boot) {
+ ast_debug(3, "adding transport monitor on %s for '%s->%s' prune on restart: %d\n",
+ rdata->tp_info.transport->obj_name,
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot);
+ sub_tree->transport = rdata->tp_info.transport;
+ ast_sip_transport_monitor_register(rdata->tp_info.transport,
+ sub_tree_transport_cb, sub_tree);
+ /*
+ * FYI: ast_sip_transport_monitor_register holds a reference to the sub_tree
+ */
+ }
+ }
+ }
+
pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, contact_hdr->uri,
sub_tree->persistence->contact_uri, sizeof(sub_tree->persistence->contact_uri));
} else {
@@ -656,6 +701,15 @@ static void subscription_persistence_remove(struct sip_subscription_tree *sub_tr
return;
}
+ if (sub_tree->persistence->prune_on_boot && sub_tree->transport) {
+ ast_debug(3, "Unregistering transport monitor on %s '%s->%s'\n",
+ sub_tree->transport->obj_name,
+ sub_tree->endpoint ? ast_sorcery_object_get_id(sub_tree->endpoint) : "Unknown",
+ sub_tree->root ? sub_tree->root->resource : "Unknown");
+ ast_sip_transport_monitor_unregister(sub_tree->transport,
+ sub_tree_transport_cb, sub_tree, NULL);
+ }
+
ast_sorcery_delete(ast_sip_get_sorcery(), sub_tree->persistence);
ao2_ref(sub_tree->persistence, -1);
sub_tree->persistence = NULL;
@@ -1564,6 +1618,14 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
pjsip_rx_data rdata;
struct persistence_recreate_data recreate_data;
+ /* If this subscription used a reliable transport it can't be reestablished so remove it */
+ if (persistence->prune_on_boot) {
+ ast_debug(3, "Deleting subscription marked as 'prune' from persistent store '%s' %s\n",
+ persistence->endpoint, persistence->tag);
+ ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
+ return 0;
+ }
+
/* If this subscription has already expired remove it */
if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
ast_debug(3, "Expired subscription retrived from persistent store '%s' %s\n",
@@ -5416,6 +5478,8 @@ static int load_module(void)
persistence_expires_str2struct, persistence_expires_struct2str, NULL, 0, 0);
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "contact_uri", "", OPT_CHAR_ARRAY_T, 0,
CHARFLDSET(struct subscription_persistence, contact_uri));
+ ast_sorcery_object_field_register(sorcery, "subscription_persistence", "prune_on_boot", "0", OPT_UINT_T, 0,
+ FLDSET(struct subscription_persistence, prune_on_boot));
if (apply_list_configuration(sorcery)) {
ast_sched_context_destroy(sched);
@@ -5492,6 +5556,8 @@ static int unload_module(void)
AST_TEST_UNREGISTER(loop);
AST_TEST_UNREGISTER(bad_event);
+ ast_sip_transport_monitor_unregister_all(sub_tree_transport_cb, NULL, NULL);
+
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_manager_unregister(AMI_SHOW_SUBSCRIPTIONS_OUTBOUND);