[Asterisk-code-review] res_pjsip_pubsub: provide a display name for RLS subscriptions (asterisk[18])

Alexei Gradinari asteriskteam at digium.com
Tue Feb 15 17:18:56 CST 2022


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


Change subject: res_pjsip_pubsub: provide a display name for RLS subscriptions
......................................................................

res_pjsip_pubsub: provide a display name for RLS subscriptions

Whereas BLFs allow to show a display name for each RLS entry,
the asterisk provides only the extension now.
This is not end user friendly.

This commit adds a new resource_list option, resource_display_name,
to indicate whether display name of resource or the resource name being
provided for RLS entries.
If this option is enabled, the Display Name will be provided.
This option is disabled by default to remain the previous behavior.
If the 'event' set to 'presence' or 'dialog' the non-empty HINT name
will be set as the Display Name.
The 'message-summary' is not supported yet.

ASTERISK-29891 #close

Change-Id: Ic5306bd5a7c73d03f5477fe235e9b0f41c69c681
---
M configs/samples/pjsip.conf.sample
A contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py
A doc/CHANGES-staging/rls_display_name.txt
M include/asterisk/res_pjsip_pubsub.h
M res/res_pjsip_exten_state.c
M res/res_pjsip_pubsub.c
6 files changed, 124 insertions(+), 9 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/21/18021/1

diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 6f0601d..8507b4e 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -1502,6 +1502,19 @@
                            ; Time Asterisk should wait, in milliseconds,
                            ; before sending notifications.
 
+;resource_display_name=no  ; Indicates whether display name of resource
+                           ; or the resource name being reported.
+                           ; If this option is enabled, the Display Name
+                           ; will be reported as resource name.
+                           ; If the event set to presence or dialog,
+                           ; the HINT name will be set as the Display Name.
+                           ; For example:
+                           ;  exten => 1234,hint,PJSIP/user1234(Alice)
+                           ; If enabled the resource name will be 'Alice'.
+                           ; If disabled the resource name will be '1234'.
+                           ; The message-summary is not supported yet.
+
+
 ;==========================INBOUND_PUBLICATION================================
 ; See https://wiki.asterisk.org/wiki/display/AST/Exchanging+Device+and+Mailbox+State+Using+PJSIP
 ; for more information.
diff --git a/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py b/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py
new file mode 100644
index 0000000..8af67bf
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py
@@ -0,0 +1,29 @@
+"""res_pjsip_pubsub add resource_list option resource_display_name
+
+Revision ID: 8f72185e437f
+Revises: a06d8f8462d9
+Create Date: 2022-02-01 10:53:55.875438
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '8f72185e437f'
+down_revision = 'a06d8f8462d9'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+AST_BOOL_NAME = 'ast_bool_values'
+AST_BOOL_VALUES = [ '0', '1',
+                    'off', 'on',
+                    'false', 'true',
+                    'no', 'yes' ]
+
+def upgrade():
+    ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False)
+    op.add_column('ps_resource_list', sa.Column('resource_display_name', ast_bool_values))
+
+def downgrade():
+    op.drop_column('ps_resource_list', 'resource_display_name')
+
diff --git a/doc/CHANGES-staging/rls_display_name.txt b/doc/CHANGES-staging/rls_display_name.txt
new file mode 100644
index 0000000..0d95b08
--- /dev/null
+++ b/doc/CHANGES-staging/rls_display_name.txt
@@ -0,0 +1,10 @@
+Subject: res_pjsip_pubsub
+
+A new resource_list option, resource_display_name, indicates
+whether display name of resource or the resource name being
+provided for RLS entries.
+If this option is enabled, the Display Name will be provided.
+This option is disabled by default to remain the previous behavior.
+If the 'event' set to 'presence' or 'dialog' the non-empty HINT name
+will be set as the Display Name.
+The 'message-summary' is not supported yet.
diff --git a/include/asterisk/res_pjsip_pubsub.h b/include/asterisk/res_pjsip_pubsub.h
index 354b0b2..aca1141 100644
--- a/include/asterisk/res_pjsip_pubsub.h
+++ b/include/asterisk/res_pjsip_pubsub.h
@@ -292,6 +292,17 @@
 	 * \return An ao2 object that can be used to create a NOTIFY body.
 	 */
 	void *(*get_notify_data)(struct ast_sip_subscription *sub);
+	/*!
+	 * \brief Supply Display Name for resource
+	 *
+	 * \param endpoint The endpoint from which we received the SUBSCRIBE
+	 * \param resource The name of the resource to which the subscription is being made
+	 * \param display_name buffer for Display Name
+	 * \param display_name_size size of display_name buffer
+	 * \retval 0 Success
+	 * \retval -1 Failure
+	 */
+	int (*get_resource_display_name)(struct ast_sip_endpoint *endpoint, const char *resource, char *display_name, int display_name_size);
 };
 
 struct ast_sip_subscriber {
diff --git a/res/res_pjsip_exten_state.c b/res/res_pjsip_exten_state.c
index df9a35f..b51df87 100644
--- a/res/res_pjsip_exten_state.c
+++ b/res/res_pjsip_exten_state.c
@@ -117,6 +117,7 @@
 static int new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource);
 static int subscription_established(struct ast_sip_subscription *sub);
 static void *get_notify_data(struct ast_sip_subscription *sub);
+static int get_resource_display_name(struct ast_sip_endpoint *endpoint, const char *resource, char *display_name, int display_name_size);
 static void to_ami(struct ast_sip_subscription *sub,
 		   struct ast_str **buf);
 static int publisher_start(struct ast_sip_outbound_publish *configuration,
@@ -128,6 +129,7 @@
 	.new_subscribe = new_subscribe,
 	.subscription_established = subscription_established,
 	.get_notify_data = get_notify_data,
+	.get_resource_display_name = get_resource_display_name,
 };
 
 struct ast_sip_notifier dialog_notifier = {
@@ -135,6 +137,7 @@
 	.new_subscribe = new_subscribe,
 	.subscription_established = subscription_established,
 	.get_notify_data = get_notify_data,
+	.get_resource_display_name = get_resource_display_name,
 };
 
 struct ast_sip_subscription_handler presence_handler = {
@@ -424,6 +427,27 @@
 	return 200;
 }
 
+static int get_resource_display_name(struct ast_sip_endpoint *endpoint,
+		const char *resource, char *display_name, int display_name_size)
+{
+	const char *context;
+
+	if (!endpoint || ast_strlen_zero(resource) || !display_name || display_name_size <= 0) {
+		return -1;
+	}
+
+	context = S_OR(endpoint->subscription.context, endpoint->context);
+
+	if (!ast_get_hint(NULL, 0, display_name, display_name_size, NULL, context, resource)) {
+		ast_log(LOG_NOTICE, "Endpoint '%s': "
+			"Extension '%s' does not exist in context '%s' or has no associated hint\n",
+			ast_sorcery_object_get_id(endpoint), resource, context);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int subscription_established(struct ast_sip_subscription *sip_sub)
 {
 	struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 31394e2..60506db 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -210,6 +210,15 @@
 						many notifications.</para>
 					</description>
 				</configOption>
+				<configOption name="resource_display_name" default="no">
+					<synopsis>Indicates whether display name of resource or the resource name being reported.</synopsis>
+					<description>
+						<para>If this option is enabled, the Display Name will be reported as resource name.
+						If the <replaceable>event</replaceable> set to <literal>presence</literal> or <literal>dialog</literal>,
+						the non-empty HINT name will be set as the Display Name.
+						The <literal>message-summary</literal> is not supported yet.</para>
+					</description>
+				</configOption>
 			</configObject>
 			<configObject name="inbound-publication">
 				<synopsis>The configuration for inbound publications</synopsis>
@@ -332,6 +341,8 @@
 	unsigned int full_state;
 	/*! Time, in milliseconds Asterisk waits before sending a batched notification.*/
 	unsigned int notification_batch_interval;
+	/*! Indicates whether display name of resource or the resource name being reported.*/
+	unsigned int resource_display_name;
 };
 
 /*!
@@ -499,6 +510,8 @@
 	pjsip_sip_uri *uri;
 	/*! Data to be persisted with the subscription */
 	struct ast_json *persistence_data;
+	/*! Display Name of resource */
+	char *display_name;
 	/*! Name of resource being subscribed to */
 	char resource[0];
 };
@@ -886,6 +899,7 @@
 struct tree_node {
 	AST_VECTOR(, struct tree_node *) children;
 	unsigned int full_state;
+	char *display_name;
 	char resource[0];
 };
 
@@ -929,7 +943,7 @@
  * \retval NULL Allocation failure.
  * \retval non-NULL The newly-allocated tree_node
  */
-static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state)
+static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state, const char *display_name)
 {
 	struct tree_node *node;
 
@@ -944,6 +958,7 @@
 		return NULL;
 	}
 	node->full_state = full_state;
+	node->display_name = ast_strdup(display_name);
 
 	if (visited) {
 		AST_VECTOR_APPEND(visited, resource);
@@ -971,6 +986,7 @@
 		tree_node_destroy(AST_VECTOR_GET(&node->children, i));
 	}
 	AST_VECTOR_FREE(&node->children);
+	ast_free(node->display_name);
 	ast_free(node);
 }
 
@@ -1035,7 +1051,11 @@
 		if (!child_list) {
 			int resp = handler->notifier->new_subscribe(endpoint, resource);
 			if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
-				current = tree_node_alloc(resource, visited, 0);
+				char display_name[AST_MAX_EXTENSION] = "";
+				if (list->resource_display_name && handler->notifier->get_resource_display_name) {
+					handler->notifier->get_resource_display_name(endpoint, resource, display_name, sizeof(display_name));
+				}
+				current = tree_node_alloc(resource, visited, 0, ast_strlen_zero(display_name) ? NULL : display_name);
 				if (!current) {
 					ast_debug(1,
 						"Subscription to leaf resource %s was successful, but encountered allocation error afterwards\n",
@@ -1053,7 +1073,7 @@
 			}
 		} else {
 			ast_debug(2, "Resource %s (child of %s) is a list\n", resource, parent->resource);
-			current = tree_node_alloc(resource, visited, child_list->full_state);
+			current = tree_node_alloc(resource, visited, child_list->full_state, NULL);
 			if (!current) {
 				ast_debug(1, "Cannot build children of resource %s due to allocation failure\n", resource);
 				continue;
@@ -1139,7 +1159,7 @@
 	if (!has_eventlist_support || !(list = retrieve_resource_list(resource, handler->event_name))) {
 		ast_debug(2, "Subscription '%s->%s' is not to a list\n",
 			ast_sorcery_object_get_id(endpoint), resource);
-		tree->root = tree_node_alloc(resource, NULL, 0);
+		tree->root = tree_node_alloc(resource, NULL, 0, NULL);
 		if (!tree->root) {
 			return 500;
 		}
@@ -1152,7 +1172,7 @@
 		return 500;
 	}
 
-	tree->root = tree_node_alloc(resource, &visited, list->full_state);
+	tree->root = tree_node_alloc(resource, &visited, list->full_state, NULL);
 	if (!tree->root) {
 		AST_VECTOR_FREE(&visited);
 		return 500;
@@ -1207,6 +1227,7 @@
 	AST_VECTOR_FREE(&sub->children);
 	ao2_cleanup(sub->datastores);
 	ast_json_unref(sub->persistence_data);
+	ast_free(sub->display_name);
 	ast_free(sub);
 }
 
@@ -1229,7 +1250,7 @@
 }
 
 static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_subscription_handler *handler,
-		const char *resource, struct sip_subscription_tree *tree)
+		const char *resource, const char *display_name, struct sip_subscription_tree *tree)
 {
 	struct ast_sip_subscription *sub;
 	pjsip_sip_uri *contact_uri;
@@ -1240,6 +1261,8 @@
 	}
 	strcpy(sub->resource, resource); /* Safe */
 
+	sub->display_name = ast_strdup(display_name);
+
 	sub->datastores = ast_datastores_alloc();
 	if (!sub->datastores) {
 		destroy_subscription(sub);
@@ -1288,7 +1311,7 @@
 	int i;
 	struct ast_sip_subscription *sub;
 
-	sub = allocate_subscription(handler, resource, tree);
+	sub = allocate_subscription(handler, resource, current->display_name, tree);
 	if (!sub) {
 		return NULL;
 	}
@@ -1880,7 +1903,7 @@
 		return NULL;
 	}
 
-	sub = allocate_subscription(handler, resource, sub_tree);
+	sub = allocate_subscription(handler, resource, NULL, sub_tree);
 	if (!sub) {
 		ao2_cleanup(sub_tree);
 		return NULL;
@@ -2088,6 +2111,8 @@
 	pjsip_evsub_state state;
 	/*! The actual body part that will be present in the multipart body */
 	pjsip_multipart_part *part;
+	/*! Display name for the resource */
+	const char *display_name;
 };
 
 /*!
@@ -2186,7 +2211,7 @@
 	for (i = 0; i < AST_VECTOR_SIZE(body_parts); ++i) {
 		const struct body_part *part = AST_VECTOR_GET(body_parts, i);
 
-		add_rlmi_resource(pool, rlmi, part->cid, part->resource, part->uri, part->state);
+		add_rlmi_resource(pool, rlmi, part->cid, S_OR(part->display_name, part->resource), part->uri, part->state);
 	}
 
 	rlmi_part = pjsip_multipart_create_part(pool);
@@ -2243,6 +2268,7 @@
 	bp->resource = sub->resource;
 	bp->state = sub->subscription_state;
 	bp->uri = sub->uri;
+	bp->display_name = sub->display_name;
 
 	return bp;
 }
@@ -4873,6 +4899,8 @@
 			"0", OPT_UINT_T, 0, FLDSET(struct resource_list, notification_batch_interval));
 	ast_sorcery_object_field_register_custom(sorcery, "resource_list", "list_item",
 			"", list_item_handler, list_item_to_str, NULL, 0, 0);
+	ast_sorcery_object_field_register(sorcery, "resource_list", "resource_display_name", "no",
+			OPT_BOOL_T, 1, FLDSET(struct resource_list, resource_display_name));
 
 	ast_sorcery_reload_object(sorcery, "resource_list");
 

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

Gerrit-Project: asterisk
Gerrit-Branch: 18
Gerrit-Change-Id: Ic5306bd5a7c73d03f5477fe235e9b0f41c69c681
Gerrit-Change-Number: 18021
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/20220215/80ea7c90/attachment-0001.html>


More information about the asterisk-code-review mailing list