[svn-commits] mmichelson: branch mmichelson/rls-subscribe r417700 - /team/mmichelson/rls-su...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 30 16:40:50 CDT 2014


Author: mmichelson
Date: Mon Jun 30 16:40:45 2014
New Revision: 417700

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=417700
Log:
Implement a scheme for detecting loops/duplicated resources.

Each resource that is visited is added to a vector. When visiting
a new resource, we check if the resource exists in the vector.

It's not a very efficient algorithm since seeing if the resource
has been visited is an O(N) operation. It could be sped up by
using a different container type, though I'd first like to
verify the algorithm's correctness before optimizing.


Modified:
    team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c

Modified: team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c?view=diff&rev=417700&r1=417699&r2=417700
==============================================================================
--- team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c (original)
+++ team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c Mon Jun 30 16:40:45 2014
@@ -633,6 +633,8 @@
 		struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *resource,
 		struct ast_sip_pubsub_body_generator *generator);
 
+AST_VECTOR(resources, const char *);
+
 struct tree_node {
 	AST_VECTOR(, struct tree_node *) children;
 	char resource[0];
@@ -668,8 +670,21 @@
 	ast_free(node);
 }
 
+static int have_visited(const char *resource, struct resources *visited)
+{
+	int i;
+
+	for (i = 0; i < AST_VECTOR_SIZE(visited); ++i) {
+		if (!strcmp(resource, AST_VECTOR_GET(visited, i))) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static void recurse_list(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
-		struct resource_list *list, struct tree_node *parent)
+		struct resource_list *list, struct tree_node *parent, struct resources *visited)
 {
 	int i;
 
@@ -677,6 +692,10 @@
 		struct tree_node *current;
 		struct resource_list *child_list;
 		const char *resource = AST_VECTOR_GET(&list->items, i);
+
+		if (have_visited(resource, visited)) {
+			continue;
+		}
 
 		child_list = retrieve_resource_list(resource);
 		if (!child_list) {
@@ -687,7 +706,7 @@
 			}
 		} else {
 			current = tree_node_alloc(resource);
-			recurse_list(endpoint, handler, child_list, current);
+			recurse_list(endpoint, handler, child_list, current, visited);
 			if (AST_VECTOR_SIZE(&current->children) > 0) {
 				AST_VECTOR_APPEND(&parent->children, current);
 			} else {
@@ -710,19 +729,20 @@
 		const char *resource, struct resource_tree *tree)
 {
 	struct resource_list *list;
+	struct resources visited;
+
+	list = retrieve_resource_list(resource);
+
+	tree->root = tree_node_alloc(resource);
 
 	/* Simple shortcut in case the requested resource is not a list */
-	list = retrieve_resource_list(resource);
 	if (!list) {
 		return handler->notifier->new_subscribe(endpoint, resource);
 	}
 
-	/* XXX This initial effort is a naive approach that assumes there are
-	 * no loops in the lists and no duplicated resources. This will have
-	 * to be addressed later
-	 */
-	tree->root = tree_node_alloc(resource);
-	recurse_list(endpoint, handler, list, tree->root);
+	AST_VECTOR_INIT(&visited, AST_VECTOR_SIZE(&list->items));
+	recurse_list(endpoint, handler, list, tree->root, &visited);
+	AST_VECTOR_FREE(&visited);
 
 	if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
 		return 200;
@@ -954,10 +974,6 @@
 			pubsub_module.id, MOD_DATA_PERSISTENCE, persistence);
 
 	memset(&tree, 0, sizeof(tree));
-	/* XXX This section needs to use the same bit of logic as is used when
-	 * processing a new inbound subscription so that a subscription tree
-	 * is created
-	 */
 	resp = build_resource_tree(endpoint, handler, resource, &tree);
 	if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
 		sub = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree);




More information about the svn-commits mailing list