2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief True call queues with optional send URL on answer
23 * \author Mark Spencer <markster@digium.com>
25 * \arg Config in \ref Config_qu queues.conf
27 * \par Development notes
28 * \note 2004-11-25: Persistent Dynamic Members added by:
29 * NetNation Communications (www.netnation.com)
30 * Kevin Lindsay <kevinl@netnation.com>
32 * Each dynamic agent in each queue is now stored in the astdb.
33 * When asterisk is restarted, each agent will be automatically
34 * readded into their recorded queues. This feature can be
35 * configured with the 'persistent_members=<1|0>' setting in the
36 * '[general]' category in queues.conf. The default is on.
38 * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
40 * \note These features added by David C. Troy <dave@toad.net>:
41 * - Per-queue holdtime calculation
42 * - Estimated holdtime announcement
43 * - Position announcement
44 * - Abandoned/completed call counters
45 * - Failout timer passed as optional app parameter
46 * - Optional monitoring of calls, started when call is answered
48 * Patch Version 1.07 2003-12-24 01
50 * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
51 * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
53 * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
54 * by Matthew Enger <m.enger@xi.com.au>
56 * \ingroup applications
61 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
70 #include <sys/signal.h>
71 #include <netinet/in.h>
73 #include "asterisk/lock.h"
74 #include "asterisk/file.h"
75 #include "asterisk/logger.h"
76 #include "asterisk/channel.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/options.h"
79 #include "asterisk/app.h"
80 #include "asterisk/linkedlists.h"
81 #include "asterisk/module.h"
82 #include "asterisk/translate.h"
83 #include "asterisk/say.h"
84 #include "asterisk/features.h"
85 #include "asterisk/musiconhold.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/manager.h"
88 #include "asterisk/config.h"
89 #include "asterisk/monitor.h"
90 #include "asterisk/utils.h"
91 #include "asterisk/causes.h"
92 #include "asterisk/astdb.h"
93 #include "asterisk/devicestate.h"
94 #include "asterisk/stringfields.h"
95 #include "asterisk/event.h"
96 #include "asterisk/astobj2.h"
99 QUEUE_STRATEGY_RINGALL = 0,
100 QUEUE_STRATEGY_LEASTRECENT,
101 QUEUE_STRATEGY_FEWESTCALLS,
102 QUEUE_STRATEGY_RANDOM,
103 QUEUE_STRATEGY_RRMEMORY
106 static struct strategy {
110 { QUEUE_STRATEGY_RINGALL, "ringall" },
111 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
112 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
113 { QUEUE_STRATEGY_RANDOM, "random" },
114 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
117 #define DEFAULT_RETRY 5
118 #define DEFAULT_TIMEOUT 15
119 #define RECHECK 1 /* Recheck every second to see we we're at the top yet */
120 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
121 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /* The minimum number of seconds between position announcements
122 The default value of 15 provides backwards compatibility */
123 #define MAX_QUEUE_BUCKETS 53
125 #define RES_OKAY 0 /* Action completed */
126 #define RES_EXISTS (-1) /* Entry already exists */
127 #define RES_OUTOFMEMORY (-2) /* Out of memory */
128 #define RES_NOSUCHQUEUE (-3) /* No such queue */
130 static char *app = "Queue";
132 static char *synopsis = "Queue a call for a call queue";
134 static char *descrip =
135 " Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub]):\n"
136 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
137 "This application will return to the dialplan if the queue does not exist, or\n"
138 "any of the join options cause the caller to not enter the queue.\n"
139 "The option string may contain zero or more of the following characters:\n"
140 " 'c' -- continue in the dialplan if the callee hangs up.\n"
141 " 'd' -- data-quality (modem) call (minimum delay).\n"
142 " 'h' -- allow callee to hang up by pressing *.\n"
143 " 'H' -- allow caller to hang up by pressing *.\n"
144 " 'n' -- no retries on the timeout; will exit this application and \n"
145 " go to the next step.\n"
146 " 'i' -- ignore call forward requests from queue members and do nothing\n"
147 " when they are requested.\n"
148 " 'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
149 " 't' -- allow the called user to transfer the calling user.\n"
150 " 'T' -- allow the calling user to transfer the call.\n"
151 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
152 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
153 " In addition to transferring the call, a call may be parked and then picked\n"
154 "up by another user.\n"
155 " The optional URL will be sent to the called party if the channel supports\n"
157 " The optional AGI parameter will setup an AGI script to be executed on the \n"
158 "calling party's channel once they are connected to a queue member.\n"
159 " The optional macro parameter will run a macro on the \n"
160 "calling party's channel once they are connected to a queue member.\n"
161 " The optional gosub parameter will run a gosub on the \n"
162 "calling party's channel once they are connected to a queue member.\n"
163 " The timeout will cause the queue to fail out after a specified number of\n"
164 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
165 " This application sets the following channel variable upon completion:\n"
166 " QUEUESTATUS The status of the call as a text string, one of\n"
167 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
169 static char *app_aqm = "AddQueueMember" ;
170 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
171 static char *app_aqm_descrip =
172 " AddQueueMember(queuename[,interface[,penalty[,options[,membername]]]]):\n"
173 "Dynamically adds interface to an existing queue.\n"
174 "If the interface is already in the queue it will return an error.\n"
175 " This application sets the following channel variable upon completion:\n"
176 " AQMSTATUS The status of the attempt to add a queue member as a \n"
177 " text string, one of\n"
178 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
179 "Example: AddQueueMember(techsupport,SIP/3000)\n"
182 static char *app_rqm = "RemoveQueueMember" ;
183 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
184 static char *app_rqm_descrip =
185 " RemoveQueueMember(queuename[,interface[,options]]):\n"
186 "Dynamically removes interface to an existing queue\n"
187 "If the interface is NOT in the queue it will return an error.\n"
188 " This application sets the following channel variable upon completion:\n"
189 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
190 " text string, one of\n"
191 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
192 "Example: RemoveQueueMember(techsupport,SIP/3000)\n"
195 static char *app_pqm = "PauseQueueMember" ;
196 static char *app_pqm_synopsis = "Pauses a queue member" ;
197 static char *app_pqm_descrip =
198 " PauseQueueMember([queuename],interface[,options[,reason]]):\n"
199 "Pauses (blocks calls for) a queue member.\n"
200 "The given interface will be paused in the given queue. This prevents\n"
201 "any calls from being sent from the queue to the interface until it is\n"
202 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
203 "queuename is given, the interface is paused in every queue it is a\n"
204 "member of. The application will fail if the interface is not found.\n"
205 "The reason string is entirely optional and is used to add extra information\n"
206 "to the appropriate queue_log entries and manager events.\n"
207 " This application sets the following channel variable upon completion:\n"
208 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
209 " text string, one of\n"
210 " PAUSED | NOTFOUND\n"
211 "Example: PauseQueueMember(,SIP/3000)\n";
213 static char *app_upqm = "UnpauseQueueMember" ;
214 static char *app_upqm_synopsis = "Unpauses a queue member" ;
215 static char *app_upqm_descrip =
216 " UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
217 "Unpauses (resumes calls to) a queue member.\n"
218 "This is the counterpart to PauseQueueMember and operates exactly the\n"
219 "same way, except it unpauses instead of pausing the given interface.\n"
220 "The reason string is entirely optional and is used to add extra information\n"
221 "to the appropriate queue_log entries and manager events.\n"
222 " This application sets the following channel variable upon completion:\n"
223 " UPQMSTATUS The status of the attempt to unpause a queue \n"
224 " member as a text string, one of\n"
225 " UNPAUSED | NOTFOUND\n"
226 "Example: UnpauseQueueMember(,SIP/3000)\n";
228 static char *app_ql = "QueueLog" ;
229 static char *app_ql_synopsis = "Writes to the queue_log" ;
230 static char *app_ql_descrip =
231 " QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
232 "Allows you to write your own events into the queue log\n"
233 "Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
235 /*! \brief Persistent Members astdb family */
236 static const char *pm_family = "Queue/PersistentMembers";
237 /* The maximum length of each persistent member queue database entry */
238 #define PM_MAX_LEN 8192
240 /*! \brief queues.conf [general] option */
241 static int queue_keep_stats = 0;
243 /*! \brief queues.conf [general] option */
244 static int queue_persistent_members = 0;
246 /*! \brief queues.conf per-queue weight option */
247 static int use_weight = 0;
249 /*! \brief queues.conf [general] option */
250 static int autofill_default = 0;
252 /*! \brief queues.conf [general] option */
253 static int montype_default = 0;
255 /*! \brief Subscription to device state change events */
256 static struct ast_event_sub *device_state_sub;
258 /*! \brief queues.conf [general] option */
259 static int update_cdr = 0;
265 QUEUE_LEAVEEMPTY = 3,
266 QUEUE_JOINUNAVAIL = 4,
267 QUEUE_LEAVEUNAVAIL = 5,
273 enum queue_result id;
275 } queue_results[] = {
276 { QUEUE_UNKNOWN, "UNKNOWN" },
277 { QUEUE_TIMEOUT, "TIMEOUT" },
278 { QUEUE_JOINEMPTY,"JOINEMPTY" },
279 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
280 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
281 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
282 { QUEUE_FULL, "FULL" },
283 { QUEUE_CONTINUE, "CONTINUE" },
286 /*! \brief We define a custom "local user" structure because we
287 use it not only for keeping track of what is in use but
288 also for keeping track of who we're dialing. */
291 struct callattempt *q_next;
292 struct ast_channel *chan;
298 struct member *member;
303 struct call_queue *parent; /*!< What queue is our parent */
304 char moh[80]; /*!< Name of musiconhold to be used */
305 char announce[80]; /*!< Announcement to play for member when call is answered */
306 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
307 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
308 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
309 int pos; /*!< Where we are in the queue */
310 int prio; /*!< Our priority */
311 int last_pos_said; /*!< Last position we told the user */
312 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
313 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
314 time_t last_pos; /*!< Last time we told the user their position */
315 int opos; /*!< Where we started in the queue */
316 int handled; /*!< Whether our call was handled */
317 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
318 time_t start; /*!< When we started holding */
319 time_t expire; /*!< When this entry should expire (time out of queue) */
320 struct ast_channel *chan; /*!< Our channel */
321 struct queue_ent *next; /*!< The next queue entry */
325 char interface[80]; /*!< Technology/Location */
326 char membername[80]; /*!< Member name to use in queue logs */
327 int penalty; /*!< Are we a last resort? */
328 int calls; /*!< Number of calls serviced by this member */
329 int dynamic; /*!< Are we dynamically added? */
330 int realtime; /*!< Is this member realtime? */
331 int status; /*!< Status of queue member */
332 int paused; /*!< Are we paused (not accepting calls)? */
333 time_t lastcall; /*!< When last successful call was hungup */
334 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
335 unsigned int delme:1; /*!< Flag to delete entry on reload */
338 struct member_interface {
340 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
343 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
345 /* values used in multi-bit flags in call_queue */
346 #define QUEUE_EMPTY_NORMAL 1
347 #define QUEUE_EMPTY_STRICT 2
348 #define QUEUE_EMPTY_LOOSE 3
349 #define ANNOUNCEHOLDTIME_ALWAYS 1
350 #define ANNOUNCEHOLDTIME_ONCE 2
351 #define QUEUE_EVENT_VARIABLES 3
354 char name[80]; /*!< Name */
355 char moh[80]; /*!< Music On Hold class to be used */
356 char announce[80]; /*!< Announcement to play when call is answered */
357 char context[AST_MAX_CONTEXT]; /*!< Exit context */
358 unsigned int monjoin:1;
360 unsigned int joinempty:2;
361 unsigned int eventwhencalled:2;
362 unsigned int leavewhenempty:2;
363 unsigned int ringinuse:1;
364 unsigned int setinterfacevar:1;
365 unsigned int setqueuevar:1;
366 unsigned int setqueueentryvar:1;
367 unsigned int reportholdtime:1;
368 unsigned int wrapped:1;
369 unsigned int timeoutrestart:1;
370 unsigned int announceholdtime:2;
371 unsigned int strategy:3;
372 unsigned int maskmemberstatus:1;
373 unsigned int realtime:1;
374 unsigned int found:1;
375 int announcefrequency; /*!< How often to announce their position */
376 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
377 int periodicannouncefrequency; /*!< How often to play periodic announcement */
378 int roundingseconds; /*!< How many seconds do we round to? */
379 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
380 int callscompleted; /*!< Number of queue calls completed */
381 int callsabandoned; /*!< Number of queue calls abandoned */
382 int servicelevel; /*!< seconds setting for servicelevel*/
383 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
384 char monfmt[8]; /*!< Format to use when recording calls */
385 int montype; /*!< Monitor type Monitor vs. MixMonitor */
386 char membermacro[32]; /*!< Macro to run upon member connection */
387 char membergosub[32]; /*!< Gosub to run upon member connection */
388 char sound_next[80]; /*!< Sound file: "Your call is now first in line" (def. queue-youarenext) */
389 char sound_thereare[80]; /*!< Sound file: "There are currently" (def. queue-thereare) */
390 char sound_calls[80]; /*!< Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/
391 char sound_holdtime[80]; /*!< Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
392 char sound_minutes[80]; /*!< Sound file: "minutes." (def. queue-minutes) */
393 char sound_lessthan[80]; /*!< Sound file: "less-than" (def. queue-lessthan) */
394 char sound_seconds[80]; /*!< Sound file: "seconds." (def. queue-seconds) */
395 char sound_thanks[80]; /*!< Sound file: "Thank you for your patience." (def. queue-thankyou) */
396 char sound_callerannounce[80]; /*!< Sound file: Custom announce for caller, no default */
397 char sound_reporthold[80]; /*!< Sound file: "Hold time" (def. queue-reporthold) */
398 char sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS][80];/*!< Sound files: Custom announce, no default */
400 int count; /*!< How many entries */
401 int maxlen; /*!< Max number of entries */
402 int wrapuptime; /*!< Wrapup Time */
404 int retry; /*!< Retry calling everyone after this amount of time */
405 int timeout; /*!< How long to wait for an answer */
406 int weight; /*!< Respective weight */
407 int autopause; /*!< Auto pause queue members if they fail to answer */
409 /* Queue strategy things */
410 int rrpos; /*!< Round Robin - position */
411 int memberdelay; /*!< Seconds to delay connecting member to caller */
412 int autofill; /*!< Ignore the head call status and ring an available agent */
414 struct ao2_container *members; /*!< Head of the list of members */
416 * \brief Number of members _logged in_
417 * \note There will be members in the members container that are not logged
418 * in, so this can not simply be replaced with ao2_container_count().
421 struct queue_ent *head; /*!< Head of the list of callers */
422 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
425 static struct ao2_container *queues;
427 static void update_realtime_members(struct call_queue *q);
428 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
430 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
434 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
435 if (queue_results[i].id == res) {
436 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
442 static char *int2strat(int strategy)
446 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
447 if (strategy == strategies[x].strategy)
448 return strategies[x].name;
454 static int strat2int(const char *strategy)
458 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
459 if (!strcasecmp(strategy, strategies[x].name))
460 return strategies[x].strategy;
466 static int queue_hash_cb(const void *obj, const int flags)
468 const struct call_queue *q = obj;
469 return ast_str_hash(q->name);
472 static int queue_cmp_cb(void *obj, void *arg, int flags)
474 struct call_queue *q = obj, *q2 = arg;
475 return !strcasecmp(q->name, q2->name) ? CMP_MATCH : 0;
478 static inline struct call_queue *queue_ref(struct call_queue *q)
484 static inline struct call_queue *queue_unref(struct call_queue *q)
490 static void set_queue_variables(struct queue_ent *qe)
493 char interfacevar[256]="";
496 if (qe->parent->setqueuevar) {
498 if (qe->parent->callscompleted > 0)
499 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
501 snprintf(interfacevar,sizeof(interfacevar),
502 "QUEUEMAX=%d|QUEUESTRATEGY=%s|QUEUECALLS=%d|QUEUEHOLDTIME=%d|QUEUECOMPLETED=%d|QUEUEABANDONED=%d|QUEUESRVLEVEL=%d|QUEUESRVLEVELPERF=%2.1f",
503 qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
504 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
506 pbx_builtin_setvar(qe->chan, interfacevar);
510 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
511 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
513 struct queue_ent *cur;
530 enum queue_member_status {
532 QUEUE_NO_REACHABLE_MEMBERS,
533 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
537 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty)
539 struct member *member;
540 struct ao2_iterator mem_iter;
541 enum queue_member_status result = QUEUE_NO_MEMBERS;
544 mem_iter = ao2_iterator_init(q->members, 0);
545 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
546 if (max_penalty && (member->penalty > max_penalty))
549 switch (member->status) {
550 case AST_DEVICE_INVALID:
553 case AST_DEVICE_UNAVAILABLE:
554 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
555 result = QUEUE_NO_REACHABLE_MEMBERS;
558 if (member->paused) {
559 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
574 AST_LIST_ENTRY(statechange) entry;
579 static void *handle_statechange(struct statechange *sc)
581 struct call_queue *q;
583 struct ao2_iterator mem_iter;
584 struct member_interface *curint;
585 struct ao2_iterator queue_iter;
589 technology = ast_strdupa(sc->dev);
590 loc = strchr(technology, '/');
597 AST_LIST_LOCK(&interfaces);
598 AST_LIST_TRAVERSE(&interfaces, curint, list) {
601 interface = ast_strdupa(curint->interface);
602 if ((slash_pos = strchr(interface, '/')))
603 if ((slash_pos = strchr(slash_pos + 1, '/')))
606 if (!strcasecmp(interface, sc->dev))
609 AST_LIST_UNLOCK(&interfaces);
612 ast_debug(3, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
616 ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
617 queue_iter = ao2_iterator_init(queues, 0);
618 while ((q = ao2_iterator_next(&queue_iter))) {
620 mem_iter = ao2_iterator_init(q->members, 0);
621 while ((cur = ao2_iterator_next(&mem_iter))) {
624 interface = ast_strdupa(cur->interface);
625 if ((slash_pos = strchr(interface, '/')))
626 if ((slash_pos = strchr(slash_pos + 1, '/')))
629 if (strcasecmp(sc->dev, interface)) {
634 if (cur->status != sc->state) {
635 cur->status = sc->state;
636 if (q->maskmemberstatus) {
641 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
651 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime" : "static",
652 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
664 * \brief Data used by the device state thread
667 /*! Set to 1 to stop the thread */
669 /*! The device state monitoring thread */
671 /*! Lock for the state change queue */
673 /*! Condition for the state change queue */
675 /*! Queue of state changes */
676 AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
678 .thread = AST_PTHREADT_NULL,
681 static void *device_state_thread(void *data)
683 struct statechange *sc;
685 while (!device_state.stop) {
686 ast_mutex_lock(&device_state.lock);
687 if (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
688 ast_cond_wait(&device_state.cond, &device_state.lock);
689 sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry);
691 ast_mutex_unlock(&device_state.lock);
693 /* Check to see if we were woken up to see the request to stop */
694 if (device_state.stop)
700 handle_statechange(sc);
708 static int statechange_queue(const char *dev, enum ast_device_state state)
710 struct statechange *sc;
712 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
716 strcpy(sc->dev, dev);
718 ast_mutex_lock(&device_state.lock);
719 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
720 ast_cond_signal(&device_state.cond);
721 ast_mutex_unlock(&device_state.lock);
726 static void device_state_cb(const struct ast_event *event, void *unused)
728 enum ast_device_state state;
731 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
732 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
734 if (ast_strlen_zero(device)) {
735 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
739 statechange_queue(device, state);
742 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
746 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
747 cur->penalty = penalty;
748 cur->paused = paused;
749 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
750 if(!ast_strlen_zero(membername))
751 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
753 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
754 if (!strchr(cur->interface, '/'))
755 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
756 cur->status = ast_device_state(interface);
763 static int compress_char(const char c)
773 static int member_hash_fn(const void *obj, const int flags)
775 const struct member *mem = obj;
776 const char *chname = strchr(mem->interface, '/');
779 chname = mem->interface;
780 for (i = 0; i < 5 && chname[i]; i++)
781 ret += compress_char(chname[i]) << (i * 6);
785 static int member_cmp_fn(void *obj1, void *obj2, int flags)
787 struct member *mem1 = obj1, *mem2 = obj2;
788 return strcmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
791 static void init_queue(struct call_queue *q)
796 q->retry = DEFAULT_RETRY;
799 q->announcefrequency = 0;
800 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
801 q->announceholdtime = 0;
802 q->roundingseconds = 0; /* Default - don't announce seconds */
805 q->setinterfacevar = 0;
807 q->setqueueentryvar = 0;
808 q->autofill = autofill_default;
809 q->montype = montype_default;
810 q->membermacro[0] = '\0';
811 q->membergosub[0] = '\0';
813 q->announce[0] = '\0';
814 q->context[0] = '\0';
816 q->periodicannouncefrequency = 0;
817 q->sound_callerannounce[0] = '\0'; /* Default, don't announce the caller that he has been answered */
819 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
822 ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
823 ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
824 ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
825 ast_copy_string(q->sound_holdtime, "queue-holdtime", sizeof(q->sound_holdtime));
826 ast_copy_string(q->sound_minutes, "queue-minutes", sizeof(q->sound_minutes));
827 ast_copy_string(q->sound_seconds, "queue-seconds", sizeof(q->sound_seconds));
828 ast_copy_string(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks));
829 ast_copy_string(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan));
830 ast_copy_string(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold));
831 ast_copy_string(q->sound_periodicannounce[0], "queue-periodic-announce", sizeof(q->sound_periodicannounce[0]));
832 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
833 q->sound_periodicannounce[i][0]='\0';
837 static void clear_queue(struct call_queue *q)
840 q->callscompleted = 0;
841 q->callsabandoned = 0;
842 q->callscompletedinsl = 0;
846 static int add_to_interfaces(const char *interface)
848 struct member_interface *curint;
850 AST_LIST_LOCK(&interfaces);
851 AST_LIST_TRAVERSE(&interfaces, curint, list) {
852 if (!strcasecmp(curint->interface, interface))
857 AST_LIST_UNLOCK(&interfaces);
861 ast_debug(1, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
863 if ((curint = ast_calloc(1, sizeof(*curint)))) {
864 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
865 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
867 AST_LIST_UNLOCK(&interfaces);
872 static int interface_exists_global(const char *interface)
874 struct call_queue *q;
875 struct member *mem, tmpmem;
876 struct ao2_iterator queue_iter;
879 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
880 queue_iter = ao2_iterator_init(queues, 0);
881 while ((q = ao2_iterator_next(&queue_iter))) {
884 if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
898 static int remove_from_interfaces(const char *interface)
900 struct member_interface *curint;
902 AST_LIST_LOCK(&interfaces);
903 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
904 if (!strcasecmp(curint->interface, interface)) {
905 if (!interface_exists_global(interface)) {
906 ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
907 AST_LIST_REMOVE_CURRENT(&interfaces, list);
913 AST_LIST_TRAVERSE_SAFE_END;
914 AST_LIST_UNLOCK(&interfaces);
919 static void clear_and_free_interfaces(void)
921 struct member_interface *curint;
923 AST_LIST_LOCK(&interfaces);
924 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
926 AST_LIST_UNLOCK(&interfaces);
929 /*! \brief Configure a queue parameter.
931 For error reporting, line number is passed for .conf static configuration.
932 For Realtime queues, linenum is -1.
933 The failunknown flag is set for config files (and static realtime) to show
934 errors for unknown parameters. It is cleared for dynamic realtime to allow
935 extra fields in the tables. */
936 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
938 if (!strcasecmp(param, "musicclass") ||
939 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
940 ast_copy_string(q->moh, val, sizeof(q->moh));
941 } else if (!strcasecmp(param, "announce")) {
942 ast_copy_string(q->announce, val, sizeof(q->announce));
943 } else if (!strcasecmp(param, "context")) {
944 ast_copy_string(q->context, val, sizeof(q->context));
945 } else if (!strcasecmp(param, "timeout")) {
946 q->timeout = atoi(val);
948 q->timeout = DEFAULT_TIMEOUT;
949 } else if (!strcasecmp(param, "ringinuse")) {
950 q->ringinuse = ast_true(val);
951 } else if (!strcasecmp(param, "setinterfacevar")) {
952 q->setinterfacevar = ast_true(val);
953 } else if (!strcasecmp(param, "setqueuevar")) {
954 q->setqueuevar = ast_true(val);
955 } else if (!strcasecmp(param, "setqueueentryvar")) {
956 q->setqueueentryvar = ast_true(val);
957 } else if (!strcasecmp(param, "monitor-join")) {
958 q->monjoin = ast_true(val);
959 } else if (!strcasecmp(param, "monitor-format")) {
960 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
961 } else if (!strcasecmp(param, "membermacro")) {
962 ast_copy_string(q->membermacro, val, sizeof(q->membermacro));
963 } else if (!strcasecmp(param, "membergosub")) {
964 ast_copy_string(q->membergosub, val, sizeof(q->membergosub));
965 } else if (!strcasecmp(param, "queue-youarenext")) {
966 ast_copy_string(q->sound_next, val, sizeof(q->sound_next));
967 } else if (!strcasecmp(param, "queue-thereare")) {
968 ast_copy_string(q->sound_thereare, val, sizeof(q->sound_thereare));
969 } else if (!strcasecmp(param, "queue-callswaiting")) {
970 ast_copy_string(q->sound_calls, val, sizeof(q->sound_calls));
971 } else if (!strcasecmp(param, "queue-holdtime")) {
972 ast_copy_string(q->sound_holdtime, val, sizeof(q->sound_holdtime));
973 } else if (!strcasecmp(param, "queue-minutes")) {
974 ast_copy_string(q->sound_minutes, val, sizeof(q->sound_minutes));
975 } else if (!strcasecmp(param, "queue-seconds")) {
976 ast_copy_string(q->sound_seconds, val, sizeof(q->sound_seconds));
977 } else if (!strcasecmp(param, "queue-lessthan")) {
978 ast_copy_string(q->sound_lessthan, val, sizeof(q->sound_lessthan));
979 } else if (!strcasecmp(param, "queue-thankyou")) {
980 ast_copy_string(q->sound_thanks, val, sizeof(q->sound_thanks));
981 } else if (!strcasecmp(param, "queue-callerannounce")) {
982 ast_copy_string(q->sound_callerannounce, val, sizeof(q->sound_callerannounce));
983 } else if (!strcasecmp(param, "queue-reporthold")) {
984 ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold));
985 } else if (!strcasecmp(param, "announce-frequency")) {
986 q->announcefrequency = atoi(val);
987 } else if (!strcasecmp(param, "min-announce-frequency")) {
988 q->minannouncefrequency = atoi(val);
989 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
990 } else if (!strcasecmp(param, "announce-round-seconds")) {
991 q->roundingseconds = atoi(val);
992 /* Rounding to any other values just doesn't make sense... */
993 if (!(q->roundingseconds == 0 || q->roundingseconds == 1 || q->roundingseconds == 5 || q->roundingseconds == 10
994 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
996 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
997 "using 0 instead for queue '%s' at line %d of queues.conf\n",
998 val, param, q->name, linenum);
1000 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1001 "using 0 instead for queue '%s'\n", val, param, q->name);
1003 q->roundingseconds=0;
1005 } else if (!strcasecmp(param, "announce-holdtime")) {
1006 if (!strcasecmp(val, "once"))
1007 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1008 else if (ast_true(val))
1009 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1011 q->announceholdtime = 0;
1012 } else if (!strcasecmp(param, "periodic-announce")) {
1013 if (strchr(val, ',')) {
1014 char *s, *buf = ast_strdupa(val);
1017 while ((s = strsep(&buf, ",|"))) {
1018 ast_copy_string(q->sound_periodicannounce[i], s, sizeof(q->sound_periodicannounce[i]));
1020 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1024 ast_copy_string(q->sound_periodicannounce[0], val, sizeof(q->sound_periodicannounce[0]));
1026 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1027 q->periodicannouncefrequency = atoi(val);
1028 } else if (!strcasecmp(param, "retry")) {
1029 q->retry = atoi(val);
1031 q->retry = DEFAULT_RETRY;
1032 } else if (!strcasecmp(param, "wrapuptime")) {
1033 q->wrapuptime = atoi(val);
1034 } else if (!strcasecmp(param, "autofill")) {
1035 q->autofill = ast_true(val);
1036 } else if (!strcasecmp(param, "monitor-type")) {
1037 if (!strcasecmp(val, "mixmonitor"))
1039 } else if (!strcasecmp(param, "autopause")) {
1040 q->autopause = ast_true(val);
1041 } else if (!strcasecmp(param, "maxlen")) {
1042 q->maxlen = atoi(val);
1045 } else if (!strcasecmp(param, "servicelevel")) {
1046 q->servicelevel= atoi(val);
1047 } else if (!strcasecmp(param, "strategy")) {
1048 q->strategy = strat2int(val);
1049 if (q->strategy < 0) {
1050 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
1052 q->strategy = QUEUE_STRATEGY_RINGALL;
1054 } else if (!strcasecmp(param, "joinempty")) {
1055 if (!strcasecmp(val, "loose"))
1056 q->joinempty = QUEUE_EMPTY_LOOSE;
1057 else if (!strcasecmp(val, "strict"))
1058 q->joinempty = QUEUE_EMPTY_STRICT;
1059 else if (ast_true(val))
1060 q->joinempty = QUEUE_EMPTY_NORMAL;
1063 } else if (!strcasecmp(param, "leavewhenempty")) {
1064 if (!strcasecmp(val, "loose"))
1065 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
1066 else if (!strcasecmp(val, "strict"))
1067 q->leavewhenempty = QUEUE_EMPTY_STRICT;
1068 else if (ast_true(val))
1069 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
1071 q->leavewhenempty = 0;
1072 } else if (!strcasecmp(param, "eventmemberstatus")) {
1073 q->maskmemberstatus = !ast_true(val);
1074 } else if (!strcasecmp(param, "eventwhencalled")) {
1075 if (!strcasecmp(val, "vars")) {
1076 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1078 q->eventwhencalled = ast_true(val);
1080 } else if (!strcasecmp(param, "reportholdtime")) {
1081 q->reportholdtime = ast_true(val);
1082 } else if (!strcasecmp(param, "memberdelay")) {
1083 q->memberdelay = atoi(val);
1084 } else if (!strcasecmp(param, "weight")) {
1085 q->weight = atoi(val);
1088 /* With Realtime queues, if the last queue using weights is deleted in realtime,
1089 we will not see any effect on use_weight until next reload. */
1090 } else if (!strcasecmp(param, "timeoutrestart")) {
1091 q->timeoutrestart = ast_true(val);
1092 } else if (failunknown) {
1094 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1095 q->name, param, linenum);
1097 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1102 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
1104 struct member *m, tmpmem;
1109 penalty = atoi(penalty_str);
1115 paused = atoi(paused_str);
1120 /* Find the member, or the place to put a new one. */
1121 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
1122 m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
1124 /* Create a new one if not found, else update penalty */
1126 if ((m = create_queue_member(interface, membername, penalty, paused))) {
1129 add_to_interfaces(interface);
1130 ao2_link(q->members, m);
1134 m->dead = 0; /* Do not delete this one. */
1137 m->penalty = penalty;
1142 static void free_members(struct call_queue *q, int all)
1144 /* Free non-dynamic members */
1146 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1148 while ((cur = ao2_iterator_next(&mem_iter))) {
1149 if (all || !cur->dynamic) {
1150 ao2_unlink(q->members, cur);
1151 remove_from_interfaces(cur->interface);
1158 static void destroy_queue(void *obj)
1160 struct call_queue *q = obj;
1161 ast_debug(0, "Queue destructor called for queue '%s'!\n", q->name);
1163 ao2_ref(q->members, -1);
1166 static struct call_queue *alloc_queue(const char *queuename)
1168 struct call_queue *q;
1170 if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
1171 ast_copy_string(q->name, queuename, sizeof(q->name));
1176 /*!\brief Reload a single queue via realtime.
1177 \return Return the queue, or NULL if it doesn't exist.
1178 \note Should be called with the global qlock locked. */
1179 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1181 struct ast_variable *v;
1182 struct call_queue *q, tmpq;
1184 struct ao2_iterator mem_iter;
1185 char *interface = NULL;
1186 char *tmp, *tmp_name;
1187 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1189 /* Find the queue in the in-core list (we will create a new one if not found). */
1190 ast_copy_string(tmpq.name, queuename, sizeof(tmpq.name));
1192 /* Static queues override realtime. */
1193 if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
1201 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
1207 } else if (!member_config)
1208 /* Not found in the list, and it's not realtime ... */
1211 /* Check if queue is defined in realtime. */
1213 /* Delete queue from in-core list if it has been deleted in realtime. */
1215 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1216 found condition... So we might delete an in-core queue
1217 in case of DB failure. */
1218 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
1221 /* Delete if unused (else will be deleted when last caller leaves). */
1222 ao2_unlink(queues, q);
1229 /* Create a new queue if an in-core entry does not exist yet. */
1231 if (!(q = alloc_queue(queuename)))
1236 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1237 ao2_link(queues, q);
1241 memset(tmpbuf, 0, sizeof(tmpbuf));
1242 for (v = queue_vars; v; v = v->next) {
1243 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1244 if ((tmp = strchr(v->name, '_'))) {
1245 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1248 while ((tmp = strchr(tmp, '_')))
1252 queue_set_param(q, tmp_name, v->value, -1, 0);
1255 /* Temporarily set realtime members dead so we can detect deleted ones.
1256 * Also set the membercount correctly for realtime*/
1257 mem_iter = ao2_iterator_init(q->members, 0);
1258 while ((m = ao2_iterator_next(&mem_iter))) {
1265 while ((interface = ast_category_browse(member_config, interface))) {
1266 rt_handle_member_record(q, interface,
1267 ast_variable_retrieve(member_config, interface, "membername"),
1268 ast_variable_retrieve(member_config, interface, "penalty"),
1269 ast_variable_retrieve(member_config, interface, "paused"));
1272 /* Delete all realtime members that have been deleted in DB. */
1273 mem_iter = ao2_iterator_init(q->members, 0);
1274 while ((m = ao2_iterator_next(&mem_iter))) {
1276 ao2_unlink(q->members, m);
1278 remove_from_interfaces(m->interface);
1290 static struct call_queue *load_realtime_queue(const char *queuename)
1292 struct ast_variable *queue_vars;
1293 struct ast_config *member_config = NULL;
1294 struct call_queue *q = NULL, tmpq;
1296 /* Find the queue in the in-core list first. */
1297 ast_copy_string(tmpq.name, queuename, sizeof(tmpq.name));
1298 q = ao2_find(queues, &tmpq, OBJ_POINTER);
1300 if (!q || q->realtime) {
1301 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1302 queue operations while waiting for the DB.
1304 This will be two separate database transactions, so we might
1305 see queue parameters as they were before another process
1306 changed the queue and member list as it was after the change.
1307 Thus we might see an empty member list when a queue is
1308 deleted. In practise, this is unlikely to cause a problem. */
1310 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1312 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1313 if (!member_config) {
1314 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1320 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1322 ast_config_destroy(member_config);
1324 ast_variables_destroy(queue_vars);
1328 update_realtime_members(q);
1333 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
1335 struct ast_variable *var;
1338 if(!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL)))
1341 if(!strcmp(var->name, "uniqueid"))
1345 if(var && !ast_strlen_zero(var->value)) {
1346 if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1)
1352 static void update_realtime_members(struct call_queue *q)
1354 struct ast_config *member_config = NULL;
1356 char *interface = NULL;
1357 struct ao2_iterator mem_iter;
1359 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL);
1360 if (!member_config) {
1361 /*This queue doesn't have realtime members*/
1362 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
1368 /* Temporarily set realtime members dead so we can detect deleted ones.*/
1369 mem_iter = ao2_iterator_init(q->members, 0);
1370 while ((m = ao2_iterator_next(&mem_iter))) {
1376 while ((interface = ast_category_browse(member_config, interface))) {
1377 rt_handle_member_record(q, interface,
1378 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1379 ast_variable_retrieve(member_config, interface, "penalty"),
1380 ast_variable_retrieve(member_config, interface, "paused"));
1383 /* Delete all realtime members that have been deleted in DB. */
1384 mem_iter = ao2_iterator_init(q->members, 0);
1385 while ((m = ao2_iterator_next(&mem_iter))) {
1387 ao2_unlink(q->members, m);
1389 remove_from_interfaces(m->interface);
1398 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1400 struct call_queue *q;
1401 struct queue_ent *cur, *prev = NULL;
1405 enum queue_member_status stat;
1407 if (!(q = load_realtime_queue(queuename)))
1413 /* This is our one */
1414 stat = get_member_status(q, qe->max_penalty);
1415 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1416 *reason = QUEUE_JOINEMPTY;
1417 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1418 *reason = QUEUE_JOINUNAVAIL;
1419 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1420 *reason = QUEUE_JOINUNAVAIL;
1421 else if (q->maxlen && (q->count >= q->maxlen))
1422 *reason = QUEUE_FULL;
1424 /* There's space for us, put us at the right position inside
1426 * Take into account the priority of the calling user */
1431 /* We have higher priority than the current user, enter
1432 * before him, after all the other users with priority
1433 * higher or equal to our priority. */
1434 if ((!inserted) && (qe->prio > cur->prio)) {
1435 insert_entry(q, prev, qe, &pos);
1442 /* No luck, join at the end of the queue */
1444 insert_entry(q, prev, qe, &pos);
1445 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1446 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1447 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1450 manager_event(EVENT_FLAG_CALL, "Join",
1451 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1453 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1454 S_OR(qe->chan->cid.cid_name, "unknown"),
1455 q->name, qe->pos, q->count, qe->chan->uniqueid );
1456 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1464 static int play_file(struct ast_channel *chan, char *filename)
1468 ast_stopstream(chan);
1470 res = ast_streamfile(chan, filename, chan->language);
1472 res = ast_waitstream(chan, AST_DIGIT_ANY);
1474 ast_stopstream(chan);
1479 static int valid_exit(struct queue_ent *qe, char digit)
1481 int digitlen = strlen(qe->digits);
1483 /* Prevent possible buffer overflow */
1484 if (digitlen < sizeof(qe->digits) - 2) {
1485 qe->digits[digitlen] = digit;
1486 qe->digits[digitlen + 1] = '\0';
1488 qe->digits[0] = '\0';
1492 /* If there's no context to goto, short-circuit */
1493 if (ast_strlen_zero(qe->context))
1496 /* If the extension is bad, then reset the digits to blank */
1497 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1498 qe->digits[0] = '\0';
1502 /* We have an exact match */
1503 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1504 qe->valid_digits = 1;
1505 /* Return 1 on a successful goto */
1512 static int say_position(struct queue_ent *qe, int ringing)
1514 int res = 0, avgholdmins, avgholdsecs;
1517 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1519 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1522 /* If either our position has changed, or we are over the freq timer, say position */
1523 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1527 ast_indicate(qe->chan,-1);
1529 ast_moh_stop(qe->chan);
1531 /* Say we're next, if we are */
1533 res = play_file(qe->chan, qe->parent->sound_next);
1539 res = play_file(qe->chan, qe->parent->sound_thereare);
1542 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1545 res = play_file(qe->chan, qe->parent->sound_calls);
1549 /* Round hold time to nearest minute */
1550 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1552 /* If they have specified a rounding then round the seconds as well */
1553 if (qe->parent->roundingseconds) {
1554 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1555 avgholdsecs *= qe->parent->roundingseconds;
1560 ast_verb(3, "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1562 /* If the hold time is >1 min, if it's enabled, and if it's not
1563 supposed to be only once and we have already said it, say it */
1564 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1565 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1566 res = play_file(qe->chan, qe->parent->sound_holdtime);
1570 if (avgholdmins > 0) {
1571 if (avgholdmins < 2) {
1572 res = play_file(qe->chan, qe->parent->sound_lessthan);
1576 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1580 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1585 res = play_file(qe->chan, qe->parent->sound_minutes);
1589 if (avgholdsecs>0) {
1590 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1594 res = play_file(qe->chan, qe->parent->sound_seconds);
1602 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
1603 qe->chan->name, qe->parent->name, qe->pos);
1604 res = play_file(qe->chan, qe->parent->sound_thanks);
1607 if (res > 0 && !valid_exit(qe, res))
1610 /* Set our last_pos indicators */
1612 qe->last_pos_said = qe->pos;
1614 /* Don't restart music on hold if we're about to exit the caller from the queue */
1617 ast_indicate(qe->chan, AST_CONTROL_RINGING);
1619 ast_moh_start(qe->chan, qe->moh, NULL);
1624 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
1628 /* Calculate holdtime using a recursive boxcar filter */
1629 /* Thanks to SRT for this contribution */
1630 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1632 ao2_lock(qe->parent);
1633 oldvalue = qe->parent->holdtime;
1634 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
1635 ao2_unlock(qe->parent);
1639 static void leave_queue(struct queue_ent *qe)
1641 struct call_queue *q;
1642 struct queue_ent *cur, *prev = NULL;
1645 if (!(q = qe->parent))
1651 for (cur = q->head; cur; cur = cur->next) {
1655 /* Take us out of the queue */
1656 manager_event(EVENT_FLAG_CALL, "Leave",
1657 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1658 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1659 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1660 /* Take us out of the queue */
1662 prev->next = cur->next;
1664 q->head = cur->next;
1666 /* Renumber the people after us in the queue based on a new count */
1673 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
1675 if(!ast_load_realtime("queues", "name", q->name, NULL))
1680 /* It's dead and nobody is in it, so kill it */
1681 ao2_unlink(queues, q);
1687 /* Hang up a list of outgoing calls */
1688 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1690 struct callattempt *oo;
1693 /* Hangup any existing lines we have open */
1694 if (outgoing->chan && (outgoing->chan != exception))
1695 ast_hangup(outgoing->chan);
1697 outgoing = outgoing->q_next;
1699 ao2_ref(oo->member, -1);
1704 static int update_status(struct call_queue *q, struct member *member, int status)
1707 struct ao2_iterator mem_iter;
1709 /* Since a reload could have taken place, we have to traverse the list to
1710 be sure it's still valid */
1712 mem_iter = ao2_iterator_init(q->members, 0);
1713 while ((cur = ao2_iterator_next(&mem_iter))) {
1714 if (member != cur) {
1719 cur->status = status;
1720 if (!q->maskmemberstatus) {
1721 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1724 "MemberName: %s\r\n"
1725 "Membership: %s\r\n"
1727 "CallsTaken: %d\r\n"
1731 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
1732 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1740 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1742 if (status == AST_CAUSE_BUSY)
1743 status = AST_DEVICE_BUSY;
1744 else if (status == AST_CAUSE_UNREGISTERED)
1745 status = AST_DEVICE_UNAVAILABLE;
1746 else if (status == AST_CAUSE_NOSUCHDRIVER)
1747 status = AST_DEVICE_INVALID;
1749 status = AST_DEVICE_UNKNOWN;
1750 return update_status(q, member, status);
1753 /* traverse all defined queues which have calls waiting and contain this member
1754 return 0 if no other queue has precedence (higher weight) or 1 if found */
1755 static int compare_weight(struct call_queue *rq, struct member *member)
1757 struct call_queue *q;
1760 struct ao2_iterator queue_iter;
1762 /* &qlock and &rq->lock already set by try_calling()
1763 * to solve deadlock */
1764 queue_iter = ao2_iterator_init(queues, 0);
1765 while ((q = ao2_iterator_next(&queue_iter))) {
1766 if (q == rq) { /* don't check myself, could deadlock */
1771 if (q->count && q->members) {
1772 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
1773 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1774 if (q->weight > rq->weight) {
1775 ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
1791 /*! \brief common hangup actions */
1792 static void do_hang(struct callattempt *o)
1795 ast_hangup(o->chan);
1799 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1801 struct ast_str *buf = ast_str_alloca(len + 1);
1804 if (pbx_builtin_serialize_variables(chan, &buf)) {
1807 /* convert "\n" to "\nVariable: " */
1808 strcpy(vars, "Variable: ");
1811 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1814 if (tmp[i + 1] == '\0')
1816 if (tmp[i] == '\n') {
1820 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1830 /* there are no channel variables; leave it blank */
1836 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1843 /* on entry here, we know that tmp->chan == NULL */
1844 if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1845 ast_debug(1, "Wrapuptime not yet expired for %s\n", tmp->interface);
1847 ast_cdr_busy(qe->chan->cdr);
1848 tmp->stillgoing = 0;
1853 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1854 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
1856 ast_cdr_busy(qe->chan->cdr);
1857 tmp->stillgoing = 0;
1861 if (tmp->member->paused) {
1862 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
1864 ast_cdr_busy(qe->chan->cdr);
1865 tmp->stillgoing = 0;
1868 if (use_weight && compare_weight(qe->parent,tmp->member)) {
1869 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1871 ast_cdr_busy(qe->chan->cdr);
1872 tmp->stillgoing = 0;
1877 ast_copy_string(tech, tmp->interface, sizeof(tech));
1878 if ((location = strchr(tech, '/')))
1883 /* Request the peer */
1884 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1885 if (!tmp->chan) { /* If we can't, just go on to the next call */
1887 ast_cdr_busy(qe->chan->cdr);
1888 tmp->stillgoing = 0;
1889 update_dial_status(qe->parent, tmp->member, status);
1891 ao2_lock(qe->parent);
1892 qe->parent->rrpos++;
1893 ao2_unlock(qe->parent);
1897 } else if (status != tmp->oldstatus)
1898 update_dial_status(qe->parent, tmp->member, status);
1900 tmp->chan->appl = "AppQueue";
1901 tmp->chan->data = "(Outgoing Line)";
1902 tmp->chan->whentohangup = 0;
1903 if (tmp->chan->cid.cid_num)
1904 ast_free(tmp->chan->cid.cid_num);
1905 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1906 if (tmp->chan->cid.cid_name)
1907 ast_free(tmp->chan->cid.cid_name);
1908 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1909 if (tmp->chan->cid.cid_ani)
1910 ast_free(tmp->chan->cid.cid_ani);
1911 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1913 /* Inherit specially named variables from parent channel */
1914 ast_channel_inherit_variables(qe->chan, tmp->chan);
1916 /* Presense of ADSI CPE on outgoing channel follows ours */
1917 tmp->chan->adsicpe = qe->chan->adsicpe;
1919 /* Place the call, but don't wait on the answer */
1920 if ((res = ast_call(tmp->chan, location, 0))) {
1921 /* Again, keep going even if there's an error */
1922 ast_debug(1, "ast call on peer returned %d\n", res);
1923 ast_verb(3, "Couldn't call %s\n", tmp->interface);
1927 } else if (qe->parent->eventwhencalled) {
1930 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1932 "AgentCalled: %s\r\n"
1934 "ChannelCalling: %s\r\n"
1935 "DestinationChannel: %s\r\n"
1936 "CallerIDNum: %s\r\n"
1937 "CallerIDName: %s\r\n"
1942 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
1943 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1944 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1945 qe->chan->context, qe->chan->exten, qe->chan->priority,
1946 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
1947 ast_verb(3, "Called %s\n", tmp->interface);
1953 /*! \brief find the entry with the best metric, or NULL */
1954 static struct callattempt *find_best(struct callattempt *outgoing)
1956 struct callattempt *best = NULL, *cur;
1958 for (cur = outgoing; cur; cur = cur->q_next) {
1959 if (cur->stillgoing && /* Not already done */
1960 !cur->chan && /* Isn't already going */
1961 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
1969 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
1974 struct callattempt *best = find_best(outgoing);
1976 ast_debug(1, "Nobody left to try ringing in queue\n");
1979 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
1980 struct callattempt *cur;
1981 /* Ring everyone who shares this best metric (for ringall) */
1982 for (cur = outgoing; cur; cur = cur->q_next) {
1983 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
1984 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1985 ring_entry(qe, cur, busies);
1989 /* Ring just the best channel */
1990 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
1991 ring_entry(qe, best, busies);
1993 if (best->chan) /* break out with result = 1 */
2000 static int store_next(struct queue_ent *qe, struct callattempt *outgoing)
2002 struct callattempt *best = find_best(outgoing);
2005 /* Ring just the best channel */
2006 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2007 qe->parent->rrpos = best->metric % 1000;
2009 /* Just increment rrpos */
2010 if (qe->parent->wrapped) {
2011 /* No more channels, start over */
2012 qe->parent->rrpos = 0;
2014 /* Prioritize next entry */
2015 qe->parent->rrpos++;
2018 qe->parent->wrapped = 0;
2023 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
2028 /* Get the current time */
2031 /* Check to see if it is time to announce */
2032 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
2035 /* Stop the music on hold so we can play our own file */
2037 ast_indicate(qe->chan,-1);
2039 ast_moh_stop(qe->chan);
2041 ast_verb(3, "Playing periodic announcement\n");
2043 /* Check to make sure we have a sound file. If not, reset to the first sound file */
2044 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
2045 qe->last_periodic_announce_sound = 0;
2048 /* play the announcement */
2049 res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
2051 if (res > 0 && !valid_exit(qe, res))
2054 /* Resume Music on Hold if the caller is going to stay in the queue */
2057 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2059 ast_moh_start(qe->chan, qe->moh, NULL);
2062 /* update last_periodic_announce_time */
2063 qe->last_periodic_announce_time = now;
2065 /* Update the current periodic announcement to the next announcement */
2066 qe->last_periodic_announce_sound++;
2071 static void record_abandoned(struct queue_ent *qe)
2073 ao2_lock(qe->parent);
2074 set_queue_variables(qe);
2075 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
2079 "OriginalPosition: %d\r\n"
2081 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
2083 qe->parent->callsabandoned++;
2084 ao2_unlock(qe->parent);
2087 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
2088 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
2090 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
2091 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
2092 if (qe->parent->autopause) {
2093 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
2094 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
2096 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
2102 #define AST_MAX_WATCHERS 256
2104 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
2106 char *queue = qe->parent->name;
2107 struct callattempt *o;
2109 int sentringing = 0;
2110 int numbusies = prebusies;
2114 struct ast_frame *f;
2115 struct callattempt *peer = NULL;
2116 struct ast_channel *winner;
2117 struct ast_channel *in = qe->chan;
2119 char membername[80] = "";
2123 struct callattempt *epollo;
2126 starttime = (long) time(NULL);
2128 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2130 ast_poll_channel_add(in, epollo->chan);
2134 while (*to && !peer) {
2135 int numlines, retry, pos = 1;
2136 struct ast_channel *watchers[AST_MAX_WATCHERS];
2139 for (retry = 0; retry < 2; retry++) {
2141 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
2142 if (o->stillgoing) { /* Keep track of important channels */
2145 watchers[pos++] = o->chan;
2149 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
2150 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
2152 /* On "ringall" strategy we only move to the next penalty level
2153 when *all* ringing phones are done in the current penalty level */
2154 ring_one(qe, outgoing, &numbusies);
2157 if (pos == 1 /* not found */) {
2158 if (numlines == (numbusies + numnochan)) {
2159 ast_debug(1, "Everyone is busy at this time\n");
2161 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
2166 winner = ast_waitfor_n(watchers, pos, to);
2167 for (o = outgoing; o; o = o->q_next) {
2168 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
2170 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2173 } else if (o->chan && (o->chan == winner)) {
2175 ast_copy_string(on, o->member->interface, sizeof(on));
2176 ast_copy_string(membername, o->member->membername, sizeof(membername));
2178 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
2179 ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
2184 } else if (!ast_strlen_zero(o->chan->call_forward)) {
2189 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
2190 if ((stuff = strchr(tmpchan, '/'))) {
2194 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
2198 /* Before processing channel, go ahead and check for forwarding */
2199 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2200 /* Setup parameters */
2201 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2202 if (status != o->oldstatus)
2203 update_dial_status(qe->parent, o->member, status);
2205 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2209 ast_channel_inherit_variables(in, o->chan);
2210 if (o->chan->cid.cid_num)
2211 ast_free(o->chan->cid.cid_num);
2212 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2214 if (o->chan->cid.cid_name)
2215 ast_free(o->chan->cid.cid_name);
2216 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2218 ast_string_field_set(o->chan, accountcode, in->accountcode);
2219 o->chan->cdrflags = in->cdrflags;
2221 if (in->cid.cid_ani) {
2222 if (o->chan->cid.cid_ani)
2223 ast_free(o->chan->cid.cid_ani);
2224 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2226 if (o->chan->cid.cid_rdnis)
2227 ast_free(o->chan->cid.cid_rdnis);
2228 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2229 if (ast_call(o->chan, tmpchan, 0)) {
2230 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2235 /* Hangup the original channel now, in case we needed it */
2239 f = ast_read(winner);
2241 if (f->frametype == AST_FRAME_CONTROL) {
2242 switch (f->subclass) {
2243 case AST_CONTROL_ANSWER:
2244 /* This is our guy if someone answered. */
2246 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2250 case AST_CONTROL_BUSY:
2251 ast_verb(3, "%s is busy\n", o->chan->name);
2253 ast_cdr_busy(in->cdr);
2255 endtime = (long) time(NULL);
2256 endtime -= starttime;
2257 rna(endtime*1000, qe, on, membername);
2258 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2259 if (qe->parent->timeoutrestart)
2261 ring_one(qe, outgoing, &numbusies);
2265 case AST_CONTROL_CONGESTION:
2266 ast_verb(3, "%s is circuit-busy\n", o->chan->name);
2268 ast_cdr_busy(in->cdr);
2269 endtime = (long) time(NULL);
2270 endtime -= starttime;
2271 rna(endtime*1000, qe, on, membername);
2273 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2274 if (qe->parent->timeoutrestart)
2276 ring_one(qe, outgoing, &numbusies);
2280 case AST_CONTROL_RINGING:
2281 ast_verb(3, "%s is ringing\n", o->chan->name);
2284 ast_indicate(in, AST_CONTROL_RINGING);
2289 case AST_CONTROL_OFFHOOK:
2290 /* Ignore going off hook */
2293 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
2298 endtime = (long) time(NULL) - starttime;
2299 rna(endtime * 1000, qe, on, membername);
2301 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2302 if (qe->parent->timeoutrestart)
2304 ring_one(qe, outgoing, &numbusies);
2311 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2319 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2320 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
2325 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2326 ast_verb(3, "User pressed digit: %c\n", f->subclass);
2328 *digit = f->subclass;
2335 rna(orig, qe, on, membername);
2339 for(epollo = outgoing; epollo; epollo = epollo->q_next) {
2341 ast_poll_channel_del(in, epollo->chan);
2348 static int is_our_turn(struct queue_ent *qe)
2350 struct queue_ent *ch;
2356 if (!qe->parent->autofill) {
2357 /* Atomically read the parent head -- does not need a lock */
2358 ch = qe->parent->head;
2359 /* If we are now at the top of the head, break out */
2361 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2364 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2369 /* This needs a lock. How many members are available to be served? */
2370 ao2_lock(qe->parent);
2372 ch = qe->parent->head;
2374 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2375 ast_debug(1, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in\n", avl);
2378 struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
2379 while ((cur = ao2_iterator_next(&mem_iter))) {
2380 switch (cur->status) {
2381 case AST_DEVICE_NOT_INUSE:
2382 case AST_DEVICE_UNKNOWN:
2391 ast_debug(1, "There are %d available members.\n", avl);
2393 while ((idx < avl) && (ch) && (ch != qe)) {
2398 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2399 if (ch && idx < avl) {
2400 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2403 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2407 ao2_unlock(qe->parent);
2413 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2417 /* This is the holding pen for callers 2 through maxlen */
2419 enum queue_member_status stat;
2421 if (is_our_turn(qe))
2424 /* If we have timed out, break out */
2425 if (qe->expire && (time(NULL) > qe->expire)) {
2426 *reason = QUEUE_TIMEOUT;
2430 stat = get_member_status(qe->parent, qe->max_penalty);
2432 /* leave the queue if no agents, if enabled */
2433 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2434 *reason = QUEUE_LEAVEEMPTY;
2435 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2440 /* leave the queue if no reachable agents, if enabled */
2441 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
2442 *reason = QUEUE_LEAVEUNAVAIL;
2443 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2447 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2448 *reason = QUEUE_LEAVEUNAVAIL;
2449 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2454 /* Make a position announcement, if enabled */
2455 if (qe->parent->announcefrequency &&
2456 (res = say_position(qe,ringing)))
2459 /* Make a periodic announcement, if enabled */
2460 if (qe->parent->periodicannouncefrequency &&
2461 (res = say_periodic_announcement(qe,ringing)))
2464 /* Wait a second before checking again */
2465 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
2466 if (res > 0 && !valid_exit(qe, res))
2476 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
2479 time(&member->lastcall);
2481 q->callscompleted++;
2482 if (callcompletedinsl)
2483 q->callscompletedinsl++;
2488 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2490 if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2493 switch (q->strategy) {
2494 case QUEUE_STRATEGY_RINGALL:
2495 /* Everyone equal, except for penalty */
2496 tmp->metric = mem->penalty * 1000000;
2498 case QUEUE_STRATEGY_RRMEMORY:
2499 if (pos < q->rrpos) {
2500 tmp->metric = 1000 + pos;
2503 /* Indicate there is another priority */
2507 tmp->metric += mem->penalty * 1000000;
2509 case QUEUE_STRATEGY_RANDOM:
2510 tmp->metric = ast_random() % 1000;
2511 tmp->metric += mem->penalty * 1000000;
2513 case QUEUE_STRATEGY_FEWESTCALLS:
2514 tmp->metric = mem->calls;
2515 tmp->metric += mem->penalty * 1000000;
2517 case QUEUE_STRATEGY_LEASTRECENT:
2521 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2522 tmp->metric += mem->penalty * 1000000;
2525 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2531 enum agent_complete_reason {
2537 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2538 const struct ast_channel *peer, const struct member *member, time_t callstart,
2539 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2543 if (!qe->parent->eventwhencalled)
2554 reason = "transfer";
2558 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2563 "MemberName: %s\r\n"
2568 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2569 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
2570 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
2573 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
2576 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2578 char oldexten[AST_MAX_EXTENSION]="";
2579 char oldcontext[AST_MAX_CONTEXT]="";
2580 char queuename[256]="";
2581 char interfacevar[256]="";
2582 struct ast_channel *peer;
2583 struct ast_channel *which;
2584 struct callattempt *lpeer;
2585 struct member *member;
2586 struct ast_app *app;
2587 int res = 0, bridge = 0;
2590 char *announce = NULL;
2593 time_t now = time(NULL);
2594 struct ast_bridge_config bridge_config;
2595 char nondataquality = 1;
2596 char *agiexec = NULL;
2597 char *macroexec = NULL;
2598 char *gosubexec = NULL;
2600 const char *monitorfilename;
2601 const char *monitor_exec;
2602 const char *monitor_options;
2603 char tmpid[256], tmpid2[256];
2604 char meid[1024], meid2[1024];
2605 char mixmonargs[1512];
2606 struct ast_app *mixmonapp = NULL;
2609 int forwardsallowed = 1;
2610 int callcompletedinsl;
2611 struct ao2_iterator memi;
2613 memset(&bridge_config, 0, sizeof(bridge_config));
2616 for (; options && *options; options++)
2619 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2622 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2625 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2628 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2634 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2637 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2640 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY)
2643 *tries = qe->parent->membercount;
2647 forwardsallowed = 0;
2651 /* Hold the lock while we setup the outgoing calls */
2654 ao2_lock(qe->parent);
2655 ast_debug(1, "%s is trying to call a queue member.\n",
2657 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2658 if (!ast_strlen_zero(qe->announce))
2659 announce = qe->announce;
2660 if (!ast_strlen_zero(announceoverride))
2661 announce = announceoverride;
2663 memi = ao2_iterator_init(qe->parent->members, 0);
2664 while ((cur = ao2_iterator_next(&memi))) {
2665 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2669 ao2_unlock(qe->parent);
2674 tmp->stillgoing = -1;
2676 tmp->oldstatus = cur->status;
2677 tmp->lastcall = cur->lastcall;
2678 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2679 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2680 just calculate their metric for the appropriate strategy */
2681 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2682 /* Put them in the list of outgoing thingies... We're ready now.
2683 XXX If we're forcibly removed, these outgoing calls won't get
2685 tmp->q_next = outgoing;
2687 /* If this line is up, don't try anybody else */
2688 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2695 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2696 to = (qe->expire - now) * 1000;
2698 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2700 ring_one(qe, outgoing, &numbusies);
2701 ao2_unlock(qe->parent);
2704 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2705 ao2_lock(qe->parent);
2706 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2707 store_next(qe, outgoing);
2709 ao2_unlock(qe->parent);
2710 peer = lpeer ? lpeer->chan : NULL;
2713 /* Must gotten hung up */
2716 /* User exited by pressing a digit */
2720 ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
2721 } else { /* peer is valid */
2722 /* Ah ha! Someone answered within the desired timeframe. Of course after this
2723 we will always return with -1 so that it is hung up properly after the
2726 if (!strcmp(qe->chan->tech->type, "Zap"))
2727 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2728 if (!strcmp(peer->tech->type, "Zap"))
2729 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2730 /* Update parameters for the queue */
2732 recalc_holdtime(qe, (now - qe->start));
2733 ao2_lock(qe->parent);
2734 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
2735 ao2_unlock(qe->parent);
2736 member = lpeer->member;
2737 hangupcalls(outgoing, peer);
2739 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2742 res2 = ast_autoservice_start(qe->chan);
2744 if (qe->parent->memberdelay) {
2745 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2746 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2748 if (!res2 && announce) {
2749 play_file(peer, announce);
2751 if (!res2 && qe->parent->reportholdtime) {
2752 if (!play_file(peer, qe->parent->sound_reporthold)) {
2756 holdtime = abs((now - qe->start) / 60);
2758 play_file(peer, qe->parent->sound_lessthan);
2759 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2761 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2762 play_file(peer, qe->parent->sound_minutes);
2766 res2 |= ast_autoservice_stop(qe->chan);
2767 if (ast_check_hangup(peer)) {
2768 /* Agent must have hung up */
2769 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
2770 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2771 record_abandoned(qe);
2772 if (qe->parent->eventwhencalled)
2773 manager_event(EVENT_FLAG_AGENT, "AgentDump",
2778 "MemberName: %s\r\n"
2780 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2781 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2785 /* Caller must have hung up just before being connected*/
2786 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2787 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2788 record_abandoned(qe);
2793 /* Stop music on hold */
2795 ast_indicate(qe->chan,-1);
2797 ast_moh_stop(qe->chan);
2798 /* If appropriate, log that we have a destination channel */
2800 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2801 /* Make sure channels are compatible */
2802 res = ast_channel_make_compatible(qe->chan, peer);
2804 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
2805 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2806 record_abandoned(qe);
2811 /* Play announcement to the caller telling it's his turn if defined */
2812 if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
2813 if (play_file(qe->chan, qe->parent->sound_callerannounce))
2814 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
2817 ao2_lock(qe->parent);
2818 /* if setinterfacevar is defined, make member variables available to the channel */
2819 /* use pbx_builtin_setvar to set a load of variables with one call */
2820 if (qe->parent->setinterfacevar) {
2821 snprintf(interfacevar,sizeof(interfacevar), "MEMBERINTERFACE=%s|MEMBERNAME=%s|MEMBERCALLS=%d|MEMBERLASTCALL=%ld|MEMBERPENALTY=%d|MEMBERDYNAMIC=%d|MEMBERREALTIME=%d",
2822 member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
2823 pbx_builtin_setvar(qe->chan, interfacevar);
2826 /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
2827 /* use pbx_builtin_setvar to set a load of variables with one call */
2828 if (qe->parent->setqueueentryvar) {
2829 snprintf(interfacevar,sizeof(interfacevar), "QEHOLDTIME=%ld|QEORIGINALPOS=%d",
2830 (long) time(NULL) - qe->start, qe->opos);
2831 pbx_builtin_setvar(qe->chan, interfacevar);
2834 /* try to set queue variables if configured to do so*/
2835 set_queue_variables(qe);
2836 ao2_unlock(qe->parent);
2838 /* Begin Monitoring */
2839 if (qe->parent->monfmt && *qe->parent->monfmt) {
2840 if (!qe->parent->montype) {
2841 ast_debug(1, "Starting Monitor as requested.\n");
2842 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2843 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2847 if (monitorfilename)
2848 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
2849 else if (qe->chan->cdr)
2850 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1, X_REC_IN | X_REC_OUT);
2852 /* Last ditch effort -- no CDR, make up something */
2853 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2854 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
2856 if (qe->parent->monjoin)
2857 ast_monitor_setjoinfiles(which, 1);
2859 ast_debug(1, "Starting MixMonitor as requested.\n");
2860 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2861 if (!monitorfilename) {
2863 ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid));
2865 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2867 const char *m = monitorfilename;
2868 for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
2871 if (*(m + 1) == '{')
2883 if (p == tmpid2 + sizeof(tmpid2))
2884 tmpid2[sizeof(tmpid2) - 1] = '\0';
2886 memset(tmpid, 0, sizeof(tmpid));
2887 pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
2890 monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC");
2891 monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS");
2894 const char *m = monitor_exec;
2895 for (p = meid2; p < meid2 + sizeof(meid2) - 1; p++, m++) {
2898 if (*(m + 1) == '{')
2910 if (p == meid2 + sizeof(meid2))
2911 meid2[sizeof(meid2) - 1] = '\0';
2913 memset(meid, 0, sizeof(meid));
2914 pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
2917 snprintf(tmpid2, sizeof(tmpid2), "%s.%s", tmpid, qe->parent->monfmt);
2919 mixmonapp = pbx_findapp("MixMonitor");
2921 if (!monitor_options)
2922 monitor_options = "";
2925 if (!ast_strlen_zero(monitor_exec))
2926 snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s,%s", tmpid2, monitor_options, monitor_exec);
2928 snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s", tmpid2, monitor_options);
2930 ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
2931 /* We purposely lock the CDR so that pbx_exec does not update the application data */
2933 ast_set_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
2934 ret = pbx_exec(qe->chan, mixmonapp, mixmonargs);
2936 ast_clear_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
2939 ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");