2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief True call queues with optional send URL on answer
23 * \author Mark Spencer <markster@digium.com>
25 * \arg Config in \ref Config_qu queues.conf
27 * \par Development notes
28 * \note 2004-11-25: Persistent Dynamic Members added by:
29 * NetNation Communications (www.netnation.com)
30 * Kevin Lindsay <kevinl@netnation.com>
32 * Each dynamic agent in each queue is now stored in the astdb.
33 * When asterisk is restarted, each agent will be automatically
34 * readded into their recorded queues. This feature can be
35 * configured with the 'persistent_members=<1|0>' setting in the
36 * '[general]' category in queues.conf. The default is on.
38 * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
40 * \note These features added by David C. Troy <dave@toad.net>:
41 * - Per-queue holdtime calculation
42 * - Estimated holdtime announcement
43 * - Position announcement
44 * - Abandoned/completed call counters
45 * - Failout timer passed as optional app parameter
46 * - Optional monitoring of calls, started when call is answered
48 * Patch Version 1.07 2003-12-24 01
50 * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
51 * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
53 * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
54 * by Matthew Enger <m.enger@xi.com.au>
56 * \ingroup applications
61 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
70 #include <sys/signal.h>
71 #include <netinet/in.h>
73 #include "asterisk/lock.h"
74 #include "asterisk/file.h"
75 #include "asterisk/logger.h"
76 #include "asterisk/channel.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/options.h"
79 #include "asterisk/app.h"
80 #include "asterisk/linkedlists.h"
81 #include "asterisk/module.h"
82 #include "asterisk/translate.h"
83 #include "asterisk/say.h"
84 #include "asterisk/features.h"
85 #include "asterisk/musiconhold.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/manager.h"
88 #include "asterisk/config.h"
89 #include "asterisk/monitor.h"
90 #include "asterisk/utils.h"
91 #include "asterisk/causes.h"
92 #include "asterisk/astdb.h"
93 #include "asterisk/devicestate.h"
94 #include "asterisk/stringfields.h"
97 QUEUE_STRATEGY_RINGALL = 0,
98 QUEUE_STRATEGY_LEASTRECENT,
99 QUEUE_STRATEGY_FEWESTCALLS,
100 QUEUE_STRATEGY_RANDOM,
101 QUEUE_STRATEGY_RRMEMORY
104 static struct strategy {
108 { QUEUE_STRATEGY_RINGALL, "ringall" },
109 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
110 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
111 { QUEUE_STRATEGY_RANDOM, "random" },
112 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
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 */
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 */
127 static char *app = "Queue";
129 static char *synopsis = "Queue a call for a call queue";
131 static char *descrip =
132 " Queue(queuename[|options[|URL][|announceoverride][|timeout][|AGI][|macro]):\n"
133 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
134 "This application will return to the dialplan if the queue does not exist, or\n"
135 "any of the join options cause the caller to not enter the queue.\n"
136 "The option string may contain zero or more of the following characters:\n"
137 " 'd' -- data-quality (modem) call (minimum delay).\n"
138 " 'h' -- allow callee to hang up by pressing *.\n"
139 " 'H' -- allow caller to hang up by pressing *.\n"
140 " 'n' -- no retries on the timeout; will exit this application and \n"
141 " go to the next step.\n"
142 " 'i' -- ignore call forward requests from queue members and do nothing\n"
143 " when they are requested.\n"
144 " 'r' -- ring instead of playing MOH.\n"
145 " 't' -- allow the called user to transfer the calling user.\n"
146 " 'T' -- allow the calling user to transfer the call.\n"
147 " 'w' -- allow the called user to write the conversation to disk via Monitor.\n"
148 " 'W' -- allow the calling user to write the conversation to disk via Monitor.\n"
149 " In addition to transferring the call, a call may be parked and then picked\n"
150 "up by another user.\n"
151 " The optional URL will be sent to the called party if the channel supports\n"
153 " The optional AGI parameter will setup an AGI script to be executed on the \n"
154 "calling party's channel once they are connected to a queue member.\n"
155 " The optional macro parameter will run a macro on the \n"
156 "calling party's channel once they are connected to a queue member.\n"
157 " The timeout will cause the queue to fail out after a specified number of\n"
158 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
159 " This application sets the following channel variable upon completion:\n"
160 " QUEUESTATUS The status of the call as a text string, one of\n"
161 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL\n";
163 static char *app_aqm = "AddQueueMember" ;
164 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
165 static char *app_aqm_descrip =
166 " AddQueueMember(queuename[|interface[|penalty[|options[|membername]]]]):\n"
167 "Dynamically adds interface to an existing queue.\n"
168 "If the interface is already in the queue and there exists an n+101 priority\n"
169 "then it will then jump to this priority. Otherwise it will return an error\n"
170 "The option string may contain zero or more of the following characters:\n"
171 " 'j' -- jump to +101 priority when appropriate.\n"
172 " This application sets the following channel variable upon completion:\n"
173 " AQMSTATUS The status of the attempt to add a queue member as a \n"
174 " text string, one of\n"
175 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
176 "Example: AddQueueMember(techsupport|SIP/3000)\n"
179 static char *app_rqm = "RemoveQueueMember" ;
180 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
181 static char *app_rqm_descrip =
182 " RemoveQueueMember(queuename[|interface[|options]]):\n"
183 "Dynamically removes interface to an existing queue\n"
184 "If the interface is NOT in the queue and there exists an n+101 priority\n"
185 "then it will then jump to this priority. Otherwise it will return an error\n"
186 "The option string may contain zero or more of the following characters:\n"
187 " 'j' -- jump to +101 priority when appropriate.\n"
188 " This application sets the following channel variable upon completion:\n"
189 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
190 " text string, one of\n"
191 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
192 "Example: RemoveQueueMember(techsupport|SIP/3000)\n"
195 static char *app_pqm = "PauseQueueMember" ;
196 static char *app_pqm_synopsis = "Pauses a queue member" ;
197 static char *app_pqm_descrip =
198 " PauseQueueMember([queuename]|interface[|options]):\n"
199 "Pauses (blocks calls for) a queue member.\n"
200 "The given interface will be paused in the given queue. This prevents\n"
201 "any calls from being sent from the queue to the interface until it is\n"
202 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
203 "queuename is given, the interface is paused in every queue it is a\n"
204 "member of. If the interface is not in the named queue, or if no queue\n"
205 "is given and the interface is not in any queue, it will jump to\n"
206 "priority n+101, if it exists and the appropriate options are set.\n"
207 "The application will fail if the interface is not found and no extension\n"
208 "to jump to exists.\n"
209 "The option string may contain zero or more of the following characters:\n"
210 " 'j' -- jump to +101 priority when appropriate.\n"
211 " This application sets the following channel variable upon completion:\n"
212 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
213 " text string, one of\n"
214 " PAUSED | NOTFOUND\n"
215 "Example: PauseQueueMember(|SIP/3000)\n";
217 static char *app_upqm = "UnpauseQueueMember" ;
218 static char *app_upqm_synopsis = "Unpauses a queue member" ;
219 static char *app_upqm_descrip =
220 " UnpauseQueueMember([queuename]|interface[|options]):\n"
221 "Unpauses (resumes calls to) a queue member.\n"
222 "This is the counterpart to PauseQueueMember and operates exactly the\n"
223 "same way, except it unpauses instead of pausing the given interface.\n"
224 "The option string may contain zero or more of the following characters:\n"
225 " 'j' -- jump to +101 priority when appropriate.\n"
226 " This application sets the following channel variable upon completion:\n"
227 " UPQMSTATUS The status of the attempt to unpause a queue \n"
228 " member as a text string, one of\n"
229 " UNPAUSED | NOTFOUND\n"
230 "Example: UnpauseQueueMember(|SIP/3000)\n";
232 static char *app_ql = "QueueLog" ;
233 static char *app_ql_synopsis = "Writes to the queue_log" ;
234 static char *app_ql_descrip =
235 " QueueLog(queuename|uniqueid|agent|event[|additionalinfo]):\n"
236 "Allows you to write your own events into the queue log\n"
237 "Example: QueueLog(101|${UNIQUEID}|${AGENT}|WENTONBREAK|600)\n";
239 /*! \brief Persistent Members astdb family */
240 static const char *pm_family = "/Queue/PersistentMembers";
241 /* The maximum length of each persistent member queue database entry */
242 #define PM_MAX_LEN 8192
244 /*! \brief queues.conf [general] option */
245 static int queue_keep_stats = 0;
247 /*! \brief queues.conf [general] option */
248 static int queue_persistent_members = 0;
250 /*! \brief queues.conf per-queue weight option */
251 static int use_weight = 0;
253 /*! \brief queues.conf [general] option */
254 static int autofill_default = 0;
256 /*! \brief queues.conf [general] option */
257 static int montype_default = 0;
263 QUEUE_LEAVEEMPTY = 3,
264 QUEUE_JOINUNAVAIL = 4,
265 QUEUE_LEAVEUNAVAIL = 5,
270 enum queue_result id;
272 } queue_results[] = {
273 { QUEUE_UNKNOWN, "UNKNOWN" },
274 { QUEUE_TIMEOUT, "TIMEOUT" },
275 { QUEUE_JOINEMPTY,"JOINEMPTY" },
276 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
277 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
278 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
279 { QUEUE_FULL, "FULL" },
282 /*! \brief We define a custom "local user" structure because we
283 use it not only for keeping track of what is in use but
284 also for keeping track of who we're dialing. */
287 struct callattempt *q_next;
288 struct ast_channel *chan;
294 struct member *member;
299 struct call_queue *parent; /*!< What queue is our parent */
300 char moh[80]; /*!< Name of musiconhold to be used */
301 char announce[80]; /*!< Announcement to play for member when call is answered */
302 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
303 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
304 int pos; /*!< Where we are in the queue */
305 int prio; /*!< Our priority */
306 int last_pos_said; /*!< Last position we told the user */
307 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
308 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
309 time_t last_pos; /*!< Last time we told the user their position */
310 int opos; /*!< Where we started in the queue */
311 int handled; /*!< Whether our call was handled */
312 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
313 time_t start; /*!< When we started holding */
314 time_t expire; /*!< When this entry should expire (time out of queue) */
315 struct ast_channel *chan; /*!< Our channel */
316 struct queue_ent *next; /*!< The next queue entry */
320 char interface[80]; /*!< Technology/Location */
321 char membername[80]; /*!< Member name to use in queue logs */
322 int penalty; /*!< Are we a last resort? */
323 int calls; /*!< Number of calls serviced by this member */
324 int dynamic; /*!< Are we dynamically added? */
325 int status; /*!< Status of queue member */
326 int paused; /*!< Are we paused (not accepting calls)? */
327 time_t lastcall; /*!< When last successful call was hungup */
328 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
329 unsigned int delme:1; /*!< Flag to delete entry on reload */
330 struct member *next; /*!< Next member */
333 struct member_interface {
335 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
338 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
340 /* values used in multi-bit flags in call_queue */
341 #define QUEUE_EMPTY_NORMAL 1
342 #define QUEUE_EMPTY_STRICT 2
343 #define QUEUE_EMPTY_LOOSE 3
344 #define ANNOUNCEHOLDTIME_ALWAYS 1
345 #define ANNOUNCEHOLDTIME_ONCE 2
346 #define QUEUE_EVENT_VARIABLES 3
350 char name[80]; /*!< Name */
351 char moh[80]; /*!< Music On Hold class to be used */
352 char announce[80]; /*!< Announcement to play when call is answered */
353 char context[AST_MAX_CONTEXT]; /*!< Exit context */
354 unsigned int monjoin:1;
356 unsigned int joinempty:2;
357 unsigned int eventwhencalled:2;
358 unsigned int leavewhenempty:2;
359 unsigned int ringinuse:1;
360 unsigned int setinterfacevar:1;
361 unsigned int setqueuevar:1;
362 unsigned int setqueueentryvar:1;
363 unsigned int reportholdtime:1;
364 unsigned int wrapped:1;
365 unsigned int timeoutrestart:1;
366 unsigned int announceholdtime:2;
367 unsigned int strategy:3;
368 unsigned int maskmemberstatus:1;
369 unsigned int realtime:1;
370 int announcefrequency; /*!< How often to announce their position */
371 int minannouncefrequency; /*!< The minimum number of seconds between position announcements (def. 15) */
372 int periodicannouncefrequency; /*!< How often to play periodic announcement */
373 int roundingseconds; /*!< How many seconds do we round to? */
374 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
375 int callscompleted; /*!< Number of queue calls completed */
376 int callsabandoned; /*!< Number of queue calls abandoned */
377 int servicelevel; /*!< seconds setting for servicelevel*/
378 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
379 char monfmt[8]; /*!< Format to use when recording calls */
380 int montype; /*!< Monitor type Monitor vs. MixMonitor */
381 char membermacro[32]; /*!< Macro to run upon member connection */
382 char sound_next[80]; /*!< Sound file: "Your call is now first in line" (def. queue-youarenext) */
383 char sound_thereare[80]; /*!< Sound file: "There are currently" (def. queue-thereare) */
384 char sound_calls[80]; /*!< Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/
385 char sound_holdtime[80]; /*!< Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
386 char sound_minutes[80]; /*!< Sound file: "minutes." (def. queue-minutes) */
387 char sound_lessthan[80]; /*!< Sound file: "less-than" (def. queue-lessthan) */
388 char sound_seconds[80]; /*!< Sound file: "seconds." (def. queue-seconds) */
389 char sound_thanks[80]; /*!< Sound file: "Thank you for your patience." (def. queue-thankyou) */
390 char sound_reporthold[80]; /*!< Sound file: "Hold time" (def. queue-reporthold) */
391 char sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS][80];/*!< Sound files: Custom announce, no default */
393 int count; /*!< How many entries */
394 int maxlen; /*!< Max number of entries */
395 int wrapuptime; /*!< Wrapup Time */
397 int retry; /*!< Retry calling everyone after this amount of time */
398 int timeout; /*!< How long to wait for an answer */
399 int weight; /*!< Respective weight */
400 int autopause; /*!< Auto pause queue members if they fail to answer */
402 /* Queue strategy things */
403 int rrpos; /*!< Round Robin - position */
404 int memberdelay; /*!< Seconds to delay connecting member to caller */
405 int autofill; /*!< Ignore the head call status and ring an available agent */
407 struct member *members; /*!< Head of the list of members */
408 struct queue_ent *head; /*!< Head of the list of callers */
409 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
412 static AST_LIST_HEAD_STATIC(queues, call_queue);
414 static int set_member_paused(const char *queuename, const char *interface, int paused);
416 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
420 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
421 if (queue_results[i].id == res) {
422 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
428 static char *int2strat(int strategy)
432 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
433 if (strategy == strategies[x].strategy)
434 return strategies[x].name;
440 static int strat2int(const char *strategy)
444 for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
445 if (!strcasecmp(strategy, strategies[x].name))
446 return strategies[x].strategy;
452 static void set_queue_variables(struct queue_ent *qe)
455 char interfacevar[256]="";
458 if (qe->parent->setqueuevar) {
460 if (qe->parent->callscompleted > 0)
461 sl = 100 * ((float) qe->parent->callscompletedinsl / (float) qe->parent->callscompleted);
463 snprintf(interfacevar,sizeof(interfacevar),
464 "QUEUEMAX=%d|QUEUESTRATEGY=%s|QUEUECALLS=%d|QUEUEHOLDTIME=%d|QUEUECOMPLETED=%d|QUEUEABANDONED=%d|QUEUESRVLEVEL=%d|QUEUESRVLEVELPERF=%2.1f",
465 qe->parent->maxlen, int2strat(qe->parent->strategy), qe->parent->count, qe->parent->holdtime, qe->parent->callscompleted,
466 qe->parent->callsabandoned, qe->parent->servicelevel, sl);
468 pbx_builtin_setvar(qe->chan, interfacevar);
472 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
473 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
475 struct queue_ent *cur;
492 enum queue_member_status {
494 QUEUE_NO_REACHABLE_MEMBERS,
495 QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
499 static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty)
501 struct member *member;
502 enum queue_member_status result = QUEUE_NO_MEMBERS;
504 ast_mutex_lock(&q->lock);
505 for (member = q->members; member; member = member->next) {
506 if (max_penalty && (member->penalty > max_penalty))
509 switch (member->status) {
510 case AST_DEVICE_INVALID:
513 case AST_DEVICE_UNAVAILABLE:
514 if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)
515 result = QUEUE_NO_REACHABLE_MEMBERS;
518 if (member->paused) {
519 result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
521 ast_mutex_unlock(&q->lock);
528 ast_mutex_unlock(&q->lock);
537 static void *changethread(void *data)
539 struct call_queue *q;
540 struct statechange *sc = data;
542 struct member_interface *curint;
546 technology = ast_strdupa(sc->dev);
547 loc = strchr(technology, '/');
555 AST_LIST_LOCK(&interfaces);
556 AST_LIST_TRAVERSE(&interfaces, curint, list) {
559 interface = ast_strdupa(curint->interface);
560 if ((slash_pos = strchr(interface, '/')))
561 if ((slash_pos = strchr(slash_pos + 1, '/')))
564 if (!strcasecmp(interface, sc->dev))
567 AST_LIST_UNLOCK(&interfaces);
570 if (option_debug > 2)
571 ast_log(LOG_DEBUG, "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));
577 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
578 AST_LIST_LOCK(&queues);
579 AST_LIST_TRAVERSE(&queues, q, list) {
580 ast_mutex_lock(&q->lock);
581 for (cur = q->members; cur; cur = cur->next) {
584 interface = ast_strdupa(cur->interface);
585 if ((slash_pos = strchr(interface, '/')))
586 if ((slash_pos = strchr(slash_pos + 1, '/')))
589 if (strcasecmp(sc->dev, interface))
592 if (cur->status != sc->state) {
593 cur->status = sc->state;
594 if (q->maskmemberstatus)
597 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
607 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
608 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
611 ast_mutex_unlock(&q->lock);
613 AST_LIST_UNLOCK(&queues);
618 static int statechange_queue(const char *dev, enum ast_device_state state, void *ign)
620 /* Avoid potential for deadlocks by spawning a new thread to handle
622 struct statechange *sc;
626 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
630 strcpy(sc->dev, dev);
631 pthread_attr_init(&attr);
632 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
633 if (ast_pthread_create_background(&t, &attr, changethread, sc)) {
634 ast_log(LOG_WARNING, "Failed to create update thread!\n");
637 pthread_attr_destroy(&attr);
642 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
646 if ((cur = ast_calloc(1, sizeof(*cur)))) {
647 cur->penalty = penalty;
648 cur->paused = paused;
649 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
650 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
651 if (!strchr(cur->interface, '/'))
652 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
653 cur->status = ast_device_state(interface);
659 static struct call_queue *alloc_queue(const char *queuename)
661 struct call_queue *q;
663 if ((q = ast_calloc(1, sizeof(*q)))) {
664 ast_mutex_init(&q->lock);
665 ast_copy_string(q->name, queuename, sizeof(q->name));
670 static void init_queue(struct call_queue *q)
675 q->retry = DEFAULT_RETRY;
678 q->announcefrequency = 0;
679 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
680 q->announceholdtime = 0;
681 q->roundingseconds = 0; /* Default - don't announce seconds */
684 q->setinterfacevar = 0;
686 q->setqueueentryvar = 0;
687 q->autofill = autofill_default;
688 q->montype = montype_default;
689 q->membermacro[0] = '\0';
691 q->announce[0] = '\0';
692 q->context[0] = '\0';
694 q->periodicannouncefrequency = 0;
695 ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
696 ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
697 ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
698 ast_copy_string(q->sound_holdtime, "queue-holdtime", sizeof(q->sound_holdtime));
699 ast_copy_string(q->sound_minutes, "queue-minutes", sizeof(q->sound_minutes));
700 ast_copy_string(q->sound_seconds, "queue-seconds", sizeof(q->sound_seconds));
701 ast_copy_string(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks));
702 ast_copy_string(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan));
703 ast_copy_string(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold));
704 ast_copy_string(q->sound_periodicannounce[0], "queue-periodic-announce", sizeof(q->sound_periodicannounce[0]));
705 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
706 q->sound_periodicannounce[i][0]='\0';
710 static void clear_queue(struct call_queue *q)
713 q->callscompleted = 0;
714 q->callsabandoned = 0;
715 q->callscompletedinsl = 0;
719 static int add_to_interfaces(const char *interface)
721 struct member_interface *curint;
723 AST_LIST_LOCK(&interfaces);
724 AST_LIST_TRAVERSE(&interfaces, curint, list) {
725 if (!strcasecmp(curint->interface, interface))
730 AST_LIST_UNLOCK(&interfaces);
735 ast_log(LOG_DEBUG, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
737 if ((curint = ast_calloc(1, sizeof(*curint)))) {
738 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
739 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
741 AST_LIST_UNLOCK(&interfaces);
746 static int interface_exists_global(const char *interface)
748 struct call_queue *q;
752 AST_LIST_LOCK(&queues);
753 AST_LIST_TRAVERSE(&queues, q, list) {
754 ast_mutex_lock(&q->lock);
755 for (mem = q->members; mem && !ret; mem = mem->next) {
756 if (!strcasecmp(interface, mem->interface))
759 ast_mutex_unlock(&q->lock);
763 AST_LIST_UNLOCK(&queues);
768 static int remove_from_interfaces(const char *interface)
770 struct member_interface *curint;
772 AST_LIST_LOCK(&interfaces);
773 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
774 if (!strcasecmp(curint->interface, interface)) {
775 if (!interface_exists_global(interface)) {
777 ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
778 AST_LIST_REMOVE_CURRENT(&interfaces, list);
784 AST_LIST_TRAVERSE_SAFE_END;
785 AST_LIST_UNLOCK(&interfaces);
790 static void clear_and_free_interfaces(void)
792 struct member_interface *curint;
794 AST_LIST_LOCK(&interfaces);
795 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
797 AST_LIST_UNLOCK(&interfaces);
800 /*! \brief Configure a queue parameter.
802 For error reporting, line number is passed for .conf static configuration.
803 For Realtime queues, linenum is -1.
804 The failunknown flag is set for config files (and static realtime) to show
805 errors for unknown parameters. It is cleared for dynamic realtime to allow
806 extra fields in the tables. */
807 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
809 if (!strcasecmp(param, "musicclass") ||
810 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
811 ast_copy_string(q->moh, val, sizeof(q->moh));
812 } else if (!strcasecmp(param, "announce")) {
813 ast_copy_string(q->announce, val, sizeof(q->announce));
814 } else if (!strcasecmp(param, "context")) {
815 ast_copy_string(q->context, val, sizeof(q->context));
816 } else if (!strcasecmp(param, "timeout")) {
817 q->timeout = atoi(val);
819 q->timeout = DEFAULT_TIMEOUT;
820 } else if (!strcasecmp(param, "ringinuse")) {
821 q->ringinuse = ast_true(val);
822 } else if (!strcasecmp(param, "setinterfacevar")) {
823 q->setinterfacevar = ast_true(val);
824 } else if (!strcasecmp(param, "setqueuevar")) {
825 q->setqueuevar = ast_true(val);
826 } else if (!strcasecmp(param, "setqueueentryvar")) {
827 q->setqueueentryvar = ast_true(val);
828 } else if (!strcasecmp(param, "monitor-join")) {
829 q->monjoin = ast_true(val);
830 } else if (!strcasecmp(param, "monitor-format")) {
831 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
832 } else if (!strcasecmp(param, "membermacro")) {
833 ast_copy_string(q->membermacro, val, sizeof(q->membermacro));
834 } else if (!strcasecmp(param, "queue-youarenext")) {
835 ast_copy_string(q->sound_next, val, sizeof(q->sound_next));
836 } else if (!strcasecmp(param, "queue-thereare")) {
837 ast_copy_string(q->sound_thereare, val, sizeof(q->sound_thereare));
838 } else if (!strcasecmp(param, "queue-callswaiting")) {
839 ast_copy_string(q->sound_calls, val, sizeof(q->sound_calls));
840 } else if (!strcasecmp(param, "queue-holdtime")) {
841 ast_copy_string(q->sound_holdtime, val, sizeof(q->sound_holdtime));
842 } else if (!strcasecmp(param, "queue-minutes")) {
843 ast_copy_string(q->sound_minutes, val, sizeof(q->sound_minutes));
844 } else if (!strcasecmp(param, "queue-seconds")) {
845 ast_copy_string(q->sound_seconds, val, sizeof(q->sound_seconds));
846 } else if (!strcasecmp(param, "queue-lessthan")) {
847 ast_copy_string(q->sound_lessthan, val, sizeof(q->sound_lessthan));
848 } else if (!strcasecmp(param, "queue-thankyou")) {
849 ast_copy_string(q->sound_thanks, val, sizeof(q->sound_thanks));
850 } else if (!strcasecmp(param, "queue-reporthold")) {
851 ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold));
852 } else if (!strcasecmp(param, "announce-frequency")) {
853 q->announcefrequency = atoi(val);
854 } else if (!strcasecmp(param, "min-announce-frequency")) {
855 q->minannouncefrequency = atoi(val);
856 ast_log(LOG_DEBUG, "%s=%s for queue '%s'\n", param, val, q->name);
857 } else if (!strcasecmp(param, "announce-round-seconds")) {
858 q->roundingseconds = atoi(val);
859 if (q->roundingseconds>60 || q->roundingseconds<0) {
861 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
862 "using 0 instead for queue '%s' at line %d of queues.conf\n",
863 val, param, q->name, linenum);
865 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
866 "using 0 instead for queue '%s'\n", val, param, q->name);
868 q->roundingseconds=0;
870 } else if (!strcasecmp(param, "announce-holdtime")) {
871 if (!strcasecmp(val, "once"))
872 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
873 else if (ast_true(val))
874 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
876 q->announceholdtime = 0;
877 } else if (!strcasecmp(param, "periodic-announce")) {
878 if (strchr(val, '|')) {
879 char *s, *buf = ast_strdupa(val);
882 while ((s = strsep(&buf, "|"))) {
883 ast_copy_string(q->sound_periodicannounce[i], s, sizeof(q->sound_periodicannounce[i]));
885 if (i == MAX_PERIODIC_ANNOUNCEMENTS)
889 ast_copy_string(q->sound_periodicannounce[0], val, sizeof(q->sound_periodicannounce[0]));
891 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
892 q->periodicannouncefrequency = atoi(val);
893 } else if (!strcasecmp(param, "retry")) {
894 q->retry = atoi(val);
896 q->retry = DEFAULT_RETRY;
897 } else if (!strcasecmp(param, "wrapuptime")) {
898 q->wrapuptime = atoi(val);
899 } else if (!strcasecmp(param, "autofill")) {
900 q->autofill = ast_true(val);
901 } else if (!strcasecmp(param, "monitor-type")) {
902 if (!strcasecmp(val, "mixmonitor"))
904 } else if (!strcasecmp(param, "autopause")) {
905 q->autopause = ast_true(val);
906 } else if (!strcasecmp(param, "maxlen")) {
907 q->maxlen = atoi(val);
910 } else if (!strcasecmp(param, "servicelevel")) {
911 q->servicelevel= atoi(val);
912 } else if (!strcasecmp(param, "strategy")) {
913 q->strategy = strat2int(val);
914 if (q->strategy < 0) {
915 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
917 q->strategy = QUEUE_STRATEGY_RINGALL;
919 } else if (!strcasecmp(param, "joinempty")) {
920 if (!strcasecmp(val, "loose"))
921 q->joinempty = QUEUE_EMPTY_LOOSE;
922 else if (!strcasecmp(val, "strict"))
923 q->joinempty = QUEUE_EMPTY_STRICT;
924 else if (ast_true(val))
925 q->joinempty = QUEUE_EMPTY_NORMAL;
928 } else if (!strcasecmp(param, "leavewhenempty")) {
929 if (!strcasecmp(val, "loose"))
930 q->leavewhenempty = QUEUE_EMPTY_LOOSE;
931 else if (!strcasecmp(val, "strict"))
932 q->leavewhenempty = QUEUE_EMPTY_STRICT;
933 else if (ast_true(val))
934 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
936 q->leavewhenempty = 0;
937 } else if (!strcasecmp(param, "eventmemberstatus")) {
938 q->maskmemberstatus = !ast_true(val);
939 } else if (!strcasecmp(param, "eventwhencalled")) {
940 if (!strcasecmp(val, "vars")) {
941 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
943 q->eventwhencalled = ast_true(val);
945 } else if (!strcasecmp(param, "reportholdtime")) {
946 q->reportholdtime = ast_true(val);
947 } else if (!strcasecmp(param, "memberdelay")) {
948 q->memberdelay = atoi(val);
949 } else if (!strcasecmp(param, "weight")) {
950 q->weight = atoi(val);
953 /* With Realtime queues, if the last queue using weights is deleted in realtime,
954 we will not see any effect on use_weight until next reload. */
955 } else if (!strcasecmp(param, "timeoutrestart")) {
956 q->timeoutrestart = ast_true(val);
957 } else if (failunknown) {
959 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
960 q->name, param, linenum);
962 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
967 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
969 struct member *m, *prev_m;
974 penalty = atoi(penalty_str);
980 paused = atoi(paused_str);
985 /* Find the member, or the place to put a new one. */
986 for (m = q->members, prev_m = NULL;
987 m && strcmp(m->interface, interface);
988 prev_m = m, m = m->next);
990 /* Create a new one if not found, else update penalty */
992 if ((m = create_queue_member(interface, membername, penalty, paused))) {
994 add_to_interfaces(interface);
1002 m->dead = 0; /* Do not delete this one. */
1005 m->penalty = penalty;
1009 static void free_members(struct call_queue *q, int all)
1011 /* Free non-dynamic members */
1012 struct member *curm, *next, *prev = NULL;
1014 for (curm = q->members; curm; curm = next) {
1016 if (all || !curm->dynamic) {
1021 remove_from_interfaces(curm->interface);
1028 static void destroy_queue(struct call_queue *q)
1031 ast_mutex_destroy(&q->lock);
1035 /*!\brief Reload a single queue via realtime.
1036 \return Return the queue, or NULL if it doesn't exist.
1037 \note Should be called with the global qlock locked. */
1038 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
1040 struct ast_variable *v;
1041 struct call_queue *q;
1042 struct member *m, *prev_m, *next_m;
1043 char *interface = NULL;
1044 char *tmp, *tmp_name;
1045 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
1047 /* Find the queue in the in-core list (we will create a new one if not found). */
1048 AST_LIST_TRAVERSE(&queues, q, list) {
1049 if (!strcasecmp(q->name, queuename))
1053 /* Static queues override realtime. */
1055 ast_mutex_lock(&q->lock);
1058 ast_mutex_unlock(&q->lock);
1061 ast_mutex_unlock(&q->lock);
1065 } else if (!member_config)
1066 /* Not found in the list, and it's not realtime ... */
1069 /* Check if queue is defined in realtime. */
1071 /* Delete queue from in-core list if it has been deleted in realtime. */
1073 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1074 found condition... So we might delete an in-core queue
1075 in case of DB failure. */
1077 ast_log(LOG_DEBUG, "Queue %s not found in realtime.\n", queuename);
1080 /* Delete if unused (else will be deleted when last caller leaves). */
1083 AST_LIST_REMOVE(&queues, q, list);
1084 ast_mutex_unlock(&q->lock);
1087 ast_mutex_unlock(&q->lock);
1092 /* Create a new queue if an in-core entry does not exist yet. */
1094 if (!(q = alloc_queue(queuename)))
1096 ast_mutex_lock(&q->lock);
1099 AST_LIST_INSERT_HEAD(&queues, q, list);
1101 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1103 memset(tmpbuf, 0, sizeof(tmpbuf));
1104 for (v = queue_vars; v; v = v->next) {
1105 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1106 if ((tmp = strchr(v->name, '_'))) {
1107 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1110 while ((tmp = strchr(tmp, '_')))
1114 queue_set_param(q, tmp_name, v->value, -1, 0);
1117 /* Temporarily set non-dynamic members dead so we can detect deleted ones. */
1118 for (m = q->members; m; m = m->next) {
1123 while ((interface = ast_category_browse(member_config, interface))) {
1124 rt_handle_member_record(q, interface,
1125 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1126 ast_variable_retrieve(member_config, interface, "penalty"),
1127 ast_variable_retrieve(member_config, interface, "paused"));
1130 /* Delete all realtime members that have been deleted in DB. */
1137 prev_m->next = next_m;
1139 q->members = next_m;
1141 remove_from_interfaces(m->interface);
1149 ast_mutex_unlock(&q->lock);
1154 static struct call_queue *load_realtime_queue(const char *queuename)
1156 struct ast_variable *queue_vars;
1157 struct ast_config *member_config = NULL;
1158 struct call_queue *q;
1160 /* Find the queue in the in-core list first. */
1161 AST_LIST_LOCK(&queues);
1162 AST_LIST_TRAVERSE(&queues, q, list) {
1163 if (!strcasecmp(q->name, queuename)) {
1167 AST_LIST_UNLOCK(&queues);
1169 if (!q || q->realtime) {
1170 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1171 queue operations while waiting for the DB.
1173 This will be two separate database transactions, so we might
1174 see queue parameters as they were before another process
1175 changed the queue and member list as it was after the change.
1176 Thus we might see an empty member list when a queue is
1177 deleted. In practise, this is unlikely to cause a problem. */
1179 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1181 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1182 if (!member_config) {
1183 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1188 AST_LIST_LOCK(&queues);
1190 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1192 ast_config_destroy(member_config);
1194 ast_variables_destroy(queue_vars);
1196 AST_LIST_UNLOCK(&queues);
1201 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1203 struct call_queue *q;
1204 struct queue_ent *cur, *prev = NULL;
1208 enum queue_member_status stat;
1210 if (!(q = load_realtime_queue(queuename)))
1213 AST_LIST_LOCK(&queues);
1214 ast_mutex_lock(&q->lock);
1216 /* This is our one */
1217 stat = get_member_status(q, qe->max_penalty);
1218 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1219 *reason = QUEUE_JOINEMPTY;
1220 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
1221 *reason = QUEUE_JOINUNAVAIL;
1222 else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1223 *reason = QUEUE_JOINUNAVAIL;
1224 else if (q->maxlen && (q->count >= q->maxlen))
1225 *reason = QUEUE_FULL;
1227 /* There's space for us, put us at the right position inside
1229 * Take into account the priority of the calling user */
1234 /* We have higher priority than the current user, enter
1235 * before him, after all the other users with priority
1236 * higher or equal to our priority. */
1237 if ((!inserted) && (qe->prio > cur->prio)) {
1238 insert_entry(q, prev, qe, &pos);
1245 /* No luck, join at the end of the queue */
1247 insert_entry(q, prev, qe, &pos);
1248 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1249 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1250 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1253 manager_event(EVENT_FLAG_CALL, "Join",
1254 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1256 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1257 S_OR(qe->chan->cid.cid_name, "unknown"),
1258 q->name, qe->pos, q->count, qe->chan->uniqueid );
1260 ast_log(LOG_DEBUG, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1262 ast_mutex_unlock(&q->lock);
1263 AST_LIST_UNLOCK(&queues);
1268 static int play_file(struct ast_channel *chan, char *filename)
1272 ast_stopstream(chan);
1273 res = ast_streamfile(chan, filename, chan->language);
1275 res = ast_waitstream(chan, AST_DIGIT_ANY);
1276 ast_stopstream(chan);
1281 static int valid_exit(struct queue_ent *qe, char digit)
1283 int digitlen = strlen(qe->digits);
1285 /* Prevent possible buffer overflow */
1286 if (digitlen < sizeof(qe->digits) - 2) {
1287 qe->digits[digitlen] = digit;
1288 qe->digits[digitlen + 1] = '\0';
1290 qe->digits[0] = '\0';
1294 /* If there's no context to goto, short-circuit */
1295 if (ast_strlen_zero(qe->context))
1298 /* If the extension is bad, then reset the digits to blank */
1299 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1300 qe->digits[0] = '\0';
1304 /* We have an exact match */
1305 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1306 /* Return 1 on a successful goto */
1313 static int say_position(struct queue_ent *qe)
1315 int res = 0, avgholdmins, avgholdsecs;
1318 /* Let minannouncefrequency seconds pass between the start of each position announcement */
1320 if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
1323 /* If either our position has changed, or we are over the freq timer, say position */
1324 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1327 ast_moh_stop(qe->chan);
1328 /* Say we're next, if we are */
1330 res = play_file(qe->chan, qe->parent->sound_next);
1331 if (res && valid_exit(qe, res))
1336 res = play_file(qe->chan, qe->parent->sound_thereare);
1337 if (res && valid_exit(qe, res))
1339 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1340 if (res && valid_exit(qe, res))
1342 res = play_file(qe->chan, qe->parent->sound_calls);
1343 if (res && valid_exit(qe, res))
1346 /* Round hold time to nearest minute */
1347 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1349 /* If they have specified a rounding then round the seconds as well */
1350 if (qe->parent->roundingseconds) {
1351 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1352 avgholdsecs *= qe->parent->roundingseconds;
1357 if (option_verbose > 2)
1358 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1360 /* If the hold time is >1 min, if it's enabled, and if it's not
1361 supposed to be only once and we have already said it, say it */
1362 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1363 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1364 res = play_file(qe->chan, qe->parent->sound_holdtime);
1365 if (res && valid_exit(qe, res))
1368 if (avgholdmins > 0) {
1369 if (avgholdmins < 2) {
1370 res = play_file(qe->chan, qe->parent->sound_lessthan);
1371 if (res && valid_exit(qe, res))
1374 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1375 if (res && valid_exit(qe, res))
1378 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1379 if (res && valid_exit(qe, res))
1383 res = play_file(qe->chan, qe->parent->sound_minutes);
1384 if (res && valid_exit(qe, res))
1387 if (avgholdsecs>0) {
1388 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1389 if (res && valid_exit(qe, res))
1392 res = play_file(qe->chan, qe->parent->sound_seconds);
1393 if (res && valid_exit(qe, res))
1400 if (option_verbose > 2)
1401 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n",
1402 qe->chan->name, qe->parent->name, qe->pos);
1403 res = play_file(qe->chan, qe->parent->sound_thanks);
1404 if (res && !valid_exit(qe, res))
1408 /* Set our last_pos indicators */
1410 qe->last_pos_said = qe->pos;
1412 /* Don't restart music on hold if we're about to exit the caller from the queue */
1414 ast_moh_start(qe->chan, qe->moh, NULL);
1419 static void recalc_holdtime(struct queue_ent *qe)
1421 int oldvalue, newvalue;
1423 /* Calculate holdtime using a recursive boxcar filter */
1424 /* Thanks to SRT for this contribution */
1425 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1427 newvalue = time(NULL) - qe->start;
1429 ast_mutex_lock(&qe->parent->lock);
1430 if (newvalue <= qe->parent->servicelevel)
1431 qe->parent->callscompletedinsl++;
1432 oldvalue = qe->parent->holdtime;
1433 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2;
1434 ast_mutex_unlock(&qe->parent->lock);
1438 static void leave_queue(struct queue_ent *qe)
1440 struct call_queue *q;
1441 struct queue_ent *cur, *prev = NULL;
1444 if (!(q = qe->parent))
1446 ast_mutex_lock(&q->lock);
1449 for (cur = q->head; cur; cur = cur->next) {
1453 /* Take us out of the queue */
1454 manager_event(EVENT_FLAG_CALL, "Leave",
1455 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1456 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1458 ast_log(LOG_DEBUG, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1459 /* Take us out of the queue */
1461 prev->next = cur->next;
1463 q->head = cur->next;
1465 /* Renumber the people after us in the queue based on a new count */
1470 ast_mutex_unlock(&q->lock);
1472 if (q->dead && !q->count) {
1473 /* It's dead and nobody is in it, so kill it */
1474 AST_LIST_LOCK(&queues);
1475 AST_LIST_REMOVE(&queues, q, list);
1476 AST_LIST_UNLOCK(&queues);
1481 /* Hang up a list of outgoing calls */
1482 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1484 struct callattempt *oo;
1487 /* Hangup any existing lines we have open */
1488 if (outgoing->chan && (outgoing->chan != exception))
1489 ast_hangup(outgoing->chan);
1491 outgoing = outgoing->q_next;
1496 static int update_status(struct call_queue *q, struct member *member, int status)
1500 /* Since a reload could have taken place, we have to traverse the list to
1501 be sure it's still valid */
1502 ast_mutex_lock(&q->lock);
1503 for (cur = q->members; cur; cur = cur->next) {
1507 cur->status = status;
1508 if (!q->maskmemberstatus) {
1509 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1512 "MemberName: %s\r\n"
1513 "Membership: %s\r\n"
1515 "CallsTaken: %d\r\n"
1519 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
1520 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1523 ast_mutex_unlock(&q->lock);
1527 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1529 if (status == AST_CAUSE_BUSY)
1530 status = AST_DEVICE_BUSY;
1531 else if (status == AST_CAUSE_UNREGISTERED)
1532 status = AST_DEVICE_UNAVAILABLE;
1533 else if (status == AST_CAUSE_NOSUCHDRIVER)
1534 status = AST_DEVICE_INVALID;
1536 status = AST_DEVICE_UNKNOWN;
1537 return update_status(q, member, status);
1540 /* traverse all defined queues which have calls waiting and contain this member
1541 return 0 if no other queue has precedence (higher weight) or 1 if found */
1542 static int compare_weight(struct call_queue *rq, struct member *member)
1544 struct call_queue *q;
1548 /* &qlock and &rq->lock already set by try_calling()
1549 * to solve deadlock */
1550 AST_LIST_TRAVERSE(&queues, q, list) {
1551 if (q == rq) /* don't check myself, could deadlock */
1553 ast_mutex_lock(&q->lock);
1554 if (q->count && q->members) {
1555 for (mem = q->members; mem; mem = mem->next) {
1556 if (strcmp(mem->interface, member->interface))
1560 ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1561 if (q->weight > rq->weight) {
1563 ast_log(LOG_DEBUG, "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);
1569 ast_mutex_unlock(&q->lock);
1576 /*! \brief common hangup actions */
1577 static void do_hang(struct callattempt *o)
1580 ast_hangup(o->chan);
1584 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1586 struct ast_str *buf = ast_str_alloca(len + 1);
1589 if (pbx_builtin_serialize_variables(chan, &buf)) {
1592 /* convert "\n" to "\nVariable: " */
1593 strcpy(vars, "Variable: ");
1596 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1599 if (tmp[i + 1] == '\0')
1601 if (tmp[i] == '\n') {
1605 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1615 /* there are no channel variables; leave it blank */
1621 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1628 /* on entry here, we know that tmp->chan == NULL */
1629 if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1631 ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
1633 ast_cdr_busy(qe->chan->cdr);
1634 tmp->stillgoing = 0;
1639 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1641 ast_log(LOG_DEBUG, "%s in use, can't receive call\n", tmp->interface);
1643 ast_cdr_busy(qe->chan->cdr);
1644 tmp->stillgoing = 0;
1648 if (tmp->member->paused) {
1650 ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
1652 ast_cdr_busy(qe->chan->cdr);
1653 tmp->stillgoing = 0;
1656 if (use_weight && compare_weight(qe->parent,tmp->member)) {
1658 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1660 ast_cdr_busy(qe->chan->cdr);
1661 tmp->stillgoing = 0;
1666 ast_copy_string(tech, tmp->interface, sizeof(tech));
1667 if ((location = strchr(tech, '/')))
1672 /* Request the peer */
1673 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1674 if (!tmp->chan) { /* If we can't, just go on to the next call */
1676 ast_cdr_busy(qe->chan->cdr);
1677 tmp->stillgoing = 0;
1678 update_dial_status(qe->parent, tmp->member, status);
1680 ast_mutex_lock(&qe->parent->lock);
1681 qe->parent->rrpos++;
1682 ast_mutex_unlock(&qe->parent->lock);
1686 } else if (status != tmp->oldstatus)
1687 update_dial_status(qe->parent, tmp->member, status);
1689 tmp->chan->appl = "AppQueue";
1690 tmp->chan->data = "(Outgoing Line)";
1691 tmp->chan->whentohangup = 0;
1692 if (tmp->chan->cid.cid_num)
1693 free(tmp->chan->cid.cid_num);
1694 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1695 if (tmp->chan->cid.cid_name)
1696 free(tmp->chan->cid.cid_name);
1697 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1698 if (tmp->chan->cid.cid_ani)
1699 free(tmp->chan->cid.cid_ani);
1700 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1702 /* Inherit specially named variables from parent channel */
1703 ast_channel_inherit_variables(qe->chan, tmp->chan);
1705 /* Presense of ADSI CPE on outgoing channel follows ours */
1706 tmp->chan->adsicpe = qe->chan->adsicpe;
1708 /* Place the call, but don't wait on the answer */
1709 if ((res = ast_call(tmp->chan, location, 0))) {
1710 /* Again, keep going even if there's an error */
1712 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1713 if (option_verbose > 2)
1714 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
1718 } else if (qe->parent->eventwhencalled) {
1721 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1722 "AgentCalled: %s\r\n"
1723 "ChannelCalling: %s\r\n"
1724 "CallerIDNum: %s\r\n"
1725 "CallerIDName: %s\r\n"
1730 tmp->interface, qe->chan->name,
1731 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1732 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1733 qe->chan->context, qe->chan->exten, qe->chan->priority,
1734 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
1735 if (option_verbose > 2)
1736 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
1742 /*! \brief find the entry with the best metric, or NULL */
1743 static struct callattempt *find_best(struct callattempt *outgoing)
1745 struct callattempt *best = NULL, *cur;
1747 for (cur = outgoing; cur; cur = cur->q_next) {
1748 if (cur->stillgoing && /* Not already done */
1749 !cur->chan && /* Isn't already going */
1750 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
1758 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
1763 struct callattempt *best = find_best(outgoing);
1766 ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
1769 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
1770 struct callattempt *cur;
1771 /* Ring everyone who shares this best metric (for ringall) */
1772 for (cur = outgoing; cur; cur = cur->q_next) {
1773 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
1775 ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1776 ring_entry(qe, cur, busies);
1780 /* Ring just the best channel */
1782 ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
1783 ring_entry(qe, best, busies);
1785 if (best->chan) /* break out with result = 1 */
1792 static int store_next(struct queue_ent *qe, struct callattempt *outgoing)
1794 struct callattempt *best = find_best(outgoing);
1797 /* Ring just the best channel */
1799 ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
1800 qe->parent->rrpos = best->metric % 1000;
1802 /* Just increment rrpos */
1803 if (qe->parent->wrapped) {
1804 /* No more channels, start over */
1805 qe->parent->rrpos = 0;
1807 /* Prioritize next entry */
1808 qe->parent->rrpos++;
1811 qe->parent->wrapped = 0;
1816 static int background_file(struct queue_ent *qe, struct ast_channel *chan, char *filename)
1820 ast_stopstream(chan);
1821 res = ast_streamfile(chan, filename, chan->language);
1824 /* Wait for a keypress */
1825 res = ast_waitstream(chan, AST_DIGIT_ANY);
1826 if (res < 0 || !valid_exit(qe, res))
1830 ast_stopstream(chan);
1836 static int say_periodic_announcement(struct queue_ent *qe)
1841 /* Get the current time */
1844 /* Check to see if it is time to announce */
1845 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
1848 /* Stop the music on hold so we can play our own file */
1849 ast_moh_stop(qe->chan);
1851 if (option_verbose > 2)
1852 ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n");
1854 /* Check to make sure we have a sound file. If not, reset to the first sound file */
1855 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || !strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
1856 qe->last_periodic_announce_sound = 0;
1859 /* play the announcement */
1860 res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
1862 /* Resume Music on Hold if the caller is going to stay in the queue */
1864 ast_moh_start(qe->chan, qe->moh, NULL);
1866 /* update last_periodic_announce_time */
1867 qe->last_periodic_announce_time = now;
1869 /* Update the current periodic announcement to the next announcement */
1870 qe->last_periodic_announce_sound++;
1875 static void record_abandoned(struct queue_ent *qe)
1877 ast_mutex_lock(&qe->parent->lock);
1878 set_queue_variables(qe);
1879 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
1883 "OriginalPosition: %d\r\n"
1885 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
1887 qe->parent->callsabandoned++;
1888 ast_mutex_unlock(&qe->parent->lock);
1891 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
1892 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
1894 if (option_verbose > 2)
1895 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", rnatime);
1896 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
1897 if (qe->parent->autopause) {
1898 if (!set_member_paused(qe->parent->name, interface, 1)) {
1899 if (option_verbose > 2)
1900 ast_verbose( VERBOSE_PREFIX_3 "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
1902 if (option_verbose > 2)
1903 ast_verbose( VERBOSE_PREFIX_3 "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
1909 #define AST_MAX_WATCHERS 256
1911 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
1913 char *queue = qe->parent->name;
1914 struct callattempt *o;
1916 int sentringing = 0;
1917 int numbusies = prebusies;
1921 struct ast_frame *f;
1922 struct callattempt *peer = NULL;
1923 struct ast_channel *winner;
1924 struct ast_channel *in = qe->chan;
1926 char membername[80] = "";
1930 starttime = (long) time(NULL);
1932 while (*to && !peer) {
1933 int numlines, retry, pos = 1;
1934 struct ast_channel *watchers[AST_MAX_WATCHERS];
1937 for (retry = 0; retry < 2; retry++) {
1939 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
1940 if (o->stillgoing) { /* Keep track of important channels */
1943 watchers[pos++] = o->chan;
1947 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
1948 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
1950 /* On "ringall" strategy we only move to the next penalty level
1951 when *all* ringing phones are done in the current penalty level */
1952 ring_one(qe, outgoing, &numbusies);
1955 if (pos == 1 /* not found */) {
1956 if (numlines == (numbusies + numnochan)) {
1958 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1960 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1965 winner = ast_waitfor_n(watchers, pos, to);
1966 for (o = outgoing; o; o = o->q_next) {
1967 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
1969 if (option_verbose > 2)
1970 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1973 } else if (o->chan && (o->chan == winner)) {
1975 ast_copy_string(on, o->member->interface, sizeof(on));
1976 ast_copy_string(membername, o->member->membername, sizeof(membername));
1978 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
1979 if (option_verbose > 2)
1980 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
1985 } else if (!ast_strlen_zero(o->chan->call_forward)) {
1990 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
1991 if ((stuff = strchr(tmpchan, '/'))) {
1995 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1999 /* Before processing channel, go ahead and check for forwarding */
2000 if (option_verbose > 2)
2001 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2002 /* Setup parameters */
2003 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2004 if (status != o->oldstatus)
2005 update_dial_status(qe->parent, o->member, status);
2007 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
2011 ast_channel_inherit_variables(in, o->chan);
2012 if (o->chan->cid.cid_num)
2013 free(o->chan->cid.cid_num);
2014 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
2016 if (o->chan->cid.cid_name)
2017 free(o->chan->cid.cid_name);
2018 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
2020 ast_string_field_set(o->chan, accountcode, in->accountcode);
2021 o->chan->cdrflags = in->cdrflags;
2023 if (in->cid.cid_ani) {
2024 if (o->chan->cid.cid_ani)
2025 free(o->chan->cid.cid_ani);
2026 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
2028 if (o->chan->cid.cid_rdnis)
2029 free(o->chan->cid.cid_rdnis);
2030 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
2031 if (ast_call(o->chan, tmpchan, 0)) {
2032 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
2037 /* Hangup the original channel now, in case we needed it */
2041 f = ast_read(winner);
2043 if (f->frametype == AST_FRAME_CONTROL) {
2044 switch (f->subclass) {
2045 case AST_CONTROL_ANSWER:
2046 /* This is our guy if someone answered. */
2048 if (option_verbose > 2)
2049 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
2053 case AST_CONTROL_BUSY:
2054 if (option_verbose > 2)
2055 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
2057 ast_cdr_busy(in->cdr);
2059 endtime = (long) time(NULL);
2060 endtime -= starttime;
2061 rna(endtime*1000, qe, on, membername);
2062 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2063 if (qe->parent->timeoutrestart)
2065 ring_one(qe, outgoing, &numbusies);
2069 case AST_CONTROL_CONGESTION:
2070 if (option_verbose > 2)
2071 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
2073 ast_cdr_busy(in->cdr);
2074 endtime = (long) time(NULL);
2075 endtime -= starttime;
2076 rna(endtime*1000, qe, on, membername);
2078 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2079 if (qe->parent->timeoutrestart)
2081 ring_one(qe, outgoing, &numbusies);
2085 case AST_CONTROL_RINGING:
2086 if (option_verbose > 2)
2087 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
2090 ast_indicate(in, AST_CONTROL_RINGING);
2095 case AST_CONTROL_OFFHOOK:
2096 /* Ignore going off hook */
2100 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
2105 endtime = (long) time(NULL) - starttime;
2106 rna(endtime * 1000, qe, on, membername);
2108 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2109 if (qe->parent->timeoutrestart)
2111 ring_one(qe, outgoing, &numbusies);
2118 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2125 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2126 if (option_verbose > 3)
2127 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
2132 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass)) {
2133 if (option_verbose > 3)
2134 ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass);
2136 *digit = f->subclass;
2143 rna(orig, qe, on, membername);
2149 static int is_our_turn(struct queue_ent *qe)
2151 struct queue_ent *ch;
2157 if (!qe->parent->autofill) {
2158 /* Atomically read the parent head -- does not need a lock */
2159 ch = qe->parent->head;
2160 /* If we are now at the top of the head, break out */
2163 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2167 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2172 /* This needs a lock. How many members are available to be served? */
2173 ast_mutex_lock(&qe->parent->lock);
2175 ch = qe->parent->head;
2177 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2179 ast_log(LOG_DEBUG, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in\n", avl);
2182 for (cur = qe->parent->members; cur; cur = cur->next) {
2183 switch (cur->status) {
2184 case AST_DEVICE_NOT_INUSE:
2185 case AST_DEVICE_UNKNOWN:
2193 ast_log(LOG_DEBUG, "There are %d available members.\n", avl);
2195 while ((idx < avl) && (ch) && (ch != qe)) {
2200 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2201 if (ch && idx < avl) {
2203 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2207 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2211 ast_mutex_unlock(&qe->parent->lock);
2217 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2221 /* This is the holding pen for callers 2 through maxlen */
2223 enum queue_member_status stat;
2225 if (is_our_turn(qe))
2228 /* If we have timed out, break out */
2229 if (qe->expire && (time(NULL) > qe->expire)) {
2230 *reason = QUEUE_TIMEOUT;
2234 stat = get_member_status(qe->parent, qe->max_penalty);
2236 /* leave the queue if no agents, if enabled */
2237 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2238 *reason = QUEUE_LEAVEEMPTY;
2239 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2244 /* leave the queue if no reachable agents, if enabled */
2245 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
2246 *reason = QUEUE_LEAVEUNAVAIL;
2247 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2251 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2252 *reason = QUEUE_LEAVEUNAVAIL;
2253 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2258 /* Make a position announcement, if enabled */
2259 if (qe->parent->announcefrequency && !ringing &&
2260 (res = say_position(qe)))
2263 /* Make a periodic announcement, if enabled */
2264 if (qe->parent->periodicannouncefrequency && !ringing &&
2265 (res = say_periodic_announcement(qe)))
2268 /* Wait a second before checking again */
2269 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000)))
2276 static int update_queue(struct call_queue *q, struct member *member)
2280 /* Since a reload could have taken place, we have to traverse the list to
2281 be sure it's still valid */
2282 ast_mutex_lock(&q->lock);
2285 if (member == cur) {
2286 time(&cur->lastcall);
2292 q->callscompleted++;
2293 ast_mutex_unlock(&q->lock);
2297 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2299 if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2302 switch (q->strategy) {
2303 case QUEUE_STRATEGY_RINGALL:
2304 /* Everyone equal, except for penalty */
2305 tmp->metric = mem->penalty * 1000000;
2307 case QUEUE_STRATEGY_RRMEMORY:
2308 if (pos < q->rrpos) {
2309 tmp->metric = 1000 + pos;
2312 /* Indicate there is another priority */
2316 tmp->metric += mem->penalty * 1000000;
2318 case QUEUE_STRATEGY_RANDOM:
2319 tmp->metric = ast_random() % 1000;
2320 tmp->metric += mem->penalty * 1000000;
2322 case QUEUE_STRATEGY_FEWESTCALLS:
2323 tmp->metric = mem->calls;
2324 tmp->metric += mem->penalty * 1000000;
2326 case QUEUE_STRATEGY_LEASTRECENT:
2330 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2331 tmp->metric += mem->penalty * 1000000;
2334 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2340 enum agent_complete_reason {
2346 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
2347 const struct ast_channel *peer, const struct member *member, time_t callstart,
2348 char *vars, size_t vars_len, enum agent_complete_reason rsn)
2352 if (!qe->parent->eventwhencalled)
2363 reason = "transfer";
2367 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2372 "MemberName: %s\r\n"
2377 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2378 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
2379 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
2382 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on, const char *agi, const char *macro)
2385 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2387 char oldexten[AST_MAX_EXTENSION]="";
2388 char oldcontext[AST_MAX_CONTEXT]="";
2389 char queuename[256]="";
2390 char interfacevar[256]="";
2391 struct ast_channel *peer;
2392 struct ast_channel *which;
2393 struct callattempt *lpeer;
2394 struct member *member;
2395 struct ast_app *app;
2396 int res = 0, bridge = 0;
2399 char *announce = NULL;
2402 time_t now = time(NULL);
2403 struct ast_bridge_config bridge_config;
2404 char nondataquality = 1;
2405 char *agiexec = NULL;
2406 char *macroexec = NULL;
2408 const char *monitorfilename;
2409 const char *monitor_exec;
2410 const char *monitor_options;
2411 char tmpid[256], tmpid2[256];
2412 char meid[1024], meid2[1024];
2413 char mixmonargs[1512];
2414 struct ast_app *mixmonapp = NULL;
2417 int forwardsallowed = 1;
2418 memset(&bridge_config, 0, sizeof(bridge_config));
2421 for (; options && *options; options++)
2424 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2427 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2430 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2433 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2439 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2442 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2445 if ((now - qe->start >= qe->parent->timeout))
2449 forwardsallowed = 0;
2453 /* Hold the lock while we setup the outgoing calls */
2455 AST_LIST_LOCK(&queues);
2456 ast_mutex_lock(&qe->parent->lock);
2458 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n",
2460 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2461 cur = qe->parent->members;
2462 if (!ast_strlen_zero(qe->announce))
2463 announce = qe->announce;
2464 if (!ast_strlen_zero(announceoverride))
2465 announce = announceoverride;
2467 for (; cur; cur = cur->next) {
2468 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2471 ast_mutex_unlock(&qe->parent->lock);
2473 AST_LIST_UNLOCK(&queues);
2476 tmp->stillgoing = -1;
2477 tmp->member = cur; /* Never directly dereference! Could change on reload */
2478 tmp->oldstatus = cur->status;
2479 tmp->lastcall = cur->lastcall;
2480 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2481 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2482 just calculate their metric for the appropriate strategy */
2483 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2484 /* Put them in the list of outgoing thingies... We're ready now.
2485 XXX If we're forcibly removed, these outgoing calls won't get
2487 tmp->q_next = outgoing;
2489 /* If this line is up, don't try anybody else */
2490 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2496 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2497 to = (qe->expire - now) * 1000;
2499 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2500 ring_one(qe, outgoing, &numbusies);
2501 ast_mutex_unlock(&qe->parent->lock);
2503 AST_LIST_UNLOCK(&queues);
2504 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2505 ast_mutex_lock(&qe->parent->lock);
2506 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2507 store_next(qe, outgoing);
2509 ast_mutex_unlock(&qe->parent->lock);
2510 peer = lpeer ? lpeer->chan : NULL;
2513 /* Must gotten hung up */
2519 ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
2520 } else { /* peer is valid */
2521 /* Ah ha! Someone answered within the desired timeframe. Of course after this
2522 we will always return with -1 so that it is hung up properly after the
2525 if (!strcmp(qe->chan->tech->type, "Zap"))
2526 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2527 if (!strcmp(peer->tech->type, "Zap"))
2528 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2529 /* Update parameters for the queue */
2530 recalc_holdtime(qe);
2531 member = lpeer->member;
2532 hangupcalls(outgoing, peer);
2534 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2537 res2 = ast_autoservice_start(qe->chan);
2539 if (qe->parent->memberdelay) {
2540 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2541 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2543 if (!res2 && announce) {
2544 if (play_file(peer, announce))
2545 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2547 if (!res2 && qe->parent->reportholdtime) {
2548 if (!play_file(peer, qe->parent->sound_reporthold)) {
2552 holdtime = abs((now - qe->start) / 60);
2554 play_file(peer, qe->parent->sound_lessthan);
2555 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2557 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2558 play_file(peer, qe->parent->sound_minutes);
2562 res2 |= ast_autoservice_stop(qe->chan);
2563 if (peer->_softhangup) {
2564 /* Agent must have hung up */
2565 ast_log(LOG_WARNING, "Agent on %s hungup on the customer. They're going to be pissed.\n", peer->name);
2566 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2567 record_abandoned(qe);
2568 if (qe->parent->eventwhencalled)
2569 manager_event(EVENT_FLAG_AGENT, "AgentDump",
2574 "MemberName: %s\r\n"
2576 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2577 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2581 /* Caller must have hung up just before being connected*/
2582 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2583 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
2584 record_abandoned(qe);
2589 /* Stop music on hold */
2590 ast_moh_stop(qe->chan);
2591 /* If appropriate, log that we have a destination channel */
2593 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2594 /* Make sure channels are compatible */
2595 res = ast_channel_make_compatible(qe->chan, peer);
2597 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
2598 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2599 record_abandoned(qe);
2603 /* Begin Monitoring */
2604 if (qe->parent->monfmt && *qe->parent->monfmt) {
2605 if (!qe->parent->montype) {
2607 ast_log(LOG_DEBUG, "Starting Monitor as requested.\n");
2608 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2609 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2613 if (monitorfilename)
2614 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2615 else if (qe->chan->cdr)
2616 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2618 /* Last ditch effort -- no CDR, make up something */
2619 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2620 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2622 if (qe->parent->monjoin)
2623 ast_monitor_setjoinfiles(which, 1);
2626 ast_log(LOG_DEBUG, "Starting MixMonitor as requested.\n");
2627 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2628 if (!monitorfilename) {
2630 ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid)-1);
2632 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2634 ast_copy_string(tmpid2, monitorfilename, sizeof(tmpid2)-1);
2635 for (p = tmpid2; *p ; p++) {
2636 if (*p == '^' && *(p+1) == '{') {
2641 memset(tmpid, 0, sizeof(tmpid));
2642 pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
2645 monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC");
2646 monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS");
2649 ast_copy_string(meid2, monitor_exec, sizeof(meid2)-1);
2650 for (p = meid2; *p ; p++) {
2651 if (*p == '^' && *(p+1) == '{') {
2656 memset(meid, 0, sizeof(meid));
2657 pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
2660 snprintf(tmpid2, sizeof(tmpid2)-1, "%s.%s", tmpid, qe->parent->monfmt);
2662 mixmonapp = pbx_findapp("MixMonitor");
2664 if (strchr(tmpid2, '|')) {
2665 ast_log(LOG_WARNING, "monitor-format (in queues.conf) and MONITOR_FILENAME cannot contain a '|'! Not recording.\n");
2669 if (!monitor_options)
2670 monitor_options = "";
2672 if (strchr(monitor_options, '|')) {
2673 ast_log(LOG_WARNING, "MONITOR_OPTIONS cannot contain a '|'! Not recording.\n");
2678 if (!ast_strlen_zero(monitor_exec))
2679 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s|%s", tmpid2, monitor_options, monitor_exec);
2681 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s", tmpid2, monitor_options);
2684 ast_log(LOG_DEBUG, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
2686 ret = pbx_exec(qe->chan, mixmonapp, mixmonargs);
2689 ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
2693 /* Drop out of the queue at this point, to prepare for next caller */
2695 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2697 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2698 ast_channel_sendurl(peer, url);
2701 ast_mutex_lock(&qe->parent->lock);
2702 /* if setinterfacevar is defined, make member variables available to the channel */
2703 /* use pbx_builtin_setvar to set a load of variables with one call */
2704 if (qe->parent->setinterfacevar) {
2705 snprintf(interfacevar,sizeof(interfacevar), "MEMBERINTERFACE=%s|MEMBERNAME=%s|MEMBERCALLS=%d|MEMBERLASTCALL=%ld|MEMBERPENALTY=%d|MEMBERDYNAMIC=%d",
2706 member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic);
2707 pbx_builtin_setvar(qe->chan, interfacevar);
2710 /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
2711 /* use pbx_builtin_setvar to set a load of variables with one call */
2712 if (qe->parent->setqueueentryvar) {
2713 snprintf(interfacevar,sizeof(interfacevar), "QEHOLDTIME=%ld|QEORIGINALPOS=%d",
2714 (long) time(NULL) - qe->start, qe->opos);
2715 pbx_builtin_setvar(qe->chan, interfacevar);
2718 /* try to set queue variables if configured to do so*/
2719 set_queue_variables(qe);
2720 ast_mutex_unlock(&qe->parent->lock);
2722 /* run a macro for this connection if defined. The macro simply returns, no action is taken on the result */
2723 /* use macro from dialplan if passed as a option, otherwise use the default queue macro */
2724 if (!ast_strlen_zero(macro)) {
2725 macroexec = ast_strdupa(macro);
2727 if (qe->parent->membermacro)
2728 macroexec = ast_strdupa(qe->parent->membermacro);
2731 if (!ast_strlen_zero(macroexec)) {
2733 ast_log(LOG_DEBUG, "app_queue: macro=%s.\n", macroexec);
2735 res = ast_autoservice_start(qe->chan);
2737 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
2741 app = pbx_findapp("Macro");
2744 res = pbx_exec(qe->chan, app, macroexec);
2746 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
2749 ast_log(LOG_ERROR, "Could not find application Macro\n");
2753 if (ast_autoservice_stop(qe->chan) < 0) {
2754 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
2759 if (!ast_strlen_zero(agi)) {
2761 ast_log(LOG_DEBUG, "app_queue: agi=%s.\n", agi);
2762 app = pbx_findapp("agi");
2764 agiexec = ast_strdupa(agi);
2765 ret = pbx_exec(qe->chan, app, agiexec);
2767 ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
2769 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s", (long) time(NULL) - qe->start, peer->uniqueid);
2770 if (qe->parent->eventwhencalled)
2771 manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2776 "MemberName: %s\r\n"
2778 "BridgedChannel: %s\r\n"
2780 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2781 (long) time(NULL) - qe->start, peer->uniqueid,
2782 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2783 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2784 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2787 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2789 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2790 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
2791 qe->chan->exten, qe->chan->context, (long) (callstart - qe->start),
2792 (long) (time(NULL) - callstart));
2793 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
2794 } else if (qe->chan->_softhangup) {
2795 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETECALLER", "%ld|%ld|%d",
2796 (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
2797 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), CALLER);
2799 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETEAGENT", "%ld|%ld|%d",
2800 (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
2801 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), AGENT);
2804 if (bridge != AST_PBX_NO_HANGUP_PEER)
2806 update_queue(qe->parent, member);
2807 res = bridge ? bridge : 1;
2810 hangupcalls(outgoing, NULL);
2815 static int wait_a_bit(struct queue_ent *qe)
2817 /* Don't need to hold the lock while we setup the outgoing calls */
2818 int retrywait = qe->parent->retry * 1000;
2820 return ast_waitfordigit(qe->chan, retrywait);
2823 static struct member *interface_exists(struct call_queue *q, const char *interface)
2830 for (mem = q->members; mem; mem = mem->next) {
2831 if (!strcasecmp(interface, mem->interface))
2839 /* Dump all members in a specific queue to the database
2841 * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2844 static void dump_queue_members(struct call_queue *pm_queue)
2846 struct member *cur_member;
2847 char value[PM_MAX_LEN];
2851 memset(value, 0, sizeof(value));
2856 for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2857 if (!cur_member->dynamic)
2860 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d;%s%s",
2861 cur_member->interface, cur_member->penalty, cur_member->paused, cur_member->membername,
2862 cur_member->next ? "|" : "");
2863 if (res != strlen(value + value_len)) {
2864 ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2870 if (value_len && !cur_member) {
2871 if (ast_db_put(pm_family, pm_queue->name, value))
2872 ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2874 /* Delete the entry if the queue is empty or there is an error */
2875 ast_db_del(pm_family, pm_queue->name);
2878 static int remove_from_queue(const char *queuename, const char *interface)
2880 struct call_queue *q;
2881 struct member *last_member, *look;
2882 int res = RES_NOSUCHQUEUE;
2884 AST_LIST_LOCK(&queues);
2885 AST_LIST_TRAVERSE(&queues, q, list) {
2886 ast_mutex_lock(&q->lock);
2887 if (strcmp(q->name, queuename)) {
2888 ast_mutex_unlock(&q->lock);
2892 if ((last_member = interface_exists(q, interface))) {
2893 if ((look = q->members) == last_member) {
2894 q->members = last_member->next;
2896 while (look != NULL) {
2897 if (look->next == last_member) {
2898 look->next = last_member->next;