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_ROUNDROBIN,
99 QUEUE_STRATEGY_LEASTRECENT,
100 QUEUE_STRATEGY_FEWESTCALLS,
101 QUEUE_STRATEGY_RANDOM,
102 QUEUE_STRATEGY_RRMEMORY
105 static struct strategy {
109 { QUEUE_STRATEGY_RINGALL, "ringall" },
110 { QUEUE_STRATEGY_ROUNDROBIN, "roundrobin" },
111 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
112 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
113 { QUEUE_STRATEGY_RANDOM, "random" },
114 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
117 #define DEFAULT_RETRY 5
118 #define DEFAULT_TIMEOUT 15
119 #define RECHECK 1 /* Recheck every second to see we we're at the top yet */
120 #define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
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]):\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 hitting *.\n"
139 " 'H' -- allow caller to hang up by hitting *.\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 transfer the calling user\n"
146 " 'T' -- to 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 timeout will cause the queue to fail out after a specified number of\n"
156 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
157 " This application sets the following channel variable upon completion:\n"
158 " QUEUESTATUS The status of the call as a text string, one of\n"
159 " TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL\n";
161 static char *app_aqm = "AddQueueMember" ;
162 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
163 static char *app_aqm_descrip =
164 " AddQueueMember(queuename[|interface[|penalty[|options]]]):\n"
165 "Dynamically adds interface to an existing queue.\n"
166 "If the interface is already in the queue and there exists an n+101 priority\n"
167 "then it will then jump to this priority. Otherwise it will return an error\n"
168 "The option string may contain zero or more of the following characters:\n"
169 " 'j' -- jump to +101 priority when appropriate.\n"
170 " This application sets the following channel variable upon completion:\n"
171 " AQMSTATUS The status of the attempt to add a queue member as a \n"
172 " text string, one of\n"
173 " ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
174 "Example: AddQueueMember(techsupport|SIP/3000)\n"
177 static char *app_rqm = "RemoveQueueMember" ;
178 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
179 static char *app_rqm_descrip =
180 " RemoveQueueMember(queuename[|interface[|options]]):\n"
181 "Dynamically removes interface to an existing queue\n"
182 "If the interface is NOT in the queue and there exists an n+101 priority\n"
183 "then it will then jump to this priority. Otherwise it will return an error\n"
184 "The option string may contain zero or more of the following characters:\n"
185 " 'j' -- jump to +101 priority when appropriate.\n"
186 " This application sets the following channel variable upon completion:\n"
187 " RQMSTATUS The status of the attempt to remove a queue member as a\n"
188 " text string, one of\n"
189 " REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
190 "Example: RemoveQueueMember(techsupport|SIP/3000)\n"
193 static char *app_pqm = "PauseQueueMember" ;
194 static char *app_pqm_synopsis = "Pauses a queue member" ;
195 static char *app_pqm_descrip =
196 " PauseQueueMember([queuename]|interface[|options]):\n"
197 "Pauses (blocks calls for) a queue member.\n"
198 "The given interface will be paused in the given queue. This prevents\n"
199 "any calls from being sent from the queue to the interface until it is\n"
200 "unpaused with UnpauseQueueMember or the manager interface. If no\n"
201 "queuename is given, the interface is paused in every queue it is a\n"
202 "member of. If the interface is not in the named queue, or if no queue\n"
203 "is given and the interface is not in any queue, it will jump to\n"
204 "priority n+101, if it exists and the appropriate options are set.\n"
205 "The application will fail if the interface is not found and no extension\n"
206 "to jump to exists.\n"
207 "The option string may contain zero or more of the following characters:\n"
208 " 'j' -- jump to +101 priority when appropriate.\n"
209 " This application sets the following channel variable upon completion:\n"
210 " PQMSTATUS The status of the attempt to pause a queue member as a\n"
211 " text string, one of\n"
212 " PAUSED | NOTFOUND\n"
213 "Example: PauseQueueMember(|SIP/3000)\n";
215 static char *app_upqm = "UnpauseQueueMember" ;
216 static char *app_upqm_synopsis = "Unpauses a queue member" ;
217 static char *app_upqm_descrip =
218 " UnpauseQueueMember([queuename]|interface[|options]):\n"
219 "Unpauses (resumes calls to) a queue member.\n"
220 "This is the counterpart to PauseQueueMember and operates exactly the\n"
221 "same way, except it unpauses instead of pausing the given interface.\n"
222 "The option string may contain zero or more of the following characters:\n"
223 " 'j' -- jump to +101 priority when appropriate.\n"
224 " This application sets the following channel variable upon completion:\n"
225 " UPQMSTATUS The status of the attempt to unpause a queue \n"
226 " member as a text string, one of\n"
227 " UNPAUSED | NOTFOUND\n"
228 "Example: UnpauseQueueMember(|SIP/3000)\n";
230 static char *app_ql = "QueueLog" ;
231 static char *app_ql_synopsis = "Writes to the queue_log" ;
232 static char *app_ql_descrip =
233 " QueueLog(queuename|uniqueid|agent|event[|additionalinfo]):\n"
234 "Allows you to write your own events into the queue log\n"
235 "Example: QueueLog(101|${UNIQUEID}|${AGENT}|WENTONBREAK|600)\n";
237 /*! \brief Persistent Members astdb family */
238 static const char *pm_family = "/Queue/PersistentMembers";
239 /* The maximum length of each persistent member queue database entry */
240 #define PM_MAX_LEN 8192
242 /*! \brief queues.conf [general] option */
243 static int queue_persistent_members = 0;
245 /*! \brief queues.conf per-queue weight option */
246 static int use_weight = 0;
248 /*! \brief queues.conf [general] option */
249 static int autofill_default = 0;
251 /*! \brief queues.conf [general] option */
252 static int montype_default = 0;
258 QUEUE_LEAVEEMPTY = 3,
259 QUEUE_JOINUNAVAIL = 4,
260 QUEUE_LEAVEUNAVAIL = 5,
265 enum queue_result id;
267 } queue_results[] = {
268 { QUEUE_UNKNOWN, "UNKNOWN" },
269 { QUEUE_TIMEOUT, "TIMEOUT" },
270 { QUEUE_JOINEMPTY,"JOINEMPTY" },
271 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
272 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
273 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
274 { QUEUE_FULL, "FULL" },
277 /*! \brief We define a custom "local user" structure because we
278 use it not only for keeping track of what is in use but
279 also for keeping track of who we're dialing. */
282 struct callattempt *q_next;
283 struct ast_channel *chan;
289 struct member *member;
294 struct call_queue *parent; /*!< What queue is our parent */
295 char moh[80]; /*!< Name of musiconhold to be used */
296 char announce[80]; /*!< Announcement to play for member when call is answered */
297 char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
298 char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
299 int pos; /*!< Where we are in the queue */
300 int prio; /*!< Our priority */
301 int last_pos_said; /*!< Last position we told the user */
302 time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
303 int last_periodic_announce_sound; /*!< The last periodic announcement we made */
304 time_t last_pos; /*!< Last time we told the user their position */
305 int opos; /*!< Where we started in the queue */
306 int handled; /*!< Whether our call was handled */
307 int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
308 time_t start; /*!< When we started holding */
309 time_t expire; /*!< When this entry should expire (time out of queue) */
310 struct ast_channel *chan; /*!< Our channel */
311 struct queue_ent *next; /*!< The next queue entry */
315 char interface[80]; /*!< Technology/Location */
316 char membername[80]; /*!< Member name to use in queue logs */
317 int penalty; /*!< Are we a last resort? */
318 int calls; /*!< Number of calls serviced by this member */
319 int dynamic; /*!< Are we dynamically added? */
320 int status; /*!< Status of queue member */
321 int paused; /*!< Are we paused (not accepting calls)? */
322 time_t lastcall; /*!< When last successful call was hungup */
323 unsigned int dead:1; /*!< Used to detect members deleted in realtime */
324 unsigned int delme:1; /*!< Flag to delete entry on reload */
325 struct member *next; /*!< Next member */
328 struct member_interface {
330 AST_LIST_ENTRY(member_interface) list; /*!< Next call queue */
333 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
335 /* values used in multi-bit flags in call_queue */
336 #define QUEUE_EMPTY_NORMAL 1
337 #define QUEUE_EMPTY_STRICT 2
338 #define ANNOUNCEHOLDTIME_ALWAYS 1
339 #define ANNOUNCEHOLDTIME_ONCE 2
340 #define QUEUE_EVENT_VARIABLES 3
344 char name[80]; /*!< Name */
345 char moh[80]; /*!< Music On Hold class to be used */
346 char announce[80]; /*!< Announcement to play when call is answered */
347 char context[AST_MAX_CONTEXT]; /*!< Exit context */
348 unsigned int monjoin:1;
350 unsigned int joinempty:2;
351 unsigned int eventwhencalled:2;
352 unsigned int leavewhenempty:2;
353 unsigned int ringinuse:1;
354 unsigned int setinterfacevar:1;
355 unsigned int reportholdtime:1;
356 unsigned int wrapped:1;
357 unsigned int timeoutrestart:1;
358 unsigned int announceholdtime:2;
359 unsigned int strategy:3;
360 unsigned int maskmemberstatus:1;
361 unsigned int realtime:1;
362 int announcefrequency; /*!< How often to announce their position */
363 int periodicannouncefrequency; /*!< How often to play periodic announcement */
364 int roundingseconds; /*!< How many seconds do we round to? */
365 int holdtime; /*!< Current avg holdtime, based on recursive boxcar filter */
366 int callscompleted; /*!< Number of queue calls completed */
367 int callsabandoned; /*!< Number of queue calls abandoned */
368 int servicelevel; /*!< seconds setting for servicelevel*/
369 int callscompletedinsl; /*!< Number of calls answered with servicelevel*/
370 char monfmt[8]; /*!< Format to use when recording calls */
371 int montype; /*!< Monitor type Monitor vs. MixMonitor */
372 char sound_next[80]; /*!< Sound file: "Your call is now first in line" (def. queue-youarenext) */
373 char sound_thereare[80]; /*!< Sound file: "There are currently" (def. queue-thereare) */
374 char sound_calls[80]; /*!< Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/
375 char sound_holdtime[80]; /*!< Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
376 char sound_minutes[80]; /*!< Sound file: "minutes." (def. queue-minutes) */
377 char sound_lessthan[80]; /*!< Sound file: "less-than" (def. queue-lessthan) */
378 char sound_seconds[80]; /*!< Sound file: "seconds." (def. queue-seconds) */
379 char sound_thanks[80]; /*!< Sound file: "Thank you for your patience." (def. queue-thankyou) */
380 char sound_reporthold[80]; /*!< Sound file: "Hold time" (def. queue-reporthold) */
381 char sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS][80];/*!< Sound files: Custom announce, no default */
383 int count; /*!< How many entries */
384 int maxlen; /*!< Max number of entries */
385 int wrapuptime; /*!< Wrapup Time */
387 int retry; /*!< Retry calling everyone after this amount of time */
388 int timeout; /*!< How long to wait for an answer */
389 int weight; /*!< Respective weight */
390 int autopause; /*!< Auto pause queue members if they fail to answer */
392 /* Queue strategy things */
393 int rrpos; /*!< Round Robin - position */
394 int memberdelay; /*!< Seconds to delay connecting member to caller */
395 int autofill; /*!< Ignore the head call status and ring an available agent */
397 struct member *members; /*!< Head of the list of members */
398 struct queue_ent *head; /*!< Head of the list of callers */
399 AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
402 static AST_LIST_HEAD_STATIC(queues, call_queue);
404 static int set_member_paused(char *queuename, char *interface, int paused);
406 static void rr_dep_warning(void)
408 static unsigned int warned = 0;
411 ast_log(LOG_NOTICE, "The 'roundrobin' queue strategy is deprecated. Please use the 'rrmemory' strategy instead.\n");
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 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
453 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
455 struct queue_ent *cur;
472 enum queue_member_status {
474 QUEUE_NO_REACHABLE_MEMBERS,
478 static enum queue_member_status get_member_status(const struct call_queue *q, int max_penalty)
480 struct member *member;
481 enum queue_member_status result = QUEUE_NO_MEMBERS;
483 for (member = q->members; member; member = member->next) {
484 if (max_penalty && (member->penalty > max_penalty))
487 if (member->paused) continue;
489 switch (member->status) {
490 case AST_DEVICE_INVALID:
493 case AST_DEVICE_UNAVAILABLE:
494 result = QUEUE_NO_REACHABLE_MEMBERS;
509 static void *changethread(void *data)
511 struct call_queue *q;
512 struct statechange *sc = data;
514 struct member_interface *curint;
518 technology = ast_strdupa(sc->dev);
519 loc = strchr(technology, '/');
527 AST_LIST_LOCK(&interfaces);
528 AST_LIST_TRAVERSE(&interfaces, curint, list) {
529 if (!strcasecmp(curint->interface, sc->dev))
532 AST_LIST_UNLOCK(&interfaces);
536 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));
542 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
543 AST_LIST_LOCK(&queues);
544 AST_LIST_TRAVERSE(&queues, q, list) {
545 ast_mutex_lock(&q->lock);
546 for (cur = q->members; cur; cur = cur->next) {
547 if (strcasecmp(sc->dev, cur->interface))
550 if (cur->status != sc->state) {
551 cur->status = sc->state;
552 if (q->maskmemberstatus)
555 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
565 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
566 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
569 ast_mutex_unlock(&q->lock);
571 AST_LIST_UNLOCK(&queues);
576 static int statechange_queue(const char *dev, int state, void *ign)
578 /* Avoid potential for deadlocks by spawning a new thread to handle
580 struct statechange *sc;
584 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
588 strcpy(sc->dev, dev);
589 pthread_attr_init(&attr);
590 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
591 if (ast_pthread_create(&t, &attr, changethread, sc)) {
592 ast_log(LOG_WARNING, "Failed to create update thread!\n");
599 static struct member *create_queue_member(char *interface, const char *membername, int penalty, int paused)
603 if ((cur = ast_calloc(1, sizeof(*cur)))) {
604 cur->penalty = penalty;
605 cur->paused = paused;
606 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
607 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
608 if (!strchr(cur->interface, '/'))
609 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
610 cur->status = ast_device_state(interface);
616 static struct call_queue *alloc_queue(const char *queuename)
618 struct call_queue *q;
620 if ((q = ast_calloc(1, sizeof(*q)))) {
621 ast_mutex_init(&q->lock);
622 ast_copy_string(q->name, queuename, sizeof(q->name));
627 static void init_queue(struct call_queue *q)
632 q->retry = DEFAULT_RETRY;
635 q->announcefrequency = 0;
636 q->announceholdtime = 0;
637 q->roundingseconds = 0; /* Default - don't announce seconds */
640 q->setinterfacevar = 0;
641 q->autofill = autofill_default;
642 q->montype = montype_default;
644 q->announce[0] = '\0';
645 q->context[0] = '\0';
647 q->periodicannouncefrequency = 0;
648 ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
649 ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
650 ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
651 ast_copy_string(q->sound_holdtime, "queue-holdtime", sizeof(q->sound_holdtime));
652 ast_copy_string(q->sound_minutes, "queue-minutes", sizeof(q->sound_minutes));
653 ast_copy_string(q->sound_seconds, "queue-seconds", sizeof(q->sound_seconds));
654 ast_copy_string(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks));
655 ast_copy_string(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan));
656 ast_copy_string(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold));
657 ast_copy_string(q->sound_periodicannounce[0], "queue-periodic-announce", sizeof(q->sound_periodicannounce[0]));
658 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
659 q->sound_periodicannounce[i][0]='\0';
663 static void clear_queue(struct call_queue *q)
666 q->callscompleted = 0;
667 q->callsabandoned = 0;
668 q->callscompletedinsl = 0;
672 static int add_to_interfaces(char *interface)
674 struct member_interface *curint;
676 AST_LIST_LOCK(&interfaces);
677 AST_LIST_TRAVERSE(&interfaces, curint, list) {
678 if (!strcasecmp(curint->interface, interface))
683 AST_LIST_UNLOCK(&interfaces);
688 ast_log(LOG_DEBUG, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
690 if ((curint = ast_calloc(1, sizeof(*curint)))) {
691 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
692 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
694 AST_LIST_UNLOCK(&interfaces);
699 static int interface_exists_global(char *interface)
701 struct call_queue *q;
705 AST_LIST_LOCK(&queues);
706 AST_LIST_TRAVERSE(&queues, q, list) {
707 ast_mutex_lock(&q->lock);
708 for (mem = q->members; mem && !ret; mem = mem->next) {
709 if (!strcasecmp(interface, mem->interface))
712 ast_mutex_unlock(&q->lock);
716 AST_LIST_UNLOCK(&queues);
721 static int remove_from_interfaces(char *interface)
723 struct member_interface *curint;
725 AST_LIST_LOCK(&interfaces);
726 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
727 if (!strcasecmp(curint->interface, interface)) {
728 if (!interface_exists_global(interface)) {
730 ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
731 AST_LIST_REMOVE_CURRENT(&interfaces, list);
737 AST_LIST_TRAVERSE_SAFE_END;
738 AST_LIST_UNLOCK(&interfaces);
743 static void clear_and_free_interfaces(void)
745 struct member_interface *curint;
747 AST_LIST_LOCK(&interfaces);
748 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
750 AST_LIST_UNLOCK(&interfaces);
753 /*! \brief Configure a queue parameter.
755 For error reporting, line number is passed for .conf static configuration.
756 For Realtime queues, linenum is -1.
757 The failunknown flag is set for config files (and static realtime) to show
758 errors for unknown parameters. It is cleared for dynamic realtime to allow
759 extra fields in the tables. */
760 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
766 if (!strcasecmp(param, "musicclass") ||
767 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
768 ast_copy_string(q->moh, val, sizeof(q->moh));
769 } else if (!strcasecmp(param, "announce")) {
770 ast_copy_string(q->announce, val, sizeof(q->announce));
771 } else if (!strcasecmp(param, "context")) {
772 ast_copy_string(q->context, val, sizeof(q->context));
773 } else if (!strcasecmp(param, "timeout")) {
774 q->timeout = atoi(val);
776 q->timeout = DEFAULT_TIMEOUT;
777 } else if (!strcasecmp(param, "ringinuse")) {
778 q->ringinuse = ast_true(val);
779 } else if (!strcasecmp(param, "setinterfacevar")) {
780 q->setinterfacevar = ast_true(val);
781 } else if (!strcasecmp(param, "monitor-join")) {
782 q->monjoin = ast_true(val);
783 } else if (!strcasecmp(param, "monitor-format")) {
784 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
785 } else if (!strcasecmp(param, "queue-youarenext")) {
786 ast_copy_string(q->sound_next, val, sizeof(q->sound_next));
787 } else if (!strcasecmp(param, "queue-thereare")) {
788 ast_copy_string(q->sound_thereare, val, sizeof(q->sound_thereare));
789 } else if (!strcasecmp(param, "queue-callswaiting")) {
790 ast_copy_string(q->sound_calls, val, sizeof(q->sound_calls));
791 } else if (!strcasecmp(param, "queue-holdtime")) {
792 ast_copy_string(q->sound_holdtime, val, sizeof(q->sound_holdtime));
793 } else if (!strcasecmp(param, "queue-minutes")) {
794 ast_copy_string(q->sound_minutes, val, sizeof(q->sound_minutes));
795 } else if (!strcasecmp(param, "queue-seconds")) {
796 ast_copy_string(q->sound_seconds, val, sizeof(q->sound_seconds));
797 } else if (!strcasecmp(param, "queue-lessthan")) {
798 ast_copy_string(q->sound_lessthan, val, sizeof(q->sound_lessthan));
799 } else if (!strcasecmp(param, "queue-thankyou")) {
800 ast_copy_string(q->sound_thanks, val, sizeof(q->sound_thanks));
801 } else if (!strcasecmp(param, "queue-reporthold")) {
802 ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold));
803 } else if (!strcasecmp(param, "announce-frequency")) {
804 q->announcefrequency = atoi(val);
805 } else if (!strcasecmp(param, "announce-round-seconds")) {
806 q->roundingseconds = atoi(val);
807 if (q->roundingseconds>60 || q->roundingseconds<0) {
809 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
810 "using 0 instead for queue '%s' at line %d of queues.conf\n",
811 val, param, q->name, linenum);
813 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
814 "using 0 instead for queue '%s'\n", val, param, q->name);
816 q->roundingseconds=0;
818 } else if (!strcasecmp(param, "announce-holdtime")) {
819 if (!strcasecmp(val, "once"))
820 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
821 else if (ast_true(val))
822 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
824 q->announceholdtime = 0;
825 } else if (!strcasecmp(param, "periodic-announce")) {
826 if (strchr(val,'|')) {
828 while ((c = strchr(lastc,'|'))) {
829 if (i > MAX_PERIODIC_ANNOUNCEMENTS)
831 strncpy(buff, lastc, abs(lastc - c));
832 buff[abs(lastc - c)] = '\0';
833 ast_copy_string(q->sound_periodicannounce[i], buff, sizeof(q->sound_periodicannounce[i]));
838 ast_copy_string(q->sound_periodicannounce[i], lastc, sizeof(q->sound_periodicannounce[i]));
841 ast_copy_string(q->sound_periodicannounce[i], val, sizeof(q->sound_periodicannounce[i]));
843 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
844 q->periodicannouncefrequency = atoi(val);
845 } else if (!strcasecmp(param, "retry")) {
846 q->retry = atoi(val);
848 q->retry = DEFAULT_RETRY;
849 } else if (!strcasecmp(param, "wrapuptime")) {
850 q->wrapuptime = atoi(val);
851 } else if (!strcasecmp(param, "autofill")) {
852 q->autofill = ast_true(val);
853 } else if (!strcasecmp(param, "monitor-type")) {
854 if (!strcasecmp(val, "mixmonitor"))
856 } else if (!strcasecmp(param, "autopause")) {
857 q->autopause = ast_true(val);
858 } else if (!strcasecmp(param, "maxlen")) {
859 q->maxlen = atoi(val);
862 } else if (!strcasecmp(param, "servicelevel")) {
863 q->servicelevel= atoi(val);
864 } else if (!strcasecmp(param, "strategy")) {
865 q->strategy = strat2int(val);
866 if (q->strategy < 0) {
867 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
869 q->strategy = QUEUE_STRATEGY_RINGALL;
871 } else if (!strcasecmp(param, "joinempty")) {
872 if (!strcasecmp(val, "strict"))
873 q->joinempty = QUEUE_EMPTY_STRICT;
874 else if (ast_true(val))
875 q->joinempty = QUEUE_EMPTY_NORMAL;
878 } else if (!strcasecmp(param, "leavewhenempty")) {
879 if (!strcasecmp(val, "strict"))
880 q->leavewhenempty = QUEUE_EMPTY_STRICT;
881 else if (ast_true(val))
882 q->leavewhenempty = QUEUE_EMPTY_NORMAL;
884 q->leavewhenempty = 0;
885 } else if (!strcasecmp(param, "eventmemberstatus")) {
886 q->maskmemberstatus = !ast_true(val);
887 } else if (!strcasecmp(param, "eventwhencalled")) {
888 if (!strcasecmp(val, "vars")) {
889 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
891 q->eventwhencalled = ast_true(val);
893 } else if (!strcasecmp(param, "reportholdtime")) {
894 q->reportholdtime = ast_true(val);
895 } else if (!strcasecmp(param, "memberdelay")) {
896 q->memberdelay = atoi(val);
897 } else if (!strcasecmp(param, "weight")) {
898 q->weight = atoi(val);
901 /* With Realtime queues, if the last queue using weights is deleted in realtime,
902 we will not see any effect on use_weight until next reload. */
903 } else if (!strcasecmp(param, "timeoutrestart")) {
904 q->timeoutrestart = ast_true(val);
905 } else if (failunknown) {
907 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
908 q->name, param, linenum);
910 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
915 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str)
917 struct member *m, *prev_m;
921 penalty = atoi(penalty_str);
926 /* Find the member, or the place to put a new one. */
927 for (m = q->members, prev_m = NULL;
928 m && strcmp(m->interface, interface);
929 prev_m = m, m = m->next);
931 /* Create a new one if not found, else update penalty */
933 if ((m = create_queue_member(interface, membername, penalty, 0))) {
935 add_to_interfaces(interface);
943 m->dead = 0; /* Do not delete this one. */
944 m->penalty = penalty;
948 static void free_members(struct call_queue *q, int all)
950 /* Free non-dynamic members */
951 struct member *curm, *next, *prev = NULL;
953 for (curm = q->members; curm; curm = next) {
955 if (all || !curm->dynamic) {
960 remove_from_interfaces(curm->interface);
967 static void destroy_queue(struct call_queue *q)
970 ast_mutex_destroy(&q->lock);
974 /*!\brief Reload a single queue via realtime.
975 \return Return the queue, or NULL if it doesn't exist.
976 \note Should be called with the global qlock locked. */
977 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
979 struct ast_variable *v;
980 struct call_queue *q;
981 struct member *m, *prev_m, *next_m;
982 char *interface = NULL;
983 char *tmp, *tmp_name;
984 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
986 /* Find the queue in the in-core list (we will create a new one if not found). */
987 AST_LIST_TRAVERSE(&queues, q, list) {
988 if (!strcasecmp(q->name, queuename))
992 /* Static queues override realtime. */
994 ast_mutex_lock(&q->lock);
997 ast_mutex_unlock(&q->lock);
1000 ast_mutex_unlock(&q->lock);
1004 } else if (!member_config)
1005 /* Not found in the list, and it's not realtime ... */
1008 /* Check if queue is defined in realtime. */
1010 /* Delete queue from in-core list if it has been deleted in realtime. */
1012 /*! \note Hmm, can't seem to distinguish a DB failure from a not
1013 found condition... So we might delete an in-core queue
1014 in case of DB failure. */
1015 ast_log(LOG_DEBUG, "Queue %s not found in realtime.\n", queuename);
1018 /* Delete if unused (else will be deleted when last caller leaves). */
1021 AST_LIST_REMOVE(&queues, q, list);
1022 ast_mutex_unlock(&q->lock);
1025 ast_mutex_unlock(&q->lock);
1030 /* Create a new queue if an in-core entry does not exist yet. */
1032 if (!(q = alloc_queue(queuename)))
1034 ast_mutex_lock(&q->lock);
1037 AST_LIST_INSERT_HEAD(&queues, q, list);
1039 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
1041 memset(tmpbuf, 0, sizeof(tmpbuf));
1042 for (v = queue_vars; v; v = v->next) {
1043 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1044 if ((tmp = strchr(v->name, '_'))) {
1045 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1048 while ((tmp = strchr(tmp, '_')))
1052 queue_set_param(q, tmp_name, v->value, -1, 0);
1055 if (q->strategy == QUEUE_STRATEGY_ROUNDROBIN)
1058 /* Temporarily set non-dynamic members dead so we can detect deleted ones. */
1059 for (m = q->members; m; m = m->next) {
1064 while ((interface = ast_category_browse(member_config, interface))) {
1065 rt_handle_member_record(q, interface,
1066 S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1067 ast_variable_retrieve(member_config, interface, "penalty"));
1070 /* Delete all realtime members that have been deleted in DB. */
1077 prev_m->next = next_m;
1079 q->members = next_m;
1081 remove_from_interfaces(m->interface);
1089 ast_mutex_unlock(&q->lock);
1094 static struct call_queue *load_realtime_queue(char *queuename)
1096 struct ast_variable *queue_vars;
1097 struct ast_config *member_config = NULL;
1098 struct call_queue *q;
1100 /* Find the queue in the in-core list first. */
1101 AST_LIST_LOCK(&queues);
1102 AST_LIST_TRAVERSE(&queues, q, list) {
1103 if (!strcasecmp(q->name, queuename)) {
1107 AST_LIST_UNLOCK(&queues);
1109 if (!q || q->realtime) {
1110 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1111 queue operations while waiting for the DB.
1113 This will be two separate database transactions, so we might
1114 see queue parameters as they were before another process
1115 changed the queue and member list as it was after the change.
1116 Thus we might see an empty member list when a queue is
1117 deleted. In practise, this is unlikely to cause a problem. */
1119 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1121 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1122 if (!member_config) {
1123 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1128 AST_LIST_LOCK(&queues);
1130 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1132 ast_config_destroy(member_config);
1134 ast_variables_destroy(queue_vars);
1136 AST_LIST_UNLOCK(&queues);
1141 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1143 struct call_queue *q;
1144 struct queue_ent *cur, *prev = NULL;
1148 enum queue_member_status stat;
1150 if (!(q = load_realtime_queue(queuename)))
1153 AST_LIST_LOCK(&queues);
1154 ast_mutex_lock(&q->lock);
1156 /* This is our one */
1157 stat = get_member_status(q, qe->max_penalty);
1158 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1159 *reason = QUEUE_JOINEMPTY;
1160 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1161 *reason = QUEUE_JOINUNAVAIL;
1162 else if (q->maxlen && (q->count >= q->maxlen))
1163 *reason = QUEUE_FULL;
1165 /* There's space for us, put us at the right position inside
1167 * Take into account the priority of the calling user */
1172 /* We have higher priority than the current user, enter
1173 * before him, after all the other users with priority
1174 * higher or equal to our priority. */
1175 if ((!inserted) && (qe->prio > cur->prio)) {
1176 insert_entry(q, prev, qe, &pos);
1183 /* No luck, join at the end of the queue */
1185 insert_entry(q, prev, qe, &pos);
1186 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1187 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1188 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1191 manager_event(EVENT_FLAG_CALL, "Join",
1192 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1194 S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1195 S_OR(qe->chan->cid.cid_name, "unknown"),
1196 q->name, qe->pos, q->count, qe->chan->uniqueid );
1198 ast_log(LOG_DEBUG, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1200 ast_mutex_unlock(&q->lock);
1201 AST_LIST_UNLOCK(&queues);
1206 static int play_file(struct ast_channel *chan, char *filename)
1210 ast_stopstream(chan);
1211 res = ast_streamfile(chan, filename, chan->language);
1213 res = ast_waitstream(chan, AST_DIGIT_ANY);
1214 ast_stopstream(chan);
1219 static int valid_exit(struct queue_ent *qe, char digit)
1221 int digitlen = strlen(qe->digits);
1223 /* Prevent possible buffer overflow */
1224 if (digitlen < sizeof(qe->digits) - 2) {
1225 qe->digits[digitlen] = digit;
1226 qe->digits[digitlen + 1] = '\0';
1228 qe->digits[0] = '\0';
1232 /* If there's no context to goto, short-circuit */
1233 if (ast_strlen_zero(qe->context))
1236 /* If the extension is bad, then reset the digits to blank */
1237 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1238 qe->digits[0] = '\0';
1242 /* We have an exact match */
1243 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1244 /* Return 1 on a successful goto */
1251 static int say_position(struct queue_ent *qe)
1253 int res = 0, avgholdmins, avgholdsecs;
1256 /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/
1258 if ((now - qe->last_pos) < 15)
1261 /* If either our position has changed, or we are over the freq timer, say position */
1262 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1265 ast_moh_stop(qe->chan);
1266 /* Say we're next, if we are */
1268 res = play_file(qe->chan, qe->parent->sound_next);
1269 if (res && valid_exit(qe, res))
1274 res = play_file(qe->chan, qe->parent->sound_thereare);
1275 if (res && valid_exit(qe, res))
1277 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1278 if (res && valid_exit(qe, res))
1280 res = play_file(qe->chan, qe->parent->sound_calls);
1281 if (res && valid_exit(qe, res))
1284 /* Round hold time to nearest minute */
1285 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1287 /* If they have specified a rounding then round the seconds as well */
1288 if (qe->parent->roundingseconds) {
1289 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1290 avgholdsecs *= qe->parent->roundingseconds;
1295 if (option_verbose > 2)
1296 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1298 /* If the hold time is >1 min, if it's enabled, and if it's not
1299 supposed to be only once and we have already said it, say it */
1300 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1301 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1302 res = play_file(qe->chan, qe->parent->sound_holdtime);
1303 if (res && valid_exit(qe, res))
1306 if (avgholdmins > 0) {
1307 if (avgholdmins < 2) {
1308 res = play_file(qe->chan, qe->parent->sound_lessthan);
1309 if (res && valid_exit(qe, res))
1312 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1313 if (res && valid_exit(qe, res))
1316 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1317 if (res && valid_exit(qe, res))
1321 res = play_file(qe->chan, qe->parent->sound_minutes);
1322 if (res && valid_exit(qe, res))
1325 if (avgholdsecs>0) {
1326 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1327 if (res && valid_exit(qe, res))
1330 res = play_file(qe->chan, qe->parent->sound_seconds);
1331 if (res && valid_exit(qe, res))
1338 if (option_verbose > 2)
1339 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n",
1340 qe->chan->name, qe->parent->name, qe->pos);
1341 res = play_file(qe->chan, qe->parent->sound_thanks);
1342 if (res && !valid_exit(qe, res))
1346 /* Set our last_pos indicators */
1348 qe->last_pos_said = qe->pos;
1350 /* Don't restart music on hold if we're about to exit the caller from the queue */
1352 ast_moh_start(qe->chan, qe->moh, NULL);
1357 static void recalc_holdtime(struct queue_ent *qe)
1359 int oldvalue, newvalue;
1361 /* Calculate holdtime using a recursive boxcar filter */
1362 /* Thanks to SRT for this contribution */
1363 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1365 newvalue = time(NULL) - qe->start;
1367 ast_mutex_lock(&qe->parent->lock);
1368 if (newvalue <= qe->parent->servicelevel)
1369 qe->parent->callscompletedinsl++;
1370 oldvalue = qe->parent->holdtime;
1371 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2;
1372 ast_mutex_unlock(&qe->parent->lock);
1376 static void leave_queue(struct queue_ent *qe)
1378 struct call_queue *q;
1379 struct queue_ent *cur, *prev = NULL;
1382 if (!(q = qe->parent))
1384 ast_mutex_lock(&q->lock);
1387 for (cur = q->head; cur; cur = cur->next) {
1391 /* Take us out of the queue */
1392 manager_event(EVENT_FLAG_CALL, "Leave",
1393 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1394 qe->chan->name, q->name, q->count, qe->chan->uniqueid);
1396 ast_log(LOG_DEBUG, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1397 /* Take us out of the queue */
1399 prev->next = cur->next;
1401 q->head = cur->next;
1403 /* Renumber the people after us in the queue based on a new count */
1408 ast_mutex_unlock(&q->lock);
1410 if (q->dead && !q->count) {
1411 /* It's dead and nobody is in it, so kill it */
1412 AST_LIST_LOCK(&queues);
1413 AST_LIST_REMOVE(&queues, q, list);
1414 AST_LIST_UNLOCK(&queues);
1419 /* Hang up a list of outgoing calls */
1420 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1422 struct callattempt *oo;
1425 /* Hangup any existing lines we have open */
1426 if (outgoing->chan && (outgoing->chan != exception))
1427 ast_hangup(outgoing->chan);
1429 outgoing = outgoing->q_next;
1434 static int update_status(struct call_queue *q, struct member *member, int status)
1438 /* Since a reload could have taken place, we have to traverse the list to
1439 be sure it's still valid */
1440 ast_mutex_lock(&q->lock);
1441 for (cur = q->members; cur; cur = cur->next) {
1445 cur->status = status;
1446 if (!q->maskmemberstatus) {
1447 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1450 "MemberName: %s\r\n"
1451 "Membership: %s\r\n"
1453 "CallsTaken: %d\r\n"
1457 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
1458 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1461 ast_mutex_unlock(&q->lock);
1465 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1467 if (status == AST_CAUSE_BUSY)
1468 status = AST_DEVICE_BUSY;
1469 else if (status == AST_CAUSE_UNREGISTERED)
1470 status = AST_DEVICE_UNAVAILABLE;
1471 else if (status == AST_CAUSE_NOSUCHDRIVER)
1472 status = AST_DEVICE_INVALID;
1474 status = AST_DEVICE_UNKNOWN;
1475 return update_status(q, member, status);
1478 /* traverse all defined queues which have calls waiting and contain this member
1479 return 0 if no other queue has precedence (higher weight) or 1 if found */
1480 static int compare_weight(struct call_queue *rq, struct member *member)
1482 struct call_queue *q;
1486 /* &qlock and &rq->lock already set by try_calling()
1487 * to solve deadlock */
1488 AST_LIST_TRAVERSE(&queues, q, list) {
1489 if (q == rq) /* don't check myself, could deadlock */
1491 ast_mutex_lock(&q->lock);
1492 if (q->count && q->members) {
1493 for (mem = q->members; mem; mem = mem->next) {
1494 if (strcmp(mem->interface, member->interface))
1497 ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1498 if (q->weight > rq->weight) {
1499 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);
1505 ast_mutex_unlock(&q->lock);
1512 /*! \brief common hangup actions */
1513 static void do_hang(struct callattempt *o)
1516 ast_hangup(o->chan);
1520 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1522 char *tmp = alloca(len);
1524 if (pbx_builtin_serialize_variables(chan, tmp, len)) {
1527 /* convert "\n" to "\nVariable: " */
1528 strcpy(vars, "Variable: ");
1530 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1533 if (tmp[i + 1] == '\0')
1535 if (tmp[i] == '\n') {
1539 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1549 /* there are no channel variables; leave it blank */
1555 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1562 /* on entry here, we know that tmp->chan == NULL */
1563 if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1565 ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
1567 ast_cdr_busy(qe->chan->cdr);
1568 tmp->stillgoing = 0;
1573 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1575 ast_log(LOG_DEBUG, "%s in use, can't receive call\n", tmp->interface);
1577 ast_cdr_busy(qe->chan->cdr);
1578 tmp->stillgoing = 0;
1582 if (tmp->member->paused) {
1584 ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
1586 ast_cdr_busy(qe->chan->cdr);
1587 tmp->stillgoing = 0;
1590 if (use_weight && compare_weight(qe->parent,tmp->member)) {
1591 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1593 ast_cdr_busy(qe->chan->cdr);
1594 tmp->stillgoing = 0;
1599 ast_copy_string(tech, tmp->interface, sizeof(tech));
1600 if ((location = strchr(tech, '/')))
1605 /* Request the peer */
1606 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1607 if (!tmp->chan) { /* If we can't, just go on to the next call */
1609 ast_cdr_busy(qe->chan->cdr);
1610 tmp->stillgoing = 0;
1611 update_dial_status(qe->parent, tmp->member, status);
1613 ast_mutex_lock(&qe->parent->lock);
1614 qe->parent->rrpos++;
1615 ast_mutex_unlock(&qe->parent->lock);
1619 } else if (status != tmp->oldstatus)
1620 update_dial_status(qe->parent, tmp->member, status);
1622 tmp->chan->appl = "AppQueue";
1623 tmp->chan->data = "(Outgoing Line)";
1624 tmp->chan->whentohangup = 0;
1625 if (tmp->chan->cid.cid_num)
1626 free(tmp->chan->cid.cid_num);
1627 tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1628 if (tmp->chan->cid.cid_name)
1629 free(tmp->chan->cid.cid_name);
1630 tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1631 if (tmp->chan->cid.cid_ani)
1632 free(tmp->chan->cid.cid_ani);
1633 tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1635 /* Inherit specially named variables from parent channel */
1636 ast_channel_inherit_variables(qe->chan, tmp->chan);
1638 /* Presense of ADSI CPE on outgoing channel follows ours */
1639 tmp->chan->adsicpe = qe->chan->adsicpe;
1641 /* Place the call, but don't wait on the answer */
1642 if ((res = ast_call(tmp->chan, location, 0))) {
1643 /* Again, keep going even if there's an error */
1645 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1646 if (option_verbose > 2)
1647 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
1651 } else if (qe->parent->eventwhencalled) {
1654 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1655 "AgentCalled: %s\r\n"
1656 "ChannelCalling: %s\r\n"
1658 "CallerIDName: %s\r\n"
1663 tmp->interface, qe->chan->name,
1664 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1665 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1666 qe->chan->context, qe->chan->exten, qe->chan->priority,
1667 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
1668 if (option_verbose > 2)
1669 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
1675 /*! \brief find the entry with the best metric, or NULL */
1676 static struct callattempt *find_best(struct callattempt *outgoing)
1678 struct callattempt *best = NULL, *cur;
1680 for (cur = outgoing; cur; cur = cur->q_next) {
1681 if (cur->stillgoing && /* Not already done */
1682 !cur->chan && /* Isn't already going */
1683 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
1691 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
1696 struct callattempt *best = find_best(outgoing);
1699 ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
1702 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
1703 struct callattempt *cur;
1704 /* Ring everyone who shares this best metric (for ringall) */
1705 for (cur = outgoing; cur; cur = cur->q_next) {
1706 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
1708 ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1709 ring_entry(qe, cur, busies);
1713 /* Ring just the best channel */
1715 ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
1716 ring_entry(qe, best, busies);
1718 if (best->chan) /* break out with result = 1 */
1725 static int store_next(struct queue_ent *qe, struct callattempt *outgoing)
1727 struct callattempt *best = find_best(outgoing);
1730 /* Ring just the best channel */
1732 ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
1733 qe->parent->rrpos = best->metric % 1000;
1735 /* Just increment rrpos */
1736 if (qe->parent->wrapped) {
1737 /* No more channels, start over */
1738 qe->parent->rrpos = 0;
1740 /* Prioritize next entry */
1741 qe->parent->rrpos++;
1744 qe->parent->wrapped = 0;
1749 static int background_file(struct queue_ent *qe, struct ast_channel *chan, char *filename)
1753 ast_stopstream(chan);
1754 res = ast_streamfile(chan, filename, chan->language);
1757 /* Wait for a keypress */
1758 res = ast_waitstream(chan, AST_DIGIT_ANY);
1759 if (res < 0 || !valid_exit(qe, res))
1763 ast_stopstream(chan);
1769 static int say_periodic_announcement(struct queue_ent *qe)
1774 /* Get the current time */
1777 /* Check to see if it is time to announce */
1778 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
1781 /* Stop the music on hold so we can play our own file */
1782 ast_moh_stop(qe->chan);
1784 if (option_verbose > 2)
1785 ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n");
1787 /* Check to make sure we have a sound file. If not, reset to the first sound file */
1788 if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || !strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
1789 qe->last_periodic_announce_sound = 0;
1792 /* play the announcement */
1793 res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
1795 /* Resume Music on Hold if the caller is going to stay in the queue */
1797 ast_moh_start(qe->chan, qe->moh, NULL);
1799 /* update last_periodic_announce_time */
1800 qe->last_periodic_announce_time = now;
1802 /* Update the current periodic announcement to the next announcement */
1803 qe->last_periodic_announce_sound++;
1808 static void record_abandoned(struct queue_ent *qe)
1810 ast_mutex_lock(&qe->parent->lock);
1811 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
1815 "OriginalPosition: %d\r\n"
1817 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
1819 qe->parent->callsabandoned++;
1820 ast_mutex_unlock(&qe->parent->lock);
1823 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
1824 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
1826 if (option_verbose > 2)
1827 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", rnatime);
1828 ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
1829 if (qe->parent->autopause) {
1830 if (!set_member_paused(qe->parent->name, interface, 1)) {
1831 if (option_verbose > 2)
1832 ast_verbose( VERBOSE_PREFIX_3 "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
1834 if (option_verbose > 2)
1835 ast_verbose( VERBOSE_PREFIX_3 "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
1841 #define AST_MAX_WATCHERS 256
1843 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
1845 char *queue = qe->parent->name;
1846 struct callattempt *o;
1848 int sentringing = 0;
1849 int numbusies = prebusies;
1853 struct ast_frame *f;
1854 struct callattempt *peer = NULL;
1855 struct ast_channel *winner;
1856 struct ast_channel *in = qe->chan;
1858 char membername[80] = "";
1862 starttime = (long) time(NULL);
1864 while (*to && !peer) {
1865 int numlines, retry, pos = 1;
1866 struct ast_channel *watchers[AST_MAX_WATCHERS];
1869 for (retry = 0; retry < 2; retry++) {
1871 for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
1872 if (o->stillgoing) { /* Keep track of important channels */
1875 watchers[pos++] = o->chan;
1879 if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
1880 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
1882 /* On "ringall" strategy we only move to the next penalty level
1883 when *all* ringing phones are done in the current penalty level */
1884 ring_one(qe, outgoing, &numbusies);
1887 if (pos == 1 /* not found */) {
1888 if (numlines == (numbusies + numnochan)) {
1889 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1891 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1896 winner = ast_waitfor_n(watchers, pos, to);
1897 for (o = outgoing; o; o = o->q_next) {
1898 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
1900 if (option_verbose > 2)
1901 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1904 } else if (o->chan && (o->chan == winner)) {
1905 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
1906 ast_copy_string(on, o->member->interface, sizeof(on));
1907 ast_copy_string(membername, o->member->membername, sizeof(membername));
1908 if (option_verbose > 2)
1909 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
1910 winner = o->chan = NULL;
1911 } else if (!ast_strlen_zero(o->chan->call_forward)) {
1916 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
1917 if ((stuff = strchr(tmpchan, '/'))) {
1921 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1925 /* Before processing channel, go ahead and check for forwarding */
1926 if (option_verbose > 2)
1927 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1928 /* Setup parameters */
1929 o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1930 if (status != o->oldstatus)
1931 update_dial_status(qe->parent, o->member, status);
1933 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
1937 ast_channel_inherit_variables(in, o->chan);
1938 if (o->chan->cid.cid_num)
1939 free(o->chan->cid.cid_num);
1940 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
1942 if (o->chan->cid.cid_name)
1943 free(o->chan->cid.cid_name);
1944 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
1946 ast_string_field_set(o->chan, accountcode, in->accountcode);
1947 o->chan->cdrflags = in->cdrflags;
1949 if (in->cid.cid_ani) {
1950 if (o->chan->cid.cid_ani)
1951 free(o->chan->cid.cid_ani);
1952 o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
1954 if (o->chan->cid.cid_rdnis)
1955 free(o->chan->cid.cid_rdnis);
1956 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
1957 if (ast_call(o->chan, tmpchan, 0)) {
1958 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
1963 /* Hangup the original channel now, in case we needed it */
1967 f = ast_read(winner);
1969 if (f->frametype == AST_FRAME_CONTROL) {
1970 switch (f->subclass) {
1971 case AST_CONTROL_ANSWER:
1972 /* This is our guy if someone answered. */
1974 if (option_verbose > 2)
1975 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1979 case AST_CONTROL_BUSY:
1980 if (option_verbose > 2)
1981 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
1983 ast_cdr_busy(in->cdr);
1985 endtime = (long)time(NULL);
1986 endtime -= starttime;
1987 rna(endtime*1000, qe, on, membername);
1988 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
1989 if (qe->parent->timeoutrestart)
1991 ring_one(qe, outgoing, &numbusies);
1995 case AST_CONTROL_CONGESTION:
1996 if (option_verbose > 2)
1997 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
1999 ast_cdr_busy(in->cdr);
2000 endtime = (long)time(NULL);
2001 endtime -= starttime;
2002 rna(endtime*1000, qe, on, membername);
2004 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2005 if (qe->parent->timeoutrestart)
2007 ring_one(qe, outgoing, &numbusies);
2011 case AST_CONTROL_RINGING:
2012 if (option_verbose > 2)
2013 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
2016 ast_indicate(in, AST_CONTROL_RINGING);
2021 case AST_CONTROL_OFFHOOK:
2022 /* Ignore going off hook */
2025 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
2030 endtime = (long) time(NULL) - starttime;
2031 rna(endtime * 1000, qe, on, membername);
2033 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2034 if (qe->parent->timeoutrestart)
2036 ring_one(qe, outgoing, &numbusies);
2043 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2050 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2051 if (option_verbose > 3)
2052 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
2057 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) {
2058 if (option_verbose > 3)
2059 ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass);
2061 *digit = f->subclass;
2068 rna(orig, qe, on, membername);
2074 static int is_our_turn(struct queue_ent *qe)
2076 struct queue_ent *ch;
2082 if (!qe->parent->autofill) {
2083 /* Atomically read the parent head -- does not need a lock */
2084 ch = qe->parent->head;
2085 /* If we are now at the top of the head, break out */
2088 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2092 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2097 /* This needs a lock. How many members are available to be served? */
2098 ast_mutex_lock(&qe->parent->lock);
2100 ch = qe->parent->head;
2102 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2104 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);
2107 for (cur = qe->parent->members; cur; cur = cur->next) {
2108 switch (cur->status) {
2109 case AST_DEVICE_NOT_INUSE:
2110 case AST_DEVICE_UNKNOWN:
2118 ast_log(LOG_DEBUG, "There are %d available members.\n", avl);
2120 while ((idx < avl) && (ch) && (ch != qe)) {
2125 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2126 if (ch && idx < avl) {
2128 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2132 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2136 ast_mutex_unlock(&qe->parent->lock);
2142 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2146 /* This is the holding pen for callers 2 through maxlen */
2148 enum queue_member_status stat;
2150 if (is_our_turn(qe))
2153 /* If we have timed out, break out */
2154 if (qe->expire && (time(NULL) > qe->expire)) {
2155 *reason = QUEUE_TIMEOUT;
2159 stat = get_member_status(qe->parent, qe->max_penalty);
2161 /* leave the queue if no agents, if enabled */
2162 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2163 *reason = QUEUE_LEAVEEMPTY;
2164 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2169 /* leave the queue if no reachable agents, if enabled */
2170 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2171 *reason = QUEUE_LEAVEUNAVAIL;
2172 ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2177 /* Make a position announcement, if enabled */
2178 if (qe->parent->announcefrequency && !ringing &&
2179 (res = say_position(qe)))
2182 /* Make a periodic announcement, if enabled */
2183 if (qe->parent->periodicannouncefrequency && !ringing &&
2184 (res = say_periodic_announcement(qe)))
2187 /* Wait a second before checking again */
2188 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000)))
2195 static int update_queue(struct call_queue *q, struct member *member)
2199 /* Since a reload could have taken place, we have to traverse the list to
2200 be sure it's still valid */
2201 ast_mutex_lock(&q->lock);
2204 if (member == cur) {
2205 time(&cur->lastcall);
2211 q->callscompleted++;
2212 ast_mutex_unlock(&q->lock);
2216 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2218 if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2221 switch (q->strategy) {
2222 case QUEUE_STRATEGY_RINGALL:
2223 /* Everyone equal, except for penalty */
2224 tmp->metric = mem->penalty * 1000000;
2226 case QUEUE_STRATEGY_ROUNDROBIN:
2229 /* No more channels, start over */
2232 /* Prioritize next entry */
2238 case QUEUE_STRATEGY_RRMEMORY:
2239 if (pos < q->rrpos) {
2240 tmp->metric = 1000 + pos;
2243 /* Indicate there is another priority */
2247 tmp->metric += mem->penalty * 1000000;
2249 case QUEUE_STRATEGY_RANDOM:
2250 tmp->metric = ast_random() % 1000;
2251 tmp->metric += mem->penalty * 1000000;
2253 case QUEUE_STRATEGY_FEWESTCALLS:
2254 tmp->metric = mem->calls;
2255 tmp->metric += mem->penalty * 1000000;
2257 case QUEUE_STRATEGY_LEASTRECENT:
2261 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2262 tmp->metric += mem->penalty * 1000000;
2265 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2271 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on, const char *agi)
2274 struct callattempt *outgoing = NULL; /* the list of calls we are building */
2276 char oldexten[AST_MAX_EXTENSION]="";
2277 char oldcontext[AST_MAX_CONTEXT]="";
2278 char queuename[256]="";
2279 struct ast_channel *peer;
2280 struct ast_channel *which;
2281 struct callattempt *lpeer;
2282 struct member *member;
2283 struct ast_app *app;
2284 int res = 0, bridge = 0;
2287 char *announce = NULL;
2290 time_t now = time(NULL);
2291 struct ast_bridge_config bridge_config;
2292 char nondataquality = 1;
2293 char *agiexec = NULL;
2295 const char *monitorfilename;
2296 const char *monitor_exec;
2297 const char *monitor_options;
2298 char tmpid[256], tmpid2[256];
2299 char meid[1024], meid2[1024];
2300 char mixmonargs[1512];
2301 struct ast_app *mixmonapp = NULL;
2304 int forwardsallowed = 1;
2306 memset(&bridge_config, 0, sizeof(bridge_config));
2309 for (; options && *options; options++)
2312 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2315 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2318 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2321 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2327 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2330 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2333 if ((now - qe->start >= qe->parent->timeout))
2337 forwardsallowed = 0;
2341 /* Hold the lock while we setup the outgoing calls */
2343 AST_LIST_LOCK(&queues);
2344 ast_mutex_lock(&qe->parent->lock);
2346 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n",
2348 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2349 cur = qe->parent->members;
2350 if (!ast_strlen_zero(qe->announce))
2351 announce = qe->announce;
2352 if (!ast_strlen_zero(announceoverride))
2353 announce = announceoverride;
2355 for (; cur; cur = cur->next) {
2356 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2359 ast_mutex_unlock(&qe->parent->lock);
2361 AST_LIST_UNLOCK(&queues);
2364 tmp->stillgoing = -1;
2365 tmp->member = cur; /* Never directly dereference! Could change on reload */
2366 tmp->oldstatus = cur->status;
2367 tmp->lastcall = cur->lastcall;
2368 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2369 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2370 just calculate their metric for the appropriate strategy */
2371 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2372 /* Put them in the list of outgoing thingies... We're ready now.
2373 XXX If we're forcibly removed, these outgoing calls won't get
2375 tmp->q_next = outgoing;
2377 /* If this line is up, don't try anybody else */
2378 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2384 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2385 to = (qe->expire - now) * 1000;
2387 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2388 ring_one(qe, outgoing, &numbusies);
2389 ast_mutex_unlock(&qe->parent->lock);
2391 AST_LIST_UNLOCK(&queues);
2392 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2393 ast_mutex_lock(&qe->parent->lock);
2394 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2395 store_next(qe, outgoing);
2397 ast_mutex_unlock(&qe->parent->lock);
2398 peer = lpeer ? lpeer->chan : NULL;
2401 /* Must gotten hung up */
2407 ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
2408 } else { /* peer is valid */
2409 /* Ah ha! Someone answered within the desired timeframe. Of course after this
2410 we will always return with -1 so that it is hung up properly after the
2413 if (!strcmp(qe->chan->tech->type, "Zap"))
2414 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2415 if (!strcmp(peer->tech->type, "Zap"))
2416 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2417 /* Update parameters for the queue */
2418 recalc_holdtime(qe);
2419 member = lpeer->member;
2420 hangupcalls(outgoing, peer);
2422 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2425 res2 = ast_autoservice_start(qe->chan);
2427 if (qe->parent->memberdelay) {
2428 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2429 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2431 if (!res2 && announce) {
2432 if (play_file(peer, announce))
2433 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2435 if (!res2 && qe->parent->reportholdtime) {
2436 if (!play_file(peer, qe->parent->sound_reporthold)) {
2440 holdtime = abs((now - qe->start) / 60);
2442 play_file(peer, qe->parent->sound_lessthan);
2443 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2445 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2446 play_file(peer, qe->parent->sound_minutes);
2450 res2 |= ast_autoservice_stop(qe->chan);
2451 if (peer->_softhangup) {
2452 /* Agent must have hung up */
2453 ast_log(LOG_WARNING, "Agent on %s hungup on the customer. They're going to be pissed.\n", peer->name);
2454 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2455 record_abandoned(qe);
2456 if (qe->parent->eventwhencalled)
2457 manager_event(EVENT_FLAG_AGENT, "AgentDump",
2462 "MemberName: %s\r\n"
2464 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2465 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2469 /* Caller must have hung up just before being connected*/
2470 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2471 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2472 record_abandoned(qe);
2477 /* Stop music on hold */
2478 ast_moh_stop(qe->chan);
2479 /* If appropriate, log that we have a destination channel */
2481 ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2482 /* Make sure channels are compatible */
2483 res = ast_channel_make_compatible(qe->chan, peer);
2485 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
2486 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2487 record_abandoned(qe);
2491 /* Begin Monitoring */
2492 if (qe->parent->monfmt && *qe->parent->monfmt) {
2493 if (!qe->parent->montype) {
2495 ast_log(LOG_DEBUG, "Starting Monitor as requested.\n");
2496 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2497 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2501 if (monitorfilename)
2502 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2503 else if (qe->chan->cdr)
2504 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2506 /* Last ditch effort -- no CDR, make up something */
2507 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2508 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2510 if (qe->parent->monjoin)
2511 ast_monitor_setjoinfiles(which, 1);
2514 ast_log(LOG_DEBUG, "Starting MixMonitor as requested.\n");
2515 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2516 if (!monitorfilename) {
2518 ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid)-1);
2520 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2522 ast_copy_string(tmpid2, monitorfilename, sizeof(tmpid2)-1);
2523 for (p = tmpid2; *p ; p++) {
2524 if (*p == '^' && *(p+1) == '{') {
2529 memset(tmpid, 0, sizeof(tmpid));
2530 pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
2533 monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC");
2534 monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS");
2537 ast_copy_string(meid2, monitor_exec, sizeof(meid2)-1);
2538 for (p = meid2; *p ; p++) {
2539 if (*p == '^' && *(p+1) == '{') {
2544 memset(meid, 0, sizeof(meid));
2545 pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
2548 snprintf(tmpid2, sizeof(tmpid2)-1, "%s.%s", tmpid, qe->parent->monfmt);
2550 mixmonapp = pbx_findapp("MixMonitor");
2552 if (strchr(tmpid2, '|')) {
2553 ast_log(LOG_WARNING, "monitor-format (in queues.conf) and MONITOR_FILENAME cannot contain a '|'! Not recording.\n");
2557 if (!monitor_options)
2558 monitor_options = "";
2560 if (strchr(monitor_options, '|')) {
2561 ast_log(LOG_WARNING, "MONITOR_OPTIONS cannot contain a '|'! Not recording.\n");
2566 if (!ast_strlen_zero(monitor_exec) && !ast_strlen_zero(monitor_options))
2567 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s|%s", tmpid2, monitor_options, monitor_exec);
2569 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s", tmpid2, monitor_options);
2572 ast_log(LOG_DEBUG, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
2574 ret = pbx_exec(qe->chan, mixmonapp, mixmonargs);
2577 ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
2581 /* Drop out of the queue at this point, to prepare for next caller */
2583 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2585 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2586 ast_channel_sendurl(peer, url);
2588 if (qe->parent->setinterfacevar)
2589 pbx_builtin_setvar_helper(qe->chan, "MEMBERINTERFACE", member->interface);
2590 if (!ast_strlen_zero(agi)) {
2592 ast_log(LOG_DEBUG, "app_queue: agi=%s.\n", agi);
2593 app = pbx_findapp("agi");
2595 agiexec = ast_strdupa(agi);
2596 ret = pbx_exec(qe->chan, app, agiexec);
2598 ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
2600 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s", (long)time(NULL) - qe->start, peer->uniqueid);
2601 if (qe->parent->eventwhencalled)
2602 manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2607 "MemberName: %s\r\n"
2609 "BridgedChannel: %s\r\n"
2611 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2612 (long)time(NULL) - qe->start, peer->uniqueid,
2613 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2614 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2615 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2618 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2620 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2621 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
2622 qe->chan->exten, qe->chan->context, (long) (callstart - qe->start),
2623 (long) (time(NULL) - callstart));
2624 } else if (qe->chan->_softhangup) {
2625 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
2626 (long) (callstart - qe->start), (long) (time(NULL) - callstart));
2627 if (qe->parent->eventwhencalled)
2628 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2633 "MemberName: %s\r\n"
2636 "Reason: caller\r\n"
2638 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2639 (long)(callstart - qe->start), (long)(time(NULL) - callstart),
2640 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2642 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETEAGENT", "%ld|%ld",
2643 (long) (callstart - qe->start), (long) (time(NULL) - callstart));
2644 if (qe->parent->eventwhencalled)
2645 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2649 "MemberName: %s\r\n"
2654 queuename, qe->chan->uniqueid, peer->name, member->membername, (long)(callstart - qe->start),
2655 (long)(time(NULL) - callstart),
2656 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2659 if (bridge != AST_PBX_NO_HANGUP_PEER)
2661 update_queue(qe->parent, member);
2662 res = bridge ? bridge : 1;
2665 hangupcalls(outgoing, NULL);
2670 static int wait_a_bit(struct queue_ent *qe)
2672 /* Don't need to hold the lock while we setup the outgoing calls */
2673 int retrywait = qe->parent->retry * 1000;
2675 return ast_waitfordigit(qe->chan, retrywait);
2678 static struct member *interface_exists(struct call_queue *q, char *interface)
2685 for (mem = q->members; mem; mem = mem->next) {
2686 if (!strcasecmp(interface, mem->interface))
2694 /* Dump all members in a specific queue to the database
2696 * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2699 static void dump_queue_members(struct call_queue *pm_queue)
2701 struct member *cur_member;
2702 char value[PM_MAX_LEN];
2706 memset(value, 0, sizeof(value));
2711 for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2712 if (!cur_member->dynamic)
2715 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d;%s%s",
2716 cur_member->interface, cur_member->penalty, cur_member->paused, cur_member->membername,
2717 cur_member->next ? "|" : "");
2718 if (res != strlen(value + value_len)) {
2719 ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2725 if (value_len && !cur_member) {
2726 if (ast_db_put(pm_family, pm_queue->name, value))
2727 ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2729 /* Delete the entry if the queue is empty or there is an error */
2730 ast_db_del(pm_family, pm_queue->name);
2733 static int remove_from_queue(char *queuename, char *interface)
2735 struct call_queue *q;
2736 struct member *last_member, *look;
2737 int res = RES_NOSUCHQUEUE;
2739 AST_LIST_LOCK(&queues);
2740 AST_LIST_TRAVERSE(&queues, q, list) {
2741 ast_mutex_lock(&q->lock);
2742 if (strcmp(q->name, queuename)) {
2743 ast_mutex_unlock(&q->lock);
2747 if ((last_member = interface_exists(q, interface))) {
2748 if ((look = q->members) == last_member) {
2749 q->members = last_member->next;
2751 while (look != NULL) {
2752 if (look->next == last_member) {
2753 look->next = last_member->next;
2760 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
2763 "MemberName: %s\r\n",
2764 q->name, last_member->interface, last_member->membername);
2767 if (queue_persistent_members)
2768 dump_queue_members(q);
2774 ast_mutex_unlock(&q->lock);
2778 if (res == RES_OKAY)
2779 remove_from_interfaces(interface);
2781 AST_LIST_UNLOCK(&queues);
2787 static int add_to_queue(char *queuename, char *interface, char *membername, int penalty, int paused, int dump)
2789 struct call_queue *q;
2790 struct member *new_member;
2791 int res = RES_NOSUCHQUEUE;
2793 /* \note Ensure the appropriate realtime queue is loaded. Note that this
2794 * short-circuits if the queue is already in memory. */
2795 if (!(q = load_realtime_queue(queuename)))
2798 AST_LIST_LOCK(&queues);
2800 ast_mutex_lock(&q->lock);
2801 if (interface_exists(q, interface) == NULL) {
2802 add_to_interfaces(interface);
2803 if ((new_member = create_queue_member(interface, membername, penalty, paused))) {
2804 new_member->dynamic = 1;
2805 new_member->next = q->members;
2806 q->members = new_member;
2807 manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
2810 "MemberName: %s\r\n"
2811 "Membership: %s\r\n"
2813 "CallsTaken: %d\r\n"
2817 q->name, new_member->interface, new_member->membername,
2818 new_member->dynamic ? "dynamic" : "static",
2819 new_member->penalty, new_member->calls, (int) new_member->lastcall,
2820 new_member->status, new_member->paused);
2823 dump_queue_members(q);
2827 res = RES_OUTOFMEMORY;
2832 ast_mutex_unlock(&q->lock);
2833 AST_LIST_UNLOCK(&queues);
2838 static int set_member_paused(char *queuename, char *interface, int paused)
2841 struct call_queue *q;
2844 /* Special event for when all queues are paused - individual events still generated */
2845 /* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */
2846 if (ast_strlen_zero(queuename))
2847 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
2849 AST_LIST_LOCK(&queues);
2850 AST_LIST_TRAVERSE(&queues, q, list) {
2851 ast_mutex_lock(&q->lock);
2852 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
2853 if ((mem = interface_exists(q, interface))) {
2855 if (mem->paused == paused)
2856 ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
2857 mem->paused = paused;
2859 if (queue_persistent_members)
2860 dump_queue_members(q);
2862 ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
2864 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
2867 "MemberName: %s\r\n"
2869 q->name, mem->interface, mem->membername, paused);
2872 ast_mutex_unlock(&q->lock);
2874 AST_LIST_UNLOCK(&queues);
2876 return found ? RESULT_SUCCESS : RESULT_FAILURE;
2879 /* Reload dynamic queue members persisted into the astdb */
2880 static void reload_queue_members(void)
2891 struct ast_db_entry *db_tree;
2892 struct ast_db_entry *entry;
2893 struct call_queue *cur_queue;
2894 char queue_data[PM_MAX_LEN];
2896 AST_LIST_LOCK(&queues);
2898 /* Each key in 'pm_family' is the name of a queue */