[asterisk-commits] mmichelson: branch group/rls r418113 - /team/group/rls/res/res_pjsip_pubsub.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jul 7 10:26:29 CDT 2014


Author: mmichelson
Date: Mon Jul  7 10:26:23 2014
New Revision: 418113

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=418113
Log:
Add testing for whether a subscriber supports resource lists.

A subscriber that does not have a Supported: eventlist header
in its inbound SUBSCRIBE should not be able to subscribe
to resource lists. Such handling has now been added. Also a
unit test has been added to ensure that this behavior works
as expected.


Modified:
    team/group/rls/res/res_pjsip_pubsub.c

Modified: team/group/rls/res/res_pjsip_pubsub.c
URL: http://svnview.digium.com/svn/asterisk/team/group/rls/res/res_pjsip_pubsub.c?view=diff&rev=418113&r1=418112&r2=418113
==============================================================================
--- team/group/rls/res/res_pjsip_pubsub.c (original)
+++ team/group/rls/res/res_pjsip_pubsub.c Mon Jul  7 10:26:23 2014
@@ -871,17 +871,20 @@
  * \param handler The subscription handler for leaf nodes in the tree.
  * \param resource The resource requested in the SUBSCRIBE request.
  * \param tree The tree that is to be built.
+ * \param supports_lists Indicates if we should attempt to find a resource list or not.
  *
  * \retval 200-299 Successfully subscribed to at least one resource.
  * \retval 300-699 Failure to subscribe to requested resource.
  */
 static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
-		const char *resource, struct resource_tree *tree)
-{
-	struct resource_list *list;
+		const char *resource, struct resource_tree *tree, int supports_lists)
+{
+	struct resource_list *list = NULL;
 	struct resources visited;
 
-	list = retrieve_resource_list(resource, handler->event_name);
+	if (supports_lists) {
+		list = retrieve_resource_list(resource, handler->event_name);
+	}
 	if (!list) {
 		ast_debug(1, "Subscription to resource %s is not to a list\n", resource);
 		tree->root = tree_node_alloc(resource, NULL);
@@ -1082,6 +1085,35 @@
 
 	create_virtual_subscriptions(handler, endpoint, rdata, resource, generator, sub, tree->root);
 	return sub;
+}
+
+/*!
+ * \param Determine if SUBSCRIBE indicates support for RLS
+ *
+ * A SUBSCRIBE must have a Supported: eventlist header in order to
+ * allow for resource list subscriptions. Otherwise, we must interpret
+ * the inbound SUBSCRIBE as being for a single resource.
+ *
+ * \param rdata The inbound SUBSCRIBE request.
+ * \retval 1 The endpoint supports RLS
+ * \retval 0 The endpoint does not support RLS
+ */
+static int supports_resource_lists(pjsip_rx_data *rdata)
+{
+	pjsip_supported_hdr *supported;
+
+	supported = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_SUPPORTED, NULL);
+	if (supported) {
+		int i;
+
+		for (i = 0; i < supported->count; ++i) {
+			if (pj_strcmp2(&supported->values[i], "eventlist")) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
 }
 
 
@@ -1101,6 +1133,7 @@
 	struct resource_tree tree;
 	pjsip_expires_hdr *expires_header;
 	struct ast_sip_subscription_handler *handler;
+	int supports_lists;
 
 	/* If this subscription has already expired remove it */
 	if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
@@ -1156,11 +1189,13 @@
 		return 0;
 	}
 
+	supports_lists = supports_resource_lists(&rdata);
+
 	ast_sip_mod_data_set(rdata.tp_info.pool, rdata.endpt_info.mod_data,
 			pubsub_module.id, MOD_DATA_PERSISTENCE, persistence);
 
 	memset(&tree, 0, sizeof(tree));
-	resp = build_resource_tree(endpoint, handler, resource, &tree);
+	resp = build_resource_tree(endpoint, handler, resource, &tree, supports_lists);
 	if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
 		sub = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree);
 		sub->persistence = ao2_bump(persistence);
@@ -1833,6 +1868,7 @@
 	size_t resource_size;
 	int resp;
 	struct resource_tree tree;
+	int supports_lists;
 
 	endpoint = ast_pjsip_rdata_get_endpoint(rdata);
 	ast_assert(endpoint != NULL);
@@ -1888,8 +1924,10 @@
 		return PJ_TRUE;
 	}
 
+	supports_lists = supports_resource_lists(rdata);
+
 	memset(&tree, 0, sizeof(tree));
-	resp = build_resource_tree(endpoint, handler, resource, &tree);
+	resp = build_resource_tree(endpoint, handler, resource, &tree, supports_lists);
 	if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
 		pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
 		resource_tree_destroy(&tree);
@@ -2948,7 +2986,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3012,7 +3050,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3067,7 +3105,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3130,7 +3168,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3197,7 +3235,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3263,7 +3301,7 @@
 	}
 
 	tree = ast_calloc(1, sizeof(*tree));
-	resp = build_resource_tree(NULL, &test_handler, "herp", tree);
+	resp = build_resource_tree(NULL, &test_handler, "herp", tree, 1);
 	if (resp == 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3304,7 +3342,7 @@
 	/* Since the test_handler is for event "test", this should not build a list, but
 	 * instead result in a single resource being created, called "foo"
 	 */
-	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);
 	if (resp != 200) {
 		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
 		return AST_TEST_FAIL;
@@ -3320,8 +3358,68 @@
 		return AST_TEST_FAIL;
 	}
 
+	if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
+		ast_test_status_update(test, "Tree root contains child nodes, but should not\n");
+		return AST_TEST_FAIL;
+	}
+
 	return AST_TEST_PASS;
 }
+
+AST_TEST_DEFINE(lists_unsupported)
+{
+	RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
+	const char *resources[] = {
+		"huey",
+		"dewey",
+		"louie",
+	};
+	int resp;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "lists_unsupported";
+		info->category = "/res/res_pjsip_pubsub/";
+		info->summary = "Ensure that subscription with no support for RLS subscribes to single resource";
+		info->description =
+			"Create a simple resource list. Ensure that building a resource tree when lists are unsupported results\n"
+			"not in subscribing to the created list but only to a single resource.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
+	if (!list) {
+		return AST_TEST_FAIL;
+	}
+
+	tree = ast_calloc(1, sizeof(*tree));
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree, 0);
+	if (resp != 200) {
+		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
+		return AST_TEST_FAIL;
+	}
+
+	if (!tree->root) {
+		ast_test_status_update(test, "Resource tree has no root\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (strcmp(tree->root->resource, "foo")) {
+		ast_test_status_update(test, "Unexpected resource %s found in tree\n", tree->root->resource);
+		return AST_TEST_FAIL;
+	}
+
+	if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
+		ast_test_status_update(test, "Tree root contains child nodes, but should not\n");
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
 
 #endif
 
@@ -3406,6 +3504,7 @@
 	AST_TEST_REGISTER(duplicate_resource);
 	AST_TEST_REGISTER(loop);
 	AST_TEST_REGISTER(bad_event);
+	AST_TEST_REGISTER(lists_unsupported);
 
 	return AST_MODULE_LOAD_SUCCESS;
 }
@@ -3427,6 +3526,7 @@
 	AST_TEST_UNREGISTER(duplicate_resource);
 	AST_TEST_UNREGISTER(loop);
 	AST_TEST_UNREGISTER(bad_event);
+	AST_TEST_UNREGISTER(lists_unsupported);
 
 	return 0;
 }




More information about the asterisk-commits mailing list