--- apps/app_queue.c.orig	2008-01-14 11:35:12.000000000 -0500
+++ apps/app_queue.c	2008-01-28 19:41:53.121988528 -0500
@@ -330,6 +330,7 @@
 
 struct member {
 	char interface[80];                 /*!< Technology/Location */
+	char state_interface[80];           /*!< Technology/Location from which to read devicestate changes */
 	char membername[80];                /*!< Member name to use in queue logs */
 	int penalty;                        /*!< Are we a last resort? */
 	int calls;                          /*!< Number of calls serviced by this member */
@@ -605,7 +606,7 @@
 		while ((cur = ao2_iterator_next(&mem_iter))) {
 			char *interface;
 			char *slash_pos;
-			interface = ast_strdupa(cur->interface);
+			interface = ast_strdupa(cur->state_interface);
 			if ((slash_pos = strchr(interface, '/')))
 				if ((slash_pos = strchr(slash_pos + 1, '/')))
 					*slash_pos = '\0';
@@ -715,7 +716,7 @@
 	return 0;
 }
 /*! \brief allocate space for new queue member and set fields based on parameters passed */
-static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
+static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
 {
 	struct member *cur;
 	
@@ -723,6 +724,10 @@
 		cur->penalty = penalty;
 		cur->paused = paused;
 		ast_copy_string(cur->interface, interface, sizeof(cur->interface));
+ 		if (!ast_strlen_zero(state_interface))
+ 			ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
+ 		else
+ 			ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
 		if (!ast_strlen_zero(membername))
 			ast_copy_string(cur->membername, membername, sizeof(cur->membername));
 		else
@@ -865,6 +870,7 @@
 {
 	struct call_queue *q;
 	struct member *mem, tmpmem;
+   	struct ao2_iterator mem_iter;
 	int ret = 0;
 
 	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
@@ -872,13 +878,16 @@
 	AST_LIST_LOCK(&queues);
 	AST_LIST_TRAVERSE(&queues, q, list) {
 		ast_mutex_lock(&q->lock);
-		if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
-			ao2_ref(mem, -1);
-			ret = 1;
+	   
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((mem = ao2_iterator_next(&mem_iter))) {
+			if (!strcasecmp(mem->state_interface, interface)) {
+	  			ao2_ref(mem, -1);
+				ret = 1;
+				break;
+		     	}
 		}
 		ast_mutex_unlock(&q->lock);
-		if (ret)
-			break;
 	}
 	AST_LIST_UNLOCK(&queues);
 
@@ -1072,7 +1081,7 @@
 	}
 }
 
-static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
+static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char *state_interface)
 {
 	struct member *m, tmpmem;
 	int penalty = 0;
@@ -1096,10 +1105,10 @@
 
 	/* Create a new one if not found, else update penalty */
 	if (!m) {
-		if ((m = create_queue_member(interface, membername, penalty, paused))) {
+		if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
 			m->dead = 0;
 			m->realtime = 1;
-			add_to_interfaces(interface);
+			add_to_interfaces(m->state_interface);
 			ao2_link(q->members, m);
 			ao2_ref(m, -1);
 			m = NULL;
@@ -1109,6 +1118,11 @@
 		m->dead = 0;	/* Do not delete this one. */
 		if (paused_str)
 			m->paused = paused;
+		if (strcasecmp(state_interface, m->state_interface)) {	   
+			remove_from_interfaces(m->state_interface);
+			ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
+			add_to_interfaces(m->state_interface);
+		}	   
 		m->penalty = penalty;
 		ao2_ref(m, -1);
 	}
@@ -1123,7 +1137,7 @@
 	while ((cur = ao2_iterator_next(&mem_iter))) {
 		if (all || !cur->dynamic) {
 			ao2_unlink(q->members, cur);
-			remove_from_interfaces(cur->interface);
+			remove_from_interfaces(cur->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(cur, -1);
@@ -1238,7 +1252,8 @@
 		rt_handle_member_record(q, interface,
 			ast_variable_retrieve(member_config, interface, "membername"),
 			ast_variable_retrieve(member_config, interface, "penalty"),
-			ast_variable_retrieve(member_config, interface, "paused"));
+			ast_variable_retrieve(member_config, interface, "paused"),
+			ast_variable_retrieve(member_config, interface, "state_interface"));
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -1246,9 +1261,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
-			ast_mutex_unlock(&q->lock);
-			remove_from_interfaces(m->interface);
-			ast_mutex_lock(&q->lock);
+			remove_from_interfaces(m->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(m, -1);
@@ -1307,7 +1320,8 @@
 		rt_handle_member_record(q, interface,
 			S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
 			ast_variable_retrieve(member_config, interface, "penalty"),
-			ast_variable_retrieve(member_config, interface, "paused"));
+			ast_variable_retrieve(member_config, interface, "paused"),
+			ast_variable_retrieve(member_config, interface, "state_interface"));
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -1315,9 +1329,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
-			ast_mutex_unlock(&q->lock);
-			remove_from_interfaces(m->interface);
-			ast_mutex_lock(&q->lock);
+			remove_from_interfaces(m->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(m, -1);
@@ -3182,6 +3194,7 @@
 				"MemberName: %s\r\n",
 				q->name, mem->interface, mem->membername);
 			ao2_unlink(q->members, mem);
+			remove_from_interfaces(mem->state_interface);
 			ao2_ref(mem, -1);
 
 			if (queue_persistent_members)
@@ -3195,16 +3208,13 @@
 		break;
 	}
 
-	if (res == RES_OKAY)
-		remove_from_interfaces(interface);
-
 	AST_LIST_UNLOCK(&queues);
 
 	return res;
 }
 
 
-static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump)
+static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
 {
 	struct call_queue *q;
 	struct member *new_member, *old_member;
@@ -3219,8 +3229,8 @@
 
 	ast_mutex_lock(&q->lock);
 	if ((old_member = interface_exists(q, interface)) == NULL) {
-		add_to_interfaces(interface);
-		if ((new_member = create_queue_member(interface, membername, penalty, paused))) {
+		if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+			add_to_interfaces(new_member->state_interface);
 			new_member->dynamic = 1;
 			ao2_link(q->members, new_member);
 			q->membercount++;
@@ -3312,6 +3322,7 @@
 	char *member;
 	char *interface;
 	char *membername = NULL;
+	char *state_interface;   
 	char *penalty_tok;
 	int penalty = 0;
 	char *paused_tok;
@@ -3360,7 +3371,11 @@
 			penalty_tok = strsep(&member, ";");
 			paused_tok = strsep(&member, ";");
 			membername = strsep(&member, ";");
+			state_interface = strsep(&member, ";");
 
+			if (ast_strlen_zero(state_interface))
+		   		state_interface = ast_strdupa(interface);
+		     
 			if (!penalty_tok) {
 				ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
 				break;
@@ -3380,13 +3395,11 @@
 				ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
 				break;
 			}
-			if (ast_strlen_zero(membername))
-				membername = interface;
 
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Name: %s  Penalty: %d  Paused: %d\n", queue_name, interface, membername, penalty, paused);
 			
-			if (add_to_queue(queue_name, interface, membername, penalty, paused, 0) == RES_OUTOFMEMORY) {
+			if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
 				ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
 				break;
 			}
@@ -3585,6 +3598,7 @@
 		AST_APP_ARG(penalty);
 		AST_APP_ARG(options);
 		AST_APP_ARG(membername);
+		AST_APP_ARG(state_interface);
 	);
 	int penalty = 0;
 
@@ -3606,6 +3620,9 @@
 			*temppos = '\0';
 	}
 
+	if (ast_strlen_zero(args.state_interface))
+   		args.state_interface = ast_strdupa(args.interface);
+   
 	if (!ast_strlen_zero(args.penalty)) {
 		if ((sscanf(args.penalty, "%d", &penalty) != 1) || penalty < 0) {
 			ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
@@ -3618,7 +3635,7 @@
 			priority_jump = 1;
 	}
 
-	switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members)) {
+	switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
 		ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
@@ -4120,13 +4137,14 @@
 	int new;
 	const char *general_val = NULL;
 	char parse[80];
-	char *interface;
+	char *interface, *state_interface;
 	char *membername = NULL;
 	int penalty;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(interface);
 		AST_APP_ARG(penalty);
 		AST_APP_ARG(membername);
+		AST_APP_ARG(state_interface);
 	);
 	
 	if (!(cfg = ast_config_load("queues.conf"))) {
@@ -4218,11 +4236,23 @@
 							while (*membername && *membername < 33) membername++;
 						}
 
+						if (!ast_strlen_zero(args.state_interface)) {
+							state_interface = args.state_interface;
+							while (*state_interface && *state_interface < 33) state_interface++;
+						} else
+							state_interface = interface;
+
 						/* Find the old position in the list */
 						ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
 						cur = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK);
 
-						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0);
+						/* Only attempt removing from interfaces list if the new state_interface is different than the old one */
+						if (cur && strcasecmp(cur->state_interface, state_interface)) {
+							remove_from_interfaces(cur->state_interface);
+						}
+						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface);
+						if (!cur || (cur && strcasecmp(cur->state_interface, state_interface)))
+							add_to_interfaces(state_interface);
 						ao2_link(q->members, newm);
 						ao2_ref(newm, -1);
 						newm = NULL;
@@ -4230,8 +4260,6 @@
 						if (cur)
 							ao2_ref(cur, -1);
 						else {
-							/* Add them to the master int list if necessary */
-							add_to_interfaces(interface);
 							q->membercount++;
 						}
 					} else {
@@ -4565,7 +4594,7 @@
 
 static int manager_add_queue_member(struct mansession *s, const struct message *m)
 {
-	const char *queuename, *interface, *penalty_s, *paused_s, *membername;
+	const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
 	int paused, penalty = 0;
 
 	queuename = astman_get_header(m, "Queue");
@@ -4573,6 +4602,7 @@
 	penalty_s = astman_get_header(m, "Penalty");
 	paused_s = astman_get_header(m, "Paused");
 	membername = astman_get_header(m, "MemberName");
+	state_interface = astman_get_header(m, "StateInterface");
 
 	if (ast_strlen_zero(queuename)) {
 		astman_send_error(s, m, "'Queue' not specified.");
@@ -4594,7 +4624,7 @@
 	else
 		paused = abs(ast_true(paused_s));
 
-	switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members)) {
+	switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
 		astman_send_ack(s, m, "Added interface to queue");
@@ -4672,16 +4702,18 @@
 
 static int handle_queue_add_member(int fd, int argc, char *argv[])
 {
-	char *queuename, *interface, *membername = NULL;
+	char *queuename, *interface, *membername = NULL, *state_interface;
 	int penalty;
 
-	if ((argc != 6) && (argc != 8) && (argc != 10)) {
+	if ((argc != 6) && (argc != 8) && (argc != 10) && (argc != 12)) {
 		return RESULT_SHOWUSAGE;
 	} else if (strcmp(argv[4], "to")) {
 		return RESULT_SHOWUSAGE;
-	} else if ((argc == 8) && strcmp(argv[6], "penalty")) {
+	} else if ((argc >= 8) && strcmp(argv[6], "penalty")) {
+		return RESULT_SHOWUSAGE;
+	} else if ((argc >= 10) && strcmp(argv[8], "as")) {
 		return RESULT_SHOWUSAGE;
-	} else if ((argc == 10) && strcmp(argv[8], "as")) {
+	} else if ((argc == 12) && strcmp(argv[10], "state_interface")) {
 		return RESULT_SHOWUSAGE;
 	}
 
@@ -4705,7 +4737,11 @@
 		membername = argv[9];
 	}
 
-	switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members)) {
+	if (argc >= 12) {
+		state_interface = argv[11];
+	}
+
+	switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
 		ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
