[svn-commits] russell: branch russell/sla_updates r54495 - in /team/russell/sla_updates: ap...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Wed Feb 14 15:00:51 MST 2007


Author: russell
Date: Wed Feb 14 16:00:50 2007
New Revision: 54495

URL: http://svn.digium.com/view/asterisk?view=rev&rev=54495
Log:
Add support for an inbound trunk ringing timeout.

Modified:
    team/russell/sla_updates/apps/app_meetme.c
    team/russell/sla_updates/configs/sla.conf.sample

Modified: team/russell/sla_updates/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/russell/sla_updates/apps/app_meetme.c?view=diff&rev=54495&r1=54494&r2=54495
==============================================================================
--- team/russell/sla_updates/apps/app_meetme.c (original)
+++ team/russell/sla_updates/apps/app_meetme.c Wed Feb 14 16:00:50 2007
@@ -435,6 +435,14 @@
 	AST_LIST_ENTRY(sla_failed_station) entry;
 };
 
+/*! \brief A trunk that is ringing */
+struct sla_ringing_trunk {
+	struct sla_trunk *trunk;
+	/*! The time that this trunk started ringing */
+	struct timeval ring_begin;
+	AST_LIST_ENTRY(sla_ringing_trunk) entry;
+};
+
 /*!
  * \brief A structure for data used by the sla thread
  */
@@ -443,7 +451,7 @@
 	pthread_t thread;
 	ast_cond_t cond;
 	ast_mutex_t lock;
-	AST_LIST_HEAD_NOLOCK(, sla_trunk_ref) ringing_trunks;
+	AST_LIST_HEAD_NOLOCK(, sla_ringing_trunk) ringing_trunks;
 	AST_LIST_HEAD_NOLOCK(, sla_station_ref) ringing_stations;
 	AST_LIST_HEAD_NOLOCK(, sla_failed_station) failed_stations;
 	AST_LIST_HEAD_NOLOCK(, sla_event) event_q;
@@ -3074,7 +3082,8 @@
 	struct sla_station_ref *station_ref;
 
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, station_ref, entry) {
-		struct sla_trunk_ref *s_trunk_ref, *trunk_ref;
+		struct sla_trunk_ref *s_trunk_ref;
+		struct sla_ringing_trunk *ringing_trunk;
 		struct run_station_args args;
 		enum ast_dial_result dial_res;
 		pthread_attr_t attr;
@@ -3099,30 +3108,30 @@
 			/* Find the appropriate trunk to answer. */
 			AST_LIST_TRAVERSE(&station_ref->station->trunks, s_trunk_ref, entry) {
 				ast_mutex_lock(&sla.lock);
-				AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, trunk_ref, entry) {
-					if (s_trunk_ref->trunk == trunk_ref->trunk) {
+				AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
+					if (s_trunk_ref->trunk == ringing_trunk->trunk) {
 						AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry);
 						break;
 					}
 				}
 				AST_LIST_TRAVERSE_SAFE_END
 				ast_mutex_unlock(&sla.lock);
-				if (trunk_ref)
+				if (ringing_trunk)
 					break;
 			}
-			if (!trunk_ref) {
+			if (!ringing_trunk) {
 				ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n",
 					station_ref->station->name);
 				break;
 			}
 			s_trunk_ref->chan = ast_dial_answered(station_ref->station->dial);
-			ast_answer(trunk_ref->trunk->chan);
-			change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, 0);
+			ast_answer(ringing_trunk->trunk->chan);
+			change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, 0);
 			args.trunk_ref = s_trunk_ref;
 			args.station = station_ref->station;
 			args.cond = &cond;
 			args.cond_lock = &cond_lock;
-			free(trunk_ref);
+			free(ringing_trunk);
 			free(station_ref);
 			ast_mutex_init(&cond_lock);
 			ast_cond_init(&cond, NULL);
@@ -3156,13 +3165,14 @@
 {
 	struct sla_trunk_ref *trunk_ref;
 	struct sla_station_ref *station_ref;
+	struct sla_ringing_trunk *ringing_trunk;
 
 	ast_mutex_lock(&sla.lock);
 
 	/* Make sure that every station that uses at least one of the ringing
 	 * trunks, is ringing. */
-	AST_LIST_TRAVERSE(&sla.ringing_trunks, trunk_ref, entry) {
-		AST_LIST_TRAVERSE(&trunk_ref->trunk->stations, station_ref, entry) {
+	AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
+		AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) {
 			char *tech, *tech_data;
 			struct ast_dial *dial;
 			struct sla_station_ref *ringing_ref;
@@ -3197,7 +3207,7 @@
 				ast_dial_destroy(dial);
 				continue;
 			}
-			if (ast_dial_run(dial, trunk_ref->trunk->chan, 1) != AST_DIAL_RESULT_TRYING) {
+			if (ast_dial_run(dial, ringing_trunk->trunk->chan, 1) != AST_DIAL_RESULT_TRYING) {
 				ast_dial_destroy(dial);
 				if (!(failed_station = ast_calloc(1, sizeof(*failed_station))))
 					continue;
@@ -3222,14 +3232,14 @@
 	/* Find stations that shouldn't be ringing anymore. */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, station_ref, entry) {
 		AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) {
-			struct sla_trunk_ref *ringing_ref;
+			struct sla_ringing_trunk *ringing_trunk;
 			ast_mutex_lock(&sla.lock);
-			AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_ref, entry) {
-				if (trunk_ref->trunk == ringing_ref->trunk)
+			AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
+				if (trunk_ref->trunk == ringing_trunk->trunk)
 					break;
 			}
 			ast_mutex_unlock(&sla.lock);
-			if (ringing_ref)
+			if (ringing_trunk)
 				break;
 		}
 		if (!trunk_ref) {
@@ -3263,6 +3273,77 @@
 	}
 }
 
+static void sla_stop_ringing_trunk(struct sla_ringing_trunk *ringing_trunk)
+{
+	char buf[80];
+
+	snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name);
+	admin_exec(NULL, buf);
+	change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, 0);
+
+	free(ringing_trunk);
+}
+
+static int sla_calc_timeout(struct timespec *ts)
+{
+	struct sla_ringing_trunk *ringing_trunk;
+	unsigned int timeout = UINT_MAX;
+	struct timeval tv;
+	unsigned int trunk_stopped = 0;
+
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
+		int time_left;
+		if (!ringing_trunk->trunk->ringtimeout)
+			continue;
+		time_left = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
+		if (time_left <= 0) {
+			AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry);
+			sla_stop_ringing_trunk(ringing_trunk);
+			trunk_stopped = 1;
+			continue;
+		}
+		if (time_left < timeout)
+			timeout = time_left;
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+
+	/* Ringing trunk removed, queue reprocessing of ringing trunks */
+	if (trunk_stopped)
+		sla_queue_event(SLA_EVENT_RINGING_TRUNK);
+
+	if (timeout == UINT_MAX)
+		return 0;
+	
+	tv = ast_samp2tv(timeout, 1000);
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = tv.tv_usec * 1000;
+
+	return 1;
+}
+
+static void sla_check_timeout(void)
+{
+	struct sla_ringing_trunk *ringing_trunk;
+	unsigned int trunk_stopped = 0;
+
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
+		int time_left;
+		if (!ringing_trunk->trunk->ringtimeout)
+			continue;
+		time_left = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
+		if (time_left <= 0) {
+			AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry);
+			sla_stop_ringing_trunk(ringing_trunk);
+			trunk_stopped = 1;
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+
+	/* Ringing trunk removed, queue reprocessing of ringing trunks */
+	if (trunk_stopped)
+		sla_queue_event(SLA_EVENT_RINGING_TRUNK);
+}
+
 static void *sla_thread(void *data)
 {
 	struct sla_failed_station *failed_station;
@@ -3272,13 +3353,21 @@
 
 	while (!sla.stop) {
 		struct sla_event *event;
+		struct timespec ts = { 0, };
+		unsigned int have_timeout = 0;
 
 		if (AST_LIST_EMPTY(&sla.event_q)) {
-			ast_cond_wait(&sla.cond, &sla.lock);
+			if ((have_timeout = sla_calc_timeout(&ts)))
+				ast_cond_timedwait(&sla.cond, &sla.lock, &ts);
+			else
+				ast_cond_wait(&sla.cond, &sla.lock);
 			if (sla.stop)
 				break;
 			ast_log(LOG_DEBUG, "Ooh, I was woken up!\n");
 		}
+
+		if (have_timeout)
+			sla_check_timeout();
 
 		while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) {
 			ast_mutex_unlock(&sla.lock);
@@ -3530,6 +3619,26 @@
 	return trunk_ref;
 }
 
+static struct sla_ringing_trunk *queue_ringing_trunk(struct sla_trunk *trunk)
+{
+	struct sla_ringing_trunk *ringing_trunk;
+
+	if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk))))
+		return NULL;
+	
+	ringing_trunk->trunk = trunk;
+	ringing_trunk->ring_begin = ast_tvnow();
+
+	change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, 0);
+
+	ast_mutex_lock(&sla.lock);
+	AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry);
+	sla_queue_event(SLA_EVENT_RINGING_TRUNK);
+	ast_mutex_unlock(&sla.lock);
+
+	return ringing_trunk;
+}
+
 static int slatrunk_exec(struct ast_channel *chan, void *data)
 {
 	const char *trunk_name = data;
@@ -3537,7 +3646,7 @@
 	struct ast_conference *conf;
 	struct ast_flags conf_flags = { 0 };
 	struct sla_trunk *trunk;
-	struct sla_trunk_ref *trunk_ref;
+	struct sla_ringing_trunk *ringing_trunk;
 
 	AST_RWLIST_RDLOCK(&sla_trunks);
 	trunk = find_trunk(trunk_name);
@@ -3557,17 +3666,10 @@
 	}
 	trunk->chan = chan;
 
-	if (!(trunk_ref = create_trunk_ref(trunk))) {
+	if (!(ringing_trunk = queue_ringing_trunk(trunk))) {
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
 		return 0;
 	}
-
-	change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, 0);
-
-	ast_mutex_lock(&sla.lock);
-	AST_LIST_INSERT_HEAD(&sla.ringing_trunks, trunk_ref, entry);
-	sla_queue_event(SLA_EVENT_RINGING_TRUNK);
-	ast_mutex_unlock(&sla.lock);
 
 	snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name);
 	conf = build_conf(conf_name, "", "", 1, 1, 1);
@@ -3585,16 +3687,16 @@
 
 	/* Remove the entry from the list of ringing trunks if it is still there. */
 	ast_mutex_lock(&sla.lock);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, trunk_ref, entry) {
-		if (trunk_ref->trunk == trunk) {
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
+		if (ringing_trunk->trunk == trunk) {
 			AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry);
 			break;
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 	ast_mutex_unlock(&sla.lock);
-	if (trunk_ref) {
-		free(trunk_ref);
+	if (ringing_trunk) {
+		free(ringing_trunk);
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED");
 	}
 

Modified: team/russell/sla_updates/configs/sla.conf.sample
URL: http://svn.digium.com/view/asterisk/team/russell/sla_updates/configs/sla.conf.sample?view=diff&rev=54495&r1=54494&r2=54495
==============================================================================
--- team/russell/sla_updates/configs/sla.conf.sample (original)
+++ team/russell/sla_updates/configs/sla.conf.sample Wed Feb 14 16:00:50 2007
@@ -23,8 +23,8 @@
 ; zapata.conf, this device should be configured to have incoming calls go to
 ; this context.
 autocontext=line1
-; Set how long to allow this trunk to ring before hanging it up as an
-; unanswered call.  The value is in seconds.
+; Set how long to allow this trunk to ring on an inbound call before hanging 
+; it up as an unanswered call.  The value is in seconds.
 ringtimeout=30
 
 [line2]



More information about the svn-commits mailing list