[svn-commits] file: trunk r227424 - in /trunk: apps/app_queue.c configs/queues.conf.sample

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Nov 3 15:16:21 CST 2009


Author: file
Date: Tue Nov  3 15:16:14 2009
New Revision: 227424

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=227424
Log:
Add support for using a hint when configuring a state interface using the format hint:<extension>@<context>.

(closes issue #15168)
Reported by: p_lindheimer
Patches:
      queue_extenstate5_1.4.svn.patch uploaded by GameGamer43 (license 894)

Modified:
    trunk/apps/app_queue.c
    trunk/configs/queues.conf.sample

Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=227424&r1=227423&r2=227424
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Tue Nov  3 15:16:14 2009
@@ -824,20 +824,22 @@
 };
 
 struct member {
-	char interface[80];                 /*!< Technology/Location to dial to reach this member*/
-	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 */
-	int dynamic;                        /*!< Are we dynamically added? */
-	int realtime;                       /*!< Is this member realtime? */
-	int status;                         /*!< Status of queue member */
-	int paused;                         /*!< Are we paused (not accepting calls)? */
-	time_t lastcall;                    /*!< When last successful call was hungup */
-	struct call_queue *lastqueue;	    /*!< Last queue we received a call */
-	unsigned int dead:1;                /*!< Used to detect members deleted in realtime */
-	unsigned int delme:1;               /*!< Flag to delete entry on reload */
-	char rt_uniqueid[80];               /*!< Unique id of realtime member entry */
+	char interface[80];                  /*!< Technology/Location to dial to reach this member*/
+	char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
+	char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
+	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 */
+	int dynamic;                         /*!< Are we dynamically added? */
+	int realtime;                        /*!< Is this member realtime? */
+	int status;                          /*!< Status of queue member */
+	int paused;                          /*!< Are we paused (not accepting calls)? */
+	time_t lastcall;                     /*!< When last successful call was hungup */
+	struct call_queue *lastqueue;	     /*!< Last queue we received a call */
+	unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
+	unsigned int delme:1;                /*!< Flag to delete entry on reload */
+	char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
 };
 
 enum empty_conditions {
@@ -1258,6 +1260,81 @@
 	}
 }
 
+/*! \brief Helper function which converts from extension state to device state values */
+static int extensionstate2devicestate(int state)
+{
+	switch (state) {
+	case AST_EXTENSION_NOT_INUSE:
+		state = AST_DEVICE_NOT_INUSE;
+		break;
+	case AST_EXTENSION_INUSE:
+		state = AST_DEVICE_INUSE;
+		break;
+	case AST_EXTENSION_BUSY:
+		state = AST_DEVICE_BUSY;
+		break;
+	case AST_EXTENSION_RINGING:
+		state = AST_DEVICE_RINGING;
+		break;
+	case AST_EXTENSION_ONHOLD:
+		state = AST_DEVICE_ONHOLD;
+		break;
+	case AST_EXTENSION_UNAVAILABLE:
+		state = AST_DEVICE_UNAVAILABLE;
+		break;
+	case AST_EXTENSION_REMOVED:
+	case AST_EXTENSION_DEACTIVATED:
+	default:
+		state = AST_DEVICE_INVALID;
+		break;
+	}
+
+	return state;
+}
+
+static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
+{
+	struct ao2_iterator miter, qiter;
+	struct member *m;
+	struct call_queue *q;
+	int found = 0, device_state = extensionstate2devicestate(state);
+
+	qiter = ao2_iterator_init(queues, 0);
+	while ((q = ao2_iterator_next(&qiter))) {
+		ao2_lock(q);
+
+		miter = ao2_iterator_init(q->members, 0);
+		for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
+			if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
+				update_status(q, m, device_state);
+				ao2_ref(m, -1);
+				found = 1;
+				break;
+			}
+		}
+		ao2_iterator_destroy(&miter);
+
+		ao2_unlock(q);
+		ao2_ref(q, -1);
+	}
+	ao2_iterator_destroy(&qiter);
+
+        if (found) {
+		ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
+	} else {
+		ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
+			  exten, context, device_state, ast_devstate2str(device_state));
+	}
+
+	return 0;
+}
+
+/*! \brief Return the current state of a member */
+static int get_queue_member_status(struct member *cur)
+{
+	return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
+}
+
 /*! \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, const char *state_interface)
 {
@@ -1277,7 +1354,14 @@
 			ast_copy_string(cur->membername, interface, sizeof(cur->membername));
 		if (!strchr(cur->interface, '/'))
 			ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
-		cur->status = ast_device_state(cur->state_interface);
+		if (!strncmp(state_interface, "hint:", 5)) {
+			char *tmp = ast_strdupa(state_interface), *context = tmp;
+			char *exten = strsep(&context, "@") + 5;
+
+			ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
+			ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
+		}
+		cur->status = get_queue_member_status(cur);
 	}
 
 	return cur;
@@ -2677,7 +2761,7 @@
 		tmp->stillgoing = 0;	
 
 		ao2_lock(qe->parent);
-		update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
+		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
 		qe->parent->rrpos++;
 		qe->linpos++;
 		ao2_unlock(qe->parent);
@@ -2760,7 +2844,7 @@
 		ast_channel_unlock(qe->chan);
 		do_hang(tmp);
 		(*busies)++;
-		update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
+		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
 		return 0;
 	} else if (qe->parent->eventwhencalled) {
 		char vars[2048];
@@ -2788,7 +2872,7 @@
 	ast_channel_unlock(tmp->chan);
 	ast_channel_unlock(qe->chan);
 
-	update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
+	update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
 	return 1;
 }
 
@@ -6093,7 +6177,7 @@
 			 */
 			q->membercount++;
 		}
-		member->status = ast_device_state(member->state_interface);
+		member->status = get_queue_member_status(member);
 		return 0;
 	} else {
 		q->membercount--;
@@ -7480,6 +7564,8 @@
 	if (device_state_sub)
 		ast_event_unsubscribe(device_state_sub);
 
+	ast_extension_state_del(0, extension_state_cb);
+
 	if ((con = ast_context_find("app_queue_gosub_virtual_context"))) {
 		ast_context_remove_extension2(con, "s", 1, NULL, 0);
 		ast_context_destroy(con, "app_queue"); /* leave no trace */
@@ -7553,6 +7639,8 @@
 		res = -1;
 	}
 
+	ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);
+
 	ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
 
 	return res ? AST_MODULE_LOAD_DECLINE : 0;

Modified: trunk/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/queues.conf.sample?view=diff&rev=227424&r1=227423&r2=227424
==============================================================================
--- trunk/configs/queues.conf.sample (original)
+++ trunk/configs/queues.conf.sample Tue Nov  3 15:16:14 2009
@@ -474,6 +474,10 @@
 ; state notifications, even though the first interface specified is the one
 ; that is actually called.
 ;
+; A hint can also be used in place of the state interface using the format
+; hint:<extension>@<context>. If no context is specified then 'default' will
+; be used.
+;
 ; It is important to ensure that channel drivers used for members are loaded
 ; before app_queue.so itself or they may be marked invalid until reload. This
 ; can be accomplished by explicitly listing them in modules.conf before




More information about the svn-commits mailing list