diff --git a/apps/app_queue.c b/apps/app_queue.c
index 5d8ca0c1c4a0cd472f817e94c0edd7dddb750ef4..fd5fb885e82e4e3484dc2c3ad09c3dbde42d65b1 100755
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -37,6 +37,12 @@
 
 #include <pthread.h>
 
+#define QUEUE_STRATEGY_RINGALL		0
+#define QUEUE_STRATEGY_ROUNDROBIN	1
+#define QUEUE_STRATEGY_LEASTRECENT	2
+#define QUEUE_STRATEGY_FEWESTCALLS	3
+#define QUEUE_STRATEGY_RANDOM		4
+
 #define DEFAULT_RETRY		5
 #define DEFAULT_TIMEOUT		15
 #define RECHECK				1		/* Recheck every second to see we we're at the top yet */
@@ -91,7 +97,10 @@ static char *app_rqm_descrip =
 
 struct localuser {
 	struct ast_channel *chan;
+	char numsubst[256];
+	char tech[40];
 	int stillgoing;
+	int metric;
 	int allowredirect_in;
 	int allowredirect_out;
 	int ringbackonly;
@@ -117,6 +126,7 @@ struct queue_ent {
 struct member {
 	char tech[80];				/* Technology */
 	char loc[256];				/* Location */
+	struct timeval lastcall;	/* When last successful call was hungup */
 	struct member *next;		/* Next member */
 };
 
@@ -126,6 +136,7 @@ struct ast_call_queue {
 	char moh[80];			/* Name of musiconhold to be used */
 	char announce[80];		/* Announcement to play */
 	char context[80];		/* Announcement to play */
+	int strategy;			/* Queueing strategy */
 	int announcetimeout;	/* How often to announce their position */
 	int count;				/* How many entries are in the queue */
 	int maxlen;				/* Max number of entries in queue */
@@ -274,7 +285,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
 	struct localuser *oo;
 	while(outgoing) {
 		/* Hangup any existing lines we have open */
-		if (outgoing->chan != exception)
+		if (outgoing->chan && (outgoing->chan != exception))
 			ast_hangup(outgoing->chan);
 		oo = outgoing;
 		outgoing=outgoing->next;
@@ -306,7 +317,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 		watchers[0] = in;
 		while(o) {
 			/* Keep track of important channels */
-			if (o->stillgoing) {
+			if (o->stillgoing && o->chan) {
 				watchers[pos++] = o->chan;
 				found = 1;
 			}
@@ -439,6 +450,65 @@ static int wait_our_turn(struct queue_ent *qe)
 	return res;
 }
 
+static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
+{
+	int res;
+	/* Request the peer */
+	tmp->chan = ast_request(tmp->tech, qe->chan->nativeformats, tmp->numsubst);
+	if (!tmp->chan) {			/* If we can't, just go on to the next call */
+#if 0
+		ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech);
+#endif			
+		if (qe->chan->cdr)
+			ast_cdr_busy(qe->chan->cdr);
+		tmp->stillgoing = 0;
+		return 0;
+	}
+	tmp->chan->appl = "AppQueue";
+	tmp->chan->data = "(Outgoing Line)";
+	tmp->chan->whentohangup = 0;
+	if (tmp->chan->callerid)
+		free(tmp->chan->callerid);
+	if (tmp->chan->ani)
+		free(tmp->chan->ani);
+	if (qe->chan->callerid)
+		tmp->chan->callerid = strdup(qe->chan->callerid);
+	else
+		tmp->chan->callerid = NULL;
+	if (qe->chan->ani)
+		tmp->chan->ani = strdup(qe->chan->ani);
+	else
+		tmp->chan->ani = NULL;
+	/* Presense of ADSI CPE on outgoing channel follows ours */
+	tmp->chan->adsicpe = qe->chan->adsicpe;
+	/* Place the call, but don't wait on the answer */
+	res = ast_call(tmp->chan, tmp->numsubst, 0);
+	if (res) {
+		/* Again, keep going even if there's an error */
+		if (option_debug)
+			ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
+		else if (option_verbose > 2)
+			ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->numsubst);
+		ast_hangup(tmp->chan);
+		tmp->chan = NULL;
+		tmp->stillgoing = 0;
+		return 0;
+	} else
+		if (option_verbose > 2)
+			ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->numsubst);
+	return 0;
+}
+
+static int calc_metric(struct ast_call_queue *q, struct queue_ent *qe, struct localuser *tmp)
+{
+	switch (q->strategy) {
+	case QUEUE_STRATEGY_RINGALL:
+		ast_log(LOG_WARNING, "Can't calculate metric for ringall strategy\n");
+		break;
+	}
+	return 0;
+}
+
 static int try_calling(struct queue_ent *qe, char *options, char *announceoverride, char *url)
 {
 	struct member *cur;
@@ -447,7 +517,6 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
 	int allowredir_in=0;
 	int allowredir_out=0;
 	int allowdisconnect=0;
-	char numsubst[AST_MAX_EXTENSION];
 	char restofit[AST_MAX_EXTENSION];
 	char *newnum;
 	struct ast_channel *peer;
@@ -469,6 +538,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
 			goto out;
 		}
 		memset(tmp, 0, sizeof(struct localuser));
+		tmp->stillgoing = -1;
 		if (options) {
 			if (strchr(options, 't'))
 				tmp->allowredirect_in = 1;
@@ -488,83 +558,28 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
 		} else 
 			ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
 
-		strncpy(numsubst, cur->loc, sizeof(numsubst)-1);
+		strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1);
+		strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1);
 		/* If we're dialing by extension, look at the extension to know what to dial */
-		if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
+		if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) {
 			strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
-			snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", qe->chan->exten,restofit);
+			snprintf(newnum, sizeof(tmp->numsubst) - (newnum - tmp->numsubst), "%s%s", qe->chan->exten,restofit);
 			if (option_debug)
-				ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
-		}
-		/* Request the peer */
-		tmp->chan = ast_request(cur->tech, qe->chan->nativeformats, numsubst);
-		if (!tmp->chan) {
-			/* If we can't, just go on to the next call */
-#if 0
-			ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech);
-#endif			
-			if (qe->chan->cdr)
-				ast_cdr_busy(qe->chan->cdr);
-			free(tmp);
-			cur = cur->next;
-			continue;
-		}
-#if 0		
-		/* Don't honor call forwarding on a queue! */
-		if (strlen(tmp->chan->call_forward)) {
-			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
-			/* Setup parameters */
-			strncpy(chan->exten, tmp->chan->call_forward, sizeof(chan->exten));
-			strncpy(chan->context, tmp->chan->context, sizeof(chan->context));
-			chan->priority = 0;
-			to = 0;
-			ast_hangup(tmp->chan);
-			free(tmp);
-			cur = rest;
-			break;
+				ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->numsubst);
 		}
-#endif		
-		tmp->chan->appl = "AppQueue";
-		tmp->chan->data = "(Outgoing Line)";
-		tmp->chan->whentohangup = 0;
-		if (tmp->chan->callerid)
-			free(tmp->chan->callerid);
-		if (tmp->chan->ani)
-			free(tmp->chan->ani);
-		if (qe->chan->callerid)
-			tmp->chan->callerid = strdup(qe->chan->callerid);
-		else
-			tmp->chan->callerid = NULL;
-		if (qe->chan->ani)
-			tmp->chan->ani = strdup(qe->chan->ani);
+		/* Special case: If we ring everyone, go ahead and ring them, otherwise
+		   just calculate their metric for the appropriate strategy */
+		if (!qe->parent->strategy)
+			ring_entry(qe, tmp);
 		else
-			tmp->chan->ani = NULL;
-		/* Presense of ADSI CPE on outgoing channel follows ours */
-		tmp->chan->adsicpe = qe->chan->adsicpe;
-		/* Place the call, but don't wait on the answer */
-		res = ast_call(tmp->chan, numsubst, 0);
-		if (res) {
-			/* Again, keep going even if there's an error */
-			if (option_debug)
-				ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
-			else if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
-			ast_hangup(tmp->chan);
-			free(tmp);
-			cur = cur->next;
-			continue;
-		} else
-			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
+			calc_metric(qe->parent, qe, tmp);
 		/* Put them in the list of outgoing thingies...  We're ready now. 
 		   XXX If we're forcibly removed, these outgoing calls won't get
 		   hung up XXX */
-		tmp->stillgoing = -1;
 		tmp->next = outgoing;
 		outgoing = tmp;		
 		/* If this line is up, don't try anybody else */
-		if (outgoing->chan->_state == AST_STATE_UP)
+		if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
 			break;
 
 		cur = cur->next;