[asterisk-commits] russell: branch russell/sla_rewrite r53293 - /team/russell/sla_rewrite/apps/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue Feb 6 16:54:51 MST 2007


Author: russell
Date: Tue Feb  6 17:54:50 2007
New Revision: 53293

URL: http://svn.digium.com/view/asterisk?view=rev&rev=53293
Log:
Add hold support to SLA.  This is not tested very heavily due to some problems
on my system right now ...

Modified:
    team/russell/sla_rewrite/apps/app_meetme.c

Modified: team/russell/sla_rewrite/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/russell/sla_rewrite/apps/app_meetme.c?view=diff&rev=53293&r1=53292&r2=53293
==============================================================================
--- team/russell/sla_rewrite/apps/app_meetme.c (original)
+++ team/russell/sla_rewrite/apps/app_meetme.c Tue Feb  6 17:54:50 2007
@@ -152,6 +152,8 @@
 	CONFFLAG_STARTMUTED = (1 << 24),
 	/*! Pass DTMF through the conference */
 	CONFFLAG_PASS_DTMF = (1 << 25),
+	CONFFLAG_SLA_STATION = (1 << 26),
+	CONFFLAG_SLA_TRUNK = (1 << 27),
 };
 
 enum {
@@ -344,6 +346,7 @@
 	SLA_TRUNK_STATE_IDLE,
 	SLA_TRUNK_STATE_RINGING,
 	SLA_TRUNK_STATE_UP,
+	SLA_TRUNK_STATE_ONHOLD,
 };
 
 struct sla_trunk_ref;
@@ -377,6 +380,8 @@
 	unsigned int num_stations;
 	/*! Number of stations currently on a call with this trunk */
 	unsigned int active_stations;
+	/*! Number of stations that have this trunk on hold. */
+	unsigned int hold_stations;
 	struct ast_channel *chan;
 	pthread_t station_thread;
 };
@@ -392,11 +397,24 @@
 
 static const char sla_registrar[] = "SLA";
 
+enum sla_event_type {
+	SLA_EVENT_HOLD,
+	SLA_EVENT_UNHOLD
+};
+
+struct sla_event {
+	enum sla_event_type type;
+	struct sla_station *station;
+	struct sla_trunk_ref *trunk_ref;
+	AST_LIST_ENTRY(sla_event) entry;
+};
+
 static struct sla {
 	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_event) event_q;
 	unsigned int stop:1;
 } sla = {
 	.thread = AST_PTHREADT_NULL,
@@ -933,6 +951,7 @@
 	S(SLA_TRUNK_STATE_IDLE)
 	S(SLA_TRUNK_STATE_RINGING)
 	S(SLA_TRUNK_STATE_UP)
+	S(SLA_TRUNK_STATE_ONHOLD)
 	}
 	return "Uknown State";
 #undef S
@@ -1069,6 +1088,47 @@
 			return;
 		AST_LIST_INSERT_TAIL(&user->frame_q, f, frame_list);
 	}
+}
+
+static void sla_queue_event(enum sla_event_type type, const struct ast_channel *chan,
+	struct ast_conference *conf)
+{
+	struct sla_event *event;
+	struct sla_station *station;
+	struct sla_trunk_ref *trunk_ref;
+	char *trunk_name;
+
+	AST_RWLIST_RDLOCK(&sla_stations);
+	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
+		if (station->chan != chan)
+			continue;
+		trunk_name = ast_strdupa(conf->confno);
+		strsep(&trunk_name, "_");
+		if (ast_strlen_zero(trunk_name)) {
+			AST_RWLIST_UNLOCK(&sla_stations);
+			ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno);
+			return;
+		}
+		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
+			if (!strcmp(trunk_ref->trunk->name, trunk_name))
+				break;
+		}
+	}
+	AST_RWLIST_UNLOCK(&sla_stations);
+
+	if (!trunk_ref) {
+		ast_log(LOG_DEBUG, "Trunk not found for event!\n");
+		return;
+	}
+
+	if (!(event = ast_calloc(1, sizeof(*event))))
+		return;
+
+	event->type = type;
+	event->trunk_ref = trunk_ref;
+	event->station = station;
+
+	AST_LIST_INSERT_TAIL(&sla.event_q, event, entry);
 }
 
 static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags, char *optargs[])
@@ -1842,6 +1902,24 @@
 				} else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END)
 					&& confflags & CONFFLAG_PASS_DTMF) {
 					conf_queue_dtmf(conf, user, f);
+				} else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) {
+					switch (f->subclass) {
+					case AST_CONTROL_HOLD:
+						ast_log(LOG_DEBUG, "Got a HOLD frame!\n");
+						ast_mutex_lock(&sla.lock);
+						sla_queue_event(SLA_EVENT_HOLD, chan, conf);
+						ast_cond_signal(&sla.cond);
+						ast_mutex_unlock(&sla.lock);
+						break;
+					case AST_CONTROL_UNHOLD:
+						ast_log(LOG_DEBUG, "Got a UNHOLD frame!\n");
+						ast_mutex_lock(&sla.lock);
+						sla_queue_event(SLA_EVENT_UNHOLD, chan, conf);
+						ast_cond_signal(&sla.cond);
+						ast_mutex_unlock(&sla.lock);
+					default:
+						break;
+					}
 				} else if (option_debug) {
 					ast_log(LOG_DEBUG,
 						"Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n",
@@ -2915,7 +2993,8 @@
 
 	ast_atomic_fetchadd_int((int *) &trunk->active_stations, 1);
 	snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk->name);
-	ast_set_flag(&conf_flags, CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF);
+	ast_set_flag(&conf_flags, 
+		CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION);
 	ast_answer(station->chan);
 	conf = build_conf(conf_name, "", "", 0, 0, 1);
 	if (conf)
@@ -2937,14 +3016,40 @@
 	for (; !sla.stop;) {
 		struct sla_trunk_ref *trunk_ref;
 		struct sla_station_ref *station_ref;
+		struct sla_event *event;
 		enum ast_dial_result dial_res = AST_DIAL_RESULT_TRYING;
 
 		ast_mutex_lock(&sla.lock);
-		if (AST_LIST_EMPTY(&sla.ringing_trunks)) {
+		if (AST_LIST_EMPTY(&sla.ringing_trunks) && AST_LIST_EMPTY(&sla.event_q)) {
 			ast_cond_wait(&sla.cond, &sla.lock);
 			if (sla.stop)
 				break;
 			ast_log(LOG_DEBUG, "Ooh, I was woken up!\n");
+		}
+
+		while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) {
+			switch (event->type) {
+			case SLA_EVENT_HOLD:
+				ast_log(LOG_DEBUG, "HOLD, station: %s  trunk: %s\n", 
+					event->station->name, event->trunk_ref->trunk->name);
+				ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1);
+				trunk_ref->state = SLA_TRUNK_STATE_ONHOLD;
+				ast_device_state_changed("SLA:%s_%s", 
+					event->station->name, event->trunk_ref->trunk->name);
+				break;
+			case SLA_EVENT_UNHOLD:
+				ast_log(LOG_DEBUG, "UNHOLD, station: %s  trunk: %s\n", 
+					event->station->name, event->trunk_ref->trunk->name);
+				if (ast_atomic_dec_and_test((int *) &event->trunk_ref->trunk->hold_stations) == 1)
+					change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP);
+				else {
+					trunk_ref->state = SLA_TRUNK_STATE_UP;
+					ast_device_state_changed("SLA:%s_%s",
+						event->station->name, event->trunk_ref->trunk->name);
+				}
+				break;
+			}
+			free(event);
 		}
 
 		/* At this point, we know there are ringing trunks.  So, make sure that every
@@ -2992,6 +3097,7 @@
 			pthread_t dont_care;
 			ast_mutex_t cond_lock;
 			ast_cond_t cond;
+			unsigned int done = 0;
 
 			switch ((dial_res = ast_dial_status(station_ref->station->dial))) {
 			case AST_DIAL_RESULT_HANGUP:
@@ -3055,6 +3161,12 @@
 			}
 			if (dial_res == AST_DIAL_RESULT_ANSWERED)
 				break;
+			ast_mutex_lock(&sla.lock);
+			if (!AST_LIST_EMPTY(&sla.event_q))
+				done = 1;
+			ast_mutex_unlock(&sla.lock);
+			if (done)
+				break;
 		}
 		AST_LIST_TRAVERSE_SAFE_END
 		if (dial_res != AST_DIAL_RESULT_ANSWERED)
@@ -3163,7 +3275,8 @@
 
 	snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk->name);
 	ast_set_flag(&conf_flags, 
-		CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF);
+		CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 
+		CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK);
 	conf = build_conf(conf_name, "", "", 1, 1, 1);
 
 	ast_mutex_lock(args->cond_lock);
@@ -3392,6 +3505,9 @@
 		case SLA_TRUNK_STATE_UP:
 			res = AST_DEVICE_INUSE;
 			break;
+		case SLA_TRUNK_STATE_ONHOLD:
+			res = AST_DEVICE_ONHOLD;
+			break;
 		}
 		AST_RWLIST_UNLOCK(&sla_trunks);
 	}



More information about the asterisk-commits mailing list