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"
90 #include "asterisk/global_datastores.h"
93 QUEUE_STRATEGY_RINGALL = 0,
94 QUEUE_STRATEGY_LEASTRECENT,
95 QUEUE_STRATEGY_FEWESTCALLS,
96 QUEUE_STRATEGY_RANDOM,
97 QUEUE_STRATEGY_RRMEMORY,
98 QUEUE_STRATEGY_LINEAR,
99 QUEUE_STRATEGY_WRANDOM
102 static struct strategy {
106 { QUEUE_STRATEGY_RINGALL, "ringall" },
107 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
108 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
109 { QUEUE_STRATEGY_RANDOM, "random" },
110 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
111 { QUEUE_STRATEGY_LINEAR, "linear" },
112 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
115 #define DEFAULT_RETRY 5
116 #define DEFAULT_TIMEOUT 15
117 #define RECHECK 1 /* Recheck every second to see we we're at the top yet */
118 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
119 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /* The minimum number of seconds between position announcements
120 The default value of 15 provides backwards compatibility */
121 #define MAX_QUEUE_BUCKETS 53
123 #define RES_OKAY 0 /* Action completed */
124 #define RES_EXISTS (-1) /* Entry already exists */
125 #define RES_OUTOFMEMORY (-2) /* Out of memory */
126 #define RES_NOSUCHQUEUE (-3) /* No such queue */
127 #define RES_NOT_DYNAMIC (-4) /* Member is not dynamic */
129 static char *app = "Queue";
131 static char *synopsis = "Queue a call for a call queue";
133 static char *descrip =
134 " Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub]):\n"
135 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
136 "This application will return to the dialplan if the queue does not exist, or\n"
137 "any of the join options cause the caller to not enter the queue.\n"
138 "The option string may contain zero or more of the following characters:\n"
139 " 'c' -- continue in the dialplan if the callee hangs up.\n"
140 " 'd' -- data-quality (modem) call (minimum delay).\n"
141 " 'h' -- allow callee to hang up by pressing *.\n"
142 " 'H' -- allow caller to hang up by pressing *.\n"
143 " 'n' -- no retries on the timeout; will exit this application and \n"
144 " go to the next step.\n"
145 " 'i' -- ignore call forward requests from queue members and do nothing\n"
146 " when they are requested.\n"
147 " 'r' -- ring instead of playing MOH. Periodic Announcements are still made, if applicable.\n"
148 " 't' -- allow the called user to transfer the calling user.\n"
149 " 'T' -- allow the calling user to transfer the call.\n"
150 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
151 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
152 " 'k' -- Allow the called party to enable parking of the call by sending\n"
153 " the DTMF sequence defined for call parking in features.conf.\n"
154 " 'K' -- Allow the calling party to enable parking of the call by sending\n"
155 " the DTMF sequence defined for call parking in features.conf.\n"
156 " 'x' -- allow the called user to write the conversation to disk via MixMonitor\n"
157 " 'X' -- allow the calling user to write the conversation to disk via MixMonitor\n"
159 " In addition to transferring the call, a call may be parked and then picked\n"
160 "up by another user.\n"
161 " The optional URL will be sent to the called party if the channel supports\n"
163 " The optional AGI parameter will setup an AGI script to be executed on the \n"
164 "calling party's channel once they are connected to a queue member.\n"
165 " The optional macro parameter will run a macro on the \n"
166 "calling party's channel once they are connected to a queue member.\n"
167 " The optional gosub parameter will run a gosub on the \n"
168 "calling party's channel once they are connected to a queue member.\n"
169 " The timeout will cause the queue to fail out after a specified number of\n"
170 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
171 " This application sets the following channel variable upon completion:\n"
172 " QUEUESTATUS The status of the call as a text string, one of\n"
173 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL | CONTINUE\n";
175 static char *app_aqm = "AddQueueMember" ;
176 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
177 static char *app_aqm_descrip =
178 " AddQueueMember(queuename[,interface[,penalty[,options[,membername]]]]):\n"
179 "Dynamically adds interface to an existing queue.\n"
180 "If the interface is already in the queue it will return an error.\n"
181 " This application sets the following channel variable upon completion:\n"
182 " AQMSTATUS The status of the attempt to add a queue member as a \n"
183 " text string, one of\n"
184 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
185 "Example: AddQueueMember(techsupport,SIP/3000)\n"
188 static char *app_rqm = "RemoveQueueMember" ;
189 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
190 static char *app_rqm_descrip =
191 " RemoveQueueMember(queuename[,interface[,options]]):\n"
192 "Dynamically removes interface to an existing queue\n"
193 "If the interface is NOT in the queue it will return an error.\n"
194 " This application sets the following channel variable upon completion:\n"
195 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
196 " text string, one of\n"
197 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
198 "Example: RemoveQueueMember(techsupport,SIP/3000)\n"
201 static char *app_pqm = "PauseQueueMember" ;
202 static char *app_pqm_synopsis = "Pauses a queue member" ;
203 static char *app_pqm_descrip =
204 " PauseQueueMember([queuename],interface[,options[,reason]]):\n"
205 "Pauses (blocks calls for) a queue member.\n"
206 "The given interface will be paused in the given queue. This prevents\n"
207 "any calls from being sent from the queue to the interface until it is\n"
208 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
209 "queuename is given, the interface is paused in every queue it is a\n"
210 "member of. The application will fail if the interface is not found.\n"
211 "The reason string is entirely optional and is used to add extra information\n"
212 "to the appropriate queue_log entries and manager events.\n"
213 " This application sets the following channel variable upon completion:\n"
214 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
215 " text string, one of\n"
216 " PAUSED | NOTFOUND\n"
217 "Example: PauseQueueMember(,SIP/3000)\n";
219 static char *app_upqm = "UnpauseQueueMember" ;
220 static char *app_upqm_synopsis = "Unpauses a queue member" ;
221 static char *app_upqm_descrip =
222 " UnpauseQueueMember([queuename],interface[,options[,reason]]):\n"
223 "Unpauses (resumes calls to) a queue member.\n"
224 "This is the counterpart to PauseQueueMember and operates exactly the\n"
225 "same way, except it unpauses instead of pausing the given interface.\n"
226 "The reason string is entirely optional and is used to add extra information\n"
227 "to the appropriate queue_log entries and manager events.\n"
228 " This application sets the following channel variable upon completion:\n"
229 " UPQMSTATUS The status of the attempt to unpause a queue \n"
230 " member as a text string, one of\n"
231 " UNPAUSED | NOTFOUND\n"
232 "Example: UnpauseQueueMember(,SIP/3000)\n";
234 static char *app_ql = "QueueLog" ;
235 static char *app_ql_synopsis = "Writes to the queue_log" ;
236 static char *app_ql_descrip =
237 " QueueLog(queuename,uniqueid,agent,event[,additionalinfo]):\n"
238 "Allows you to write your own events into the queue log\n"
239 "Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)\n";
241 /*! \brief Persistent Members astdb family */
242 static const char *pm_family = "Queue/PersistentMembers";
243 /* The maximum length of each persistent member queue database entry */
244 #define PM_MAX_LEN 8192
246 /*! \brief queues.conf [general] option */
247 static int queue_keep_stats = 0;
249 /*! \brief queues.conf [general] option */
250 static int queue_persistent_members = 0;
252 /*! \brief queues.conf per-queue weight option */
253 static int use_weight = 0;
255 /*! \brief queues.conf [general] option */
256 static int autofill_default = 0;
258 /*! \brief queues.conf [general] option */
259 static int montype_default = 0;
261 /*! \brief queues.conf [general] option */
262 static int shared_lastcall = 0;
264 /*! \brief Subscription to device state change events */
265 static struct ast_event_sub *device_state_sub;
267 /*! \brief queues.conf [general] option */
268 static int update_cdr = 0;
274 QUEUE_LEAVEEMPTY = 3,
275 QUEUE_JOINUNAVAIL = 4,
276 QUEUE_LEAVEUNAVAIL = 5,
282 enum queue_result id;
284 } queue_results[] = {
285 { QUEUE_UNKNOWN, "UNKNOWN" },
286 { QUEUE_TIMEOUT, "TIMEOUT" },
287 { QUEUE_JOINEMPTY,"JOINEMPTY" },
288 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
289 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
290 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
291 { QUEUE_FULL, "FULL" },
292 { QUEUE_CONTINUE, "CONTINUE" },
295 /*! \brief We define a custom "local user" structure because we
296 use it not only for keeping track of what is in use but
297 also for keeping track of who we're dialing. */
300 struct callattempt *q_next;
301 struct ast_channel *chan;
307 struct call_queue *lastqueue;
308 struct member *member;
313 struct call_queue *parent; /*!< What queue is our parent */
314 char moh[80]; /*!< Name of musiconhold to be used */
315 char announce[80]; /*!< Announcement to play for member when call is answered */
316 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
317 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
318 int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
319 int pos; /*!< Where we are in the queue */
320 int prio; /*!< Our priority */
321 int last_pos_said; /*!< Last position we told the user */
322 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
323 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
324 time_t last_pos; /*!< Last time we told the user their position */
325 int opos; /*!< Where we started in the queue */
326 int handled; /*!< Whether our call was handled */
327 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
328 int linpos; /*!< If using linear strategy, what position are we at? */
329 int linwrapped; /*!< Is the linpos wrapped? */
330 time_t start; /*!< When we started holding */
331 time_t expire; /*!< When this entry should expire (time out of queue) */
332 struct ast_channel *chan; /*!< Our channel */
333 struct queue_ent *next; /*!< The next queue entry */
337 char interface[80]; /*!< Technology/Location */
338 char membername[80]; /*!< Member name to use in queue logs */
339 int penalty; /*!< Are we a last resort? */
340 int calls; /*!< Number of calls serviced by this member */
341 int dynamic; /*!< Are we dynamically added? */
342 int realtime; /*!< Is this member realtime? */
343 int status; /*!< Status of queue member */
344 int paused; /*!< Are we paused (not accepting calls)? */
345 time_t lastcall; /*!< When last successful call was hungup */
346 struct call_queue *lastqueue; /*!< Last queue we received a call */
347 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
348 unsigned int delme:1; /*!< Flag to delete entry on reload */
351 struct member_interface {
353 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
356 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
358 /* values used in multi-bit flags in call_queue */
359 #define QUEUE_EMPTY_NORMAL 1
360 #define QUEUE_EMPTY_STRICT 2
361 #define QUEUE_EMPTY_LOOSE 3
362 #define ANNOUNCEHOLDTIME_ALWAYS 1
363 #define ANNOUNCEHOLDTIME_ONCE 2
364 #define QUEUE_EVENT_VARIABLES 3
367 AST_DECLARE_STRING_FIELDS(
369 AST_STRING_FIELD(name);
370 /*! Music on Hold class */
371 AST_STRING_FIELD(moh);
372 /*! Announcement to play when call is answered */
373 AST_STRING_FIELD(announce);
375 AST_STRING_FIELD(context);
376 /*! Macro to run upon member connection */
377 AST_STRING_FIELD(membermacro);
378 /*! Gosub to run upon member connection */
379 AST_STRING_FIELD(membergosub);
380 /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
381 AST_STRING_FIELD(sound_next);
382 /*! Sound file: "There are currently" (def. queue-thereare) */
383 AST_STRING_FIELD(sound_thereare);
384 /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
385 AST_STRING_FIELD(sound_calls);
386 /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
387 AST_STRING_FIELD(sound_holdtime);
388 /*! Sound file: "minutes." (def. queue-minutes) */
389 AST_STRING_FIELD(sound_minutes);
390 /*! Sound file: "less-than" (def. queue-lessthan) */
391 AST_STRING_FIELD(sound_lessthan);
392 /*! Sound file: "seconds." (def. queue-seconds) */
393 AST_STRING_FIELD(sound_seconds);
394 /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
395 AST_STRING_FIELD(sound_thanks);
396 /*! Sound file: Custom announce for caller, no default */
397 AST_STRING_FIELD(sound_callerannounce);
398 /*! Sound file: "Hold time" (def. queue-reporthold) */
399 AST_STRING_FIELD(sound_reporthold);
401 /*! Sound files: Custom announce, no default */
402 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
404 unsigned int joinempty:2;
405 unsigned int eventwhencalled:2;
406 unsigned int leavewhenempty:2;
407 unsigned int ringinuse:1;
408 unsigned int setinterfacevar:1;
409 unsigned int setqueuevar:1;
410 unsigned int setqueueentryvar:1;
411 unsigned int reportholdtime:1;
412 unsigned int wrapped:1;
413 unsigned int timeoutrestart:1;
414 unsigned int announceholdtime:2;
415 unsigned int announceposition:1;
417 unsigned int maskmemberstatus:1;
418 unsigned int realtime:1;
419 unsigned int found:1;
420 int announcefrequency; /*!< How often to announce their position */
421 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
422 int periodicannouncefrequency; /*!< How often to play periodic announcement */
423 int roundingseconds; /*!< How many seconds do we round to? */
424 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
425 int callscompleted; /*!< Number of queue calls completed */
426 int callsabandoned; /*!< Number of queue calls abandoned */
427 int servicelevel; /*!< seconds setting for servicelevel*/
428 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
429 char monfmt[8]; /*!< Format to use when recording calls */
430 int montype; /*!< Monitor type Monitor vs. MixMonitor */
431 int count; /*!< How many entries */
432 int maxlen; /*!< Max number of entries */
433 int wrapuptime; /*!< Wrapup Time */
435 int retry; /*!< Retry calling everyone after this amount of time */
436 int timeout; /*!< How long to wait for an answer */
437 int weight; /*!< Respective weight */
438 int autopause; /*!< Auto pause queue members if they fail to answer */
440 /* Queue strategy things */
441 int rrpos; /*!< Round Robin - position */
442 int memberdelay; /*!< Seconds to delay connecting member to caller */
443 int autofill; /*!< Ignore the head call status and ring an available agent */
445 struct ao2_container *members; /*!< Head of the list of members */
447 * \brief Number of members _logged in_
448 * \note There will be members in the members container that are not logged
449 * in, so this can not simply be replaced with ao2_container_count().
452 struct queue_ent *head; /*!< Head of the list of callers */
453 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
456 static struct ao2_container *queues;
458 static void update_realtime_members(struct call_queue *q);
459 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
461 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
465 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
466 if (queue_results[i].id == res) {
467 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
473 static char *int2strat(int strategy)
477 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
478 if (strategy == strategies[x].strategy)
479 return strategies[x].name;
485 static int strat2int(const char *strategy)
489 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
490 if (!strcasecmp(strategy, strategies[x].name))
491 return strategies[x].strategy;
497 static int queue_hash_cb(const void *obj, const int flags)
499 const struct call_queue *q = obj;
500 return ast_str_hash(q->name);
503 static int queue_cmp_cb(void *obj, void *arg, int flags)
505 struct call_queue *q = obj, *q2 = arg;
506 return !strcasecmp(q->name, q2->name) ? CMP_MATCH : 0;
509 static inline struct call_queue *queue_ref(struct call_queue *q)
515 static inline struct call_queue *queue_unref(struct call_queue *q)
521 static void set_queue_variables(struct queue_ent *qe)
524 char interfacevar[256]="";
527 if (qe->parent->setqueuevar) {
529 if (qe->parent->callscompleted > 0)
530 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
532 snprintf(interfacevar,sizeof(interfacevar),
533 "QUEUEMAX=%d|QUEUESTRATEGY=%s|QUEUECALLS=%d|QUEUEHOLDTIME=%d|QUEUECOMPLETED=%d|QUEUEABANDONED=%d|QUEUESRVLEVEL=%d|QUEUESRVLEVELPERF=%2.1f",
534 qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
535 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
537 pbx_builtin_setvar(qe->chan, interfacevar);
541 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
542 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
544 struct queue_ent *cur;
561 enum queue_member_status {
563 QUEUE_NO_REACHABLE_MEMBERS,
564 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
568 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty)
570 struct member *member;
571 struct ao2_iterator mem_iter;
572 enum queue_member_status result = QUEUE_NO_MEMBERS;
575 mem_iter = ao2_iterator_init(q->members, 0);
576 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
577 if (max_penalty && (member->penalty > max_penalty))
580 switch (member->status) {
581 case AST_DEVICE_INVALID:
584 case AST_DEVICE_UNAVAILABLE:
585 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
586 result = QUEUE_NO_REACHABLE_MEMBERS;
589 if (member->paused) {
590 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
605 AST_LIST_ENTRY(statechange) entry;
610 static void *handle_statechange(struct statechange *sc)
612 struct call_queue *q;
614 struct ao2_iterator mem_iter;
615 struct member_interface *curint;
616 struct ao2_iterator queue_iter;
620 technology = ast_strdupa(sc->dev);
621 loc = strchr(technology, '/');
628 AST_LIST_LOCK(&interfaces);
629 AST_LIST_TRAVERSE(&interfaces, curint, list) {
632 interface = ast_strdupa(curint->interface);
633 if ((slash_pos = strchr(interface, '/')))
634 if ((slash_pos = strchr(slash_pos + 1, '/')))
637 if (!strcasecmp(interface, sc->dev))
640 AST_LIST_UNLOCK(&interfaces);
643 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));
647 ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
648 queue_iter = ao2_iterator_init(queues, 0);
649 while ((q = ao2_iterator_next(&queue_iter))) {
651 mem_iter = ao2_iterator_init(q->members, 0);
652 while ((cur = ao2_iterator_next(&mem_iter))) {
655 interface = ast_strdupa(cur->interface);
656 if ((slash_pos = strchr(interface, '/')))
657 if ((slash_pos = strchr(slash_pos + 1, '/')))
660 if (strcasecmp(sc->dev, interface)) {
665 if (cur->status != sc->state) {
666 cur->status = sc->state;
667 if (q->maskmemberstatus) {
672 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
682 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime" : "static",
683 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
695 * \brief Data used by the device state thread
698 /*! Set to 1 to stop the thread */
700 /*! The device state monitoring thread */
702 /*! Lock for the state change queue */
704 /*! Condition for the state change queue */
706 /*! Queue of state changes */
707 AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
709 .thread = AST_PTHREADT_NULL,
712 static void *device_state_thread(void *data)
714 struct statechange *sc = NULL;
716 while (!device_state.stop) {
717 ast_mutex_lock(&device_state.lock);
718 if (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
719 ast_cond_wait(&device_state.cond, &device_state.lock);
720 sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry);
722 ast_mutex_unlock(&device_state.lock);
724 /* Check to see if we were woken up to see the request to stop */
725 if (device_state.stop)
731 handle_statechange(sc);
740 while ((sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry)))
746 static int statechange_queue(const char *dev, enum ast_device_state state)
748 struct statechange *sc;
750 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
754 strcpy(sc->dev, dev);
756 ast_mutex_lock(&device_state.lock);
757 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
758 ast_cond_signal(&device_state.cond);
759 ast_mutex_unlock(&device_state.lock);
764 static void device_state_cb(const struct ast_event *event, void *unused)
766 enum ast_device_state state;
769 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
770 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
772 if (ast_strlen_zero(device)) {
773 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
777 statechange_queue(device, state);
780 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
784 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
785 cur->penalty = penalty;
786 cur->paused = paused;
787 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
788 if(!ast_strlen_zero(membername))
789 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
791 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
792 if (!strchr(cur->interface, '/'))
793 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
794 cur->status = ast_device_state(interface);
801 static int compress_char(const char c)
811 static int member_hash_fn(const void *obj, const int flags)
813 const struct member *mem = obj;
814 const char *chname = strchr(mem->interface, '/');
817 chname = mem->interface;
818 for (i = 0; i < 5 && chname[i]; i++)
819 ret += compress_char(chname[i]) << (i * 6);
823 static int member_cmp_fn(void *obj1, void *obj2, int flags)
825 struct member *mem1 = obj1, *mem2 = obj2;
826 return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
829 static void init_queue(struct call_queue *q)
834 q->retry = DEFAULT_RETRY;
837 q->announcefrequency = 0;
838 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
839 q->announceholdtime = 0;
840 q->announceholdtime = 1;
841 q->roundingseconds = 0; /* Default - don't announce seconds */
844 q->setinterfacevar = 0;
846 q->setqueueentryvar = 0;
847 q->autofill = autofill_default;
848 q->montype = montype_default;
850 q->periodicannouncefrequency = 0;
852 if(q->strategy == QUEUE_STRATEGY_LINEAR)
853 /* linear strategy depends on order, so we have to place all members in a single bucket */
854 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
856 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
861 ast_string_field_set(q, sound_next, "queue-youarenext");
862 ast_string_field_set(q, sound_thereare, "queue-thereare");
863 ast_string_field_set(q, sound_calls, "queue-callswaiting");
864 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
865 ast_string_field_set(q, sound_minutes, "queue-minutes");
866 ast_string_field_set(q, sound_seconds, "queue-seconds");
867 ast_string_field_set(q, sound_thanks, "queue-thankyou");
868 ast_string_field_set(q, sound_lessthan, "queue-less-than");
869 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
871 if ((q->sound_periodicannounce[0] = ast_str_create(32)))
872 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
874 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
875 if (q->sound_periodicannounce[i])
876 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
880 static void clear_queue(struct call_queue *q)
883 q->callscompleted = 0;
884 q->callsabandoned = 0;
885 q->callscompletedinsl = 0;
889 static int add_to_interfaces(const char *interface)
891 struct member_interface *curint;
893 AST_LIST_LOCK(&interfaces);
894 AST_LIST_TRAVERSE(&interfaces, curint, list) {
895 if (!strcasecmp(curint->interface, interface))
900 AST_LIST_UNLOCK(&interfaces);
904 ast_debug(1, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
906 if ((curint = ast_calloc(1, sizeof(*curint)))) {
907 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
908 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
910 AST_LIST_UNLOCK(&interfaces);
915 static int interface_exists_global(const char *interface)
917 struct call_queue *q;
918 struct member *mem, tmpmem;
919 struct ao2_iterator queue_iter;
922 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
923 queue_iter = ao2_iterator_init(queues, 0);
924 while ((q = ao2_iterator_next(&queue_iter))) {
927 if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
941 static int remove_from_interfaces(const char *interface)
943 struct member_interface *curint;
945 AST_LIST_LOCK(&interfaces);
946 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
947 if (!strcasecmp(curint->interface, interface)) {
948 if (!interface_exists_global(interface)) {
949 ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
950 AST_LIST_REMOVE_CURRENT(list);
956 AST_LIST_TRAVERSE_SAFE_END;
957 AST_LIST_UNLOCK(&interfaces);
962 static void clear_and_free_interfaces(void)
964 struct member_interface *curint;
966 AST_LIST_LOCK(&interfaces);
967 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
969 AST_LIST_UNLOCK(&interfaces);
972 /*! \brief Configure a queue parameter.
974 For error reporting, line number is passed for .conf static configuration.
975 For Realtime queues, linenum is -1.
976 The failunknown flag is set for config files (and static realtime) to show
977 errors for unknown parameters. It is cleared for dynamic realtime to allow
978 extra fields in the tables. */
979 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
981 if (!strcasecmp(param, "musicclass") ||
982 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
983 ast_string_field_set(q, moh, val);
984 } else if (!strcasecmp(param, "announce")) {
985 ast_string_field_set(q, announce, val);
986 } else if (!strcasecmp(param, "context")) {
987 ast_string_field_set(q, context, val);
988 } else if (!strcasecmp(param, "timeout")) {
989 q->timeout = atoi(val);
991 q->timeout = DEFAULT_TIMEOUT;
992 } else if (!strcasecmp(param, "ringinuse")) {
993 q->ringinuse = ast_true(val);
994 } else if (!strcasecmp(param, "setinterfacevar")) {
995 q->setinterfacevar = ast_true(val);
996 } else if (!strcasecmp(param, "setqueuevar")) {
997 q->setqueuevar = ast_true(val);
998 } else if (!strcasecmp(param, "setqueueentryvar")) {
999 q->setqueueentryvar = ast_true(val);
1000 } else if (!strcasecmp(param, "monitor-format")) {
1001 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
1002 } else if (!strcasecmp(param, "membermacro")) {
1003 ast_string_field_set(q, membermacro, val);
1004 } else if (!strcasecmp(param, "membergosub")) {
1005 ast_string_field_set(q, membergosub, val);
1006 } else if (!strcasecmp(param, "queue-youarenext")) {
1007 ast_string_field_set(q, sound_next, val);
1008 } else if (!strcasecmp(param, "queue-thereare")) {
1009 ast_string_field_set(q, sound_thereare, val);
1010 } else if (!strcasecmp(param, "queue-callswaiting")) {
1011 ast_string_field_set(q, sound_calls, val);
1012 } else if (!strcasecmp(param, "queue-holdtime")) {
1013 ast_string_field_set(q, sound_holdtime, val);
1014 } else if (!strcasecmp(param, "queue-minutes")) {
1015 ast_string_field_set(q, sound_minutes, val);
1016 } else if (!strcasecmp(param, "queue-seconds")) {
1017 ast_string_field_set(q, sound_seconds, val);
1018 } else if (!strcasecmp(param, "queue-lessthan")) {
1019 ast_string_field_set(q, sound_lessthan, val);
1020 } else if (!strcasecmp(param, "queue-thankyou")) {
1021 ast_string_field_set(q, sound_thanks, val);
1022 } else if (!strcasecmp(param, "queue-callerannounce")) {
1023 ast_string_field_set(q, sound_callerannounce, val);
1024 } else if (!strcasecmp(param, "queue-reporthold")) {
1025 ast_string_field_set(q, sound_reporthold, val);
1026 } else if (!strcasecmp(param, "announce-frequency")) {
1027 q->announcefrequency = atoi(val);
1028 } else if (!strcasecmp(param, "min-announce-frequency")) {
1029 q->minannouncefrequency = atoi(val);
1030 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
1031 } else if (!strcasecmp(param, "announce-round-seconds")) {
1032 q->roundingseconds = atoi(val);
1033 /* Rounding to any other values just doesn't make sense... */
1034 if (!(q->roundingseconds == 0 || q->roundingseconds == 1 || q->roundingseconds == 5 || q->roundingseconds == 10
1035 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
1037 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1038 "using 0 instead for queue '%s' at line %d of queues.conf\n",
1039 val, param, q->name, linenum);
1041 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
1042 "using 0 instead for queue '%s'\n", val, param, q->name);
1044 q->roundingseconds=0;
1046 } else if (!strcasecmp(param, "announce-holdtime")) {
1047 if (!strcasecmp(val, "once"))
1048 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1049 else if (ast_true(val))
1050 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1052 q->announceholdtime = 0;
1053 } else if (!strcasecmp(param, "announce-position")) {
1054 q->announceposition = ast_true(val);
1055 } else if (!strcasecmp(param, "periodic-announce")) {
1056 if (strchr(val, ',')) {
1057 char *s, *buf = ast_strdupa(val);
1060 while ((s = strsep(&buf, ",|"))) {
1061 if (!q->sound_periodicannounce[i])
1062 q->sound_periodicannounce[i] = ast_str_create(16);
1063 ast_str_set(&q->sound_periodicannounce[i], 0, s);
1065 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
1069 ast_str_set(&q->sound_periodicannounce[0], 0, val);
1071 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
1072 q->periodicannouncefrequency = atoi(val);
1073 } else if (!strcasecmp(param, "retry")) {
1074 q->retry = atoi(val);
1076 q->retry = DEFAULT_RETRY;
1077 } else if (!strcasecmp(param, "wrapuptime")) {
1078 q->wrapuptime = atoi(val);
1079 } else if (!strcasecmp(param, "autofill")) {
1080 q->autofill = ast_true(val);
1081 } else if (!strcasecmp(param, "monitor-type")) {
1082 if (!strcasecmp(val, "mixmonitor"))
1084 } else if (!strcasecmp(param, "autopause")) {
1085 q->autopause = ast_true(val);
1086 } else if (!strcasecmp(param, "maxlen")) {
1087 q->maxlen = atoi(val);
1090 } else if (!strcasecmp(param, "servicelevel")) {
1091 q->servicelevel= atoi(val);
1092 } else if (!strcasecmp(param, "strategy")) {
1093 /* We already have set this, no need to do it again */
1095 } else if (!strcasecmp(param, "joinempty")) {
1096 if (!strcasecmp(val, "loose"))
1097 q->joinempty = QUEUE_EMPTY_LOOSE;
1098 else if (!strcasecmp(val, "strict"))
1099 q->joinempty = QUEUE_EMPTY_STRICT;
1100 else if (ast_true(val))
1101 q->joinempty = QUEUE_EMPTY_NORMAL;
1104 } else if (!strcasecmp(param, "leavewhenempty")) {
1105 if (!strcasecmp(val, "loose"))
1106 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
1107 else if (!strcasecmp(val, "strict"))
1108 q->leavewhenempty = QUEUE_EMPTY_STRICT;
1109 else if (ast_true(val))
1110 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
1112 q->leavewhenempty = 0;
1113 } else if (!strcasecmp(param, "eventmemberstatus")) {
1114 q->maskmemberstatus = !ast_true(val);
1115 } else if (!strcasecmp(param, "eventwhencalled")) {
1116 if (!strcasecmp(val, "vars")) {
1117 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
1119 q->eventwhencalled = ast_true(val) ? 1 : 0;
1121 } else if (!strcasecmp(param, "reportholdtime")) {
1122 q->reportholdtime = ast_true(val);
1123 } else if (!strcasecmp(param, "memberdelay")) {
1124 q->memberdelay = atoi(val);
1125 } else if (!strcasecmp(param, "weight")) {
1126 q->weight = atoi(val);
1129 /* With Realtime queues, if the last queue using weights is deleted in realtime,
1130 we will not see any effect on use_weight until next reload. */
1131 } else if (!strcasecmp(param, "timeoutrestart")) {
1132 q->timeoutrestart = ast_true(val);
1133 } else if (failunknown) {
1135 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
1136 q->name, param, linenum);
1138 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
1143 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
1145 struct member *m, tmpmem;
1150 penalty = atoi(penalty_str);
1156 paused = atoi(paused_str);
1161 /* Find the member, or the place to put a new one. */
1162 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
1163 m = ao2_find(q->members, &tmpmem, OBJ_POINTER);
1165 /* Create a new one if not found, else update penalty */
1167 if ((m = create_queue_member(interface, membername, penalty, paused))) {
1170 add_to_interfaces(interface);
1171 ao2_link(q->members, m);
1177 m->dead = 0; /* Do not delete this one. */
1180 m->penalty = penalty;
1185 static void free_members(struct call_queue *q, int all)
1187 /* Free non-dynamic members */
1189 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1191 while ((cur = ao2_iterator_next(&mem_iter))) {
1192 if (all || !cur->dynamic) {
1193 ao2_unlink(q->members, cur);
1194 remove_from_interfaces(cur->interface);
1201 static void destroy_queue(void *obj)
1203 struct call_queue *q = obj;
1206 ast_debug(0, "Queue destructor called for queue '%s'!\n", q->name);
1209 ast_string_field_free_memory(q);
1210 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1211 if (q->sound_periodicannounce[i])
1212 free(q->sound_periodicannounce[i]);
1214 ao2_ref(q->members, -1);
1217 static struct call_queue *alloc_queue(const char *queuename)
1219 struct call_queue *q;
1221 if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
1222 if (ast_string_field_init(q, 64)) {
1226 ast_string_field_set(q, name, queuename);
1231 /*!\brief Reload a single queue via realtime.
1232 \return Return the queue, or NULL if it doesn't exist.
1233 \note Should be called with the global qlock locked. */
1234 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1236 struct ast_variable *v;
1237 struct call_queue *q, tmpq = {
1241 struct ao2_iterator mem_iter;
1242 char *interface = NULL;
1243 const char *tmp_name;
1245 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1247 /* Static queues override realtime. */
1248 if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
1256 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
1262 } else if (!member_config)
1263 /* Not found in the list, and it's not realtime ... */
1266 /* Check if queue is defined in realtime. */
1268 /* Delete queue from in-core list if it has been deleted in realtime. */
1270 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1271 found condition... So we might delete an in-core queue
1272 in case of DB failure. */
1273 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
1276 /* Delete if unused (else will be deleted when last caller leaves). */
1277 ao2_unlink(queues, q);
1284 /* Create a new queue if an in-core entry does not exist yet. */
1286 if (!(q = alloc_queue(queuename)))
1291 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1292 ao2_link(queues, q);
1295 memset(tmpbuf, 0, sizeof(tmpbuf));
1296 for (v = queue_vars; v; v = v->next) {
1297 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1298 if ((tmp = strchr(v->name, '_'))) {
1299 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1302 while ((tmp = strchr(tmp, '_')))
1306 queue_set_param(q, tmp_name, v->value, -1, 0);
1309 /* Temporarily set realtime members dead so we can detect deleted ones.
1310 * Also set the membercount correctly for realtime*/
1311 mem_iter = ao2_iterator_init(q->members, 0);
1312 while ((m = ao2_iterator_next(&mem_iter))) {
1319 while ((interface = ast_category_browse(member_config, interface))) {
1320 rt_handle_member_record(q, interface,
1321 ast_variable_retrieve(member_config, interface, "membername"),
1322 ast_variable_retrieve(member_config, interface, "penalty"),
1323 ast_variable_retrieve(member_config, interface, "paused"));
1326 /* Delete all realtime members that have been deleted in DB. */
1327 mem_iter = ao2_iterator_init(q->members, 0);
1328 while ((m = ao2_iterator_next(&mem_iter))) {
1330 ao2_unlink(q->members, m);
1332 remove_from_interfaces(m->interface);
1344 static struct call_queue *load_realtime_queue(const char *queuename)
1346 struct ast_variable *queue_vars;
1347 struct ast_config *member_config = NULL;
1348 struct call_queue *q = NULL, tmpq = {
1352 /* Find the queue in the in-core list first. */
1353 q = ao2_find(queues, &tmpq, OBJ_POINTER);
1355 if (!q || q->realtime) {
1356 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1357 queue operations while waiting for the DB.
1359 This will be two separate database transactions, so we might
1360 see queue parameters as they were before another process
1361 changed the queue and member list as it was after the change.
1362 Thus we might see an empty member list when a queue is
1363 deleted. In practise, this is unlikely to cause a problem. */
1365 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1367 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1368 if (!member_config) {
1369 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1370 ast_variables_destroy(queue_vars);
1376 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1378 ast_config_destroy(member_config);
1380 ast_variables_destroy(queue_vars);
1384 update_realtime_members(q);
1389 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
1391 struct ast_variable *var;
1394 if(!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL)))
1397 if(!strcmp(var->name, "uniqueid"))
1401 if(var && !ast_strlen_zero(var->value)) {
1402 if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1)
1408 static void update_realtime_members(struct call_queue *q)
1410 struct ast_config *member_config = NULL;
1412 char *interface = NULL;
1413 struct ao2_iterator mem_iter;
1415 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , NULL);
1416 if (!member_config) {
1417 /*This queue doesn't have realtime members*/
1418 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
1424 /* Temporarily set realtime members dead so we can detect deleted ones.*/
1425 mem_iter = ao2_iterator_init(q->members, 0);
1426 while ((m = ao2_iterator_next(&mem_iter))) {
1432 while ((interface = ast_category_browse(member_config, interface))) {
1433 rt_handle_member_record(q, interface,
1434 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1435 ast_variable_retrieve(member_config, interface, "penalty"),
1436 ast_variable_retrieve(member_config, interface, "paused"));
1439 /* Delete all realtime members that have been deleted in DB. */
1440 mem_iter = ao2_iterator_init(q->members, 0);
1441 while ((m = ao2_iterator_next(&mem_iter))) {
1443 ao2_unlink(q->members, m);
1445 remove_from_interfaces(m->interface);
1454 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1456 struct call_queue *q;
1457 struct queue_ent *cur, *prev = NULL;
1461 enum queue_member_status stat;
1463 if (!(q = load_realtime_queue(queuename)))
1469 /* This is our one */
1470 stat = get_member_status(q, qe->max_penalty);
1471 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1472 *reason = QUEUE_JOINEMPTY;
1473 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1474 *reason = QUEUE_JOINUNAVAIL;
1475 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1476 *reason = QUEUE_JOINUNAVAIL;
1477 else if (q->maxlen && (q->count >= q->maxlen))
1478 *reason = QUEUE_FULL;
1480 /* There's space for us, put us at the right position inside
1482 * Take into account the priority of the calling user */
1487 /* We have higher priority than the current user, enter
1488 * before him, after all the other users with priority
1489 * higher or equal to our priority. */
1490 if ((!inserted) && (qe->prio > cur->prio)) {
1491 insert_entry(q, prev, qe, &pos);
1498 /* No luck, join at the end of the queue */
1500 insert_entry(q, prev, qe, &pos);
1501 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1502 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1503 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1506 manager_event(EVENT_FLAG_CALL, "Join",
1507 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1509 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1510 S_OR(qe->chan->cid.cid_name, "unknown"),
1511 q->name, qe->pos, q->count, qe->chan->uniqueid );
1512 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1520 static int play_file(struct ast_channel *chan, const char *filename)
1524 ast_stopstream(chan);
1526 res = ast_streamfile(chan, filename, chan->language);
1528 res = ast_waitstream(chan, AST_DIGIT_ANY);
1530 ast_stopstream(chan);
1535 static int valid_exit(struct queue_ent *qe, char digit)
1537 int digitlen = strlen(qe->digits);
1539 /* Prevent possible buffer overflow */
1540 if (digitlen < sizeof(qe->digits) - 2) {
1541 qe->digits[digitlen] = digit;
1542 qe->digits[digitlen + 1] = '\0';
1544 qe->digits[0] = '\0';
1548 /* If there's no context to goto, short-circuit */
1549 if (ast_strlen_zero(qe->context))
1552 /* If the extension is bad, then reset the digits to blank */
1553 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1554 qe->digits[0] = '\0';
1558 /* We have an exact match */
1559 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1560 qe->valid_digits = 1;
1561 /* Return 1 on a successful goto */
1568 static int say_position(struct queue_ent *qe, int ringing)
1570 int res = 0, avgholdmins, avgholdsecs;
1573 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1575 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1578 /* If either our position has changed, or we are over the freq timer, say position */
1579 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1583 ast_indicate(qe->chan,-1);
1585 ast_moh_stop(qe->chan);
1587 if (qe->parent->announceposition) {
1588 /* Say we're next, if we are */
1590 res = play_file(qe->chan, qe->parent->sound_next);
1596 res = play_file(qe->chan, qe->parent->sound_thereare);
1599 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1602 res = play_file(qe->chan, qe->parent->sound_calls);
1607 /* Round hold time to nearest minute */
1608 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1610 /* If they have specified a rounding then round the seconds as well */
1611 if (qe->parent->roundingseconds) {
1612 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1613 avgholdsecs *= qe->parent->roundingseconds;
1618 ast_verb(3, "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1620 /* If the hold time is >1 min, if it's enabled, and if it's not
1621 supposed to be only once and we have already said it, say it */
1622 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1623 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1624 res = play_file(qe->chan, qe->parent->sound_holdtime);
1628 if (avgholdmins > 0) {
1629 if (avgholdmins < 2) {
1630 res = play_file(qe->chan, qe->parent->sound_lessthan);
1634 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1638 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1643 res = play_file(qe->chan, qe->parent->sound_minutes);
1647 if (avgholdsecs>0) {
1648 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1652 res = play_file(qe->chan, qe->parent->sound_seconds);
1660 if (qe->parent->announceposition) {
1661 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
1662 qe->chan->name, qe->parent->name, qe->pos);
1664 res = play_file(qe->chan, qe->parent->sound_thanks);
1667 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
1670 /* Set our last_pos indicators */
1672 qe->last_pos_said = qe->pos;
1674 /* Don't restart music on hold if we're about to exit the caller from the queue */
1677 ast_indicate(qe->chan, AST_CONTROL_RINGING);
1679 ast_moh_start(qe->chan, qe->moh, NULL);
1684 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
1688 /* Calculate holdtime using a recursive boxcar filter */
1689 /* Thanks to SRT for this contribution */
1690 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1692 ao2_lock(qe->parent);
1693 oldvalue = qe->parent->holdtime;
1694 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
1695 ao2_unlock(qe->parent);
1699 static void leave_queue(struct queue_ent *qe)
1701 struct call_queue *q;
1702 struct queue_ent *cur, *prev = NULL;
1705 if (!(q = qe->parent))
1711 for (cur = q->head; cur; cur = cur->next) {
1715 /* Take us out of the queue */
1716 manager_event(EVENT_FLAG_CALL, "Leave",
1717 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1718 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1719 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1720 /* Take us out of the queue */
1722 prev->next = cur->next;
1724 q->head = cur->next;
1726 /* Renumber the people after us in the queue based on a new count */
1733 /*If the queue is a realtime queue, check to see if it's still defined in real time*/
1735 if(!ast_load_realtime("queues", "name", q->name, NULL))
1740 /* It's dead and nobody is in it, so kill it */
1741 ao2_unlink(queues, q);
1747 /* Hang up a list of outgoing calls */
1748 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1750 struct callattempt *oo;
1753 /* Hangup any existing lines we have open */
1754 if (outgoing->chan && (outgoing->chan != exception))
1755 ast_hangup(outgoing->chan);
1757 outgoing = outgoing->q_next;
1759 ao2_ref(oo->member, -1);
1764 static int update_status(struct call_queue *q, struct member *member, int status)
1767 struct ao2_iterator mem_iter;
1769 /* Since a reload could have taken place, we have to traverse the list to
1770 be sure it's still valid */
1772 mem_iter = ao2_iterator_init(q->members, 0);
1773 while ((cur = ao2_iterator_next(&mem_iter))) {
1774 if (member != cur) {
1779 cur->status = status;
1780 if (!q->maskmemberstatus) {
1781 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1784 "MemberName: %s\r\n"
1785 "Membership: %s\r\n"
1787 "CallsTaken: %d\r\n"
1791 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
1792 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1800 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1802 if (status == AST_CAUSE_BUSY)
1803 status = AST_DEVICE_BUSY;
1804 else if (status == AST_CAUSE_UNREGISTERED)
1805 status = AST_DEVICE_UNAVAILABLE;
1806 else if (status == AST_CAUSE_NOSUCHDRIVER)
1807 status = AST_DEVICE_INVALID;
1809 status = AST_DEVICE_UNKNOWN;
1810 return update_status(q, member, status);
1813 /* traverse all defined queues which have calls waiting and contain this member
1814 return 0 if no other queue has precedence (higher weight) or 1 if found */
1815 static int compare_weight(struct call_queue *rq, struct member *member)
1817 struct call_queue *q;
1820 struct ao2_iterator queue_iter;
1822 /* &qlock and &rq->lock already set by try_calling()
1823 * to solve deadlock */
1824 queue_iter = ao2_iterator_init(queues, 0);
1825 while ((q = ao2_iterator_next(&queue_iter))) {
1826 if (q == rq) { /* don't check myself, could deadlock */
1831 if (q->count && q->members) {
1832 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
1833 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1834 if (q->weight > rq->weight) {
1835 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);
1851 /*! \brief common hangup actions */
1852 static void do_hang(struct callattempt *o)
1855 ast_hangup(o->chan);
1859 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1861 struct ast_str *buf = ast_str_alloca(len + 1);
1864 if (pbx_builtin_serialize_variables(chan, &buf)) {
1867 /* convert "\n" to "\nVariable: " */
1868 strcpy(vars, "Variable: ");
1871 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1874 if (tmp[i + 1] == '\0')
1876 if (tmp[i] == '\n') {
1880 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1890 /* there are no channel variables; leave it blank */
1896 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1903 /* on entry here, we know that tmp->chan == NULL */
1904 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
1905 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
1906 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
1907 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
1909 ast_cdr_busy(qe->chan->cdr);
1910 tmp->stillgoing = 0;
1915 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1916 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
1918 ast_cdr_busy(qe->chan->cdr);
1919 tmp->stillgoing = 0;
1923 if (tmp->member->paused) {
1924 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
1926 ast_cdr_busy(qe->chan->cdr);
1927 tmp->stillgoing = 0;
1930 if (use_weight && compare_weight(qe->parent,tmp->member)) {
1931 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1933 ast_cdr_busy(qe->chan->cdr);
1934 tmp->stillgoing = 0;
1939 ast_copy_string(tech, tmp->interface, sizeof(tech));
1940 if ((location = strchr(tech, '/')))
1945 /* Request the peer */
1946 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1947 if (!tmp->chan) { /* If we can't, just go on to the next call */
1949 ast_cdr_busy(qe->chan->cdr);
1950 tmp->stillgoing = 0;
1951 update_dial_status(qe->parent, tmp->member, status);
1953 ao2_lock(qe->parent);
1954 qe->parent->rrpos++;
1956 ao2_unlock(qe->parent);
1961 } else if (status != tmp->oldstatus)
1962 update_dial_status(qe->parent, tmp->member, status);
1964 tmp->chan->appl = "AppQueue";
1965 tmp->chan->data = "(Outgoing Line)";
1966 tmp->chan->whentohangup = 0;
1967 if (tmp->chan->cid.cid_num)
1968 ast_free(tmp->chan->cid.cid_num);
1969 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1970 if (tmp->chan->cid.cid_name)
1971 ast_free(tmp->chan->cid.cid_name);
1972 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1973 if (tmp->chan->cid.cid_ani)
1974 ast_free(tmp->chan->cid.cid_ani);
1975 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1977 /* Inherit specially named variables from parent channel */
1978 ast_channel_inherit_variables(qe->chan, tmp->chan);
1980 /* Presense of ADSI CPE on outgoing channel follows ours */
1981 tmp->chan->adsicpe = qe->chan->adsicpe;
1983 /* Place the call, but don't wait on the answer */
1984 if ((res = ast_call(tmp->chan, location, 0))) {
1985 /* Again, keep going even if there's an error */
1986 ast_debug(1, "ast call on peer returned %d\n", res);
1987 ast_verb(3, "Couldn't call %s\n", tmp->interface);
1991 } else if (qe->parent->eventwhencalled) {
1994 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1996 "AgentCalled: %s\r\n"
1998 "ChannelCalling: %s\r\n"
1999 "DestinationChannel: %s\r\n"
2000 "CallerIDNum: %s\r\n"
2001 "CallerIDName: %s\r\n"
2006 qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
2007 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
2008 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
2009 qe->chan->context, qe->chan->exten, qe->chan->priority,
2010 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2011 ast_verb(3, "Called %s\n", tmp->interface);
2017 /*! \brief find the entry with the best metric, or NULL */
2018 static struct callattempt *find_best(struct callattempt *outgoing)
2020 struct callattempt *best = NULL, *cur;
2022 for (cur = outgoing; cur; cur = cur->q_next) {
2023 if (cur->stillgoing && /* Not already done */
2024 !cur->chan && /* Isn't already going */
2025 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
2033 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
2038 struct callattempt *best = find_best(outgoing);
2040 ast_debug(1, "Nobody left to try ringing in queue\n");
2043 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2044 struct callattempt *cur;
2045 /* Ring everyone who shares this best metric (for ringall) */
2046 for (cur = outgoing; cur; cur = cur->q_next) {
2047 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
2048 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
2049 ring_entry(qe, cur, busies);
2053 /* Ring just the best channel */
2054 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
2055 ring_entry(qe, best, busies);
2057 if (best->chan) /* break out with result = 1 */
2064 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
2066 struct callattempt *best = find_best(outgoing);
2069 /* Ring just the best channel */
2070 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2071 qe->parent->rrpos = best->metric % 1000;
2073 /* Just increment rrpos */
2074 if (qe->parent->wrapped) {
2075 /* No more channels, start over */
2076 qe->parent->rrpos = 0;
2078 /* Prioritize next entry */
2079 qe->parent->rrpos++;
2082 qe->parent->wrapped = 0;
2087 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
2089 struct callattempt *best = find_best(outgoing);
2092 /* Ring just the best channel */
2093 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
2094 qe->linpos = best->metric % 1000;
2096 /* Just increment rrpos */
2097 if (qe->linwrapped) {
2098 /* No more channels, start over */
2101 /* Prioritize next entry */
2110 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
2115 /* Get the current time */
2118 /* Check to see if it is time to announce */
2119 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
2122 /* Stop the music on hold so we can play our own file */
2124 ast_indicate(qe->chan,-1);
2126 ast_moh_stop(qe->chan);
2128 ast_verb(3, "Playing periodic announcement\n");
2130 /* Check to make sure we have a sound file. If not, reset to the first sound file */
2131 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS ||
2132 !qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound] ||
2133 ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) {
2134 qe->last_periodic_announce_sound = 0;
2137 /* play the announcement */
2138 res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str);
2140 if ((res > 0 && !valid_exit(qe, res)) || res < 0)
2143 /* Resume Music on Hold if the caller is going to stay in the queue */
2146 ast_indicate(qe->chan, AST_CONTROL_RINGING);
2148 ast_moh_start(qe->chan, qe->moh, NULL);
2151 /* update last_periodic_announce_time */
2152 qe->last_periodic_announce_time = now;
2154 /* Update the current periodic announcement to the next announcement */
2155 qe->last_periodic_announce_sound++;
2160 static void record_abandoned(struct queue_ent *qe)
2162 ao2_lock(qe->parent);
2163 set_queue_variables(qe);
2164 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
2168 "OriginalPosition: %d\r\n"
2170 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
2172 qe->parent->callsabandoned++;
2173 ao2_unlock(qe->parent);
2176 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
2177 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
2179 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
2180 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
2181 if (qe->parent->autopause) {
2182 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
2183 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
2185 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
2191 #define AST_MAX_WATCHERS 256
2193 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
2195 const char *queue = qe->parent->name;
2196 struct callattempt *o;
2198 int sentringing = 0;
2199 int numbusies = prebusies;
2203 struct ast_frame *f;
2204 struct callattempt *peer = NULL;
2205 struct ast_channel *winner;
2206 struct ast_channel *in = qe->chan;
2208 char membername[80] = "";
2212 struct callattempt *epollo;
2215 starttime = (long) time(NULL);
2217 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
2219 ast_poll_channel_add(in, epollo->chan);
2223 while (*to && !peer) {
2224 int numlines, retry, pos = 1;
2225 struct ast_channel *watchers[AST_MAX_WATCHERS];
2228 for (retry = 0; retry < 2; retry++) {
2230 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
2231 if (o->stillgoing) { /* Keep track of important channels */
2234 watchers[pos++] = o->chan;
2238 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
2239 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
2241 /* On "ringall" strategy we only move to the next penalty level
2242 when *all* ringing phones are done in the current penalty level */
2243 ring_one(qe, outgoing, &numbusies);
2246 if (pos == 1 /* not found */) {
2247 if (numlines == (numbusies + numnochan)) {
2248 ast_debug(1, "Everyone is busy at this time\n");
2250 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
2255 winner = ast_waitfor_n(watchers, pos, to);
2256 for (o = outgoing; o; o = o->q_next) {
2257 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
2259 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2262 } else if (o->chan && (o->chan == winner)) {
2264 ast_copy_string(on, o->member->interface, sizeof(on));
2265 ast_copy_string(membername, o->member->membername, sizeof(membername));
2267 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
2268 ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
2273 } else if (!ast_strlen_zero(o->chan->call_forward)) {
2278 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
2279 if ((stuff = strchr(tmpchan, '/'))) {
2283 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
2287 /* Before processing channel, go ahead and check for forwarding */
2288 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2289 /* Setup parameters */
2290 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2291 if (status != o->oldstatus)
2292 update_dial_status(qe->parent, o->member, status);
2294 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2298 ast_channel_inherit_variables(in, o->chan);
2299 ast_channel_datastore_inherit(in, o->chan);
2300 if (o->chan->cid.cid_num)
2301 ast_free(o->chan->cid.cid_num);
2302 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2304 if (o->chan->cid.cid_name)
2305 ast_free(o->chan->cid.cid_name);
2306 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2308 ast_string_field_set(o->chan, accountcode, in->accountcode);
2309 o->chan->cdrflags = in->cdrflags;
2311 if (in->cid.cid_ani) {
2312 if (o->chan->cid.cid_ani)
2313 ast_free(o->chan->cid.cid_ani);
2314 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2316 if (o->chan->cid.cid_rdnis)
2317 ast_free(o->chan->cid.cid_rdnis);
2318 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2319 if (ast_call(o->chan, tmpchan, 0)) {
2320 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2325 /* Hangup the original channel now, in case we needed it */
2329 f = ast_read(winner);
2331 if (f->frametype == AST_FRAME_CONTROL) {
2332 switch (f->subclass) {
2333 case AST_CONTROL_ANSWER:
2334 /* This is our guy if someone answered. */
2336 ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
2340 case AST_CONTROL_BUSY:
2341 ast_verb(3, "%s is busy\n", o->chan->name);
2343 ast_cdr_busy(in->cdr);
2345 endtime = (long) time(NULL);
2346 endtime -= starttime;
2347 rna(endtime*1000, qe, on, membername);
2348 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2349 if (qe->parent->timeoutrestart)
2351 ring_one(qe, outgoing, &numbusies);
2355 case AST_CONTROL_CONGESTION:
2356 ast_verb(3, "%s is circuit-busy\n", o->chan->name);
2358 ast_cdr_busy(in->cdr);
2359 endtime = (long) time(NULL);
2360 endtime -= starttime;
2361 rna(endtime*1000, qe, on, membername);
2363 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2364 if (qe->parent->timeoutrestart)
2366 ring_one(qe, outgoing, &numbusies);
2370 case AST_CONTROL_RINGING:
2371 ast_verb(3, "%s is ringing\n", o->chan->name);
2374 ast_indicate(in, AST_CONTROL_RINGING);
2379 case AST_CONTROL_OFFHOOK:
2380 /* Ignore going off hook */
2383 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
2388 endtime = (long) time(NULL) - starttime;
2389 rna(endtime * 1000, qe, on, membername);
2391 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2392 if (qe->parent->timeoutrestart)
2394 ring_one(qe, outgoing, &numbusies);
2401 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2409 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2410 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
2415 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2416 ast_verb(3, "User pressed digit: %c\n", f->subclass);
2418 *digit = f->subclass;
2425 rna(orig, qe, on, membername);
2429 for(epollo = outgoing; epollo; epollo = epollo->q_next) {
2431 ast_poll_channel_del(in, epollo->chan);
2438 static int is_our_turn(struct queue_ent *qe)
2440 struct queue_ent *ch;
2446 if (!qe->parent->autofill) {
2447 /* Atomically read the parent head -- does not need a lock */
2448 ch = qe->parent->head;
2449 /* If we are now at the top of the head, break out */
2451 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2454 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2459 /* This needs a lock. How many members are available to be served? */
2460 ao2_lock(qe->parent);
2462 ch = qe->parent->head;
2464 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2465 ast_debug(1, "Even though there may be multiple members available, the strategy is ringall so only the head call is allowed in\n");
2468 struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
2469 while ((cur = ao2_iterator_next(&mem_iter))) {
2470 switch (cur->status) {
2471 case AST_DEVICE_NOT_INUSE:
2472 case AST_DEVICE_UNKNOWN:
2481 ast_debug(1, "There are %d available members.\n", avl);
2483 while ((idx < avl) && (ch) && (ch != qe)) {
2488 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2489 if (ch && idx < avl) {
2490 ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
2493 ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
2497 ao2_unlock(qe->parent);
2503 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2507 /* This is the holding pen for callers 2 through maxlen */
2509 enum queue_member_status stat;
2511 if (is_our_turn(qe))
2514 /* If we have timed out, break out */
2515 if (qe->expire && (time(NULL) > qe->expire)) {
2516 *reason = QUEUE_TIMEOUT;
2520 stat = get_member_status(qe->parent, qe->max_penalty);
2522 /* leave the queue if no agents, if enabled */
2523 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2524 *reason = QUEUE_LEAVEEMPTY;
2525 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2530 /* leave the queue if no reachable agents, if enabled */
2531 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_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);
2537 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2538 *reason = QUEUE_LEAVEUNAVAIL;
2539 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2544 /* Make a position announcement, if enabled */
2545 if (qe->parent->announcefrequency &&
2546 (res = say_position(qe,ringing)))
2549 /* Make a periodic announcement, if enabled */
2550 if (qe->parent->periodicannouncefrequency &&
2551 (res = say_periodic_announcement(qe,ringing)))
2554 /* Wait a second before checking again */
2555 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
2556 if (res > 0 && !valid_exit(qe, res))
2566 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
2569 struct call_queue *qtmp;
2570 struct ao2_iterator queue_iter;
2572 if (shared_lastcall) {
2573 queue_iter = ao2_iterator_init(queues, 0);
2574 while ((qtmp = ao2_iterator_next(&queue_iter))) {
2576 if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
2577 time(&mem->lastcall);
2587 time(&member->lastcall);
2589 member->lastqueue = q;
2593 q->callscompleted++;
2594 if (callcompletedinsl)
2595 q->callscompletedinsl++;
2600 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2602 if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2605 switch (q->strategy) {
2606 case QUEUE_STRATEGY_RINGALL:
2607 /* Everyone equal, except for penalty */
2608 tmp->metric = mem->penalty * 1000000;
2610 case QUEUE_STRATEGY_LINEAR:
2611 if (pos < qe->linpos) {
2612 tmp->metric = 1000 + pos;
2614 if (pos > qe->linpos)
2615 /* Indicate there is another priority */
2619 tmp->metric += mem->penalty * 1000000;
2621 case QUEUE_STRATEGY_RRMEMORY:
2622 if (pos < q->rrpos) {
2623 tmp->metric = 1000 + pos;
2626 /* Indicate there is another priority */
2630 tmp->metric += mem->penalty * 1000000;
2632 case QUEUE_STRATEGY_RANDOM:
2633 tmp->metric = ast_random() % 1000;
2634 tmp->metric += mem->penalty * 1000000;
2636 case QUEUE_STRATEGY_WRANDOM:
2637 tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
2639 case QUEUE_STRATEGY_FEWESTCALLS:
2640 tmp->metric = mem->calls;
2641 tmp->metric += mem->penalty * 1000000;
2643 case QUEUE_STRATEGY_LEASTRECENT:
2647 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2648 tmp->metric += mem->penalty * 1000000;
2651 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2657 enum agent_complete_reason {
2663 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2664 const struct ast_channel *peer, const struct member *member, time_t callstart,
2665 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2667 const char *reason = NULL; /* silence dumb compilers */
2669 if (!qe->parent->eventwhencalled)
2680 reason = "transfer";
2684 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2689 "MemberName: %s\r\n"
2694 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2695 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
2696 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
2699 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)
2702 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2704 char oldexten[AST_MAX_EXTENSION]="";
2705 char oldcontext[AST_MAX_CONTEXT]="";
2706 char queuename[256]="";
2707 char interfacevar[256]="";
2708 struct ast_channel *peer;
2709 struct ast_channel *which;
2710 struct callattempt *lpeer;
2711 struct member *member;
2712 struct ast_app *app;
2713 int res = 0, bridge = 0;
2716 char *announce = NULL;
2719 time_t now = time(NULL);
2720 struct ast_bridge_config bridge_config;
2721 char nondataquality = 1;
2722 char *agiexec = NULL;
2723 char *macroexec = NULL;
2724 char *gosubexec = NULL;
2726 const char *monitorfilename;
2727 const char *monitor_exec;
2728 const char *monitor_options;
2729 char tmpid[256], tmpid2[256];
2730 char meid[1024], meid2[1024];
2731 char mixmonargs[1512];
2732 struct ast_app *mixmonapp = NULL;
2735 int forwardsallowed = 1;
2736 int callcompletedinsl;
2737 struct ao2_iterator memi;
2738 struct ast_datastore *datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
2740 memset(&bridge_config, 0, sizeof(bridge_config));
2745 for (; options && *options; options++)
2748 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2751 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2754 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2757 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2763 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2766 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2769 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
2772 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
2775 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR)
2778 *tries = qe->parent->membercount;
2782 forwardsallowed = 0;
2785 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
2788 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
2793 /* Hold the lock while we setup the outgoing calls */
2796 ao2_lock(qe->parent);
2797 ast_debug(1, "%s is trying to call a queue member.\n",
2799 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2800 if (!ast_strlen_zero(qe->announce))
2801 announce = qe->announce;
2802 if (!ast_strlen_zero(announceoverride))
2803 announce = announceoverride;
2805 memi = ao2_iterator_init(qe->parent->members, 0);
2806 while ((cur = ao2_iterator_next(&memi))) {
2807 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2808 struct ast_dialed_interface *di;
2810 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
2813 ao2_unlock(qe->parent);
2819 if(!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
2821 ao2_unlock(qe->parent);
2827 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
2828 dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces));
2829 datastore->data = dialed_interfaces;
2830 AST_LIST_HEAD_INIT(dialed_interfaces);
2831 ast_channel_datastore_add(qe->chan, datastore);
2833 dialed_interfaces = datastore->data;
2834 AST_LIST_LOCK(dialed_interfaces);
2835 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
2836 /* XXX case sensitive ?? */
2837 if(!strcasecmp(cur->interface, di->interface)) {
2842 if (!dialed && strncasecmp(cur->interface, "Local/", 6)) {
2843 if(!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
2845 AST_LIST_UNLOCK(dialed_interfaces);
2846 ao2_unlock(qe->parent);
2852 strcpy(di->interface, cur->interface);
2853 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
2854 } else if (dialed) {
2855 ast_log(LOG_DEBUG, "Skipping dialing interface '%s' since it has already been dialed\n", di->interface);
2856 AST_LIST_UNLOCK(dialed_interfaces);
2860 AST_LIST_UNLOCK(dialed_interfaces);
2861 tmp->stillgoing = -1;
2863 tmp->oldstatus = cur->status;
2864 tmp->lastcall = cur->lastcall;
2865 tmp->lastqueue = cur->lastqueue;
2866 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2867 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2868 just calculate their metric for the appropriate strategy */
2869 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2870 /* Put them in the list of outgoing thingies... We're ready now.
2871 XXX If we're forcibly removed, these outgoing calls won't get
2873 tmp->q_next = outgoing;
2875 /* If this line is up, don't try anybody else */
2876 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2883 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2884 to = (qe->expire - now) * 1000;
2886 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2888 ring_one(qe, outgoing, &numbusies);
2889 ao2_unlock(qe->parent);
2892 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2893 ast_channel_datastore_remove(qe->chan, datastore);
2894 ast_channel_datastore_free(datastore);
2895 ao2_lock(qe->parent);
2896 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2897 store_next_rr(qe, outgoing);
2899 if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
2900 store_next_lin(qe, outgoing);
2902 ao2_unlock(qe->parent);
2903 peer = lpeer ? lpeer->chan : NULL;
2906 /* Must gotten hung up */
2909 /* User exited by pressing a digit */
2913 ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
2914 } else { /* peer is valid */
2915 /* Ah ha! Someone answered within the desired timeframe. Of course after this
2916 we will always return with -1 so that it is hung up properly after the
2919 if (!strcmp(qe->chan->tech->type, "Zap"))
2920 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2921 if (!strcmp(peer->tech->type, "Zap"))
2922 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2923 /* Update parameters for the queue */
2925 recalc_holdtime(qe, (now - qe->start));
2926 ao2_lock(qe->parent);
2927 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
2928 ao2_unlock(qe->parent);
2929 member = lpeer->member;
2930 /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
2932 hangupcalls(outgoing, peer);
2934 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2937 res2 = ast_autoservice_start(qe->chan);
2939 if (qe->parent->memberdelay) {
2940 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2941 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2943 if (!res2 && announce) {
2944 play_file(peer, announce);
2946 if (!res2 && qe->parent->reportholdtime) {
2947 if (!play_file(peer, qe->parent->sound_reporthold)) {
2951 holdtime = abs((now - qe->start) / 60);
2953 play_file(peer, qe->parent->sound_lessthan);
2954 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2956 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2957 play_file(peer, qe->parent->sound_minutes);
2961 res2 |= ast_autoservice_stop(qe->chan);
2962 if (ast_check_hangup(peer)) {
2963 /* Agent must have hung up */
2964 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
2965 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2966 record_abandoned(qe);
2967 if (qe->parent->eventwhencalled)
2968 manager_event(EVENT_FLAG_AGENT, "AgentDump",
2973 "MemberName: %s\r\n"
2975 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2976 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2978 ao2_ref(member, -1);
2981 /* Caller must have hung up just before being connected*/
2982 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2983 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2984 record_abandoned(qe);