[svn-commits] mmichelson: branch mmichelson/rls-rlmi r418254 - /team/mmichelson/rls-rlmi/res/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jul 9 14:52:58 CDT 2014


Author: mmichelson
Date: Wed Jul  9 14:52:53 2014
New Revision: 418254

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=418254
Log:
Implement partial state notification for RLS.

Now if a subset of resources in a resource list changes
states, only those updated resources will be communicated
in NOTIFYs. Forced full state NOTIFYs are still working
properly.


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

Modified: team/mmichelson/rls-rlmi/res/res_pjsip_pubsub.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-rlmi/res/res_pjsip_pubsub.c?view=diff&rev=418254&r1=418253&r2=418254
==============================================================================
--- team/mmichelson/rls-rlmi/res/res_pjsip_pubsub.c (original)
+++ team/mmichelson/rls-rlmi/res/res_pjsip_pubsub.c Wed Jul  9 14:52:53 2014
@@ -412,6 +412,8 @@
 	pjsip_evsub_state subscription_state;
 	/*! For lists, the current version to place in the RLMI body */
 	unsigned int version;
+	/*! For lists, indicates if full state should always be communicated. */
+	unsigned int full_state;
 	/*! Name of resource being subscribed to */
 	char resource[0];
 };
@@ -1466,10 +1468,18 @@
 	ast_sip_presence_xml_create_attr(pool, instance, "cid", ast_strip_quoted(ast_strdupa(cid), "<", ">"));
 }
 
-AST_VECTOR(cid_list, const char *);
+struct body_part {
+	const char *cid;
+	const char *resource;
+	const char *uri;
+	pjsip_evsub_state state;
+	pjsip_multipart_part *part;
+};
+
+AST_VECTOR(body_part_list, struct body_part *);
 
 static pj_xml_node *build_rlmi_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
-		struct cid_list *cids)
+		struct body_part_list *body_parts, int full_state)
 {
 	pj_xml_node *rlmi;
 	pj_xml_node *name;
@@ -1487,38 +1497,63 @@
 	ast_sip_subscription_get_local_uri(sub, uri, sizeof(uri));
 	ast_sip_presence_xml_create_attr(pool, rlmi, "uri", uri);
 
-	/* XXX Hardcoding RLMI fullState attribute for the moment. */
 	snprintf(version_str, sizeof(version_str), "%u", sub->version++);
 	ast_sip_presence_xml_create_attr(pool, rlmi, "version", version_str);
-	ast_sip_presence_xml_create_attr(pool, rlmi, "fullState", "true");
+	ast_sip_presence_xml_create_attr(pool, rlmi, "fullState", full_state ? "true" : "false");
 
 	name = ast_sip_presence_xml_create_node(pool, rlmi, "name");
 	pj_strdup2(pool, &name->content, ast_sip_subscription_get_resource_name(sub));
 
-	for (i = 0; i < AST_VECTOR_SIZE(cids); ++i) {
-		/* XXX Using a hardcoded URI for the moment */
-		add_rlmi_resource(pool, rlmi, AST_VECTOR_GET(cids, i),
-				AST_VECTOR_GET(&sub->children, i)->resource, "sip:johndoe at example.org",
-				AST_VECTOR_GET(&sub->children, i)->subscription_state);
+	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);
 	}
 
 	return rlmi;
 }
 
-static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root);
-
-static void free_cids(struct cid_list *cids)
+static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
+		int force_full_state);
+
+static void free_body_parts(struct body_part_list *parts)
 {
 	int i;
 
-	for (i = 0; i < AST_VECTOR_SIZE(cids); ++i) {
-		ast_free((char *) AST_VECTOR_GET(cids, i));
-	}
-
-	AST_VECTOR_FREE(cids);
-}
-
-static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscription *sub)
+	for (i = 0; i < AST_VECTOR_SIZE(parts); ++i) {
+		struct body_part *part = AST_VECTOR_GET(parts, i);
+		ast_free((char *) part->cid);
+		ast_free(part);
+	}
+
+	AST_VECTOR_FREE(parts);
+}
+
+static struct body_part *allocate_body_part(const struct ast_sip_subscription *sub)
+{
+	struct body_part *bp;
+
+	bp = ast_calloc(1, sizeof(*bp));
+	if (!bp) {
+		return NULL;
+	}
+
+	bp->cid = ast_strdup("<prawnstar at bass-turd.org>");
+	if (!bp->cid) {
+		ast_free(bp);
+		return NULL;
+	}
+
+	bp->resource = sub->resource;
+	bp->state = sub->subscription_state;
+	/* XXX This is hardcoded */
+	bp->uri = "sip:johndoe at example.org";
+
+	return bp;
+}
+
+static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
+		int force_full_state)
 {
 	int i;
 	pj_xml_node *rlmi;
@@ -1532,21 +1567,39 @@
 	static const pj_str_t rlmi_type = { "application", 11};
 	static const pj_str_t rlmi_subtype = {"rlmi+xml", 8};
 	pj_str_t rlmi_text;
-	struct cid_list cids;
-
-	AST_VECTOR_INIT(&cids, AST_VECTOR_SIZE(&sub->children));
+	struct body_part_list body_parts;
+	int use_full_state = force_full_state ? 1 : sub->full_state;
+
+	AST_VECTOR_INIT(&body_parts, AST_VECTOR_SIZE(&sub->children));
 	
 	multipart = pjsip_multipart_create(pool, &media_type, NULL);
 
-	/* Start by generating content IDs for children.
-	 * Do this by creating a parallel vector to the vector of child subscriptions.
-	 */
 	for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
-		/* XXX Using a hard-coded value for the moment */
-		AST_VECTOR_APPEND(&cids, ast_strdup("<prawnstar at bass-turd.org>"));
+		/* XXX This should probably be factored into a function */
+		struct ast_sip_subscription *child = AST_VECTOR_GET(&sub->children, i);
+		struct body_part *bp = allocate_body_part(child);
+		pjsip_generic_string_hdr *cid;
+		static const pj_str_t cid_name = { "Content-ID", 10 };
+		pjsip_msg_body *body;
+		pj_str_t cid_value;
+
+		body = generate_notify_body(pool, child, use_full_state);
+		if (!body) {
+			/* Partial state was requested and the resource has not changed state */
+			continue;
+		}
+
+		bp->part = pjsip_multipart_create_part(pool);
+		bp->part->body = body;
+
+		pj_cstr(&cid_value, bp->cid);
+		cid = pjsip_generic_string_hdr_create(pool, &cid_name, &cid_value);
+		pj_list_insert_before(&bp->part->hdr, cid);
+
+		AST_VECTOR_APPEND(&body_parts, bp);
 	}
 	
-	rlmi = build_rlmi_body(pool, sub, &cids);
+	rlmi = build_rlmi_body(pool, sub, &body_parts, use_full_state);
 	pj_xml_print(rlmi, rlmi_str, sizeof(rlmi_str) - 1, PJ_TRUE);
 	pj_cstr(&rlmi_text, rlmi_str);
 
@@ -1554,53 +1607,45 @@
 	rlmi_part->body = pjsip_msg_body_create(pool, &rlmi_type, &rlmi_subtype, &rlmi_text);
 	pjsip_multipart_add_part(pool, multipart, rlmi_part);
 
-	for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
-		/* XXX This should probably be factored into a function */
-		struct ast_sip_subscription *child = AST_VECTOR_GET(&sub->children, i);
-		pjsip_multipart_part *part = pjsip_multipart_create_part(pool);
-		pjsip_generic_string_hdr *cid;
-		static const pj_str_t cid_name = { "Content-ID", 10 };
-		pj_str_t cid_value;
-
-		part->body = generate_notify_body(pool, child);
-
-		pj_cstr(&cid_value, AST_VECTOR_GET(&cids, i));
-		cid = pjsip_generic_string_hdr_create(pool, &cid_name, &cid_value);
-		pj_list_insert_before(&part->hdr, cid);
-
-		pjsip_multipart_add_part(pool, multipart, part);
-	}
-
-	free_cids(&cids);
+	for (i = 0; i < AST_VECTOR_SIZE(&body_parts); ++i) {
+		pjsip_multipart_add_part(pool, multipart, AST_VECTOR_GET(&body_parts, i)->part);
+	}
+
+	free_body_parts(&body_parts);
 	return multipart;
 }
 
-static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root)
+static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
+		int force_full_state)
 {
 	pjsip_msg_body *body;
 
 	if (AST_VECTOR_SIZE(&root->children) == 0) {
-		/* Not a list. We've already generated the body and saved it on the subscription.
-		 * Use that directly.
-		 */
-		pj_str_t type;
-		pj_str_t subtype;
-		pj_str_t text;
-
-		pj_cstr(&type, ast_sip_subscription_get_body_type(root));
-		pj_cstr(&subtype, ast_sip_subscription_get_body_subtype(root));
-		pj_cstr(&text, ast_str_buffer(root->body_text));
-
-		body = pjsip_msg_body_create(pool, &type, &subtype, &text);
-		root->body_changed = 0;
+		if (force_full_state || root->body_changed) {
+			/* Not a list. We've already generated the body and saved it on the subscription.
+			 * Use that directly.
+			 */
+			pj_str_t type;
+			pj_str_t subtype;
+			pj_str_t text;
+
+			pj_cstr(&type, ast_sip_subscription_get_body_type(root));
+			pj_cstr(&subtype, ast_sip_subscription_get_body_subtype(root));
+			pj_cstr(&text, ast_str_buffer(root->body_text));
+
+			body = pjsip_msg_body_create(pool, &type, &subtype, &text);
+			root->body_changed = 0;
+		} else {
+			body = NULL;
+		}
 	} else {
-		body = generate_list_body(pool, root);
+		body = generate_list_body(pool, root, force_full_state);
 	}
 
 	return body;
 }
 
-static int send_notify(struct sip_subscription_tree *sub_tree)
+static int send_notify(struct sip_subscription_tree *sub_tree, int force_full_state)
 {
 	pjsip_evsub *evsub = sub_tree->evsub;
 	pjsip_tx_data *tdata;
@@ -1610,7 +1655,7 @@
 		return -1;
 	}
 
-	tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root);
+	tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root, force_full_state);
 
 	if (sip_subscription_send_request(sub_tree, tdata)) {
 		pjsip_tx_data_dec_ref(tdata);
@@ -1635,7 +1680,7 @@
 		return 0;
 	}
 
-	send_notify(sub_tree);
+	send_notify(sub_tree, 0);
 	ao2_cleanup(sub_tree);
 	return 0;
 }
@@ -1681,7 +1726,7 @@
 	if (sub->tree->notification_batch_interval) {
 		return schedule_notification(sub->tree);
 	} else {
-		return send_notify(sub->tree);
+		return send_notify(sub->tree, 0);
 	}
 }
 
@@ -2122,7 +2167,7 @@
 		if (generate_initial_notify(sub_tree->root)) {
 			pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
 		}
-		send_notify(sub_tree);
+		send_notify(sub_tree, 1);
 	}
 
 	resource_tree_destroy(&tree);
@@ -2620,7 +2665,7 @@
 		set_state_terminated(sub_tree->root);
 	}
 
-	if (send_notify(sub_tree)) {
+	if (send_notify(sub_tree, 1)) {
 		*p_st_code = 500;
 	}
 
@@ -2670,7 +2715,7 @@
 	struct sip_subscription_tree *sub_tree = userdata;
 
 	set_state_terminated(sub_tree->root);
-	send_notify(sub_tree);
+	send_notify(sub_tree, 1);
 
 	ao2_cleanup(sub_tree);
 	return 0;




More information about the svn-commits mailing list