[Asterisk-code-review] res_pjsip_pubsub: update RLS to reflect the changes to the lists (asterisk[master])

Alexei Gradinari asteriskteam at digium.com
Wed Feb 23 08:32:01 CST 2022


Alexei Gradinari has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/18046 )


Change subject: res_pjsip_pubsub: update RLS to reflect the changes to the lists
......................................................................

res_pjsip_pubsub: update RLS to reflect the changes to the lists

This patch makes the Resource List Subscriptions (RLS) dynamic.
The asterisk updates the current subscriptions to reflect the changes
to the list on the subscriptions refresh. If list items are added,
removed, updated or do not exist anymore, the asterisk regenerates
the resource list.

ASTERISK-29906 #close

Change-Id: Icee8c00459a7aaa43c643d77ce6f16fb7ab037d3
---
A doc/CHANGES-staging/rls_refresh.txt
M res/res_pjsip_pubsub.c
2 files changed, 116 insertions(+), 4 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/46/18046/1

diff --git a/doc/CHANGES-staging/rls_refresh.txt b/doc/CHANGES-staging/rls_refresh.txt
new file mode 100644
index 0000000..fb36160
--- /dev/null
+++ b/doc/CHANGES-staging/rls_refresh.txt
@@ -0,0 +1,7 @@
+Subject: res_pjsip_pubsub
+
+The Resource List Subscriptions (RLS) is dynamic now.
+The asterisk now updates current subscriptions to reflect the changes
+to the list on subscription refresh. If list items are added,
+removed, updated or do not exist anymore, the asterisk regenerates
+the resource list.
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 31394e2..d741a65 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -464,6 +464,10 @@
 	 * Only used for reliable transports.
 	 */
 	pjsip_transport *transport;
+	/*! Indicator if initial notify should be generated.
+	 * Used to refresh modified RLS.
+	 */
+	unsigned int generate_initial_notify;
 };
 
 /*!
@@ -2438,10 +2442,13 @@
 		return -1;
 	}
 
-	tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root, force_full_state);
-	if (!tdata->msg->body) {
-		pjsip_tx_data_dec_ref(tdata);
-		return -1;
+	/* Do not generate body if Subscription is terminated */
+	if (sub_tree->root->subscription_state != PJSIP_EVSUB_STATE_TERMINATED) {
+		tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root, force_full_state);
+		if (!tdata->msg->body) {
+			pjsip_tx_data_dec_ref(tdata);
+			return -1;
+		}
 	}
 
 	if (sub_tree->is_list) {
@@ -3875,6 +3882,15 @@
 		set_state_terminated(sub_tree->root);
 	}
 
+	if (sub_tree->generate_initial_notify) {
+		sub_tree->generate_initial_notify = 0;
+		if (generate_initial_notify(sub_tree->root)) {
+			pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
+			pjsip_dlg_dec_lock(dlg);
+			return 0;
+		}
+	}
+
 	send_notify(sub_tree, 1);
 
 	ast_test_suite_event_notify(sub_tree->root->subscription_state == PJSIP_EVSUB_STATE_TERMINATED ?
@@ -3900,6 +3916,53 @@
 }
 
 /*!
+ * \brief Compare strings for equality checking for NULL.
+ *
+ * This function considers NULL values as empty strings.
+ * This means NULL or empty strings are equal.
+ *
+ * \retval 0 The strings are equal
+ * \retval 1 The strings are not equal
+ */
+static int cmp_strings(char *s1, char *s2)
+{
+	if (!ast_strlen_zero(s1) && !ast_strlen_zero(s2)) {
+		return strcmp(s1, s2);
+	}
+
+	return ast_strlen_zero(s1) == ast_strlen_zero(s2) ? 0 : 1;
+}
+
+/*!
+ * \brief compares the childrens of two ast_sip_subscription s1 and s2
+ *
+ * \retval 0 The s1 childrens match the s2 childrens
+ * \retval 1 The s1 childrens do not match the s2 childrens
+ */
+static int cmp_subscription_childrens(struct ast_sip_subscription *s1, struct ast_sip_subscription *s2)
+{
+	int i;
+
+	if (AST_VECTOR_SIZE(&s1->children) != AST_VECTOR_SIZE(&s2->children)) {
+		return 1;
+	}
+
+	for (i = 0; i < AST_VECTOR_SIZE(&s1->children); ++i) {
+		struct ast_sip_subscription *c1 = AST_VECTOR_GET(&s1->children, i);
+		struct ast_sip_subscription *c2 = AST_VECTOR_GET(&s2->children, i);
+
+		if (cmp_strings(c1->resource, c2->resource)
+			/* display_name is added in ASTERISK-29891, uncomment it when ASTERISK-29891 be merged
+			|| cmp_strings(c1->display_name, c2->display_name)*/) {
+
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*!
  * \brief Called whenever an in-dialog SUBSCRIBE is received
  *
  * This includes both SUBSCRIBE requests that actually refresh the subscription
@@ -3939,6 +4002,48 @@
 		sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING;
 	}
 
+	if (sub_tree->state == SIP_SUB_TREE_NORMAL && sub_tree->is_list) {
+		/* update RLS */
+		const char *resource = sub_tree->root->resource;
+		struct ast_sip_subscription *old_root = sub_tree->root;
+		struct ast_sip_subscription *new_root = NULL;
+		RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
+		struct ast_sip_subscription_handler *handler = NULL;
+		struct ast_sip_pubsub_body_generator *generator = NULL;
+
+		if ((endpoint = ast_pjsip_rdata_get_endpoint(rdata))
+			&& (handler = subscription_get_handler_from_rdata(rdata, ast_sorcery_object_get_id(endpoint)))
+			&& (generator = subscription_get_generator_from_rdata(rdata, handler))) {
+
+			struct resource_tree tree;
+			int resp;
+
+			memset(&tree, 0, sizeof(tree));
+			resp = build_resource_tree(endpoint, handler, resource, &tree,
+				ast_sip_pubsub_has_eventlist_support(rdata));
+			if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
+				new_root = create_virtual_subscriptions(handler, resource, generator, sub_tree, tree.root);
+				if (new_root) {
+					if (cmp_subscription_childrens(old_root, new_root)) {
+						ast_debug(1, "RLS '%s->%s' was modified, regenerate it\n", ast_sorcery_object_get_id(endpoint), old_root->resource);
+						new_root->version = old_root->version;
+						sub_tree->root = new_root;
+						sub_tree->generate_initial_notify = 1;
+						shutdown_subscriptions(old_root);
+						destroy_subscriptions(old_root);
+					} else {
+						destroy_subscriptions(new_root);
+					}
+				}
+			} else {
+				sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING;
+				pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
+			}
+
+			resource_tree_destroy(&tree);
+		}
+	}
+
 	subscription_persistence_update(sub_tree, rdata, SUBSCRIPTION_PERSISTENCE_REFRESHED);
 
 	if (ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_refresh_timeout, ao2_bump(sub_tree))) {

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18046
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: Icee8c00459a7aaa43c643d77ce6f16fb7ab037d3
Gerrit-Change-Number: 18046
Gerrit-PatchSet: 1
Gerrit-Owner: Alexei Gradinari <alex2grad at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220223/5c396c71/attachment-0001.html>


More information about the asterisk-code-review mailing list