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$")
64 #include <sys/signal.h>
65 #include <netinet/in.h>
67 #include "asterisk/lock.h"
68 #include "asterisk/file.h"
69 #include "asterisk/channel.h"
70 #include "asterisk/pbx.h"
71 #include "asterisk/app.h"
72 #include "asterisk/linkedlists.h"
73 #include "asterisk/module.h"
74 #include "asterisk/translate.h"
75 #include "asterisk/say.h"
76 #include "asterisk/features.h"
77 #include "asterisk/musiconhold.h"
78 #include "asterisk/cli.h"
79 #include "asterisk/manager.h"
80 #include "asterisk/config.h"
81 #include "asterisk/monitor.h"
82 #include "asterisk/utils.h"
83 #include "asterisk/causes.h"
84 #include "asterisk/astdb.h"
85 #include "asterisk/devicestate.h"
86 #include "asterisk/stringfields.h"
87 #include "asterisk/event.h"
88 #include "asterisk/astobj2.h"
89 #include "asterisk/strings.h"
92 QUEUE_STRATEGY_RINGALL = 0,
93 QUEUE_STRATEGY_LEASTRECENT,
94 QUEUE_STRATEGY_FEWESTCALLS,
95 QUEUE_STRATEGY_RANDOM,
96 QUEUE_STRATEGY_RRMEMORY,
97 QUEUE_STRATEGY_LINEAR,
98 QUEUE_STRATEGY_WRANDOM
101 static struct strategy {
105 { QUEUE_STRATEGY_RINGALL, "ringall" },
106 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
107 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
108 { QUEUE_STRATEGY_RANDOM, "random" },
109 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
110 { QUEUE_STRATEGY_LINEAR, "linear" },
111 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
114 #define DEFAULT_RETRY 5
115 #define DEFAULT_TIMEOUT 15
116 #define RECHECK 1 /* Recheck every second to see we we're at the top yet */
117 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
118 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /* The minimum number of seconds between position announcements
119 The default value of 15 provides backwards compatibility */
120 #define MAX_QUEUE_BUCKETS 53
122 #define RES_OKAY 0 /* Action completed */
123 #define RES_EXISTS (-1) /* Entry already exists */
124 #define RES_OUTOFMEMORY (-2) /* Out of memory */
125 #define RES_NOSUCHQUEUE (-3) /* No such queue */
126 #define RES_NOT_DYNAMIC (-4) /* Member is not dynamic */
128 static char *app = "Queue";
130 static char *synopsis = "Queue a call for a call queue";
132 static char *descrip =
133 " Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub]):\n"
134 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
135 "This application will return to the dialplan if the queue does not exist, or\n"
136 "any of the join options cause the caller to not enter the queue.\n"
137 "The option string may contain zero or more of the following characters:\n"
138 " 'c' -- continue in the dialplan if the callee hangs up.\n"
139 " 'd' -- data-quality (modem) call (minimum delay).\n"
140 " 'h' -- allow callee to hang up by pressing *.\n"
141 " 'H' -- allow caller to hang up by pressing *.\n"
142 " 'n' -- no retries on the timeout; will exit this application and \n"
143 " go to the next step.\n"
144 " 'i' -- ignore call forward requests from queue members and do nothing\n"
145 " when they are requested.\n"
146 " 'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
147 " 't' -- allow the called user to transfer the calling user.\n"
148 " 'T' -- allow the calling user to transfer the call.\n"
149 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
150 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
151 " 'k' -- Allow the called party to enable parking of the call by sending\n"
152 " the DTMF sequence defined for call parking in features.conf.\n"
153 " 'K' -- Allow the calling party to enable parking of the call by sending\n"
154 " the DTMF sequence defined for call parking in features.conf.\n"
155 " In addition to transferring the call, a call may be parked and then picked\n"
156 "up by another user.\n"
157 " The optional URL will be sent to the called party if the channel supports\n"
159 " The optional AGI parameter will setup an AGI script to be executed on the \n"
160 "calling party's channel once they are connected to a queue member.\n"
161 " The optional macro parameter will run a macro on the \n"
162 "calling party's channel once they are connected to a queue member.\n"
163 " The optional gosub parameter will run a gosub on the \n"
164 "calling party's channel once they are connected to a queue member.\n"
165 " The timeout will cause the queue to fail out after a specified number of\n"
166 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
167 " This application sets the following channel variable upon completion:\n"
168 " QUEUESTATUS The status of the call as a text string, one of\n"
169 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
171 static char *app_aqm = "AddQueueMember" ;
172 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
173 static char *app_aqm_descrip =
174 " AddQueueMember(queuename[,interface[,penalty[,options[,membername]]]]):\n"
175 "Dynamically adds interface to an existing queue.\n"
176 "If the interface is already in the queue it will return an error.\n"
177 " This application sets the following channel variable upon completion:\n"
178 " AQMSTATUS The status of the attempt to add a queue member as a \n"
179 " text string, one of\n"
180 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
181 "Example: AddQueueMember(techsupport,SIP/3000)\n"
184 static char *app_rqm = "RemoveQueueMember" ;
185 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
186 static char *app_rqm_descrip =
187 " RemoveQueueMember(queuename[,interface[,options]]):\n"
188 "Dynamically removes interface to an existing queue\n"
189 "If the interface is NOT in the queue it will return an error.\n"
190 " This application sets the following channel variable upon completion:\n"
191 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
192 " text string, one of\n"
193 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
194 "Example: RemoveQueueMember(techsupport,SIP/3000)\n"
197 static char *app_pqm = "PauseQueueMember" ;
198 static char *app_pqm_synopsis = "Pauses a queue member" ;
199 static char *app_pqm_descrip =
200 " PauseQueueMember([queuename],interface[,options[,reason]]):\n"
201 "Pauses (blocks calls for) a queue member.\n"
202 "The given interface will be paused in the given queue. This prevents\n"
203 "any calls from being sent from the queue to the interface until it is\n"
204 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
205 "queuename is given, the interface is paused in every queue it is a\n"
206 "member of. The application will fail if the interface is not found.\n"
207 "The reason string is entirely optional and is used to add extra information\n"
208 "to the appropriate queue_log entries and manager events.\n"
209 " This application sets the following channel variable upon completion:\n"
210 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
211 " text string, one of\n"
212 " PAUSED | NOTFOUND\n"
213 "Example: PauseQueueMember(,SIP/3000)\n";
215 static char *app_upqm = "UnpauseQueueMember" ;
216 static char *app_upqm_synopsis = "Unpauses a queue member" ;
217 static char *app_upqm_descrip =
218 " UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
219 "Unpauses (resumes calls to) a queue member.\n"
220 "This is the counterpart to PauseQueueMember and operates exactly the\n"
221 "same way, except it unpauses instead of pausing the given interface.\n"
222 "The reason string is entirely optional and is used to add extra information\n"
223 "to the appropriate queue_log entries and manager events.\n"
224 " This application sets the following channel variable upon completion:\n"
225 " UPQMSTATUS The status of the attempt to unpause a queue \n"
226 " member as a text string, one of\n"
227 " UNPAUSED | NOTFOUND\n"
228 "Example: UnpauseQueueMember(,SIP/3000)\n";
230 static char *app_ql = "QueueLog" ;
231 static char *app_ql_synopsis = "Writes to the queue_log" ;
232 static char *app_ql_descrip =
233 " QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
234 "Allows you to write your own events into the queue log\n"
235 "Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
237 /*! \brief Persistent Members astdb family */
238 static const char *pm_family = "Queue/PersistentMembers";
239 /* The maximum length of each persistent member queue database entry */
240 #define PM_MAX_LEN 8192
242 /*! \brief queues.conf [general] option */
243 static int queue_keep_stats = 0;
245 /*! \brief queues.conf [general] option */
246 static int queue_persistent_members = 0;
248 /*! \brief queues.conf per-queue weight option */
249 static int use_weight = 0;
251 /*! \brief queues.conf [general] option */
252 static int autofill_default = 0;
254 /*! \brief queues.conf [general] option */
255 static int montype_default = 0;
257 /*! \brief queues.conf [general] option */
258 static int shared_lastcall = 0;
260 /*! \brief Subscription to device state change events */
261 static struct ast_event_sub *device_state_sub;
263 /*! \brief queues.conf [general] option */
264 static int update_cdr = 0;
270 QUEUE_LEAVEEMPTY = 3,
271 QUEUE_JOINUNAVAIL = 4,
272 QUEUE_LEAVEUNAVAIL = 5,
278 enum queue_result id;
280 } queue_results[] = {
281 { QUEUE_UNKNOWN, "UNKNOWN" },
282 { QUEUE_TIMEOUT, "TIMEOUT" },
283 { QUEUE_JOINEMPTY,"JOINEMPTY" },
284 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
285 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
286 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
287 { QUEUE_FULL, "FULL" },
288 { QUEUE_CONTINUE, "CONTINUE" },
291 /*! \brief We define a custom "local user" structure because we
292 use it not only for keeping track of what is in use but
293 also for keeping track of who we're dialing. */
296 struct callattempt *q_next;
297 struct ast_channel *chan;
303 struct call_queue *lastqueue;
304 struct member *member;
309 struct call_queue *parent; /*!< What queue is our parent */
310 char moh[80]; /*!< Name of musiconhold to be used */
311 char announce[80]; /*!< Announcement to play for member when call is answered */
312 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
313 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
314 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
315 int pos; /*!< Where we are in the queue */
316 int prio; /*!< Our priority */
317 int last_pos_said; /*!< Last position we told the user */
318 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
319 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
320 time_t last_pos; /*!< Last time we told the user their position */
321 int opos; /*!< Where we started in the queue */
322 int handled; /*!< Whether our call was handled */
323 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
324 int linpos; /*!< If using linear strategy, what position are we at? */
325 int linwrapped; /*!< Is the linpos wrapped? */
326 time_t start; /*!< When we started holding */
327 time_t expire; /*!< When this entry should expire (time out of queue) */
328 struct ast_channel *chan; /*!< Our channel */
329 struct queue_ent *next; /*!< The next queue entry */
333 char interface[80]; /*!< Technology/Location */
334 char membername[80]; /*!< Member name to use in queue logs */
335 int penalty; /*!< Are we a last resort? */
336 int calls; /*!< Number of calls serviced by this member */
337 int dynamic; /*!< Are we dynamically added? */
338 int realtime; /*!< Is this member realtime? */
339 int status; /*!< Status of queue member */
340 int paused; /*!< Are we paused (not accepting calls)? */
341 time_t lastcall; /*!< When last successful call was hungup */
342 struct call_queue *lastqueue; /*!< Last queue we received a call */
343 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
344 unsigned int delme:1; /*!< Flag to delete entry on reload */
347 struct member_interface {
349 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
352 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
354 /* values used in multi-bit flags in call_queue */
355 #define QUEUE_EMPTY_NORMAL 1
356 #define QUEUE_EMPTY_STRICT 2
357 #define QUEUE_EMPTY_LOOSE 3
358 #define ANNOUNCEHOLDTIME_ALWAYS 1
359 #define ANNOUNCEHOLDTIME_ONCE 2
360 #define QUEUE_EVENT_VARIABLES 3
363 AST_DECLARE_STRING_FIELDS(
365 AST_STRING_FIELD(name);
366 /*! Music on Hold class */
367 AST_STRING_FIELD(moh);
368 /*! Announcement to play when call is answered */
369 AST_STRING_FIELD(announce);
371 AST_STRING_FIELD(context);
372 /*! Macro to run upon member connection */
373 AST_STRING_FIELD(membermacro);
374 /*! Gosub to run upon member connection */
375 AST_STRING_FIELD(membergosub);
376 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
377 AST_STRING_FIELD(sound_next);
378 /*! Sound file: "There are currently" (def. queue-thereare) */
379 AST_STRING_FIELD(sound_thereare);
380 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
381 AST_STRING_FIELD(sound_calls);
382 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
383 AST_STRING_FIELD(sound_holdtime);
384 /*! Sound file: "minutes." (def. queue-minutes) */
385 AST_STRING_FIELD(sound_minutes);
386 /*! Sound file: "less-than" (def. queue-lessthan) */
387 AST_STRING_FIELD(sound_lessthan);
388 /*! Sound file: "seconds." (def. queue-seconds) */
389 AST_STRING_FIELD(sound_seconds);
390 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
391 AST_STRING_FIELD(sound_thanks);
392 /*! Sound file: Custom announce for caller, no default */
393 AST_STRING_FIELD(sound_callerannounce);
394 /*! Sound file: "Hold time" (def. queue-reporthold) */
395 AST_STRING_FIELD(sound_reporthold);
397 /*! Sound files: Custom announce, no default */
398 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
400 unsigned int joinempty:2;
401 unsigned int eventwhencalled:2;
402 unsigned int leavewhenempty:2;
403 unsigned int ringinuse:1;
404 unsigned int setinterfacevar:1;
405 unsigned int setqueuevar:1;
406 unsigned int setqueueentryvar:1;
407 unsigned int reportholdtime:1;
408 unsigned int wrapped:1;
409 unsigned int timeoutrestart:1;
410 unsigned int announceholdtime:2;
411 unsigned int announceposition:1;
413 unsigned int maskmemberstatus:1;
414 unsigned int realtime:1;
415 unsigned int found:1;
416 int announcefrequency; /*!< How often to announce their position */
417 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
418 int periodicannouncefrequency; /*!< How often to play periodic announcement */
419 int roundingseconds; /*!< How many seconds do we round to? */
420 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
421 int callscompleted; /*!< Number of queue calls completed */
422 int callsabandoned; /*!< Number of queue calls abandoned */
423 int servicelevel; /*!< seconds setting for servicelevel*/
424 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
425 char monfmt[8]; /*!< Format to use when recording calls */
426 int montype; /*!< Monitor type Monitor vs. MixMonitor */
427 int count; /*!< How many entries */
428 int maxlen; /*!< Max number of entries */
429 int wrapuptime; /*!< Wrapup Time */
431 int retry; /*!< Retry calling everyone after this amount of time */
432 int timeout; /*!< How long to wait for an answer */
433 int weight; /*!< Respective weight */
434 int autopause; /*!< Auto pause queue members if they fail to answer */
436 /* Queue strategy things */
437 int rrpos; /*!< Round Robin - position */
438 int memberdelay; /*!< Seconds to delay connecting member to caller */
439 int autofill; /*!< Ignore the head call status and ring an available agent */
441 struct ao2_container *members; /*!< Head of the list of members */
443 * \brief Number of members _logged in_
444 * \note There will be members in the members container that are not logged
445 * in, so this can not simply be replaced with ao2_container_count().
448 struct queue_ent *head; /*!< Head of the list of callers */
449 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
452 static struct ao2_container *queues;
454 static void update_realtime_members(struct call_queue *q);
455 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
457 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
461 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
462 if (queue_results[i].id == res) {
463 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
469 static char *int2strat(int strategy)
473 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
474 if (strategy == strategies[x].strategy)
475 return strategies[x].name;
481 static int strat2int(const char *strategy)
485 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
486 if (!strcasecmp(strategy, strategies[x].name))
487 return strategies[x].strategy;
493 static int queue_hash_cb(const void *obj, const int flags)
495 const struct call_queue *q = obj;
496 return ast_str_hash(q->name);
499 static int queue_cmp_cb(void *obj, void *arg, int flags)
501 struct call_queue *q = obj, *q2 = arg;
502 return !strcasecmp(q->name, q2->name) ? CMP_MATCH : 0;
505 static inline struct call_queue *queue_ref(struct call_queue *q)
511 static inline struct call_queue *queue_unref(struct call_queue *q)
517 static void set_queue_variables(struct queue_ent *qe)
520 char interfacevar[256]="";
523 if (qe->parent->setqueuevar) {
525 if (qe->parent->callscompleted > 0)
526 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
528 snprintf(interfacevar,sizeof(interfacevar),
529 "QUEUEMAX=%d|QUEUESTRATEGY=%s|QUEUECALLS=%d|QUEUEHOLDTIME=%d|QUEUECOMPLETED=%d|QUEUEABANDONED=%d|QUEUESRVLEVEL=%d|QUEUESRVLEVELPERF=%2.1f",
530 qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
531 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
533 pbx_builtin_setvar(qe->chan, interfacevar);
537 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
538 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
540 struct queue_ent *cur;
557 enum queue_member_status {
559 QUEUE_NO_REACHABLE_MEMBERS,
560 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
564 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty)
566 struct member *member;
567 struct ao2_iterator mem_iter;
568 enum queue_member_status result = QUEUE_NO_MEMBERS;
571 mem_iter = ao2_iterator_init(q->members, 0);
572 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
573 if (max_penalty && (member->penalty > max_penalty))
576 switch (member->status) {
577 case AST_DEVICE_INVALID:
580 case AST_DEVICE_UNAVAILABLE:
581 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
582 result = QUEUE_NO_REACHABLE_MEMBERS;
585 if (member->paused) {
586 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
601 AST_LIST_ENTRY(statechange) entry;
606 static void *handle_statechange(struct statechange *sc)
608 struct call_queue *q;
610 struct ao2_iterator mem_iter;
611 struct member_interface *curint;
612 struct ao2_iterator queue_iter;
616 technology = ast_strdupa(sc->dev);
617 loc = strchr(technology, '/');
624 AST_LIST_LOCK(&interfaces);
625 AST_LIST_TRAVERSE(&interfaces, curint, list) {
628 interface = ast_strdupa(curint->interface);
629 if ((slash_pos = strchr(interface, '/')))
630 if ((slash_pos = strchr(slash_pos + 1, '/')))
633 if (!strcasecmp(interface, sc->dev))
636 AST_LIST_UNLOCK(&interfaces);
639 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));
643 ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
644 queue_iter = ao2_iterator_init(queues, 0);
645 while ((q = ao2_iterator_next(&queue_iter))) {
647 mem_iter = ao2_iterator_init(q->members, 0);
648 while ((cur = ao2_iterator_next(&mem_iter))) {
651 interface = ast_strdupa(cur->interface);
652 if ((slash_pos = strchr(interface, '/')))
653 if ((slash_pos = strchr(slash_pos + 1, '/')))
656 if (strcasecmp(sc->dev, interface)) {
661 if (cur->status != sc->state) {
662 cur->status = sc->state;
663 if (q->maskmemberstatus) {
668 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
678 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime" : "static",
679 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
691 * \brief Data used by the device state thread
694 /*! Set to 1 to stop the thread */
696 /*! The device state monitoring thread */
698 /*! Lock for the state change queue */
700 /*! Condition for the state change queue */
702 /*! Queue of state changes */
703 AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
705 .thread = AST_PTHREADT_NULL,
708 static void *device_state_thread(void *data)
710 struct statechange *sc = NULL;
712 while (!device_state.stop) {
713 ast_mutex_lock(&device_state.lock);
714 if (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
715 ast_cond_wait(&device_state.cond, &device_state.lock);
716 sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry);
718 ast_mutex_unlock(&device_state.lock);
720 /* Check to see if we were woken up to see the request to stop */
721 if (device_state.stop)
727 handle_statechange(sc);
736 while ((sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry)))
742 static int statechange_queue(const char *dev, enum ast_device_state state)
744 struct statechange *sc;
746 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
750 strcpy(sc->dev, dev);
752 ast_mutex_lock(&device_state.lock);
753 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
754 ast_cond_signal(&device_state.cond);
755 ast_mutex_unlock(&device_state.lock);
760 static void device_state_cb(const struct ast_event *event, void *unused)
762 enum ast_device_state state;
765 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
766 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
768 if (ast_strlen_zero(device)) {
769 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
773 statechange_queue(device, state);
776 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
780 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
781 cur->penalty = penalty;
782 cur->paused = paused;
783 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
784 if(!ast_strlen_zero(membername))
785 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
787 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
788 if (!strchr(cur->interface, '/'))
789 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
790 cur->status = ast_device_state(interface);
797 static int compress_char(const char c)
807 static int member_hash_fn(const void *obj, const int flags)
809 const struct member *mem = obj;
810 const char *chname = strchr(mem->interface, '/');
813 chname = mem->interface;
814 for (i = 0; i < 5 && chname[i]; i++)
815 ret += compress_char(chname[i]) << (i * 6);
819 static int member_cmp_fn(void *obj1, void *obj2, int flags)
821 struct member *mem1 = obj1, *mem2 = obj2;
822 return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
825 static void init_queue(struct call_queue *q)
830 q->retry = DEFAULT_RETRY;
833 q->announcefrequency = 0;
834 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
835 q->announceholdtime = 0;
836 q->announceholdtime = 1;
837 q->roundingseconds = 0; /* Default - don't announce seconds */
840 q->setinterfacevar = 0;
842 q->setqueueentryvar = 0;
843 q->autofill = autofill_default;
844 q->montype = montype_default;
846 q->periodicannouncefrequency = 0;
848 if(q->strategy == QUEUE_STRATEGY_LINEAR)
849 /* linear strategy depends on order, so we have to place all members in a single bucket */
850 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
852 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
857 ast_string_field_set(q, sound_next, "queue-youarenext");
858 ast_string_field_set(q, sound_thereare, "queue-thereare");
859 ast_string_field_set(q, sound_calls, "queue-callswaiting");
860 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
861 ast_string_field_set(q, sound_minutes, "queue-minutes");
862 ast_string_field_set(q, sound_seconds, "queue-seconds");
863 ast_string_field_set(q, sound_thanks, "queue-thankyou");
864 ast_string_field_set(q, sound_lessthan, "queue-less-than");
865 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
867 if ((q->sound_periodicannounce[0] = ast_str_create(32)))
868 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
870 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
871 if (q->sound_periodicannounce[i])
872 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
876 static void clear_queue(struct call_queue *q)
879 q->callscompleted = 0;
880 q->callsabandoned = 0;
881 q->callscompletedinsl = 0;
885 static int add_to_interfaces(const char *interface)
887 struct member_interface *curint;
889 AST_LIST_LOCK(&interfaces);
890 AST_LIST_TRAVERSE(&interfaces, curint, list) {
891 if (!strcasecmp(curint->interface, interface))
896 AST_LIST_UNLOCK(&interfaces);
900 ast_debug(1, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
902 if ((curint = ast_calloc(1, sizeof(*curint)))) {
903 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
904 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
906 AST_LIST_UNLOCK(&interfaces);
911 static int interface_exists_global(const char *interface)
913 struct call_queue *q;
914 struct member *mem, tmpmem;
915 struct ao2_iterator queue_iter;
918 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
919 queue_iter = ao2_iterator_init(queues, 0);
920 while ((q = ao2_iterator_next(&queue_iter))) {
923 if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
937 static int remove_from_interfaces(const char *interface)
939 struct member_interface *curint;
941 AST_LIST_LOCK(&interfaces);
942 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
943 if (!strcasecmp(curint->interface, interface)) {
944 if (!interface_exists_global(interface)) {
945 ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
946 AST_LIST_REMOVE_CURRENT(list);
952 AST_LIST_TRAVERSE_SAFE_END;
953 AST_LIST_UNLOCK(&interfaces);
958 static void clear_and_free_interfaces(void)
960 struct member_interface *curint;
962 AST_LIST_LOCK(&interfaces);
963 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
965 AST_LIST_UNLOCK(&interfaces);
968 /*! \brief Configure a queue parameter.
970 For error reporting, line number is passed for .conf static configuration.
971 For Realtime queues, linenum is -1.
972 The failunknown flag is set for config files (and static realtime) to show
973 errors for unknown parameters. It is cleared for dynamic realtime to allow
974 extra fields in the tables. */
975 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
977 if (!strcasecmp(param, "musicclass") ||
978 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
979 ast_string_field_set(q, moh, val);
980 } else if (!strcasecmp(param, "announce")) {
981 ast_string_field_set(q, announce, val);
982 } else if (!strcasecmp(param, "context")) {
983 ast_string_field_set(q, context, val);
984 } else if (!strcasecmp(param, "timeout")) {
985 q->timeout = atoi(val);
987 q->timeout = DEFAULT_TIMEOUT;
988 } else if (!strcasecmp(param, "ringinuse")) {
989 q->ringinuse = ast_true(val);
990 } else if (!strcasecmp(param, "setinterfacevar")) {
991 q->setinterfacevar = ast_true(val);
992 } else if (!strcasecmp(param, "setqueuevar")) {
993 q->setqueuevar = ast_true(val);
994 } else if (!strcasecmp(param, "setqueueentryvar")) {
995 q->setqueueentryvar = ast_true(val);
996 } else if (!strcasecmp(param, "monitor-format")) {
997 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
998 } else if (!strcasecmp(param, "membermacro")) {
999 ast_string_field_set(q, membermacro, val);
1000 } else if (!strcasecmp(param, "membergosub")) {
1001 ast_string_field_set(q, membergosub, val);
1002 } else if (!strcasecmp(param, "queue-youarenext")) {
1003 ast_string_field_set(q, sound_next, val);
1004 } else if (!strcasecmp(param, "queue-thereare")) {
1005 ast_string_field_set(q, sound_thereare, val);
1006 } else if (!strcasecmp(param, "queue-callswaiting")) {
1007 ast_string_field_set(q, sound_calls, val);
1008 } else if (!strcasecmp(param, "queue-holdtime")) {
1009 ast_string_field_set(q, sound_holdtime, val);
1010 } else if (!strcasecmp(param, "queue-minutes")) {
1011 ast_string_field_set(q, sound_minutes, val);
1012 } else if (!strcasecmp(param, "queue-seconds")) {
1013 ast_string_field_set(q, sound_seconds, val);
1014 } else if (!strcasecmp(param, "queue-lessthan")) {
1015 ast_string_field_set(q, sound_lessthan, val);
1016 } else if (!strcasecmp(param, "queue-thankyou")) {
1017 ast_string_field_set(q, sound_thanks, val);
1018 } else if (!strcasecmp(param, "queue-callerannounce")) {
1019 ast_string_field_set(q, sound_callerannounce, val);
1020 } else if (!strcasecmp(param, "queue-reporthold")) {
1021 ast_string_field_set(q, sound_reporthold, val);
1022 } else if (!strcasecmp(param, "announce-frequency")) {
1023 q->announcefrequency = atoi(val);
1024 } else if (!strcasecmp(param, "min-announce-frequency")) {
1025 q->minannouncefrequency = atoi(val);
1026 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
1027 } else if (!strcasecmp(param, "announce-round-seconds")) {
1028 q->roundingseconds = atoi(val);
1029 /* Rounding to any other values just doesn't make sense... */
1030 if (!(q->roundingseconds == 0 || q->roundingseconds == 1 || q->roundingseconds == 5 || q->roundingseconds == 10
1031 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
1033 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1034 "using 0 instead for queue '%s' at line %d of queues.conf\n",
1035 val, param, q->name, linenum);
1037 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1038 "using 0 instead for queue '%s'\n", val, param, q->name);
1040 q->roundingseconds=0;
1042 } else if (!strcasecmp(param, "announce-holdtime")) {
1043 if (!strcasecmp(val, "once"))
1044 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1045 else if (ast_true(val))
1046 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1048 q->announceholdtime = 0;
1049 } else if (!strcasecmp(param, "announce-position")) {
1050 q->announceposition = ast_true(val);
1051 } else if (!strcasecmp(param, "periodic-announce")) {
1052 if (strchr(val, ',')) {
1053 char *s, *buf = ast_strdupa(val);
1056 while ((s = strsep(&buf, ",|"))) {
1057 if (!q->sound_periodicannounce[i])
1058 q->sound_periodicannounce[i] = ast_str_create(16);
1059 ast_str_set(&q->sound_periodicannounce[i], 0, s);
1061 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1065 ast_str_set(&q->sound_periodicannounce[0], 0, val);
1067 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1068 q->periodicannouncefrequency = atoi(val);
1069 } else if (!strcasecmp(param, "retry")) {
1070 q->retry = atoi(val);
1072 q->retry = DEFAULT_RETRY;
1073 } else if (!strcasecmp(param, "wrapuptime")) {
1074 q->wrapuptime = atoi(val);
1075 } else if (!strcasecmp(param, "autofill")) {
1076 q->autofill = ast_true(val);
1077 } else if (!strcasecmp(param, "monitor-type")) {
1078 if (!strcasecmp(val, "mixmonitor"))
1080 } else if (!strcasecmp(param, "autopause")) {
1081 q->autopause = ast_true(val);
1082 } else if (!strcasecmp(param, "maxlen")) {
1083 q->maxlen = atoi(val);
1086 } else if (!strcasecmp(param, "servicelevel")) {
1087 q->servicelevel= atoi(val);
1088 } else if (!strcasecmp(param, "strategy")) {
1089 /* We already have set this, no need to do it again */
1091 } else if (!strcasecmp(param, "joinempty")) {
1092 if (!strcasecmp(val, "loose"))
1093 q->joinempty = QUEUE_EMPTY_LOOSE;
1094 else if (!strcasecmp(val, "strict"))
1095 q->joinempty = QUEUE_EMPTY_STRICT;
1096 else if (ast_true(val))
1097 q->joinempty = QUEUE_EMPTY_NORMAL;
1100 } else if (!strcasecmp(param, "leavewhenempty")) {
1101 if (!strcasecmp(val, "loose"))
1102 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
1103 else if (!strcasecmp(val, "strict"))
1104 q->leavewhenempty = QUEUE_EMPTY_STRICT;
1105 else if (ast_true(val))
1106 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
1108 q->leavewhenempty = 0;
1109 } else if (!strcasecmp(param, "eventmemberstatus")) {
1110 q->maskmemberstatus = !ast_true(val);
1111 } else if (!strcasecmp(param, "eventwhencalled")) {
1112 if (!strcasecmp(val, "vars")) {
1113 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1115 q->eventwhencalled = ast_true(val) ? 1 : 0;
1117 } else if (!strcasecmp(param, "reportholdtime")) {
1118 q->reportholdtime = ast_true(val);
1119 } else if (!strcasecmp(param, "memberdelay")) {
1120 q->memberdelay = atoi(val);
1121 } else if (!strcasecmp(param, "weight")) {
1122 q->weight = atoi(val);
1125 /* With Realtime queues, if the last queue using weights is deleted in realtime,
1126 we will not see any effect on use_weight until next reload. */
1127 } else if (!strcasecmp(param, "timeoutrestart")) {
1128 q->timeoutrestart = ast_true(val);
1129 } else if (failunknown) {
1131 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1132 q->name, param, linenum);
1134 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1139 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
1141 struct member *m, tmpmem;
1146 penalty = atoi(penalty_str);
1152 paused = atoi(paused_str);
1157 /* Find the member, or the place to put a new one. */
1158 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
1159 m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
1161 /* Create a new one if not found, else update penalty */
1163 if ((m = create_queue_member(interface, membername, penalty, paused))) {
1166 add_to_interfaces(interface);
1167 ao2_link(q->members, m);
1171 m->dead = 0; /* Do not delete this one. */
1174 m->penalty = penalty;
1179 static void free_members(struct call_queue *q, int all)
1181 /* Free non-dynamic members */
1183 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1185 while ((cur = ao2_iterator_next(&mem_iter))) {
1186 if (all || !cur->dynamic) {
1187 ao2_unlink(q->members, cur);
1188 remove_from_interfaces(cur->interface);
1195 static void destroy_queue(void *obj)
1197 struct call_queue *q = obj;
1200 ast_debug(0, "Queue destructor called for queue '%s'!\n", q->name);
1203 ast_string_field_free_memory(q);
1204 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1205 if (q->sound_periodicannounce[i])
1206 free(q->sound_periodicannounce[i]);
1208 ao2_ref(q->members, -1);
1211 static struct call_queue *alloc_queue(const char *queuename)
1213 struct call_queue *q;
1215 if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
1216 if (ast_string_field_init(q, 64)) {
1220 ast_string_field_set(q, name, queuename);
1225 /*!\brief Reload a single queue via realtime.
1226 \return Return the queue, or NULL if it doesn't exist.
1227 \note Should be called with the global qlock locked. */
1228 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1230 struct ast_variable *v;
1231 struct call_queue *q, tmpq = {
1235 struct ao2_iterator mem_iter;
1236 char *interface = NULL;
1237 const char *tmp_name;
1239 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1241 /* Static queues override realtime. */
1242 if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
1250 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
1256 } else if (!member_config)
1257 /* Not found in the list, and it's not realtime ... */
1260 /* Check if queue is defined in realtime. */
1262 /* Delete queue from in-core list if it has been deleted in realtime. */
1264 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1265 found condition... So we might delete an in-core queue
1266 in case of DB failure. */
1267 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
1270 /* Delete if unused (else will be deleted when last caller leaves). */
1271 ao2_unlink(queues, q);
1278 /* Create a new queue if an in-core entry does not exist yet. */
1280 if (!(q = alloc_queue(queuename)))
1285 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1286 ao2_link(queues, q);
1290 memset(tmpbuf, 0, sizeof(tmpbuf));
1291 for (v = queue_vars; v; v = v->next) {
1292 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1293 if ((tmp = strchr(v->name, '_'))) {
1294 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1297 while ((tmp = strchr(tmp, '_')))
1301 queue_set_param(q, tmp_name, v->value, -1, 0);
1304 /* Temporarily set realtime members dead so we can detect deleted ones.
1305 * Also set the membercount correctly for realtime*/
1306 mem_iter = ao2_iterator_init(q->members, 0);
1307 while ((m = ao2_iterator_next(&mem_iter))) {
1314 while ((interface = ast_category_browse(member_config, interface))) {
1315 rt_handle_member_record(q, interface,
1316 ast_variable_retrieve(member_config, interface, "membername"),
1317 ast_variable_retrieve(member_config, interface, "penalty"),
1318 ast_variable_retrieve(member_config, interface, "paused"));
1321 /* Delete all realtime members that have been deleted in DB. */
1322 mem_iter = ao2_iterator_init(q->members, 0);
1323 while ((m = ao2_iterator_next(&mem_iter))) {
1325 ao2_unlink(q->members, m);
1327 remove_from_interfaces(m->interface);
1339 static struct call_queue *load_realtime_queue(const char *queuename)
1341 struct ast_variable *queue_vars;
1342 struct ast_config *member_config = NULL;
1343 struct call_queue *q = NULL, tmpq = {
1347 /* Find the queue in the in-core list first. */
1348 q = ao2_find(queues, &tmpq, OBJ_POINTER);
1350 if (!q || q->realtime) {
1351 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1352 queue operations while waiting for the DB.
1354 This will be two separate database transactions, so we might
1355 see queue parameters as they were before another process
1356 changed the queue and member list as it was after the change.
1357 Thus we might see an empty member list when a queue is
1358 deleted. In practise, this is unlikely to cause a problem. */
1360 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1362 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1363 if (!member_config) {
1364 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1365 ast_variables_destroy(queue_vars);
1371 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1373 ast_config_destroy(member_config);
1375 ast_variables_destroy(queue_vars);
1379 update_realtime_members(q);
1384 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
1386 struct ast_variable *var;
1389 if(!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL)))
1392 if(!strcmp(var->name, "uniqueid"))
1396 if(var && !ast_strlen_zero(var->value)) {
1397 if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1)
1403 static void update_realtime_members(struct call_queue *q)
1405 struct ast_config *member_config = NULL;
1407 char *interface = NULL;
1408 struct ao2_iterator mem_iter;
1410 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL);
1411 if (!member_config) {
1412 /*This queue doesn't have realtime members*/
1413 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
1419 /* Temporarily set realtime members dead so we can detect deleted ones.*/
1420 mem_iter = ao2_iterator_init(q->members, 0);
1421 while ((m = ao2_iterator_next(&mem_iter))) {
1427 while ((interface = ast_category_browse(member_config, interface))) {
1428 rt_handle_member_record(q, interface,
1429 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1430 ast_variable_retrieve(member_config, interface, "penalty"),
1431 ast_variable_retrieve(member_config, interface, "paused"));
1434 /* Delete all realtime members that have been deleted in DB. */
1435 mem_iter = ao2_iterator_init(q->members, 0);
1436 while ((m = ao2_iterator_next(&mem_iter))) {
1438 ao2_unlink(q->members, m);
1440 remove_from_interfaces(m->interface);
1449 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1451 struct call_queue *q;
1452 struct queue_ent *cur, *prev = NULL;
1456 enum queue_member_status stat;
1458 if (!(q = load_realtime_queue(queuename)))
1464 /* This is our one */
1465 stat = get_member_status(q, qe->max_penalty);
1466 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1467 *reason = QUEUE_JOINEMPTY;
1468 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1469 *reason = QUEUE_JOINUNAVAIL;
1470 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1471 *reason = QUEUE_JOINUNAVAIL;
1472 else if (q->maxlen && (q->count >= q->maxlen))
1473 *reason = QUEUE_FULL;
1475 /* There's space for us, put us at the right position inside
1477 * Take into account the priority of the calling user */
1482 /* We have higher priority than the current user, enter
1483 * before him, after all the other users with priority
1484 * higher or equal to our priority. */
1485 if ((!inserted) && (qe->prio > cur->prio)) {
1486 insert_entry(q, prev, qe, &pos);
1493 /* No luck, join at the end of the queue */
1495 insert_entry(q, prev, qe, &pos);
1496 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1497 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1498 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1501 manager_event(EVENT_FLAG_CALL, "Join",
1502 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1504 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1505 S_OR(qe->chan->cid.cid_name, "unknown"),
1506 q->name, qe->pos, q->count, qe->chan->uniqueid );
1507 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1515 static int play_file(struct ast_channel *chan, const char *filename)
1519 ast_stopstream(chan);
1521 res = ast_streamfile(chan, filename, chan->language);
1523 res = ast_waitstream(chan, AST_DIGIT_ANY);
1525 ast_stopstream(chan);
1530 static int valid_exit(struct queue_ent *qe, char digit)
1532 int digitlen = strlen(qe->digits);
1534 /* Prevent possible buffer overflow */
1535 if (digitlen < sizeof(qe->digits) - 2) {
1536 qe->digits[digitlen] = digit;
1537 qe->digits[digitlen + 1] = '\0';
1539 qe->digits[0] = '\0';
1543 /* If there's no context to goto, short-circuit */
1544 if (ast_strlen_zero(qe->context))
1547 /* If the extension is bad, then reset the digits to blank */
1548 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1549 qe->digits[0] = '\0';
1553 /* We have an exact match */
1554 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1555 qe->valid_digits = 1;
1556 /* Return 1 on a successful goto */
1563 static int say_position(struct queue_ent *qe, int ringing)
1565 int res = 0, avgholdmins, avgholdsecs;
1568 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1570 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1573 /* If either our position has changed, or we are over the freq timer, say position */
1574 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1578 ast_indicate(qe->chan,-1);
1580 ast_moh_stop(qe->chan);
1582 if (qe->parent->announceposition) {
1583 /* Say we're next, if we are */
1585 res = play_file(qe->chan, qe->parent->sound_next);
1591 res = play_file(qe->chan, qe->parent->sound_thereare);
1594 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1597 res = play_file(qe->chan, qe->parent->sound_calls);
1602 /* Round hold time to nearest minute */
1603 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1605 /* If they have specified a rounding then round the seconds as well */
1606 if (qe->parent->roundingseconds) {
1607 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1608 avgholdsecs *= qe->parent->roundingseconds;
1613 ast_verb(3, "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1615 /* If the hold time is >1 min, if it's enabled, and if it's not
1616 supposed to be only once and we have already said it, say it */
1617 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1618 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1619 res = play_file(qe->chan, qe->parent->sound_holdtime);
1623 if (avgholdmins > 0) {
1624 if (avgholdmins < 2) {
1625 res = play_file(qe->chan, qe->parent->sound_lessthan);
1629 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1633 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1638 res = play_file(qe->chan, qe->parent->sound_minutes);
1642 if (avgholdsecs>0) {
1643 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1647 res = play_file(qe->chan, qe->parent->sound_seconds);
1655 if (qe->parent->announceposition) {
1656 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
1657 qe->chan->name, qe->parent->name, qe->pos);
1659 res = play_file(qe->chan, qe->parent->sound_thanks);
1662 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
1665 /* Set our last_pos indicators */
1667 qe->last_pos_said = qe->pos;
1669 /* Don't restart music on hold if we're about to exit the caller from the queue */
1672 ast_indicate(qe->chan, AST_CONTROL_RINGING);
1674 ast_moh_start(qe->chan, qe->moh, NULL);
1679 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
1683 /* Calculate holdtime using a recursive boxcar filter */
1684 /* Thanks to SRT for this contribution */
1685 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1687 ao2_lock(qe->parent);
1688 oldvalue = qe->parent->holdtime;
1689 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
1690 ao2_unlock(qe->parent);
1694 static void leave_queue(struct queue_ent *qe)
1696 struct call_queue *q;
1697 struct queue_ent *cur, *prev = NULL;
1700 if (!(q = qe->parent))
1706 for (cur = q->head; cur; cur = cur->next) {
1710 /* Take us out of the queue */
1711 manager_event(EVENT_FLAG_CALL, "Leave",
1712 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1713 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1714 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1715 /* Take us out of the queue */
1717 prev->next = cur->next;
1719 q->head = cur->next;
1721 /* Renumber the people after us in the queue based on a new count */
1728 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
1730 if(!ast_load_realtime("queues", "name", q->name, NULL))
1735 /* It's dead and nobody is in it, so kill it */
1736 ao2_unlink(queues, q);
1742 /* Hang up a list of outgoing calls */
1743 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1745 struct callattempt *oo;
1748 /* Hangup any existing lines we have open */
1749 if (outgoing->chan && (outgoing->chan != exception))
1750 ast_hangup(outgoing->chan);
1752 outgoing = outgoing->q_next;
1754 ao2_ref(oo->member, -1);
1759 static int update_status(struct call_queue *q, struct member *member, int status)
1762 struct ao2_iterator mem_iter;
1764 /* Since a reload could have taken place, we have to traverse the list to
1765 be sure it's still valid */
1767 mem_iter = ao2_iterator_init(q->members, 0);
1768 while ((cur = ao2_iterator_next(&mem_iter))) {
1769 if (member != cur) {
1774 cur->status = status;
1775 if (!q->maskmemberstatus) {
1776 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1779 "MemberName: %s\r\n"
1780 "Membership: %s\r\n"
1782 "CallsTaken: %d\r\n"
1786 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
1787 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1795 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1797 if (status == AST_CAUSE_BUSY)
1798 status = AST_DEVICE_BUSY;
1799 else if (status == AST_CAUSE_UNREGISTERED)
1800 status = AST_DEVICE_UNAVAILABLE;
1801 else if (status == AST_CAUSE_NOSUCHDRIVER)
1802 status = AST_DEVICE_INVALID;
1804 status = AST_DEVICE_UNKNOWN;
1805 return update_status(q, member, status);
1808 /* traverse all defined queues which have calls waiting and contain this member
1809 return 0 if no other queue has precedence (higher weight) or 1 if found */
1810 static int compare_weight(struct call_queue *rq, struct member *member)
1812 struct call_queue *q;
1815 struct ao2_iterator queue_iter;
1817 /* &qlock and &rq->lock already set by try_calling()
1818 * to solve deadlock */
1819 queue_iter = ao2_iterator_init(queues, 0);
1820 while ((q = ao2_iterator_next(&queue_iter))) {
1821 if (q == rq) { /* don't check myself, could deadlock */
1826 if (q->count && q->members) {
1827 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
1828 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1829 if (q->weight > rq->weight) {
1830 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);
1846 /*! \brief common hangup actions */
1847 static void do_hang(struct callattempt *o)
1850 ast_hangup(o->chan);
1854 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1856 struct ast_str *buf = ast_str_alloca(len + 1);
1859 if (pbx_builtin_serialize_variables(chan, &buf)) {
1862 /* convert "\n" to "\nVariable: " */
1863 strcpy(vars, "Variable: ");
1866 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1869 if (tmp[i + 1] == '\0')
1871 if (tmp[i] == '\n') {
1875 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1885 /* there are no channel variables; leave it blank */
1891 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1898 /* on entry here, we know that tmp->chan == NULL */
1899 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
1900 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
1901 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
1902 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
1904 ast_cdr_busy(qe->chan->cdr);
1905 tmp->stillgoing = 0;
1910 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1911 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
1913 ast_cdr_busy(qe->chan->cdr);
1914 tmp->stillgoing = 0;
1918 if (tmp->member->paused) {
1919 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
1921 ast_cdr_busy(qe->chan->cdr);
1922 tmp->stillgoing = 0;
1925 if (use_weight && compare_weight(qe->parent,tmp->member)) {
1926 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1928 ast_cdr_busy(qe->chan->cdr);
1929 tmp->stillgoing = 0;
1934 ast_copy_string(tech, tmp->interface, sizeof(tech));
1935 if ((location = strchr(tech, '/')))
1940 /* Request the peer */
1941 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1942 if (!tmp->chan) { /* If we can't, just go on to the next call */
1944 ast_cdr_busy(qe->chan->cdr);
1945 tmp->stillgoing = 0;
1946 update_dial_status(qe->parent, tmp->member, status);
1948 ao2_lock(qe->parent);
1949 qe->parent->rrpos++;
1951 ao2_unlock(qe->parent);
1956 } else if (status != tmp->oldstatus)
1957 update_dial_status(qe->parent, tmp->member, status);
1959 tmp->chan->appl = "AppQueue";
1960 tmp->chan->data = "(Outgoing Line)";
1961 tmp->chan->whentohangup = 0;
1962 if (tmp->chan->cid.cid_num)
1963 ast_free(tmp->chan->cid.cid_num);
1964 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1965 if (tmp->chan->cid.cid_name)
1966 ast_free(tmp->chan->cid.cid_name);
1967 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1968 if (tmp->chan->cid.cid_ani)
1969 ast_free(tmp->chan->cid.cid_ani);
1970 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1972 /* Inherit specially named variables from parent channel */
1973 ast_channel_inherit_variables(qe->chan, tmp->chan);
1975 /* Presense of ADSI CPE on outgoing channel follows ours */
1976 tmp->chan->adsicpe = qe->chan->adsicpe;
1978 /* Place the call, but don't wait on the answer */
1979 if ((res = ast_call(tmp->chan, location, 0))) {
1980 /* Again, keep going even if there's an error */
1981 ast_debug(1, "ast call on peer returned %d\n", res);
1982 ast_verb(3, "Couldn't call %s\n", tmp->interface);
1986 } else if (qe->parent->eventwhencalled) {
1989 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1991 "AgentCalled: %s\r\n"
1993 "ChannelCalling: %s\r\n"
1994 "DestinationChannel: %s\r\n"
1995 "CallerIDNum: %s\r\n"
1996 "CallerIDName: %s\r\n"
2001 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
2002 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
2003 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
2004 qe->chan->context, qe->chan->exten, qe->chan->priority,
2005 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2006 ast_verb(3, "Called %s\n", tmp->interface);
2012 /*! \brief find the entry with the best metric, or NULL */
2013 static struct callattempt *find_best(struct callattempt *outgoing)
2015 struct callattempt *best = NULL, *cur;
2017 for (cur = outgoing; cur; cur = cur->q_next) {
2018 if (cur->stillgoing && /* Not already done */
2019 !cur->chan && /* Isn't already going */
2020 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
2028 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
2033 struct callattempt *best = find_best(outgoing);
2035 ast_debug(1, "Nobody left to try ringing in queue\n");
2038 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2039 struct callattempt *cur;
2040 /* Ring everyone who shares this best metric (for ringall) */
2041 for (cur = outgoing; cur; cur = cur->q_next) {
2042 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
2043 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
2044 ring_entry(qe, cur, busies);
2048 /* Ring just the best channel */
2049 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
2050 ring_entry(qe, best, busies);
2052 if (best->chan) /* break out with result = 1 */
2059 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
2061 struct callattempt *best = find_best(outgoing);
2064 /* Ring just the best channel */
2065 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2066 qe->parent->rrpos = best->metric % 1000;
2068 /* Just increment rrpos */
2069 if (qe->parent->wrapped) {
2070 /* No more channels, start over */
2071 qe->parent->rrpos = 0;
2073 /* Prioritize next entry */
2074 qe->parent->rrpos++;
2077 qe->parent->wrapped = 0;
2082 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
2084 struct callattempt *best = find_best(outgoing);
2087 /* Ring just the best channel */
2088 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2089 qe->linpos = best->metric % 1000;
2091 /* Just increment rrpos */
2092 if (qe->linwrapped) {
2093 /* No more channels, start over */
2096 /* Prioritize next entry */
2105 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
2110 /* Get the current time */
2113 /* Check to see if it is time to announce */
2114 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
2117 /* Stop the music on hold so we can play our own file */
2119 ast_indicate(qe->chan,-1);
2121 ast_moh_stop(qe->chan);
2123 ast_verb(3, "Playing periodic announcement\n");
2125 /* Check to make sure we have a sound file. If not, reset to the first sound file */
2126 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS ||
2127 !qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound] ||
2128 ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) {
2129 qe->last_periodic_announce_sound = 0;
2132 /* play the announcement */
2133 res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str);
2135 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
2138 /* Resume Music on Hold if the caller is going to stay in the queue */
2141 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2143 ast_moh_start(qe->chan, qe->moh, NULL);
2146 /* update last_periodic_announce_time */
2147 qe->last_periodic_announce_time = now;
2149 /* Update the current periodic announcement to the next announcement */
2150 qe->last_periodic_announce_sound++;
2155 static void record_abandoned(struct queue_ent *qe)
2157 ao2_lock(qe->parent);
2158 set_queue_variables(qe);
2159 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
2163 "OriginalPosition: %d\r\n"
2165 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
2167 qe->parent->callsabandoned++;
2168 ao2_unlock(qe->parent);
2171 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
2172 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
2174 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
2175 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
2176 if (qe->parent->autopause) {
2177 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
2178 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
2180 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
2186 #define AST_MAX_WATCHERS 256
2188 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
2190 const char *queue = qe->parent->name;
2191 struct callattempt *o;
2193 int sentringing = 0;
2194 int numbusies = prebusies;
2198 struct ast_frame *f;
2199 struct callattempt *peer = NULL;
2200 struct ast_channel *winner;
2201 struct ast_channel *in = qe->chan;
2203 char membername[80] = "";
2207 struct callattempt *epollo;
2210 starttime = (long) time(NULL);
2212 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2214 ast_poll_channel_add(in, epollo->chan);
2218 while (*to && !peer) {
2219 int numlines, retry, pos = 1;
2220 struct ast_channel *watchers[AST_MAX_WATCHERS];
2223 for (retry = 0; retry < 2; retry++) {
2225 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
2226 if (o->stillgoing) { /* Keep track of important channels */
2229 watchers[pos++] = o->chan;
2233 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
2234 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
2236 /* On "ringall" strategy we only move to the next penalty level
2237 when *all* ringing phones are done in the current penalty level */
2238 ring_one(qe, outgoing, &numbusies);
2241 if (pos == 1 /* not found */) {
2242 if (numlines == (numbusies + numnochan)) {
2243 ast_debug(1, "Everyone is busy at this time\n");
2245 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
2250 winner = ast_waitfor_n(watchers, pos, to);
2251 for (o = outgoing; o; o = o->q_next) {
2252 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
2254 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2257 } else if (o->chan && (o->chan == winner)) {
2259 ast_copy_string(on, o->member->interface, sizeof(on));
2260 ast_copy_string(membername, o->member->membername, sizeof(membername));
2262 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
2263 ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
2268 } else if (!ast_strlen_zero(o->chan->call_forward)) {
2273 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
2274 if ((stuff = strchr(tmpchan, '/'))) {
2278 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
2282 /* Before processing channel, go ahead and check for forwarding */
2283 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2284 /* Setup parameters */
2285 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2286 if (status != o->oldstatus)
2287 update_dial_status(qe->parent, o->member, status);
2289 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2293 ast_channel_inherit_variables(in, o->chan);
2294 if (o->chan->cid.cid_num)
2295 ast_free(o->chan->cid.cid_num);
2296 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2298 if (o->chan->cid.cid_name)
2299 ast_free(o->chan->cid.cid_name);
2300 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2302 ast_string_field_set(o->chan, accountcode, in->accountcode);
2303 o->chan->cdrflags = in->cdrflags;
2305 if (in->cid.cid_ani) {
2306 if (o->chan->cid.cid_ani)
2307 ast_free(o->chan->cid.cid_ani);
2308 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2310 if (o->chan->cid.cid_rdnis)
2311 ast_free(o->chan->cid.cid_rdnis);
2312 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2313 if (ast_call(o->chan, tmpchan, 0)) {
2314 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2319 /* Hangup the original channel now, in case we needed it */
2323 f = ast_read(winner);
2325 if (f->frametype == AST_FRAME_CONTROL) {
2326 switch (f->subclass) {
2327 case AST_CONTROL_ANSWER:
2328 /* This is our guy if someone answered. */
2330 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2334 case AST_CONTROL_BUSY:
2335 ast_verb(3, "%s is busy\n", o->chan->name);
2337 ast_cdr_busy(in->cdr);
2339 endtime = (long) time(NULL);
2340 endtime -= starttime;
2341 rna(endtime*1000, qe, on, membername);
2342 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2343 if (qe->parent->timeoutrestart)
2345 ring_one(qe, outgoing, &numbusies);
2349 case AST_CONTROL_CONGESTION:
2350 ast_verb(3, "%s is circuit-busy\n", o->chan->name);
2352 ast_cdr_busy(in->cdr);
2353 endtime = (long) time(NULL);
2354 endtime -= starttime;
2355 rna(endtime*1000, qe, on, membername);
2357 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2358 if (qe->parent->timeoutrestart)
2360 ring_one(qe, outgoing, &numbusies);
2364 case AST_CONTROL_RINGING:
2365 ast_verb(3, "%s is ringing\n", o->chan->name);
2368 ast_indicate(in, AST_CONTROL_RINGING);
2373 case AST_CONTROL_OFFHOOK:
2374 /* Ignore going off hook */
2377 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
2382 endtime = (long) time(NULL) - starttime;
2383 rna(endtime * 1000, qe, on, membername);
2385 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2386 if (qe->parent->timeoutrestart)
2388 ring_one(qe, outgoing, &numbusies);
2395 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2403 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2404 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
2409 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2410 ast_verb(3, "User pressed digit: %c\n", f->subclass);
2412 *digit = f->subclass;
2419 rna(orig, qe, on, membername);
2423 for(epollo = outgoing; epollo; epollo = epollo->q_next) {
2425 ast_poll_channel_del(in, epollo->chan);
2432 static int is_our_turn(struct queue_ent *qe)
2434 struct queue_ent *ch;
2440 if (!qe->parent->autofill) {
2441 /* Atomically read the parent head -- does not need a lock */
2442 ch = qe->parent->head;
2443 /* If we are now at the top of the head, break out */
2445 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2448 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2453 /* This needs a lock. How many members are available to be served? */
2454 ao2_lock(qe->parent);
2456 ch = qe->parent->head;
2458 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2459 ast_debug(1, "Even though there may be multiple members available, the strategy is ringall so only the head call is allowed in\n");
2462 struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
2463 while ((cur = ao2_iterator_next(&mem_iter))) {
2464 switch (cur->status) {
2465 case AST_DEVICE_NOT_INUSE:
2466 case AST_DEVICE_UNKNOWN:
2475 ast_debug(1, "There are %d available members.\n", avl);
2477 while ((idx < avl) && (ch) && (ch != qe)) {
2482 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2483 if (ch && idx < avl) {
2484 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2487 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2491 ao2_unlock(qe->parent);
2497 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2501 /* This is the holding pen for callers 2 through maxlen */
2503 enum queue_member_status stat;
2505 if (is_our_turn(qe))
2508 /* If we have timed out, break out */
2509 if (qe->expire && (time(NULL) > qe->expire)) {
2510 *reason = QUEUE_TIMEOUT;
2514 stat = get_member_status(qe->parent, qe->max_penalty);
2516 /* leave the queue if no agents, if enabled */
2517 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2518 *reason = QUEUE_LEAVEEMPTY;
2519 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2524 /* leave the queue if no reachable agents, if enabled */
2525 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
2526 *reason = QUEUE_LEAVEUNAVAIL;
2527 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2531 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2532 *reason = QUEUE_LEAVEUNAVAIL;
2533 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2538 /* Make a position announcement, if enabled */
2539 if (qe->parent->announcefrequency &&
2540 (res = say_position(qe,ringing)))
2543 /* Make a periodic announcement, if enabled */
2544 if (qe->parent->periodicannouncefrequency &&
2545 (res = say_periodic_announcement(qe,ringing)))
2548 /* Wait a second before checking again */
2549 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
2550 if (res > 0 && !valid_exit(qe, res))
2560 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
2563 struct call_queue *qtmp;
2564 struct ao2_iterator queue_iter;
2566 if (shared_lastcall) {
2567 queue_iter = ao2_iterator_init(queues, 0);
2568 while ((qtmp = ao2_iterator_next(&queue_iter))) {
2570 if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
2571 time(&mem->lastcall);
2581 time(&member->lastcall);
2583 member->lastqueue = q;
2587 q->callscompleted++;
2588 if (callcompletedinsl)
2589 q->callscompletedinsl++;
2594 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2596 if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2599 switch (q->strategy) {
2600 case QUEUE_STRATEGY_RINGALL:
2601 /* Everyone equal, except for penalty */
2602 tmp->metric = mem->penalty * 1000000;
2604 case QUEUE_STRATEGY_LINEAR:
2605 if (pos < qe->linpos) {
2606 tmp->metric = 1000 + pos;
2608 if (pos > qe->linpos)
2609 /* Indicate there is another priority */
2613 tmp->metric += mem->penalty * 1000000;
2615 case QUEUE_STRATEGY_RRMEMORY:
2616 if (pos < q->rrpos) {
2617 tmp->metric = 1000 + pos;
2620 /* Indicate there is another priority */
2624 tmp->metric += mem->penalty * 1000000;
2626 case QUEUE_STRATEGY_RANDOM:
2627 tmp->metric = ast_random() % 1000;
2628 tmp->metric += mem->penalty * 1000000;
2630 case QUEUE_STRATEGY_WRANDOM:
2631 tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
2633 case QUEUE_STRATEGY_FEWESTCALLS:
2634 tmp->metric = mem->calls;
2635 tmp->metric += mem->penalty * 1000000;
2637 case QUEUE_STRATEGY_LEASTRECENT:
2641 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2642 tmp->metric += mem->penalty * 1000000;
2645 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2651 enum agent_complete_reason {
2657 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2658 const struct ast_channel *peer, const struct member *member, time_t callstart,
2659 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2661 const char *reason = NULL; /* silence dumb compilers */
2663 if (!qe->parent->eventwhencalled)
2674 reason = "transfer";
2678 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2683 "MemberName: %s\r\n"
2688 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2689 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
2690 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
2693 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)
2696 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2698 char oldexten[AST_MAX_EXTENSION]="";
2699 char oldcontext[AST_MAX_CONTEXT]="";
2700 char queuename[256]="";
2701 char interfacevar[256]="";
2702 struct ast_channel *peer;
2703 struct ast_channel *which;
2704 struct callattempt *lpeer;
2705 struct member *member;
2706 struct ast_app *app;
2707 int res = 0, bridge = 0;
2710 char *announce = NULL;
2713 time_t now = time(NULL);
2714 struct ast_bridge_config bridge_config;
2715 char nondataquality = 1;
2716 char *agiexec = NULL;
2717 char *macroexec = NULL;
2718 char *gosubexec = NULL;
2720 const char *monitorfilename;
2721 const char *monitor_exec;
2722 const char *monitor_options;
2723 char tmpid[256], tmpid2[256];
2724 char meid[1024], meid2[1024];
2725 char mixmonargs[1512];
2726 struct ast_app *mixmonapp = NULL;
2729 int forwardsallowed = 1;
2730 int callcompletedinsl;
2731 struct ao2_iterator memi;
2733 memset(&bridge_config, 0, sizeof(bridge_config));
2738 for (; options && *options; options++)
2741 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2744 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2747 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2750 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2756 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2759 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2762 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
2765 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
2768 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR)
2771 *tries = qe->parent->membercount;
2775 forwardsallowed = 0;
2779 /* Hold the lock while we setup the outgoing calls */
2782 ao2_lock(qe->parent);
2783 ast_debug(1, "%s is trying to call a queue member.\n",
2785 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2786 if (!ast_strlen_zero(qe->announce))
2787 announce = qe->announce;
2788 if (!ast_strlen_zero(announceoverride))
2789 announce = announceoverride;
2791 memi = ao2_iterator_init(qe->parent->members, 0);
2792 while ((cur = ao2_iterator_next(&memi))) {
2793 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2797 ao2_unlock(qe->parent);
2802 tmp->stillgoing = -1;
2804 tmp->oldstatus = cur->status;
2805 tmp->lastcall = cur->lastcall;
2806 tmp->lastqueue = cur->lastqueue;
2807 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2808 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2809 just calculate their metric for the appropriate strategy */
2810 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2811 /* Put them in the list of outgoing thingies... We're ready now.
2812 XXX If we're forcibly removed, these outgoing calls won't get
2814 tmp->q_next = outgoing;
2816 /* If this line is up, don't try anybody else */
2817 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2824 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2825 to = (qe->expire - now) * 1000;
2827 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2829 ring_one(qe, outgoing, &numbusies);
2830 ao2_unlock(qe->parent);
2833 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2834 ao2_lock(qe->parent);
2835 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2836 store_next_rr(qe, outgoing);
2838 if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
2839 store_next_lin(qe, outgoing);
2841 ao2_unlock(qe->parent);
2842 peer = lpeer ? lpeer->chan : NULL;
2845 /* Must gotten hung up */
2848 /* User exited by pressing a digit */
2852 ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
2853 } else { /* peer is valid */
2854 /* Ah ha! Someone answered within the desired timeframe. Of course after this
2855 we will always return with -1 so that it is hung up properly after the
2858 if (!strcmp(qe->chan->tech->type, "Zap"))
2859 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2860 if (!strcmp(peer->tech->type, "Zap"))
2861 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2862 /* Update parameters for the queue */
2864 recalc_holdtime(qe, (now - qe->start));
2865 ao2_lock(qe->parent);
2866 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
2867 ao2_unlock(qe->parent);
2868 member = lpeer->member;
2869 /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
2871 hangupcalls(outgoing, peer);
2873 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2876 res2 = ast_autoservice_start(qe->chan);
2878 if (qe->parent->memberdelay) {
2879 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2880 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2882 if (!res2 && announce) {
2883 play_file(peer, announce);
2885 if (!res2 && qe->parent->reportholdtime) {
2886 if (!play_file(peer, qe->parent->sound_reporthold)) {
2890 holdtime = abs((now - qe->start) / 60);
2892 play_file(peer, qe->parent->sound_lessthan);
2893 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2895 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2896 play_file(peer, qe->parent->sound_minutes);
2900 res2 |= ast_autoservice_stop(qe->chan);
2901 if (ast_check_hangup(peer)) {
2902 /* Agent must have hung up */
2903 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
2904 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2905 record_abandoned(qe);
2906 if (qe->parent->eventwhencalled)
2907 manager_event(EVENT_FLAG_AGENT, "AgentDump",
2912 "MemberName: %s\r\n"
2914 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2915 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2917 ao2_ref(member, -1);
2920 /* Caller must have hung up just before being connected*/
2921 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2922 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2923 record_abandoned(qe);
2925 ao2_ref(member, -1);
2929 /* Stop music on hold */
2931 ast_indicate(qe->chan,-1);
2933 ast_moh_stop(qe->chan);
2934 /* If appropriate, log that we have a destination channel */
2936 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2937 /* Make sure channels are compatible */
2938 res = ast_channel_make_compatible(qe->chan, peer);
2940 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
2941 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2942 record_abandoned(qe);
2944 ao2_ref(member, -1);
2948 /* Play announcement to the caller telling it's his turn if defined */
2949 if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
2950 if (play_file(qe->chan, qe->parent->sound_callerannounce))
2951 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
2954 ao2_lock(qe->parent);
2955 /* if setinterfacevar is defined, make member variables available to the channel */
2956 /* use pbx_builtin_setvar to set a load of variables with one call */
2957 if (qe->parent->setinterfacevar) {
2958 snprintf(interfacevar,sizeof(interfacevar), "MEMBERINTERFACE=%s|MEMBERNAME=%s|MEMBERCALLS=%d|MEMBERLASTCALL=%ld|MEMBERPENALTY=%d|MEMBERDYNAMIC=%d|MEMBERREALTIME=%d",
2959 member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
2960 pbx_builtin_setvar(qe->chan, interfacevar);
2963 /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
2964 /* use pbx_builtin_setvar to set a load of variables with one call */
2965 if (qe->parent->setqueueentryvar) {
2966 snprintf(interfacevar,sizeof(interfacevar), "QEHOLDTIME=%ld|QEORIGINALPOS=%d",
2967 (long) time(NULL) - qe->start, qe->opos);
2968 pbx_builtin_setvar(qe->chan, interfacevar);
2971 /* try to set queue variables if configured to do so*/
2972 set_queue_variables(qe);
2973 ao2_unlock(qe->parent);
2975 /* Begin Monitoring */
2976 if (qe->parent->monfmt && *qe->parent->monfmt) {
2977 if (!qe->parent->montype) {
2978 ast_debug(1, "Starting Monitor as requested.\n");
2979 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2980 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))