[asterisk-commits] file: trunk r227424 - in /trunk: apps/app_queue.c configs/queues.conf.sample
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list