[svn-commits] dvossel: branch dvossel/sip_resource_list_trunk r186718 - /team/dvossel/sip_r...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Apr 7 12:15:09 CDT 2009


Author: dvossel
Date: Tue Apr  7 12:15:05 2009
New Revision: 186718

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=186718
Log:
Added callback for exten state changes.  callback returns pointer to rlist so all watchers can be updated.  Stuff left to do, add locking for rlist, add transmit_rlist_notify function to create and send NOTIFY to every watcher on update. 

Modified:
    team/dvossel/sip_resource_list_trunk/channels/chan_sip.c

Modified: team/dvossel/sip_resource_list_trunk/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/sip_resource_list_trunk/channels/chan_sip.c?view=diff&rev=186718&r1=186717&r2=186718
==============================================================================
--- team/dvossel/sip_resource_list_trunk/channels/chan_sip.c (original)
+++ team/dvossel/sip_resource_list_trunk/channels/chan_sip.c Tue Apr  7 12:15:05 2009
@@ -1901,6 +1901,7 @@
 	int version;
 	int the_mark;
 	int num_watchers;
+	int startmonitor;
 	AST_LIST_HEAD_NOLOCK(, sip_pvt) watchers;
 	AST_LIST_HEAD_NOLOCK(, sip_rlist_resource) resources;
 };
@@ -2450,6 +2451,8 @@
 /* add and remove resource list watchers */
 static int rlist_add_watcher(struct sip_pvt *p);
 static int rlist_remove_watcher(struct sip_pvt *p);
+static int rlist_start_monitor(struct sip_rlist *rlist);
+static int rlist_stop_monitor(struct sip_rlist *rlist);
 
 /*!
  * \brief generic function for determining if a correct transport is being 
@@ -4341,7 +4344,8 @@
 
 static void destroy_rlist_resources(struct sip_rlist *rlist) {
 	struct sip_rlist_resource *resource = NULL;
-
+	/*since resources are being removed, make sure to del exten state callback. */
+	rlist_stop_monitor(rlist);
 	while ((resource = AST_LIST_REMOVE_HEAD(&rlist->resources, entry))) {
 		ast_string_field_free_memory(resource);
 	}
@@ -12179,6 +12183,44 @@
 	ao2_lock(peer);
 	sip_send_mwi_to_peer(peer, event, 0);
 	ao2_unlock(peer);
+}
+
+static int cb_rlist_extensionstate(char *context, char* exten, int state, void *data)
+{
+	struct sip_rlist *rlist = data;
+	struct sip_rlist_resource *resource;
+	int found = 0;
+
+
+	ast_log(LOG_NOTICE, "CALLED BACK!!! exten: %s, state:%d, rlist_name:%s", exten, state, rlist->name); //todohere remove
+	/* check to see if there are any watchers for this list, if not stop monitoring */
+	if (!rlist->num_watchers) {
+		rlist_stop_monitor(rlist);
+		return 0;
+	}
+	AST_LIST_TRAVERSE(&rlist->resources, resource, entry) {
+		if (!strcmp(resource->exten, exten)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		return -1;
+	}
+
+	switch(state) {
+	case AST_EXTENSION_DEACTIVATED:	/* Retry after a while */
+	case AST_EXTENSION_REMOVED:	/* Extension is gone */
+		resource->stateid = -1;
+		break;
+	default:	/* Tell user */
+		resource->laststate = state;
+		break;
+	}
+
+//todohere transmit notify to all rlist watchers, something like this transmit_rlist_state_notify(p, state, 1, FALSE);
+	return 0;
 }
 
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
@@ -21119,7 +21161,7 @@
 				ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
 				transmit_response(p, "200 OK", req);
 				ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context);
-				//todohere force first notify
+				//todohere force first notify and delete any matching old subscriptions (they will time out, but why wait
 			} else {
 				transmit_response(p, "404 Not found", req);
 				pvt_set_needdestroy(p, "no extension for SUBSCRIBE");
@@ -23275,6 +23317,47 @@
 	}
 }
 
+static int rlist_start_monitor(struct sip_rlist *rlist)
+{
+	struct sip_rlist_resource *resource;
+
+	if (!rlist->num_watchers) {
+		if (rlist->startmonitor) {
+			rlist_stop_monitor(rlist); /* no watchers, no need to monitor */
+		}
+		return 0;
+	} else if (rlist->startmonitor) { /* monitor already started */
+		return 0;
+	}
+	AST_LIST_TRAVERSE(&rlist->resources, resource, entry) {
+		if (resource->stateid > -1) {
+			ast_extension_state_del(resource->stateid, cb_rlist_extensionstate);
+			resource->stateid = -1;
+		}
+		resource->stateid = ast_extension_state_add(rlist->context, resource->exten, cb_rlist_extensionstate, rlist);
+		if (resource->stateid > -1) {
+			ao2_t_ref(rlist, 1, "monitoring new extension"); 
+		}
+	}
+	rlist->startmonitor = 1;
+	return 1;
+}
+
+static int rlist_stop_monitor(struct sip_rlist *rlist)
+{
+	struct sip_rlist_resource *resource;
+
+	AST_LIST_TRAVERSE(&rlist->resources, resource, entry) {
+		if (resource->stateid > -1) {
+			ast_extension_state_del(resource->stateid, cb_rlist_extensionstate);
+			resource->stateid = -1;
+			ao2_t_ref(rlist, -1, "stopped monitoring extension");
+		}
+	}
+	rlist->startmonitor = 0;
+	return 1;
+}
+
 static int rlist_add_watcher(struct sip_pvt *p)
 {
 	if (p) {
@@ -23283,10 +23366,8 @@
 		if (p->rlist) {
 			dialog_ref(p, "add sip_pvt watcher to resource list notifications");
 			AST_LIST_INSERT_TAIL(&p->rlist->watchers, p, rlist_entry);
-			if (!p->rlist->num_watchers) { /* num_watchers is zero, meaning this is the first watcher so start monitoring */
-			// todohere add logic to start monitoring extensions since we have a watcher
-			}
 			p->rlist->num_watchers++;
+			rlist_start_monitor(p->rlist);
 			return 1;
 		}
 	} else {
@@ -23305,7 +23386,7 @@
 		AST_LIST_REMOVE(&p->rlist->watchers, p, rlist_entry);
 		p->rlist->num_watchers--;
 		if (!p->rlist->num_watchers) { /* num_watchers is decremented to zero, stop monitoring extensions. */
-			//todohere add logic to stop monitoring extensions since nothing is watching
+			rlist_stop_monitor(p->rlist);
 		}
 		ao2_t_ref(p->rlist, -1, "remove dialog's ref to resource list");
 		p->rlist = NULL;
@@ -23324,6 +23405,7 @@
 	}
 	ast_string_field_init(resource, 128);
 	ast_string_field_set(resource, exten, monitorexten);
+	resource->stateid = -1;
 	AST_LIST_INSERT_TAIL(&rlist->resources, resource, entry);
 
 	return 0;
@@ -23353,7 +23435,7 @@
 			ao2_t_ref(rlist, -1, "rlist failed to init string field");
 			return NULL;
 		}
-
+		rlist->startmonitor = 0;
 		ast_copy_string(rlist->name, name, sizeof(rlist->name));
 	}
 
@@ -23367,6 +23449,8 @@
 	rlist->the_mark = 0; /* unmark this resource list for deletion */
 
 	if (found) {
+		/* monitor was stopped when resources were destroyed.  now that they are added back, restart monitor.  this only takes affect if rlist has watchers. */
+		rlist_start_monitor(rlist);
 		ao2_t_ref(rlist, -1, "rlist found and updated, decrement ref and return NULL");
 		return NULL;
 	}




More information about the svn-commits mailing list