[asterisk-commits] russell: branch russell/sla_updates r54495 - in
/team/russell/sla_updates: ap...
asterisk-commits at lists.digium.com
asterisk-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 asterisk-commits
mailing list