Remove deprecated CLI apps from the core
[asterisk/asterisk.git] / apps / app_queue.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*! \file
20  *
21  * \brief True call queues with optional send URL on answer
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \arg Config in \ref Config_qu queues.conf
26  *
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>
31  *
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.
37  *
38  * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
39  *
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
47  *
48  * Patch Version 1.07 2003-12-24 01
49  *
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>
52  *
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>
55  *
56  * \ingroup applications
57  */
58
59 #include "asterisk.h"
60
61 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
62
63 #include <stdlib.h>
64 #include <errno.h>
65 #include <unistd.h>
66 #include <string.h>
67 #include <stdlib.h>
68 #include <stdio.h>
69 #include <sys/time.h>
70 #include <sys/signal.h>
71 #include <netinet/in.h>
72
73 #include "asterisk/lock.h"
74 #include "asterisk/file.h"
75 #include "asterisk/logger.h"
76 #include "asterisk/channel.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/options.h"
79 #include "asterisk/app.h"
80 #include "asterisk/linkedlists.h"
81 #include "asterisk/module.h"
82 #include "asterisk/translate.h"
83 #include "asterisk/say.h"
84 #include "asterisk/features.h"
85 #include "asterisk/musiconhold.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/manager.h"
88 #include "asterisk/config.h"
89 #include "asterisk/monitor.h"
90 #include "asterisk/utils.h"
91 #include "asterisk/causes.h"
92 #include "asterisk/astdb.h"
93 #include "asterisk/devicestate.h"
94 #include "asterisk/stringfields.h"
95
96 enum {
97         QUEUE_STRATEGY_RINGALL = 0,
98         QUEUE_STRATEGY_LEASTRECENT,
99         QUEUE_STRATEGY_FEWESTCALLS,
100         QUEUE_STRATEGY_RANDOM,
101         QUEUE_STRATEGY_RRMEMORY
102 };
103
104 static struct strategy {
105         int strategy;
106         char *name;
107 } strategies[] = {
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" },
113 };
114
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
120 #define RES_OKAY        0               /* Action completed */
121 #define RES_EXISTS      (-1)            /* Entry already exists */
122 #define RES_OUTOFMEMORY (-2)            /* Out of memory */
123 #define RES_NOSUCHQUEUE (-3)            /* No such queue */
124
125 static char *app = "Queue";
126
127 static char *synopsis = "Queue a call for a call queue";
128
129 static char *descrip =
130 "  Queue(queuename[|options[|URL][|announceoverride][|timeout][|AGI]):\n"
131 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
132 "This application will return to the dialplan if the queue does not exist, or\n"
133 "any of the join options cause the caller to not enter the queue.\n"
134 "The option string may contain zero or more of the following characters:\n"
135 "      'd' -- data-quality (modem) call (minimum delay).\n"
136 "      'h' -- allow callee to hang up by hitting *.\n"
137 "      'H' -- allow caller to hang up by hitting *.\n"
138 "      'n' -- no retries on the timeout; will exit this application and \n"
139 "             go to the next step.\n"
140 "      'i' -- ignore call forward requests from queue members and do nothing\n"
141 "             when they are requested.\n"
142 "      'r' -- ring instead of playing MOH\n"
143 "      't' -- allow the called user transfer the calling user\n"
144 "      'T' -- to allow the calling user to transfer the call.\n"
145 "      'w' -- allow the called user to write the conversation to disk via Monitor\n"
146 "      'W' -- allow the calling user to write the conversation to disk via Monitor\n"
147 "  In addition to transferring the call, a call may be parked and then picked\n"
148 "up by another user.\n"
149 "  The optional URL will be sent to the called party if the channel supports\n"
150 "it.\n"
151 "  The optional AGI parameter will setup an AGI script to be executed on the \n"
152 "calling party's channel once they are connected to a queue member.\n"
153 "  The timeout will cause the queue to fail out after a specified number of\n"
154 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
155 "  This application sets the following channel variable upon completion:\n"
156 "      QUEUESTATUS    The status of the call as a text string, one of\n"
157 "             TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL\n";
158
159 static char *app_aqm = "AddQueueMember" ;
160 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
161 static char *app_aqm_descrip =
162 "   AddQueueMember(queuename[|interface[|penalty[|options]]]):\n"
163 "Dynamically adds interface to an existing queue.\n"
164 "If the interface is already in the queue and there exists an n+101 priority\n"
165 "then it will then jump to this priority.  Otherwise it will return an error\n"
166 "The option string may contain zero or more of the following characters:\n"
167 "       'j' -- jump to +101 priority when appropriate.\n"
168 "  This application sets the following channel variable upon completion:\n"
169 "     AQMSTATUS    The status of the attempt to add a queue member as a \n"
170 "                     text string, one of\n"
171 "           ADDED | MEMBERALREADY | NOSUCHQUEUE \n"
172 "Example: AddQueueMember(techsupport|SIP/3000)\n"
173 "";
174
175 static char *app_rqm = "RemoveQueueMember" ;
176 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
177 static char *app_rqm_descrip =
178 "   RemoveQueueMember(queuename[|interface[|options]]):\n"
179 "Dynamically removes interface to an existing queue\n"
180 "If the interface is NOT in the queue and there exists an n+101 priority\n"
181 "then it will then jump to this priority.  Otherwise it will return an error\n"
182 "The option string may contain zero or more of the following characters:\n"
183 "       'j' -- jump to +101 priority when appropriate.\n"
184 "  This application sets the following channel variable upon completion:\n"
185 "     RQMSTATUS      The status of the attempt to remove a queue member as a\n"
186 "                     text string, one of\n"
187 "           REMOVED | NOTINQUEUE | NOSUCHQUEUE \n"
188 "Example: RemoveQueueMember(techsupport|SIP/3000)\n"
189 "";
190
191 static char *app_pqm = "PauseQueueMember" ;
192 static char *app_pqm_synopsis = "Pauses a queue member" ;
193 static char *app_pqm_descrip =
194 "   PauseQueueMember([queuename]|interface[|options]):\n"
195 "Pauses (blocks calls for) a queue member.\n"
196 "The given interface will be paused in the given queue.  This prevents\n"
197 "any calls from being sent from the queue to the interface until it is\n"
198 "unpaused with UnpauseQueueMember or the manager interface.  If no\n"
199 "queuename is given, the interface is paused in every queue it is a\n"
200 "member of.  If the interface is not in the named queue, or if no queue\n"
201 "is given and the interface is not in any queue, it will jump to\n"
202 "priority n+101, if it exists and the appropriate options are set.\n"
203 "The application will fail if the interface is not found and no extension\n"
204 "to jump to exists.\n"
205 "The option string may contain zero or more of the following characters:\n"
206 "       'j' -- jump to +101 priority when appropriate.\n"
207 "  This application sets the following channel variable upon completion:\n"
208 "     PQMSTATUS      The status of the attempt to pause a queue member as a\n"
209 "                     text string, one of\n"
210 "           PAUSED | NOTFOUND\n"
211 "Example: PauseQueueMember(|SIP/3000)\n";
212
213 static char *app_upqm = "UnpauseQueueMember" ;
214 static char *app_upqm_synopsis = "Unpauses a queue member" ;
215 static char *app_upqm_descrip =
216 "   UnpauseQueueMember([queuename]|interface[|options]):\n"
217 "Unpauses (resumes calls to) a queue member.\n"
218 "This is the counterpart to PauseQueueMember and operates exactly the\n"
219 "same way, except it unpauses instead of pausing the given interface.\n"
220 "The option string may contain zero or more of the following characters:\n"
221 "       'j' -- jump to +101 priority when appropriate.\n"
222 "  This application sets the following channel variable upon completion:\n"
223 "     UPQMSTATUS       The status of the attempt to unpause a queue \n"
224 "                      member as a text string, one of\n"
225 "            UNPAUSED | NOTFOUND\n"
226 "Example: UnpauseQueueMember(|SIP/3000)\n";
227
228 static char *app_ql = "QueueLog" ;
229 static char *app_ql_synopsis = "Writes to the queue_log" ;
230 static char *app_ql_descrip =
231 "   QueueLog(queuename|uniqueid|agent|event[|additionalinfo]):\n"
232 "Allows you to write your own events into the queue log\n"
233 "Example: QueueLog(101|${UNIQUEID}|${AGENT}|WENTONBREAK|600)\n";
234
235 /*! \brief Persistent Members astdb family */
236 static const char *pm_family = "/Queue/PersistentMembers";
237 /* The maximum length of each persistent member queue database entry */
238 #define PM_MAX_LEN 8192
239
240 /*! \brief queues.conf [general] option */
241 static int queue_persistent_members = 0;
242
243 /*! \brief queues.conf per-queue weight option */
244 static int use_weight = 0;
245
246 /*! \brief queues.conf [general] option */
247 static int autofill_default = 0;
248
249 /*! \brief queues.conf [general] option */
250 static int montype_default = 0;
251
252 enum queue_result {
253         QUEUE_UNKNOWN = 0,
254         QUEUE_TIMEOUT = 1,
255         QUEUE_JOINEMPTY = 2,
256         QUEUE_LEAVEEMPTY = 3,
257         QUEUE_JOINUNAVAIL = 4,
258         QUEUE_LEAVEUNAVAIL = 5,
259         QUEUE_FULL = 6,
260 };
261
262 const struct {
263         enum queue_result id;
264         char *text;
265 } queue_results[] = {
266         { QUEUE_UNKNOWN, "UNKNOWN" },
267         { QUEUE_TIMEOUT, "TIMEOUT" },
268         { QUEUE_JOINEMPTY,"JOINEMPTY" },
269         { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
270         { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
271         { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
272         { QUEUE_FULL, "FULL" },
273 };
274
275 /*! \brief We define a custom "local user" structure because we
276    use it not only for keeping track of what is in use but
277    also for keeping track of who we're dialing. */
278
279 struct callattempt {
280         struct callattempt *q_next;
281         struct ast_channel *chan;
282         char interface[256];
283         int stillgoing;
284         int metric;
285         int oldstatus;
286         time_t lastcall;
287         struct member *member;
288 };
289
290
291 struct queue_ent {
292         struct call_queue *parent;          /*!< What queue is our parent */
293         char moh[80];                       /*!< Name of musiconhold to be used */
294         char announce[80];                  /*!< Announcement to play for member when call is answered */
295         char context[AST_MAX_CONTEXT];      /*!< Context when user exits queue */
296         char digits[AST_MAX_EXTENSION];     /*!< Digits entered while in queue */
297         int pos;                            /*!< Where we are in the queue */
298         int prio;                           /*!< Our priority */
299         int last_pos_said;                  /*!< Last position we told the user */
300         time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
301         int last_periodic_announce_sound;   /*!< The last periodic announcement we made */
302         time_t last_pos;                    /*!< Last time we told the user their position */
303         int opos;                           /*!< Where we started in the queue */
304         int handled;                        /*!< Whether our call was handled */
305         int max_penalty;                    /*!< Limit the members that can take this call to this penalty or lower */
306         time_t start;                       /*!< When we started holding */
307         time_t expire;                      /*!< When this entry should expire (time out of queue) */
308         struct ast_channel *chan;           /*!< Our channel */
309         struct queue_ent *next;             /*!< The next queue entry */
310 };
311
312 struct member {
313         char interface[80];                 /*!< Technology/Location */
314         char membername[80];                /*!< Member name to use in queue logs */
315         int penalty;                        /*!< Are we a last resort? */
316         int calls;                          /*!< Number of calls serviced by this member */
317         int dynamic;                        /*!< Are we dynamically added? */
318         int status;                         /*!< Status of queue member */
319         int paused;                         /*!< Are we paused (not accepting calls)? */
320         time_t lastcall;                    /*!< When last successful call was hungup */
321         unsigned int dead:1;                /*!< Used to detect members deleted in realtime */
322         unsigned int delme:1;               /*!< Flag to delete entry on reload */
323         struct member *next;                /*!< Next member */
324 };
325
326 struct member_interface {
327         char interface[80];
328         AST_LIST_ENTRY(member_interface) list;    /*!< Next call queue */
329 };
330
331 static AST_LIST_HEAD_STATIC(interfaces, member_interface);
332
333 /* values used in multi-bit flags in call_queue */
334 #define QUEUE_EMPTY_NORMAL 1
335 #define QUEUE_EMPTY_STRICT 2
336 #define ANNOUNCEHOLDTIME_ALWAYS 1
337 #define ANNOUNCEHOLDTIME_ONCE 2
338 #define QUEUE_EVENT_VARIABLES 3
339
340 struct call_queue {
341         ast_mutex_t lock;       
342         char name[80];                      /*!< Name */
343         char moh[80];                       /*!< Music On Hold class to be used */
344         char announce[80];                  /*!< Announcement to play when call is answered */
345         char context[AST_MAX_CONTEXT];      /*!< Exit context */
346         unsigned int monjoin:1;
347         unsigned int dead:1;
348         unsigned int joinempty:2;
349         unsigned int eventwhencalled:2;
350         unsigned int leavewhenempty:2;
351         unsigned int ringinuse:1;
352         unsigned int setinterfacevar:1;
353         unsigned int reportholdtime:1;
354         unsigned int wrapped:1;
355         unsigned int timeoutrestart:1;
356         unsigned int announceholdtime:2;
357         unsigned int strategy:3;
358         unsigned int maskmemberstatus:1;
359         unsigned int realtime:1;
360         int announcefrequency;              /*!< How often to announce their position */
361         int periodicannouncefrequency;      /*!< How often to play periodic announcement */
362         int roundingseconds;                /*!< How many seconds do we round to? */
363         int holdtime;                       /*!< Current avg holdtime, based on recursive boxcar filter */
364         int callscompleted;                 /*!< Number of queue calls completed */
365         int callsabandoned;                 /*!< Number of queue calls abandoned */
366         int servicelevel;                   /*!< seconds setting for servicelevel*/
367         int callscompletedinsl;             /*!< Number of calls answered with servicelevel*/
368         char monfmt[8];                     /*!< Format to use when recording calls */
369         int montype;                        /*!< Monitor type  Monitor vs. MixMonitor */
370         char sound_next[80];                /*!< Sound file: "Your call is now first in line" (def. queue-youarenext) */
371         char sound_thereare[80];            /*!< Sound file: "There are currently" (def. queue-thereare) */
372         char sound_calls[80];               /*!< Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/
373         char sound_holdtime[80];            /*!< Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
374         char sound_minutes[80];             /*!< Sound file: "minutes." (def. queue-minutes) */
375         char sound_lessthan[80];            /*!< Sound file: "less-than" (def. queue-lessthan) */
376         char sound_seconds[80];             /*!< Sound file: "seconds." (def. queue-seconds) */
377         char sound_thanks[80];              /*!< Sound file: "Thank you for your patience." (def. queue-thankyou) */
378         char sound_reporthold[80];          /*!< Sound file: "Hold time" (def. queue-reporthold) */
379         char sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS][80];/*!< Sound files: Custom announce, no default */
380
381         int count;                          /*!< How many entries */
382         int maxlen;                         /*!< Max number of entries */
383         int wrapuptime;                     /*!< Wrapup Time */
384
385         int retry;                          /*!< Retry calling everyone after this amount of time */
386         int timeout;                        /*!< How long to wait for an answer */
387         int weight;                         /*!< Respective weight */
388         int autopause;                      /*!< Auto pause queue members if they fail to answer */
389
390         /* Queue strategy things */
391         int rrpos;                          /*!< Round Robin - position */
392         int memberdelay;                    /*!< Seconds to delay connecting member to caller */
393         int autofill;                       /*!< Ignore the head call status and ring an available agent */
394         
395         struct member *members;             /*!< Head of the list of members */
396         struct queue_ent *head;             /*!< Head of the list of callers */
397         AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
398 };
399
400 static AST_LIST_HEAD_STATIC(queues, call_queue);
401
402 static int set_member_paused(char *queuename, char *interface, int paused);
403
404 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
405 {
406         int i;
407
408         for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
409                 if (queue_results[i].id == res) {
410                         pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
411                         return;
412                 }
413         }
414 }
415
416 static char *int2strat(int strategy)
417 {
418         int x;
419
420         for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
421                 if (strategy == strategies[x].strategy)
422                         return strategies[x].name;
423         }
424
425         return "<unknown>";
426 }
427
428 static int strat2int(const char *strategy)
429 {
430         int x;
431
432         for (x = 0; x < sizeof(strategies) / sizeof(strategies[0]); x++) {
433                 if (!strcasecmp(strategy, strategies[x].name))
434                         return strategies[x].strategy;
435         }
436
437         return -1;
438 }
439
440 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
441 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
442 {
443         struct queue_ent *cur;
444
445         if (!q || !new)
446                 return;
447         if (prev) {
448                 cur = prev->next;
449                 prev->next = new;
450         } else {
451                 cur = q->head;
452                 q->head = new;
453         }
454         new->next = cur;
455         new->parent = q;
456         new->pos = ++(*pos);
457         new->opos = *pos;
458 }
459
460 enum queue_member_status {
461         QUEUE_NO_MEMBERS,
462         QUEUE_NO_REACHABLE_MEMBERS,
463         QUEUE_NORMAL
464 };
465
466 static enum queue_member_status get_member_status(const struct call_queue *q, int max_penalty)
467 {
468         struct member *member;
469         enum queue_member_status result = QUEUE_NO_MEMBERS;
470
471         for (member = q->members; member; member = member->next) {
472                 if (max_penalty && (member->penalty > max_penalty))
473                         continue;
474
475                 if (member->paused) continue;
476
477                 switch (member->status) {
478                 case AST_DEVICE_INVALID:
479                         /* nothing to do */
480                         break;
481                 case AST_DEVICE_UNAVAILABLE:
482                         result = QUEUE_NO_REACHABLE_MEMBERS;
483                         break;
484                 default:
485                         return QUEUE_NORMAL;
486                 }
487         }
488         
489         return result;
490 }
491
492 struct statechange {
493         int state;
494         char dev[0];
495 };
496
497 static void *changethread(void *data)
498 {
499         struct call_queue *q;
500         struct statechange *sc = data;
501         struct member *cur;
502         struct member_interface *curint;
503         char *loc;
504         char *technology;
505
506         technology = ast_strdupa(sc->dev);
507         loc = strchr(technology, '/');
508         if (loc) {
509                 *loc++ = '\0';
510         } else {
511                 free(sc);
512                 return NULL;
513         }
514
515         AST_LIST_LOCK(&interfaces);
516         AST_LIST_TRAVERSE(&interfaces, curint, list) {
517                 if (!strcasecmp(curint->interface, sc->dev))
518                         break;
519         }
520         AST_LIST_UNLOCK(&interfaces);
521
522         if (!curint) {
523                 if (option_debug)
524                         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));
525                 free(sc);
526                 return NULL;
527         }
528
529         if (option_debug)
530                 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
531         AST_LIST_LOCK(&queues);
532         AST_LIST_TRAVERSE(&queues, q, list) {
533                 ast_mutex_lock(&q->lock);
534                 for (cur = q->members; cur; cur = cur->next) {
535                         if (strcasecmp(sc->dev, cur->interface))
536                                 continue;
537
538                         if (cur->status != sc->state) {
539                                 cur->status = sc->state;
540                                 if (q->maskmemberstatus)
541                                         continue;
542
543                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
544                                         "Queue: %s\r\n"
545                                         "Location: %s\r\n"
546                                         "MemberName: %s\r\n"
547                                         "Membership: %s\r\n"
548                                         "Penalty: %d\r\n"
549                                         "CallsTaken: %d\r\n"
550                                         "LastCall: %d\r\n"
551                                         "Status: %d\r\n"
552                                         "Paused: %d\r\n",
553                                         q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
554                                         cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
555                         }
556                 }
557                 ast_mutex_unlock(&q->lock);
558         }
559         AST_LIST_UNLOCK(&queues);
560
561         return NULL;
562 }
563
564 static int statechange_queue(const char *dev, int state, void *ign)
565 {
566         /* Avoid potential for deadlocks by spawning a new thread to handle
567            the event */
568         struct statechange *sc;
569         pthread_t t;
570         pthread_attr_t attr;
571
572         if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
573                 return 0;
574
575         sc->state = state;
576         strcpy(sc->dev, dev);
577         pthread_attr_init(&attr);
578         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
579         if (ast_pthread_create(&t, &attr, changethread, sc)) {
580                 ast_log(LOG_WARNING, "Failed to create update thread!\n");
581                 free(sc);
582         }
583
584         return 0;
585 }
586
587 static struct member *create_queue_member(char *interface, const char *membername, int penalty, int paused)
588 {
589         struct member *cur;
590         
591         if ((cur = ast_calloc(1, sizeof(*cur)))) {
592                 cur->penalty = penalty;
593                 cur->paused = paused;
594                 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
595                 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
596                 if (!strchr(cur->interface, '/'))
597                         ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
598                 cur->status = ast_device_state(interface);
599         }
600
601         return cur;
602 }
603
604 static struct call_queue *alloc_queue(const char *queuename)
605 {
606         struct call_queue *q;
607
608         if ((q = ast_calloc(1, sizeof(*q)))) {
609                 ast_mutex_init(&q->lock);
610                 ast_copy_string(q->name, queuename, sizeof(q->name));
611         }
612         return q;
613 }
614
615 static void init_queue(struct call_queue *q)
616 {
617         int i;
618
619         q->dead = 0;
620         q->retry = DEFAULT_RETRY;
621         q->timeout = -1;
622         q->maxlen = 0;
623         q->announcefrequency = 0;
624         q->announceholdtime = 0;
625         q->roundingseconds = 0; /* Default - don't announce seconds */
626         q->servicelevel = 0;
627         q->ringinuse = 1;
628         q->setinterfacevar = 0;
629         q->autofill = autofill_default;
630         q->montype = montype_default;
631         q->moh[0] = '\0';
632         q->announce[0] = '\0';
633         q->context[0] = '\0';
634         q->monfmt[0] = '\0';
635         q->periodicannouncefrequency = 0;
636         ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
637         ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
638         ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
639         ast_copy_string(q->sound_holdtime, "queue-holdtime", sizeof(q->sound_holdtime));
640         ast_copy_string(q->sound_minutes, "queue-minutes", sizeof(q->sound_minutes));
641         ast_copy_string(q->sound_seconds, "queue-seconds", sizeof(q->sound_seconds));
642         ast_copy_string(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks));
643         ast_copy_string(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan));
644         ast_copy_string(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold));
645         ast_copy_string(q->sound_periodicannounce[0], "queue-periodic-announce", sizeof(q->sound_periodicannounce[0]));
646         for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
647                 q->sound_periodicannounce[i][0]='\0';
648         }
649 }
650
651 static void clear_queue(struct call_queue *q)
652 {
653         q->holdtime = 0;
654         q->callscompleted = 0;
655         q->callsabandoned = 0;
656         q->callscompletedinsl = 0;
657         q->wrapuptime = 0;
658 }
659
660 static int add_to_interfaces(char *interface)
661 {
662         struct member_interface *curint;
663
664         AST_LIST_LOCK(&interfaces);
665         AST_LIST_TRAVERSE(&interfaces, curint, list) {
666                 if (!strcasecmp(curint->interface, interface))
667                         break;
668         }
669
670         if (curint) {
671                 AST_LIST_UNLOCK(&interfaces);
672                 return 0;
673         }
674
675         if (option_debug)
676                 ast_log(LOG_DEBUG, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface);
677         
678         if ((curint = ast_calloc(1, sizeof(*curint)))) {
679                 ast_copy_string(curint->interface, interface, sizeof(curint->interface));
680                 AST_LIST_INSERT_HEAD(&interfaces, curint, list);
681         }
682         AST_LIST_UNLOCK(&interfaces);
683
684         return 0;
685 }
686
687 static int interface_exists_global(char *interface)
688 {
689         struct call_queue *q;
690         struct member *mem;
691         int ret = 0;
692
693         AST_LIST_LOCK(&queues);
694         AST_LIST_TRAVERSE(&queues, q, list) {
695                 ast_mutex_lock(&q->lock);
696                 for (mem = q->members; mem && !ret; mem = mem->next) {
697                         if (!strcasecmp(interface, mem->interface))
698                                 ret = 1;
699                 }
700                 ast_mutex_unlock(&q->lock);
701                 if (ret)
702                         break;
703         }
704         AST_LIST_UNLOCK(&queues);
705
706         return ret;
707 }
708
709 static int remove_from_interfaces(char *interface)
710 {
711         struct member_interface *curint;
712
713         AST_LIST_LOCK(&interfaces);
714         AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) {
715                 if (!strcasecmp(curint->interface, interface)) {
716                         if (!interface_exists_global(interface)) {
717                                 if (option_debug)
718                                         ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
719                                 AST_LIST_REMOVE_CURRENT(&interfaces, list);
720                                 free(curint);
721                         }
722                         break;
723                 }
724         }
725         AST_LIST_TRAVERSE_SAFE_END;
726         AST_LIST_UNLOCK(&interfaces);
727
728         return 0;
729 }
730
731 static void clear_and_free_interfaces(void)
732 {
733         struct member_interface *curint;
734
735         AST_LIST_LOCK(&interfaces);
736         while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list)))
737                 free(curint);
738         AST_LIST_UNLOCK(&interfaces);
739 }
740
741 /*! \brief Configure a queue parameter.
742 \par
743    For error reporting, line number is passed for .conf static configuration.
744    For Realtime queues, linenum is -1.
745    The failunknown flag is set for config files (and static realtime) to show
746    errors for unknown parameters. It is cleared for dynamic realtime to allow
747    extra fields in the tables. */
748 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
749 {
750         int i = 0;
751         char *c, *lastc;
752         char buff[80];
753
754         if (!strcasecmp(param, "musicclass") || 
755                 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
756                 ast_copy_string(q->moh, val, sizeof(q->moh));
757         } else if (!strcasecmp(param, "announce")) {
758                 ast_copy_string(q->announce, val, sizeof(q->announce));
759         } else if (!strcasecmp(param, "context")) {
760                 ast_copy_string(q->context, val, sizeof(q->context));
761         } else if (!strcasecmp(param, "timeout")) {
762                 q->timeout = atoi(val);
763                 if (q->timeout < 0)
764                         q->timeout = DEFAULT_TIMEOUT;
765         } else if (!strcasecmp(param, "ringinuse")) {
766                 q->ringinuse = ast_true(val);
767         } else if (!strcasecmp(param, "setinterfacevar")) {
768                 q->setinterfacevar = ast_true(val);
769         } else if (!strcasecmp(param, "monitor-join")) {
770                 q->monjoin = ast_true(val);
771         } else if (!strcasecmp(param, "monitor-format")) {
772                 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
773         } else if (!strcasecmp(param, "queue-youarenext")) {
774                 ast_copy_string(q->sound_next, val, sizeof(q->sound_next));
775         } else if (!strcasecmp(param, "queue-thereare")) {
776                 ast_copy_string(q->sound_thereare, val, sizeof(q->sound_thereare));
777         } else if (!strcasecmp(param, "queue-callswaiting")) {
778                 ast_copy_string(q->sound_calls, val, sizeof(q->sound_calls));
779         } else if (!strcasecmp(param, "queue-holdtime")) {
780                 ast_copy_string(q->sound_holdtime, val, sizeof(q->sound_holdtime));
781         } else if (!strcasecmp(param, "queue-minutes")) {
782                 ast_copy_string(q->sound_minutes, val, sizeof(q->sound_minutes));
783         } else if (!strcasecmp(param, "queue-seconds")) {
784                 ast_copy_string(q->sound_seconds, val, sizeof(q->sound_seconds));
785         } else if (!strcasecmp(param, "queue-lessthan")) {
786                 ast_copy_string(q->sound_lessthan, val, sizeof(q->sound_lessthan));
787         } else if (!strcasecmp(param, "queue-thankyou")) {
788                 ast_copy_string(q->sound_thanks, val, sizeof(q->sound_thanks));
789         } else if (!strcasecmp(param, "queue-reporthold")) {
790                 ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold));
791         } else if (!strcasecmp(param, "announce-frequency")) {
792                 q->announcefrequency = atoi(val);
793         } else if (!strcasecmp(param, "announce-round-seconds")) {
794                 q->roundingseconds = atoi(val);
795                 if (q->roundingseconds>60 || q->roundingseconds<0) {
796                         if (linenum >= 0) {
797                                 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
798                                         "using 0 instead for queue '%s' at line %d of queues.conf\n",
799                                         val, param, q->name, linenum);
800                         } else {
801                                 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
802                                         "using 0 instead for queue '%s'\n", val, param, q->name);
803                         }
804                         q->roundingseconds=0;
805                 }
806         } else if (!strcasecmp(param, "announce-holdtime")) {
807                 if (!strcasecmp(val, "once"))
808                         q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
809                 else if (ast_true(val))
810                         q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
811                 else
812                         q->announceholdtime = 0;
813         } else if (!strcasecmp(param, "periodic-announce")) {
814                 if (strchr(val,'|')) {
815                         lastc = (char *)val;
816                         while ((c = strchr(lastc,'|'))) {
817                                 if (i > MAX_PERIODIC_ANNOUNCEMENTS)
818                                         break;
819                                 strncpy(buff, lastc, abs(lastc - c));
820                                 buff[abs(lastc - c)] = '\0';
821                                 ast_copy_string(q->sound_periodicannounce[i], buff, sizeof(q->sound_periodicannounce[i]));
822                                 lastc = (c + 1);
823                                 i++;
824                         }
825                         if (strlen(lastc)) {
826                                 ast_copy_string(q->sound_periodicannounce[i], lastc, sizeof(q->sound_periodicannounce[i]));
827                         }
828                 } else {
829                         ast_copy_string(q->sound_periodicannounce[i], val, sizeof(q->sound_periodicannounce[i]));
830                 }
831         } else if (!strcasecmp(param, "periodic-announce-frequency")) {
832                 q->periodicannouncefrequency = atoi(val);
833         } else if (!strcasecmp(param, "retry")) {
834                 q->retry = atoi(val);
835                 if (q->retry <= 0)
836                         q->retry = DEFAULT_RETRY;
837         } else if (!strcasecmp(param, "wrapuptime")) {
838                 q->wrapuptime = atoi(val);
839         } else if (!strcasecmp(param, "autofill")) {
840                 q->autofill = ast_true(val);
841         } else if (!strcasecmp(param, "monitor-type")) {
842                 if (!strcasecmp(val, "mixmonitor"))
843                         q->montype = 1;
844         } else if (!strcasecmp(param, "autopause")) {
845                 q->autopause = ast_true(val);
846         } else if (!strcasecmp(param, "maxlen")) {
847                 q->maxlen = atoi(val);
848                 if (q->maxlen < 0)
849                         q->maxlen = 0;
850         } else if (!strcasecmp(param, "servicelevel")) {
851                 q->servicelevel= atoi(val);
852         } else if (!strcasecmp(param, "strategy")) {
853                 q->strategy = strat2int(val);
854                 if (q->strategy < 0) {
855                         ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
856                                 val, q->name);
857                         q->strategy = QUEUE_STRATEGY_RINGALL;
858                 }
859         } else if (!strcasecmp(param, "joinempty")) {
860                 if (!strcasecmp(val, "strict"))
861                         q->joinempty = QUEUE_EMPTY_STRICT;
862                 else if (ast_true(val))
863                         q->joinempty = QUEUE_EMPTY_NORMAL;
864                 else
865                         q->joinempty = 0;
866         } else if (!strcasecmp(param, "leavewhenempty")) {
867                 if (!strcasecmp(val, "strict"))
868                         q->leavewhenempty = QUEUE_EMPTY_STRICT;
869                 else if (ast_true(val))
870                         q->leavewhenempty = QUEUE_EMPTY_NORMAL;
871                 else
872                         q->leavewhenempty = 0;
873         } else if (!strcasecmp(param, "eventmemberstatus")) {
874                 q->maskmemberstatus = !ast_true(val);
875         } else if (!strcasecmp(param, "eventwhencalled")) {
876                 if (!strcasecmp(val, "vars")) {
877                         q->eventwhencalled = QUEUE_EVENT_VARIABLES;
878                 } else {
879                         q->eventwhencalled = ast_true(val);
880                 }
881         } else if (!strcasecmp(param, "reportholdtime")) {
882                 q->reportholdtime = ast_true(val);
883         } else if (!strcasecmp(param, "memberdelay")) {
884                 q->memberdelay = atoi(val);
885         } else if (!strcasecmp(param, "weight")) {
886                 q->weight = atoi(val);
887                 if (q->weight)
888                         use_weight++;
889                 /* With Realtime queues, if the last queue using weights is deleted in realtime,
890                    we will not see any effect on use_weight until next reload. */
891         } else if (!strcasecmp(param, "timeoutrestart")) {
892                 q->timeoutrestart = ast_true(val);
893         } else if (failunknown) {
894                 if (linenum >= 0) {
895                         ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
896                                 q->name, param, linenum);
897                 } else {
898                         ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
899                 }
900         }
901 }
902
903 static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str)
904 {
905         struct member *m, *prev_m;
906         int penalty = 0;
907
908         if (penalty_str) {
909                 penalty = atoi(penalty_str);
910                 if (penalty < 0)
911                         penalty = 0;
912         }
913
914         /* Find the member, or the place to put a new one. */
915         for (m = q->members, prev_m = NULL;
916                 m && strcmp(m->interface, interface);
917                 prev_m = m, m = m->next);
918
919         /* Create a new one if not found, else update penalty */
920         if (!m) {
921                 if ((m = create_queue_member(interface, membername, penalty, 0))) {
922                         m->dead = 0;
923                         add_to_interfaces(interface);
924                         if (prev_m) {
925                                 prev_m->next = m;
926                         } else {
927                                 q->members = m;
928                         }
929                 }
930         } else {
931                 m->dead = 0;    /* Do not delete this one. */
932                 m->penalty = penalty;
933         }
934 }
935
936 static void free_members(struct call_queue *q, int all)
937 {
938         /* Free non-dynamic members */
939         struct member *curm, *next, *prev = NULL;
940
941         for (curm = q->members; curm; curm = next) {
942                 next = curm->next;
943                 if (all || !curm->dynamic) {
944                         if (prev)
945                                 prev->next = next;
946                         else
947                                 q->members = next;
948                         remove_from_interfaces(curm->interface);
949                         free(curm);
950                 } else
951                         prev = curm;
952         }
953 }
954
955 static void destroy_queue(struct call_queue *q)
956 {
957         free_members(q, 1);
958         ast_mutex_destroy(&q->lock);
959         free(q);
960 }
961
962 /*!\brief Reload a single queue via realtime.
963    \return Return the queue, or NULL if it doesn't exist.
964    \note Should be called with the global qlock locked. */
965 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
966 {
967         struct ast_variable *v;
968         struct call_queue *q;
969         struct member *m, *prev_m, *next_m;
970         char *interface = NULL;
971         char *tmp, *tmp_name;
972         char tmpbuf[64];        /* Must be longer than the longest queue param name. */
973
974         /* Find the queue in the in-core list (we will create a new one if not found). */
975         AST_LIST_TRAVERSE(&queues, q, list) {
976                 if (!strcasecmp(q->name, queuename))
977                         break;
978         }
979
980         /* Static queues override realtime. */
981         if (q) {
982                 ast_mutex_lock(&q->lock);
983                 if (!q->realtime) {
984                         if (q->dead) {
985                                 ast_mutex_unlock(&q->lock);
986                                 return NULL;
987                         } else {
988                                 ast_mutex_unlock(&q->lock);
989                                 return q;
990                         }
991                 }
992         } else if (!member_config)
993                 /* Not found in the list, and it's not realtime ... */
994                 return NULL;
995
996         /* Check if queue is defined in realtime. */
997         if (!queue_vars) {
998                 /* Delete queue from in-core list if it has been deleted in realtime. */
999                 if (q) {
1000                         /*! \note Hmm, can't seem to distinguish a DB failure from a not
1001                            found condition... So we might delete an in-core queue
1002                            in case of DB failure. */
1003                         ast_log(LOG_DEBUG, "Queue %s not found in realtime.\n", queuename);
1004
1005                         q->dead = 1;
1006                         /* Delete if unused (else will be deleted when last caller leaves). */
1007                         if (!q->count) {
1008                                 /* Delete. */
1009                                 AST_LIST_REMOVE(&queues, q, list);
1010                                 ast_mutex_unlock(&q->lock);
1011                                 destroy_queue(q);
1012                         } else
1013                                 ast_mutex_unlock(&q->lock);
1014                 }
1015                 return NULL;
1016         }
1017
1018         /* Create a new queue if an in-core entry does not exist yet. */
1019         if (!q) {
1020                 if (!(q = alloc_queue(queuename)))
1021                         return NULL;
1022                 ast_mutex_lock(&q->lock);
1023                 clear_queue(q);
1024                 q->realtime = 1;
1025                 AST_LIST_INSERT_HEAD(&queues, q, list);
1026         }
1027         init_queue(q);          /* Ensure defaults for all parameters not set explicitly. */
1028
1029         memset(tmpbuf, 0, sizeof(tmpbuf));
1030         for (v = queue_vars; v; v = v->next) {
1031                 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
1032                 if ((tmp = strchr(v->name, '_'))) {
1033                         ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
1034                         tmp_name = tmpbuf;
1035                         tmp = tmp_name;
1036                         while ((tmp = strchr(tmp, '_')))
1037                                 *tmp++ = '-';
1038                 } else
1039                         tmp_name = v->name;
1040                 queue_set_param(q, tmp_name, v->value, -1, 0);
1041         }
1042
1043         /* Temporarily set non-dynamic members dead so we can detect deleted ones. */
1044         for (m = q->members; m; m = m->next) {
1045                 if (!m->dynamic)
1046                         m->dead = 1;
1047         }
1048
1049         while ((interface = ast_category_browse(member_config, interface))) {
1050                 rt_handle_member_record(q, interface,
1051                         S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
1052                         ast_variable_retrieve(member_config, interface, "penalty"));
1053         }
1054
1055         /* Delete all realtime members that have been deleted in DB. */
1056         m = q->members;
1057         prev_m = NULL;
1058         while (m) {
1059                 next_m = m->next;
1060                 if (m->dead) {
1061                         if (prev_m) {
1062                                 prev_m->next = next_m;
1063                         } else {
1064                                 q->members = next_m;
1065                         }
1066                         remove_from_interfaces(m->interface);
1067                         free(m);
1068                 } else {
1069                         prev_m = m;
1070                 }
1071                 m = next_m;
1072         }
1073
1074         ast_mutex_unlock(&q->lock);
1075
1076         return q;
1077 }
1078
1079 static struct call_queue *load_realtime_queue(char *queuename)
1080 {
1081         struct ast_variable *queue_vars;
1082         struct ast_config *member_config = NULL;
1083         struct call_queue *q;
1084
1085         /* Find the queue in the in-core list first. */
1086         AST_LIST_LOCK(&queues);
1087         AST_LIST_TRAVERSE(&queues, q, list) {
1088                 if (!strcasecmp(q->name, queuename)) {
1089                         break;
1090                 }
1091         }
1092         AST_LIST_UNLOCK(&queues);
1093
1094         if (!q || q->realtime) {
1095                 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
1096                    queue operations while waiting for the DB.
1097
1098                    This will be two separate database transactions, so we might
1099                    see queue parameters as they were before another process
1100                    changed the queue and member list as it was after the change.
1101                    Thus we might see an empty member list when a queue is
1102                    deleted. In practise, this is unlikely to cause a problem. */
1103
1104                 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
1105                 if (queue_vars) {
1106                         member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
1107                         if (!member_config) {
1108                                 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
1109                                 return NULL;
1110                         }
1111                 }
1112
1113                 AST_LIST_LOCK(&queues);
1114
1115                 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
1116                 if (member_config)
1117                         ast_config_destroy(member_config);
1118                 if (queue_vars)
1119                         ast_variables_destroy(queue_vars);
1120
1121                 AST_LIST_UNLOCK(&queues);
1122         }
1123         return q;
1124 }
1125
1126 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
1127 {
1128         struct call_queue *q;
1129         struct queue_ent *cur, *prev = NULL;
1130         int res = -1;
1131         int pos = 0;
1132         int inserted = 0;
1133         enum queue_member_status stat;
1134
1135         if (!(q = load_realtime_queue(queuename)))
1136                 return res;
1137
1138         AST_LIST_LOCK(&queues);
1139         ast_mutex_lock(&q->lock);
1140
1141         /* This is our one */
1142         stat = get_member_status(q, qe->max_penalty);
1143         if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1144                 *reason = QUEUE_JOINEMPTY;
1145         else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1146                 *reason = QUEUE_JOINUNAVAIL;
1147         else if (q->maxlen && (q->count >= q->maxlen))
1148                 *reason = QUEUE_FULL;
1149         else {
1150                 /* There's space for us, put us at the right position inside
1151                  * the queue.
1152                  * Take into account the priority of the calling user */
1153                 inserted = 0;
1154                 prev = NULL;
1155                 cur = q->head;
1156                 while (cur) {
1157                         /* We have higher priority than the current user, enter
1158                          * before him, after all the other users with priority
1159                          * higher or equal to our priority. */
1160                         if ((!inserted) && (qe->prio > cur->prio)) {
1161                                 insert_entry(q, prev, qe, &pos);
1162                                 inserted = 1;
1163                         }
1164                         cur->pos = ++pos;
1165                         prev = cur;
1166                         cur = cur->next;
1167                 }
1168                 /* No luck, join at the end of the queue */
1169                 if (!inserted)
1170                         insert_entry(q, prev, qe, &pos);
1171                 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1172                 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1173                 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1174                 q->count++;
1175                 res = 0;
1176                 manager_event(EVENT_FLAG_CALL, "Join",
1177                         "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
1178                         qe->chan->name,
1179                         S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
1180                         S_OR(qe->chan->cid.cid_name, "unknown"),
1181                         q->name, qe->pos, q->count, qe->chan->uniqueid );
1182                 if (option_debug)
1183                         ast_log(LOG_DEBUG, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1184         }
1185         ast_mutex_unlock(&q->lock);
1186         AST_LIST_UNLOCK(&queues);
1187
1188         return res;
1189 }
1190
1191 static int play_file(struct ast_channel *chan, char *filename)
1192 {
1193         int res;
1194
1195         ast_stopstream(chan);
1196         res = ast_streamfile(chan, filename, chan->language);
1197         if (!res)
1198                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1199         ast_stopstream(chan);
1200
1201         return res;
1202 }
1203
1204 static int valid_exit(struct queue_ent *qe, char digit)
1205 {
1206         int digitlen = strlen(qe->digits);
1207
1208         /* Prevent possible buffer overflow */
1209         if (digitlen < sizeof(qe->digits) - 2) {
1210                 qe->digits[digitlen] = digit;
1211                 qe->digits[digitlen + 1] = '\0';
1212         } else {
1213                 qe->digits[0] = '\0';
1214                 return 0;
1215         }
1216
1217         /* If there's no context to goto, short-circuit */
1218         if (ast_strlen_zero(qe->context))
1219                 return 0;
1220
1221         /* If the extension is bad, then reset the digits to blank */
1222         if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1223                 qe->digits[0] = '\0';
1224                 return 0;
1225         }
1226
1227         /* We have an exact match */
1228         if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1229                 /* Return 1 on a successful goto */
1230                 return 1;
1231         }
1232
1233         return 0;
1234 }
1235
1236 static int say_position(struct queue_ent *qe)
1237 {
1238         int res = 0, avgholdmins, avgholdsecs;
1239         time_t now;
1240
1241         /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/
1242         time(&now);
1243         if ((now - qe->last_pos) < 15)
1244                 return 0;
1245
1246         /* If either our position has changed, or we are over the freq timer, say position */
1247         if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
1248                 return 0;
1249
1250         ast_moh_stop(qe->chan);
1251         /* Say we're next, if we are */
1252         if (qe->pos == 1) {
1253                 res = play_file(qe->chan, qe->parent->sound_next);
1254                 if (res && valid_exit(qe, res))
1255                         goto playout;
1256                 else
1257                         goto posout;
1258         } else {
1259                 res = play_file(qe->chan, qe->parent->sound_thereare);
1260                 if (res && valid_exit(qe, res))
1261                         goto playout;
1262                 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1263                 if (res && valid_exit(qe, res))
1264                         goto playout;
1265                 res = play_file(qe->chan, qe->parent->sound_calls);
1266                 if (res && valid_exit(qe, res))
1267                         goto playout;
1268         }
1269         /* Round hold time to nearest minute */
1270         avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
1271
1272         /* If they have specified a rounding then round the seconds as well */
1273         if (qe->parent->roundingseconds) {
1274                 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
1275                 avgholdsecs *= qe->parent->roundingseconds;
1276         } else {
1277                 avgholdsecs = 0;
1278         }
1279
1280         if (option_verbose > 2)
1281                 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1282
1283         /* If the hold time is >1 min, if it's enabled, and if it's not
1284            supposed to be only once and we have already said it, say it */
1285         if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1286                 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1287                 res = play_file(qe->chan, qe->parent->sound_holdtime);
1288                 if (res && valid_exit(qe, res))
1289                         goto playout;
1290
1291                 if (avgholdmins > 0) {
1292                         if (avgholdmins < 2) {
1293                                 res = play_file(qe->chan, qe->parent->sound_lessthan);
1294                                 if (res && valid_exit(qe, res))
1295                                         goto playout;
1296
1297                                 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, NULL);
1298                                 if (res && valid_exit(qe, res))
1299                                         goto playout;
1300                         } else {
1301                                 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
1302                                 if (res && valid_exit(qe, res))
1303                                         goto playout;
1304                         }
1305                         
1306                         res = play_file(qe->chan, qe->parent->sound_minutes);
1307                         if (res && valid_exit(qe, res))
1308                                 goto playout;
1309                 }
1310                 if (avgholdsecs>0) {
1311                         res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
1312                         if (res && valid_exit(qe, res))
1313                                 goto playout;
1314
1315                         res = play_file(qe->chan, qe->parent->sound_seconds);
1316                         if (res && valid_exit(qe, res))
1317                                 goto playout;
1318                 }
1319
1320         }
1321
1322 posout:
1323         if (option_verbose > 2)
1324                 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n",
1325                         qe->chan->name, qe->parent->name, qe->pos);
1326         res = play_file(qe->chan, qe->parent->sound_thanks);
1327         if (res && !valid_exit(qe, res))
1328                 res = 0;
1329
1330 playout:
1331         /* Set our last_pos indicators */
1332         qe->last_pos = now;
1333         qe->last_pos_said = qe->pos;
1334
1335         /* Don't restart music on hold if we're about to exit the caller from the queue */
1336         if (!res)
1337                 ast_moh_start(qe->chan, qe->moh, NULL);
1338
1339         return res;
1340 }
1341
1342 static void recalc_holdtime(struct queue_ent *qe)
1343 {
1344         int oldvalue, newvalue;
1345
1346         /* Calculate holdtime using a recursive boxcar filter */
1347         /* Thanks to SRT for this contribution */
1348         /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1349
1350         newvalue = time(NULL) - qe->start;
1351
1352         ast_mutex_lock(&qe->parent->lock);
1353         if (newvalue <= qe->parent->servicelevel)
1354                 qe->parent->callscompletedinsl++;
1355         oldvalue = qe->parent->holdtime;
1356         qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2;
1357         ast_mutex_unlock(&qe->parent->lock);
1358 }
1359
1360
1361 static void leave_queue(struct queue_ent *qe)
1362 {
1363         struct call_queue *q;
1364         struct queue_ent *cur, *prev = NULL;
1365         int pos = 0;
1366
1367         if (!(q = qe->parent))
1368                 return;
1369         ast_mutex_lock(&q->lock);
1370
1371         prev = NULL;
1372         for (cur = q->head; cur; cur = cur->next) {
1373                 if (cur == qe) {
1374                         q->count--;
1375
1376                         /* Take us out of the queue */
1377                         manager_event(EVENT_FLAG_CALL, "Leave",
1378                                 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
1379                                 qe->chan->name, q->name,  q->count, qe->chan->uniqueid);
1380                         if (option_debug)
1381                                 ast_log(LOG_DEBUG, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1382                         /* Take us out of the queue */
1383                         if (prev)
1384                                 prev->next = cur->next;
1385                         else
1386                                 q->head = cur->next;
1387                 } else {
1388                         /* Renumber the people after us in the queue based on a new count */
1389                         cur->pos = ++pos;
1390                         prev = cur;
1391                 }
1392         }
1393         ast_mutex_unlock(&q->lock);
1394
1395         if (q->dead && !q->count) {     
1396                 /* It's dead and nobody is in it, so kill it */
1397                 AST_LIST_LOCK(&queues);
1398                 AST_LIST_REMOVE(&queues, q, list);
1399                 AST_LIST_UNLOCK(&queues);
1400                 destroy_queue(q);
1401         }
1402 }
1403
1404 /* Hang up a list of outgoing calls */
1405 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
1406 {
1407         struct callattempt *oo;
1408
1409         while (outgoing) {
1410                 /* Hangup any existing lines we have open */
1411                 if (outgoing->chan && (outgoing->chan != exception))
1412                         ast_hangup(outgoing->chan);
1413                 oo = outgoing;
1414                 outgoing = outgoing->q_next;
1415                 free(oo);
1416         }
1417 }
1418
1419 static int update_status(struct call_queue *q, struct member *member, int status)
1420 {
1421         struct member *cur;
1422
1423         /* Since a reload could have taken place, we have to traverse the list to
1424                 be sure it's still valid */
1425         ast_mutex_lock(&q->lock);
1426         for (cur = q->members; cur; cur = cur->next) {
1427                 if (member != cur)
1428                         continue;
1429
1430                 cur->status = status;
1431                 if (!q->maskmemberstatus) {
1432                         manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1433                                 "Queue: %s\r\n"
1434                                 "Location: %s\r\n"
1435                                 "MemberName: %s\r\n"
1436                                 "Membership: %s\r\n"
1437                                 "Penalty: %d\r\n"
1438                                 "CallsTaken: %d\r\n"
1439                                 "LastCall: %d\r\n"
1440                                 "Status: %d\r\n"
1441                                 "Paused: %d\r\n",
1442                                 q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : "static",
1443                                 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1444                 }
1445         }
1446         ast_mutex_unlock(&q->lock);
1447         return 0;
1448 }
1449
1450 static int update_dial_status(struct call_queue *q, struct member *member, int status)
1451 {
1452         if (status == AST_CAUSE_BUSY)
1453                 status = AST_DEVICE_BUSY;
1454         else if (status == AST_CAUSE_UNREGISTERED)
1455                 status = AST_DEVICE_UNAVAILABLE;
1456         else if (status == AST_CAUSE_NOSUCHDRIVER)
1457                 status = AST_DEVICE_INVALID;
1458         else
1459                 status = AST_DEVICE_UNKNOWN;
1460         return update_status(q, member, status);
1461 }
1462
1463 /* traverse all defined queues which have calls waiting and contain this member
1464    return 0 if no other queue has precedence (higher weight) or 1 if found  */
1465 static int compare_weight(struct call_queue *rq, struct member *member)
1466 {
1467         struct call_queue *q;
1468         struct member *mem;
1469         int found = 0;
1470         
1471         /* &qlock and &rq->lock already set by try_calling()
1472          * to solve deadlock */
1473         AST_LIST_TRAVERSE(&queues, q, list) {
1474                 if (q == rq) /* don't check myself, could deadlock */
1475                         continue;
1476                 ast_mutex_lock(&q->lock);
1477                 if (q->count && q->members) {
1478                         for (mem = q->members; mem; mem = mem->next) {
1479                                 if (strcmp(mem->interface, member->interface))
1480                                         continue;
1481
1482                                 ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1483                                 if (q->weight > rq->weight) {
1484                                         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);
1485                                         found = 1;
1486                                         break;
1487                                 }
1488                         }
1489                 }
1490                 ast_mutex_unlock(&q->lock);
1491                 if (found)
1492                         break;
1493         }
1494         return found;
1495 }
1496
1497 /*! \brief common hangup actions */
1498 static void do_hang(struct callattempt *o)
1499 {
1500         o->stillgoing = 0;
1501         ast_hangup(o->chan);
1502         o->chan = NULL;
1503 }
1504
1505 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
1506 {
1507         char *tmp = alloca(len);
1508
1509         if (pbx_builtin_serialize_variables(chan, tmp, len)) {
1510                 int i, j;
1511
1512                 /* convert "\n" to "\nVariable: " */
1513                 strcpy(vars, "Variable: ");
1514
1515                 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
1516                         vars[j] = tmp[i];
1517
1518                         if (tmp[i + 1] == '\0')
1519                                 break;
1520                         if (tmp[i] == '\n') {
1521                                 vars[j] = '\r';
1522                                 vars[++j] = '\n';
1523
1524                                 ast_copy_string(&(vars[j]), "Variable: ", len - j);
1525                                 j += 9;
1526                         }
1527                 }
1528                 if (j > len - 1)
1529                         j = len - 1;
1530                 vars[j - 2] = '\r';
1531                 vars[j - 1] = '\n';
1532                 vars[j] = '\0';
1533         } else {
1534                 /* there are no channel variables; leave it blank */
1535                 *vars = '\0';
1536         }
1537         return vars;
1538 }
1539
1540 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
1541 {
1542         int res;
1543         int status;
1544         char tech[256];
1545         char *location;
1546
1547         /* on entry here, we know that tmp->chan == NULL */
1548         if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1549                 if (option_debug)
1550                         ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
1551                 if (qe->chan->cdr)
1552                         ast_cdr_busy(qe->chan->cdr);
1553                 tmp->stillgoing = 0;
1554                 (*busies)++;
1555                 return 0;
1556         }
1557
1558         if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
1559                 if (option_debug)
1560                         ast_log(LOG_DEBUG, "%s in use, can't receive call\n", tmp->interface);
1561                 if (qe->chan->cdr)
1562                         ast_cdr_busy(qe->chan->cdr);
1563                 tmp->stillgoing = 0;
1564                 return 0;
1565         }
1566
1567         if (tmp->member->paused) {
1568                 if (option_debug)
1569                         ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
1570                 if (qe->chan->cdr)
1571                         ast_cdr_busy(qe->chan->cdr);
1572                 tmp->stillgoing = 0;
1573                 return 0;
1574         }
1575         if (use_weight && compare_weight(qe->parent,tmp->member)) {
1576                 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1577                 if (qe->chan->cdr)
1578                         ast_cdr_busy(qe->chan->cdr);
1579                 tmp->stillgoing = 0;
1580                 (*busies)++;
1581                 return 0;
1582         }
1583
1584         ast_copy_string(tech, tmp->interface, sizeof(tech));
1585         if ((location = strchr(tech, '/')))
1586                 *location++ = '\0';
1587         else
1588                 location = "";
1589
1590         /* Request the peer */
1591         tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1592         if (!tmp->chan) {                       /* If we can't, just go on to the next call */
1593                 if (qe->chan->cdr)
1594                         ast_cdr_busy(qe->chan->cdr);
1595                 tmp->stillgoing = 0;
1596                 update_dial_status(qe->parent, tmp->member, status);
1597
1598                 ast_mutex_lock(&qe->parent->lock);
1599                 qe->parent->rrpos++;
1600                 ast_mutex_unlock(&qe->parent->lock);
1601
1602                 (*busies)++;
1603                 return 0;
1604         } else if (status != tmp->oldstatus)
1605                 update_dial_status(qe->parent, tmp->member, status);
1606         
1607         tmp->chan->appl = "AppQueue";
1608         tmp->chan->data = "(Outgoing Line)";
1609         tmp->chan->whentohangup = 0;
1610         if (tmp->chan->cid.cid_num)
1611                 free(tmp->chan->cid.cid_num);
1612         tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
1613         if (tmp->chan->cid.cid_name)
1614                 free(tmp->chan->cid.cid_name);
1615         tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
1616         if (tmp->chan->cid.cid_ani)
1617                 free(tmp->chan->cid.cid_ani);
1618         tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
1619
1620         /* Inherit specially named variables from parent channel */
1621         ast_channel_inherit_variables(qe->chan, tmp->chan);
1622
1623         /* Presense of ADSI CPE on outgoing channel follows ours */
1624         tmp->chan->adsicpe = qe->chan->adsicpe;
1625
1626         /* Place the call, but don't wait on the answer */
1627         if ((res = ast_call(tmp->chan, location, 0))) {
1628                 /* Again, keep going even if there's an error */
1629                 if (option_debug)
1630                         ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1631                 if (option_verbose > 2)
1632                         ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
1633                 do_hang(tmp);
1634                 (*busies)++;
1635                 return 0;
1636         } else if (qe->parent->eventwhencalled) {
1637                 char vars[2048];
1638
1639                 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1640                                         "AgentCalled: %s\r\n"
1641                                         "ChannelCalling: %s\r\n"
1642                                         "CallerID: %s\r\n"
1643                                         "CallerIDName: %s\r\n"
1644                                         "Context: %s\r\n"
1645                                         "Extension: %s\r\n"
1646                                         "Priority: %d\r\n"
1647                                         "%s",
1648                                         tmp->interface, qe->chan->name,
1649                                         tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1650                                         tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1651                                         qe->chan->context, qe->chan->exten, qe->chan->priority,
1652                                         qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
1653                 if (option_verbose > 2)
1654                         ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
1655         }
1656
1657         return 1;
1658 }
1659
1660 /*! \brief find the entry with the best metric, or NULL */
1661 static struct callattempt *find_best(struct callattempt *outgoing)
1662 {
1663         struct callattempt *best = NULL, *cur;
1664
1665         for (cur = outgoing; cur; cur = cur->q_next) {
1666                 if (cur->stillgoing &&                                  /* Not already done */
1667                         !cur->chan &&                                   /* Isn't already going */
1668                         (!best || cur->metric < best->metric)) {                /* We haven't found one yet, or it's better */
1669                         best = cur;
1670                 }
1671         }
1672
1673         return best;
1674 }
1675
1676 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
1677 {
1678         int ret = 0;
1679
1680         while (ret == 0) {
1681                 struct callattempt *best = find_best(outgoing);
1682                 if (!best) {
1683                         if (option_debug)
1684                                 ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
1685                         break;
1686                 }
1687                 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
1688                         struct callattempt *cur;
1689                         /* Ring everyone who shares this best metric (for ringall) */
1690                         for (cur = outgoing; cur; cur = cur->q_next) {
1691                                 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
1692                                         if (option_debug)
1693                                                 ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1694                                         ring_entry(qe, cur, busies);
1695                                 }
1696                         }
1697                 } else {
1698                         /* Ring just the best channel */
1699                         if (option_debug)
1700                                 ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
1701                         ring_entry(qe, best, busies);
1702                 }
1703                 if (best->chan) /* break out with result = 1 */
1704                         ret = 1;
1705         }
1706
1707         return ret;
1708 }
1709
1710 static int store_next(struct queue_ent *qe, struct callattempt *outgoing)
1711 {
1712         struct callattempt *best = find_best(outgoing);
1713
1714         if (best) {
1715                 /* Ring just the best channel */
1716                 if (option_debug)
1717                         ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
1718                 qe->parent->rrpos = best->metric % 1000;
1719         } else {
1720                 /* Just increment rrpos */
1721                 if (qe->parent->wrapped) {
1722                         /* No more channels, start over */
1723                         qe->parent->rrpos = 0;
1724                 } else {
1725                         /* Prioritize next entry */
1726                         qe->parent->rrpos++;
1727                 }
1728         }
1729         qe->parent->wrapped = 0;
1730
1731         return 0;
1732 }
1733
1734 static int background_file(struct queue_ent *qe, struct ast_channel *chan, char *filename)
1735 {
1736         int res;
1737
1738         ast_stopstream(chan);
1739         res = ast_streamfile(chan, filename, chan->language);
1740
1741         if (!res) {
1742                 /* Wait for a keypress */
1743                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1744                 if (res < 0 || !valid_exit(qe, res))
1745                         res = 0;
1746
1747                 /* Stop playback */
1748                 ast_stopstream(chan);
1749         }
1750         
1751         return res;
1752 }
1753
1754 static int say_periodic_announcement(struct queue_ent *qe)
1755 {
1756         int res = 0;
1757         time_t now;
1758
1759         /* Get the current time */
1760         time(&now);
1761
1762         /* Check to see if it is time to announce */
1763         if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
1764                 return 0;
1765
1766         /* Stop the music on hold so we can play our own file */
1767         ast_moh_stop(qe->chan);
1768
1769         if (option_verbose > 2)
1770                 ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n");
1771
1772         /* Check to make sure we have a sound file. If not, reset to the first sound file */
1773         if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || !strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
1774                 qe->last_periodic_announce_sound = 0;
1775         }
1776         
1777         /* play the announcement */
1778         res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
1779
1780         /* Resume Music on Hold if the caller is going to stay in the queue */
1781         if (!res)
1782                 ast_moh_start(qe->chan, qe->moh, NULL);
1783
1784         /* update last_periodic_announce_time */
1785         qe->last_periodic_announce_time = now;
1786
1787         /* Update the current periodic announcement to the next announcement */
1788         qe->last_periodic_announce_sound++;
1789         
1790         return res;
1791 }
1792
1793 static void record_abandoned(struct queue_ent *qe)
1794 {
1795         ast_mutex_lock(&qe->parent->lock);
1796         manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
1797                 "Queue: %s\r\n"
1798                 "Uniqueid: %s\r\n"
1799                 "Position: %d\r\n"
1800                 "OriginalPosition: %d\r\n"
1801                 "HoldTime: %d\r\n",
1802                 qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
1803
1804         qe->parent->callsabandoned++;
1805         ast_mutex_unlock(&qe->parent->lock);
1806 }
1807
1808 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
1809 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername)
1810 {
1811         if (option_verbose > 2)
1812                 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", rnatime);
1813         ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
1814         if (qe->parent->autopause) {
1815                 if (!set_member_paused(qe->parent->name, interface, 1)) {
1816                         if (option_verbose > 2)
1817                                 ast_verbose( VERBOSE_PREFIX_3 "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", interface, qe->parent->name);
1818                 } else {
1819                         if (option_verbose > 2)
1820                                 ast_verbose( VERBOSE_PREFIX_3 "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
1821                 }
1822         }
1823         return;
1824 }
1825
1826 #define AST_MAX_WATCHERS 256
1827
1828 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
1829 {
1830         char *queue = qe->parent->name;
1831         struct callattempt *o;
1832         int status;
1833         int sentringing = 0;
1834         int numbusies = prebusies;
1835         int numnochan = 0;
1836         int stillgoing = 0;
1837         int orig = *to;
1838         struct ast_frame *f;
1839         struct callattempt *peer = NULL;
1840         struct ast_channel *winner;
1841         struct ast_channel *in = qe->chan;
1842         char on[80] = "";
1843         char membername[80] = "";
1844         long starttime = 0;
1845         long endtime = 0;       
1846
1847         starttime = (long) time(NULL);
1848         
1849         while (*to && !peer) {
1850                 int numlines, retry, pos = 1;
1851                 struct ast_channel *watchers[AST_MAX_WATCHERS];
1852                 watchers[0] = in;
1853
1854                 for (retry = 0; retry < 2; retry++) {
1855                         numlines = 0;
1856                         for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
1857                                 if (o->stillgoing) {    /* Keep track of important channels */
1858                                         stillgoing = 1;
1859                                         if (o->chan)
1860                                                 watchers[pos++] = o->chan;
1861                                 }
1862                                 numlines++;
1863                         }
1864                         if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
1865                                 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
1866                                 break;
1867                         /* On "ringall" strategy we only move to the next penalty level
1868                            when *all* ringing phones are done in the current penalty level */
1869                         ring_one(qe, outgoing, &numbusies);
1870                         /* and retry... */
1871                 }
1872                 if (pos == 1 /* not found */) {
1873                         if (numlines == (numbusies + numnochan)) {
1874                                 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1875                         } else {
1876                                 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1877                         }
1878                         *to = 0;
1879                         return NULL;
1880                 }
1881                 winner = ast_waitfor_n(watchers, pos, to);
1882                 for (o = outgoing; o; o = o->q_next) {
1883                         if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
1884                                 if (!peer) {
1885                                         if (option_verbose > 2)
1886                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1887                                         peer = o;
1888                                 }
1889                         } else if (o->chan && (o->chan == winner)) {
1890                                 if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
1891                                         ast_copy_string(on, o->member->interface, sizeof(on));
1892                                         ast_copy_string(membername, o->member->membername, sizeof(membername));
1893                                         if (option_verbose > 2)
1894                                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
1895                                         winner = o->chan = NULL;
1896                                 } else if (!ast_strlen_zero(o->chan->call_forward)) {
1897                                         char tmpchan[256];
1898                                         char *stuff;
1899                                         char *tech;
1900
1901                                         ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
1902                                         if ((stuff = strchr(tmpchan, '/'))) {
1903                                                 *stuff++ = '\0';
1904                                                 tech = tmpchan;
1905                                         } else {
1906                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1907                                                 stuff = tmpchan;
1908                                                 tech = "Local";
1909                                         }
1910                                         /* Before processing channel, go ahead and check for forwarding */
1911                                         if (option_verbose > 2)
1912                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1913                                         /* Setup parameters */
1914                                         o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1915                                         if (status != o->oldstatus)
1916                                                 update_dial_status(qe->parent, o->member, status);                                              
1917                                         if (!o->chan) {
1918                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
1919                                                 o->stillgoing = 0;
1920                                                 numnochan++;
1921                                         } else {
1922                                                 ast_channel_inherit_variables(in, o->chan);
1923                                                 if (o->chan->cid.cid_num)
1924                                                         free(o->chan->cid.cid_num);
1925                                                 o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
1926
1927                                                 if (o->chan->cid.cid_name)
1928                                                         free(o->chan->cid.cid_name);
1929                                                 o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
1930
1931                                                 ast_string_field_set(o->chan, accountcode, in->accountcode);
1932                                                 o->chan->cdrflags = in->cdrflags;
1933
1934                                                 if (in->cid.cid_ani) {
1935                                                         if (o->chan->cid.cid_ani)
1936                                                                 free(o->chan->cid.cid_ani);
1937                                                         o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
1938                                                 }
1939                                                 if (o->chan->cid.cid_rdnis)
1940                                                         free(o->chan->cid.cid_rdnis);
1941                                                 o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
1942                                                 if (ast_call(o->chan, tmpchan, 0)) {
1943                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
1944                                                         do_hang(o);
1945                                                         numnochan++;
1946                                                 }
1947                                         }
1948                                         /* Hangup the original channel now, in case we needed it */
1949                                         ast_hangup(winner);
1950                                         continue;
1951                                 }
1952                                 f = ast_read(winner);
1953                                 if (f) {
1954                                         if (f->frametype == AST_FRAME_CONTROL) {
1955                                                 switch (f->subclass) {
1956                                                 case AST_CONTROL_ANSWER:
1957                                                         /* This is our guy if someone answered. */
1958                                                         if (!peer) {
1959                                                                 if (option_verbose > 2)
1960                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1961                                                                 peer = o;
1962                                                         }
1963                                                         break;
1964                                                 case AST_CONTROL_BUSY:
1965                                                         if (option_verbose > 2)
1966                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
1967                                                         if (in->cdr)
1968                                                                 ast_cdr_busy(in->cdr);
1969                                                         do_hang(o);
1970                                                         endtime = (long)time(NULL);
1971                                                         endtime -= starttime;
1972                                                         rna(endtime*1000, qe, on, membername);
1973                                                         if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
1974                                                                 if (qe->parent->timeoutrestart)
1975                                                                         *to = orig;
1976                                                                 ring_one(qe, outgoing, &numbusies);
1977                                                         }
1978                                                         numbusies++;
1979                                                         break;
1980                                                 case AST_CONTROL_CONGESTION:
1981                                                         if (option_verbose > 2)
1982                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
1983                                                         if (in->cdr)
1984                                                                 ast_cdr_busy(in->cdr);
1985                                                         endtime = (long)time(NULL);
1986                                                         endtime -= starttime;
1987                                                         rna(endtime*1000, qe, on, membername);
1988                                                         do_hang(o);
1989                                                         if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
1990                                                                 if (qe->parent->timeoutrestart)
1991                                                                         *to = orig;
1992                                                                 ring_one(qe, outgoing, &numbusies);
1993                                                         }
1994                                                         numbusies++;
1995                                                         break;
1996                                                 case AST_CONTROL_RINGING:
1997                                                         if (option_verbose > 2)
1998                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1999                                                         if (!sentringing) {
2000 #if 0
2001                                                                 ast_indicate(in, AST_CONTROL_RINGING);
2002 #endif                                                          
2003                                                                 sentringing++;
2004                                                         }
2005                                                         break;
2006                                                 case AST_CONTROL_OFFHOOK:
2007                                                         /* Ignore going off hook */
2008                                                         break;
2009                                                 default:
2010                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
2011                                                 }
2012                                         }
2013                                         ast_frfree(f);
2014                                 } else {
2015                                         endtime = (long) time(NULL) - starttime;
2016                                         rna(endtime * 1000, qe, on, membername);
2017                                         do_hang(o);
2018                                         if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
2019                                                 if (qe->parent->timeoutrestart)
2020                                                         *to = orig;
2021                                                 ring_one(qe, outgoing, &numbusies);
2022                                         }
2023                                 }
2024                         }
2025                 }
2026                 if (winner == in) {
2027                         f = ast_read(in);
2028                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2029                                 /* Got hung up */
2030                                 *to = -1;
2031                                 if (f)
2032                                         ast_frfree(f);
2033                                 return NULL;
2034                         }
2035                         if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
2036                                 if (option_verbose > 3)
2037                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
2038                                 *to = 0;
2039                                 ast_frfree(f);
2040                                 return NULL;
2041                         }
2042                         if ((f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) {
2043                                 if (option_verbose > 3)
2044                                         ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass);
2045                                 *to = 0;
2046                                 *digit = f->subclass;
2047                                 ast_frfree(f);
2048                                 return NULL;
2049                         }
2050                         ast_frfree(f);
2051                 }
2052                 if (!*to)
2053                         rna(orig, qe, on, membername);
2054         }
2055
2056         return peer;
2057 }
2058
2059 static int is_our_turn(struct queue_ent *qe)
2060 {
2061         struct queue_ent *ch;
2062         struct member *cur;
2063         int avl = 0;
2064         int idx = 0;
2065         int res;
2066
2067         if (!qe->parent->autofill) {
2068                 /* Atomically read the parent head -- does not need a lock */
2069                 ch = qe->parent->head;
2070                 /* If we are now at the top of the head, break out */
2071                 if (ch == qe) {
2072                         if (option_debug)
2073                                 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2074                         res = 1;
2075                 } else {
2076                         if (option_debug)
2077                                 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2078                         res = 0;
2079                 }       
2080
2081         } else {
2082                 /* This needs a lock. How many members are available to be served? */
2083                 ast_mutex_lock(&qe->parent->lock);
2084                         
2085                 ch = qe->parent->head;
2086         
2087                 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
2088                         if (option_debug)
2089                                 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);
2090                         avl = 1;
2091                 } else {
2092                         for (cur = qe->parent->members; cur; cur = cur->next) {
2093                                 switch (cur->status) {
2094                                 case AST_DEVICE_NOT_INUSE:
2095                                 case AST_DEVICE_UNKNOWN:
2096                                         avl++;
2097                                         break;
2098                                 }
2099                         }
2100                 }
2101
2102                 if (option_debug)
2103                         ast_log(LOG_DEBUG, "There are %d available members.\n", avl);
2104         
2105                 while ((idx < avl) && (ch) && (ch != qe)) {
2106                         idx++;
2107                         ch = ch->next;                  
2108                 }
2109         
2110                 /* If the queue entry is within avl [the number of available members] calls from the top ... */
2111                 if (ch && idx < avl) {
2112                         if (option_debug)
2113                                 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
2114                         res = 1;
2115                 } else {
2116                         if (option_debug)
2117                                 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
2118                         res = 0;
2119                 }
2120                 
2121                 ast_mutex_unlock(&qe->parent->lock);
2122         }
2123
2124         return res;
2125 }
2126
2127 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
2128 {
2129         int res = 0;
2130
2131         /* This is the holding pen for callers 2 through maxlen */
2132         for (;;) {
2133                 enum queue_member_status stat;
2134
2135                 if (is_our_turn(qe))
2136                         break;
2137
2138                 /* If we have timed out, break out */
2139                 if (qe->expire && (time(NULL) > qe->expire)) {
2140                         *reason = QUEUE_TIMEOUT;
2141                         break;
2142                 }
2143
2144                 stat = get_member_status(qe->parent, qe->max_penalty);
2145
2146                 /* leave the queue if no agents, if enabled */
2147                 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2148                         *reason = QUEUE_LEAVEEMPTY;
2149                         ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2150                         leave_queue(qe);
2151                         break;
2152                 }
2153
2154                 /* leave the queue if no reachable agents, if enabled */
2155                 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2156                         *reason = QUEUE_LEAVEUNAVAIL;
2157                         ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2158                         leave_queue(qe);
2159                         break;
2160                 }
2161
2162                 /* Make a position announcement, if enabled */
2163                 if (qe->parent->announcefrequency && !ringing &&
2164                         (res = say_position(qe)))
2165                         break;
2166
2167                 /* Make a periodic announcement, if enabled */
2168                 if (qe->parent->periodicannouncefrequency && !ringing &&
2169                         (res = say_periodic_announcement(qe)))
2170                         break;
2171
2172                 /* Wait a second before checking again */
2173                 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000)))
2174                         break;
2175         }
2176
2177         return res;
2178 }
2179
2180 static int update_queue(struct call_queue *q, struct member *member)
2181 {
2182         struct member *cur;
2183
2184         /* Since a reload could have taken place, we have to traverse the list to
2185                 be sure it's still valid */
2186         ast_mutex_lock(&q->lock);
2187         cur = q->members;
2188         while (cur) {
2189                 if (member == cur) {
2190                         time(&cur->lastcall);
2191                         cur->calls++;
2192                         break;
2193                 }
2194                 cur = cur->next;
2195         }
2196         q->callscompleted++;
2197         ast_mutex_unlock(&q->lock);
2198         return 0;
2199 }
2200
2201 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
2202 {
2203         if (qe->max_penalty && (mem->penalty > qe->max_penalty))
2204                 return -1;
2205
2206         switch (q->strategy) {
2207         case QUEUE_STRATEGY_RINGALL:
2208                 /* Everyone equal, except for penalty */
2209                 tmp->metric = mem->penalty * 1000000;
2210                 break;
2211         case QUEUE_STRATEGY_RRMEMORY:
2212                 if (pos < q->rrpos) {
2213                         tmp->metric = 1000 + pos;
2214                 } else {
2215                         if (pos > q->rrpos)
2216                                 /* Indicate there is another priority */
2217                                 q->wrapped = 1;
2218                         tmp->metric = pos;
2219                 }
2220                 tmp->metric += mem->penalty * 1000000;
2221                 break;
2222         case QUEUE_STRATEGY_RANDOM:
2223                 tmp->metric = ast_random() % 1000;
2224                 tmp->metric += mem->penalty * 1000000;
2225                 break;
2226         case QUEUE_STRATEGY_FEWESTCALLS:
2227                 tmp->metric = mem->calls;
2228                 tmp->metric += mem->penalty * 1000000;
2229                 break;
2230         case QUEUE_STRATEGY_LEASTRECENT:
2231                 if (!mem->lastcall)
2232                         tmp->metric = 0;
2233                 else
2234                         tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2235                 tmp->metric += mem->penalty * 1000000;
2236                 break;
2237         default:
2238                 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2239                 break;
2240         }
2241         return 0;
2242 }
2243
2244 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on, const char *agi)
2245 {
2246         struct member *cur;
2247         struct callattempt *outgoing = NULL; /* the list of calls we are building */
2248         int to;
2249         char oldexten[AST_MAX_EXTENSION]="";
2250         char oldcontext[AST_MAX_CONTEXT]="";
2251         char queuename[256]="";
2252         struct ast_channel *peer;
2253         struct ast_channel *which;
2254         struct callattempt *lpeer;
2255         struct member *member;
2256         struct ast_app *app;
2257         int res = 0, bridge = 0;
2258         int numbusies = 0;
2259         int x=0;
2260         char *announce = NULL;
2261         char digit = 0;
2262         time_t callstart;
2263         time_t now = time(NULL);
2264         struct ast_bridge_config bridge_config;
2265         char nondataquality = 1;
2266         char *agiexec = NULL;
2267         int ret = 0;
2268         const char *monitorfilename;
2269         const char *monitor_exec;
2270         const char *monitor_options;
2271         char tmpid[256], tmpid2[256];
2272         char meid[1024], meid2[1024];
2273         char mixmonargs[1512];
2274         struct ast_app *mixmonapp = NULL;
2275         char *p;
2276         char vars[2048];
2277         int forwardsallowed = 1;
2278
2279         memset(&bridge_config, 0, sizeof(bridge_config));
2280         time(&now);
2281                 
2282         for (; options && *options; options++)
2283                 switch (*options) {
2284                 case 't':
2285                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2286                         break;
2287                 case 'T':
2288                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2289                         break;
2290                 case 'w':
2291                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2292                         break;
2293                 case 'W':
2294                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2295                         break;
2296                 case 'd':
2297                         nondataquality = 0;
2298                         break;
2299                 case 'h':
2300                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2301                         break;
2302                 case 'H':
2303                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2304                         break;
2305                 case 'n':
2306                         if ((now - qe->start >= qe->parent->timeout))
2307                                 *go_on = 1;
2308                         break;
2309                 case 'i':
2310                         forwardsallowed = 0;
2311                         break;
2312                 }
2313
2314         /* Hold the lock while we setup the outgoing calls */
2315         if (use_weight)
2316                 AST_LIST_LOCK(&queues);
2317         ast_mutex_lock(&qe->parent->lock);
2318         if (option_debug)
2319                 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n",
2320                                                         qe->chan->name);
2321         ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2322         cur = qe->parent->members;
2323         if (!ast_strlen_zero(qe->announce))
2324                 announce = qe->announce;
2325         if (!ast_strlen_zero(announceoverride))
2326                 announce = announceoverride;
2327
2328         for (; cur; cur = cur->next) {
2329                 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
2330
2331                 if (!tmp) {
2332                         ast_mutex_unlock(&qe->parent->lock);
2333                         if (use_weight)
2334                                 AST_LIST_UNLOCK(&queues);
2335                         goto out;
2336                 }
2337                 tmp->stillgoing = -1;
2338                 tmp->member = cur;              /* Never directly dereference!  Could change on reload */
2339                 tmp->oldstatus = cur->status;
2340                 tmp->lastcall = cur->lastcall;
2341                 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2342                 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2343                    just calculate their metric for the appropriate strategy */
2344                 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2345                         /* Put them in the list of outgoing thingies...  We're ready now.
2346                            XXX If we're forcibly removed, these outgoing calls won't get
2347                            hung up XXX */
2348                         tmp->q_next = outgoing;
2349                         outgoing = tmp;         
2350                         /* If this line is up, don't try anybody else */
2351                         if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2352                                 break;
2353                 } else {
2354                         free(tmp);
2355                 }
2356         }
2357         if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
2358                 to = (qe->expire - now) * 1000;
2359         else
2360                 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
2361         ring_one(qe, outgoing, &numbusies);
2362         ast_mutex_unlock(&qe->parent->lock);
2363         if (use_weight)
2364                 AST_LIST_UNLOCK(&queues);
2365         lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
2366         ast_mutex_lock(&qe->parent->lock);
2367         if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2368                 store_next(qe, outgoing);
2369         }
2370         ast_mutex_unlock(&qe->parent->lock);
2371         peer = lpeer ? lpeer->chan : NULL;
2372         if (!peer) {
2373                 if (to) {
2374                         /* Must gotten hung up */
2375                         res = -1;
2376                 } else {
2377                         res = digit;
2378                 }
2379                 if (option_debug)
2380                         ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
2381         } else { /* peer is valid */
2382                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
2383                    we will always return with -1 so that it is hung up properly after the
2384                    conversation.  */
2385                 qe->handled++;
2386                 if (!strcmp(qe->chan->tech->type, "Zap"))
2387                         ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2388                 if (!strcmp(peer->tech->type, "Zap"))
2389                         ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2390                 /* Update parameters for the queue */
2391                 recalc_holdtime(qe);
2392                 member = lpeer->member;
2393                 hangupcalls(outgoing, peer);
2394                 outgoing = NULL;
2395                 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2396                         int res2;
2397
2398                         res2 = ast_autoservice_start(qe->chan);
2399                         if (!res2) {
2400                                 if (qe->parent->memberdelay) {
2401                                         ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2402                                         res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2403                                 }
2404                                 if (!res2 && announce) {
2405                                         if (play_file(peer, announce))
2406                                                 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2407                                 }
2408                                 if (!res2 && qe->parent->reportholdtime) {
2409                                         if (!play_file(peer, qe->parent->sound_reporthold)) {
2410                                                 int holdtime;
2411
2412                                                 time(&now);
2413                                                 holdtime = abs((now - qe->start) / 60);
2414                                                 if (holdtime < 2) {
2415                                                         play_file(peer, qe->parent->sound_lessthan);
2416                                                         ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2417                                                 } else
2418                                                         ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2419                                                 play_file(peer, qe->parent->sound_minutes);
2420                                         }
2421                                 }
2422                         }
2423                         res2 |= ast_autoservice_stop(qe->chan);
2424                         if (peer->_softhangup) {
2425                                 /* Agent must have hung up */
2426                                 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
2427                                 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
2428                                 record_abandoned(qe);
2429                                 if (qe->parent->eventwhencalled)
2430                                         manager_event(EVENT_FLAG_AGENT, "AgentDump",
2431                                                         "Queue: %s\r\n"
2432                                                         "Uniqueid: %s\r\n"
2433                                                         "Channel: %s\r\n"
2434                                                         "Member: %s\r\n"
2435                                                         "MemberName: %s\r\n"
2436                                                         "%s",
2437                                                         queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2438                                                         qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2439                                 ast_hangup(peer);
2440                                 goto out;
2441                         } else if (res2) {
2442                                 /* Caller must have hung up just before being connected*/
2443                                 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2444                                 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2445                                 record_abandoned(qe);
2446                                 ast_hangup(peer);
2447                                 return -1;
2448                         }
2449                 }
2450                 /* Stop music on hold */
2451                 ast_moh_stop(qe->chan);
2452                 /* If appropriate, log that we have a destination channel */
2453                 if (qe->chan->cdr)
2454                         ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2455                 /* Make sure channels are compatible */
2456                 res = ast_channel_make_compatible(qe->chan, peer);
2457                 if (res < 0) {
2458                         ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
2459                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2460                         record_abandoned(qe);
2461                         ast_hangup(peer);
2462                         return -1;
2463                 }
2464                 /* Begin Monitoring */
2465                 if (qe->parent->monfmt && *qe->parent->monfmt) {
2466                         if (!qe->parent->montype) {
2467                                 if (option_debug)
2468                                         ast_log(LOG_DEBUG, "Starting Monitor as requested.\n");
2469                                 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2470                                 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2471                                         which = qe->chan;
2472                                 else
2473                                         which = peer;
2474                                 if (monitorfilename)
2475                                         ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2476                                 else if (qe->chan->cdr)
2477                                         ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2478                                 else {
2479                                         /* Last ditch effort -- no CDR, make up something */
2480                                         snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2481                                         ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2482                                 }
2483                                 if (qe->parent->monjoin)
2484                                         ast_monitor_setjoinfiles(which, 1);
2485                         } else {
2486                                 if (option_debug)
2487                                         ast_log(LOG_DEBUG, "Starting MixMonitor as requested.\n");
2488                                 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2489                                 if (!monitorfilename) {
2490                                         if (qe->chan->cdr)
2491                                                 ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid)-1);
2492                                         else
2493                                                 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
2494                                 } else {
2495                                         ast_copy_string(tmpid2, monitorfilename, sizeof(tmpid2)-1);
2496                                         for (p = tmpid2; *p ; p++) {
2497                                                 if (*p == '^' && *(p+1) == '{') {
2498                                                         *p = '$';
2499                                                 }
2500                                         }
2501
2502                                         memset(tmpid, 0, sizeof(tmpid));
2503                                         pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
2504                                 }
2505
2506                                 monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC");
2507                                 monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS");
2508
2509                                 if (monitor_exec) {
2510                                         ast_copy_string(meid2, monitor_exec, sizeof(meid2)-1);
2511                                         for (p = meid2; *p ; p++) {
2512                                                 if (*p == '^' && *(p+1) == '{') {
2513                                                         *p = '$';
2514                                                 }
2515                                         }
2516
2517                                         memset(meid, 0, sizeof(meid));
2518                                         pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
2519                                 }
2520         
2521                                 snprintf(tmpid2, sizeof(tmpid2)-1, "%s.%s", tmpid, qe->parent->monfmt);
2522
2523                                 mixmonapp = pbx_findapp("MixMonitor");
2524
2525                                 if (strchr(tmpid2, '|')) {
2526                                         ast_log(LOG_WARNING, "monitor-format (in queues.conf) and MONITOR_FILENAME cannot contain a '|'! Not recording.\n");
2527                                         mixmonapp = NULL;
2528                                 }
2529
2530                                 if (!monitor_options)
2531                                         monitor_options = "";
2532                                 
2533                                 if (strchr(monitor_options, '|')) {
2534                                         ast_log(LOG_WARNING, "MONITOR_OPTIONS cannot contain a '|'! Not recording.\n");
2535                                         mixmonapp = NULL;
2536                                 }
2537
2538                                 if (mixmonapp) {
2539                                         if (!ast_strlen_zero(monitor_exec) && !ast_strlen_zero(monitor_options))
2540                                                 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s|%s", tmpid2, monitor_options, monitor_exec);
2541                                         else
2542                                                 snprintf(mixmonargs, sizeof(mixmonargs)-1, "%s|b%s", tmpid2, monitor_options);
2543                                                 
2544                                         if (option_debug)
2545                                                 ast_log(LOG_DEBUG, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
2546
2547                                         ret = pbx_exec(qe->chan, mixmonapp, mixmonargs);
2548
2549                                 } else
2550                                         ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
2551
2552                         }
2553                 }
2554                 /* Drop out of the queue at this point, to prepare for next caller */
2555                 leave_queue(qe);                        
2556                 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2557                         if (option_debug)
2558                                 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2559                         ast_channel_sendurl(peer, url);
2560                 }
2561                 if (qe->parent->setinterfacevar)
2562                                 pbx_builtin_setvar_helper(qe->chan, "MEMBERINTERFACE", member->interface);
2563                 if (!ast_strlen_zero(agi)) {
2564                         if (option_debug)
2565                                 ast_log(LOG_DEBUG, "app_queue: agi=%s.\n", agi);
2566                         app = pbx_findapp("agi");
2567                         if (app) {
2568                                 agiexec = ast_strdupa(agi);
2569                                 ret = pbx_exec(qe->chan, app, agiexec);
2570                         } else
2571                                 ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
2572                 }
2573                 ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s", (long)time(NULL) - qe->start, peer->uniqueid);
2574                 if (qe->parent->eventwhencalled)
2575                         manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2576                                         "Queue: %s\r\n"
2577                                         "Uniqueid: %s\r\n"
2578                                         "Channel: %s\r\n"
2579                                         "Member: %s\r\n"
2580                                         "MemberName: %s\r\n"
2581                                         "Holdtime: %ld\r\n"
2582                                         "BridgedChannel: %s\r\n"
2583                                         "%s",
2584                                         queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2585                                         (long)time(NULL) - qe->start, peer->uniqueid,
2586                                         qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2587                 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2588                 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2589                 time(&callstart);
2590
2591                 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2592
2593                 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2594                         ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
2595                                 qe->chan->exten, qe->chan->context, (long) (callstart - qe->start),
2596                                 (long) (time(NULL) - callstart));
2597                 } else if (qe->chan->_softhangup) {
2598                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
2599                                 (long) (callstart - qe->start), (long) (time(NULL) - callstart));
2600                         if (qe->parent->eventwhencalled)
2601                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2602                                                 "Queue: %s\r\n"
2603                                                 "Uniqueid: %s\r\n"
2604                                                 "Channel: %s\r\n"
2605                                                 "Member: %s\r\n"
2606                                                 "MemberName: %s\r\n"
2607                                                 "HoldTime: %ld\r\n"
2608                                                 "TalkTime: %ld\r\n"
2609                                                 "Reason: caller\r\n"
2610                                                 "%s",
2611                                                 queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
2612                                                 (long)(callstart - qe->start), (long)(time(NULL) - callstart),
2613                                                 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2614                 } else {
2615                         ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETEAGENT", "%ld|%ld",
2616                                 (long) (callstart - qe->start), (long) (time(NULL) - callstart));
2617                         if (qe->parent->eventwhencalled)
2618                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2619                                                 "Queue: %s\r\n"
2620                                                 "Uniqueid: %s\r\n"
2621                                                 "Channel: %s\r\n"
2622                                                 "MemberName: %s\r\n"
2623                                                 "HoldTime: %ld\r\n"
2624                                                 "TalkTime: %ld\r\n"
2625                                                 "Reason: agent\r\n"
2626                                                 "%s",
2627                                                 queuename, qe->chan->uniqueid, peer->name, member->membername, (long)(callstart - qe->start),
2628                                                 (long)(time(NULL) - callstart),
2629                                                 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
2630                 }
2631
2632                 if (bridge != AST_PBX_NO_HANGUP_PEER)
2633                         ast_hangup(peer);
2634                 update_queue(qe->parent, member);
2635                 res = bridge ? bridge : 1;
2636         }
2637 out:
2638         hangupcalls(outgoing, NULL);
2639
2640         return res;
2641 }
2642
2643 static int wait_a_bit(struct queue_ent *qe)
2644 {
2645         /* Don't need to hold the lock while we setup the outgoing calls */
2646         int retrywait = qe->parent->retry * 1000;
2647
2648         return ast_waitfordigit(qe->chan, retrywait);
2649 }
2650
2651 static struct member *interface_exists(struct call_queue *q, char *interface)
2652 {
2653         struct member *mem;
2654
2655         if (!q)
2656                 return NULL;
2657
2658         for (mem = q->members; mem; mem = mem->next) {
2659                 if (!strcasecmp(interface, mem->interface))
2660                         return mem;
2661         }
2662
2663         return NULL;
2664 }
2665
2666
2667 /* Dump all members in a specific queue to the database
2668  *
2669  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2670  *
2671  */
2672 static void dump_queue_members(struct call_queue *pm_queue)
2673 {
2674         struct member *cur_member;
2675         char value[PM_MAX_LEN];
2676         int value_len = 0;
2677         int res;
2678
2679         memset(value, 0, sizeof(value));
2680
2681         if (!pm_queue)
2682                 return;
2683
2684         for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2685                 if (!cur_member->dynamic)
2686                         continue;
2687
2688                 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d;%s%s",
2689                         cur_member->interface, cur_member->penalty, cur_member->paused, cur_member->membername,
2690                         cur_member->next ? "|" : "");
2691                 if (res != strlen(value + value_len)) {
2692                         ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2693                         break;
2694                 }
2695                 value_len += res;
2696         }
2697         
2698         if (value_len && !cur_member) {
2699                 if (ast_db_put(pm_family, pm_queue->name, value))
2700                         ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2701         } else
2702                 /* Delete the entry if the queue is empty or there is an error */
2703                 ast_db_del(pm_family, pm_queue->name);
2704 }
2705
2706 static int remove_from_queue(char *queuename, char *interface)
2707 {
2708         struct call_queue *q;
2709         struct member *last_member, *look;
2710         int res = RES_NOSUCHQUEUE;
2711
2712         AST_LIST_LOCK(&queues);
2713         AST_LIST_TRAVERSE(&queues, q, list) {
2714                 ast_mutex_lock(&q->lock);
2715                 if (strcmp(q->name, queuename)) {
2716                         ast_mutex_unlock(&q->lock);
2717                         continue;
2718                 }
2719
2720                 if ((last_member = interface_exists(q, interface))) {
2721                         if ((look = q->members) == last_member) {
2722                                 q->members = last_member->next;
2723                         } else {
2724                                 while (look != NULL) {
2725                                         if (look->next == last_member) {
2726                                                 look->next = last_member->next;
2727                                                 break;
2728                                         } else {
2729                                                 look = look->next;
2730                                         }
2731                                 }
2732                         }
2733                         manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
2734                                 "Queue: %s\r\n"
2735                                 "Location: %s\r\n"
2736                                 "MemberName: %s\r\n",
2737                                 q->name, last_member->interface, last_member->membername);
2738                         free(last_member);
2739                         
2740                         if (queue_persistent_members)
2741                                 dump_queue_members(q);
2742                         
2743                         res = RES_OKAY;
2744                 } else {
2745                         res = RES_EXISTS;
2746                 }
2747                 ast_mutex_unlock(&q->lock);
2748                 break;
2749         }
2750
2751         if (res == RES_OKAY)
2752                 remove_from_interfaces(interface);
2753
2754         AST_LIST_UNLOCK(&queues);
2755
2756         return res;
2757 }
2758
2759
2760 static int add_to_queue(char *queuename, char *interface, char *membername, int penalty, int paused, int dump)
2761 {
2762         struct call_queue *q;
2763         struct member *new_member;
2764         int res = RES_NOSUCHQUEUE;
2765
2766         /* \note Ensure the appropriate realtime queue is loaded.  Note that this
2767          * short-circuits if the queue is already in memory. */
2768         if (!(q = load_realtime_queue(queuename)))
2769                 return res;
2770
2771         AST_LIST_LOCK(&queues);
2772
2773         ast_mutex_lock(&q->lock);
2774         if (interface_exists(q, interface) == NULL) {
2775                 add_to_interfaces(interface);
2776                 if ((new_member = create_queue_member(interface, membername, penalty, paused))) {
2777                         new_member->dynamic = 1;
2778                         new_member->next = q->members;
2779                         q->members = new_member;
2780                         manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
2781                                 "Queue: %s\r\n"
2782                                 "Location: %s\r\n"
2783                                 "MemberName: %s\r\n"
2784                                 "Membership: %s\r\n"
2785                                 "Penalty: %d\r\n"
2786                                 "CallsTaken: %d\r\n"
2787                                 "LastCall: %d\r\n"
2788                                 "Status: %d\r\n"
2789                                 "Paused: %d\r\n",
2790                                 q->name, new_member->interface, new_member->membername,
2791                                 new_member->dynamic ? "dynamic" : "static",
2792                                 new_member->penalty, new_member->calls, (int) new_member->lastcall,
2793                                 new_member->status, new_member->paused);
2794                         
2795                         if (dump)
2796                                 dump_queue_members(q);
2797                         
2798                         res = RES_OKAY;
2799                 } else {
2800                         res = RES_OUTOFMEMORY;
2801                 }
2802         } else {
2803                 res = RES_EXISTS;
2804         }
2805         ast_mutex_unlock(&q->lock);
2806         AST_LIST_UNLOCK(&queues);
2807
2808         return res;
2809 }
2810
2811 static int set_member_paused(char *queuename, char *interface, int paused)
2812 {
2813         int found = 0;
2814         struct call_queue *q;
2815         struct member *mem;
2816
2817         /* Special event for when all queues are paused - individual events still generated */
2818         /* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */
2819         if (ast_strlen_zero(queuename))
2820                 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
2821
2822         AST_LIST_LOCK(&queues);
2823         AST_LIST_TRAVERSE(&queues, q, list) {
2824                 ast_mutex_lock(&q->lock);
2825                 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
2826                         if ((mem = interface_exists(q, interface))) {
2827                                 found++;
2828                                 if (mem->paused == paused)
2829                                         ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
2830                                 mem->paused = paused;
2831
2832                                 if (queue_persistent_members)
2833                                         dump_queue_members(q);
2834
2835                                 ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
2836
2837                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
2838                                         "Queue: %s\r\n"
2839                                         "Location: %s\r\n"
2840                                         "MemberName: %s\r\n"
2841                                         "Paused: %d\r\n",
2842                                                 q->name, mem->interface, mem->membername, paused);
2843                         }
2844                 }
2845                 ast_mutex_unlock(&q->lock);
2846         }
2847         AST_LIST_UNLOCK(&queues);
2848
2849         return found ? RESULT_SUCCESS : RESULT_FAILURE;
2850 }
2851
2852 /* Reload dynamic queue members persisted into the astdb */
2853 static void reload_queue_members(void)
2854 {
2855         char *cur_ptr;  
2856         char *queue_name;
2857         char *member;
2858         char *interface;
2859         char *membername;
2860         char *penalty_tok;
2861         int penalty = 0;
2862         char *paused_tok;
2863         int paused = 0;
2864         struct ast_db_entry *db_tree;
2865         struct ast_db_entry *entry;
2866         struct call_queue *cur_queue;
2867         char queue_data[PM_MAX_LEN];
2868
2869         AST_LIST_LOCK(&queues);
2870
2871         /* Each key in 'pm_family' is the name of a queue */
2872         db_tree = ast_db_gettree(pm_family, NULL);
2873         for (entry = db_tree; entry; entry = entry->next) {
2874
2875                 queue_name = entry->key + strlen(pm_family) + 2;
2876
2877                 AST_LIST_TRAVERSE(&queues, cur_queue, list) {
2878                         ast_mutex_lock(&cur_queue->lock);
2879                         if (!strcmp(queue_name, cur_queue->name))
2880                                 break;
2881                         ast_mutex_unlock(&cur_queue->lock);
2882                 }
2883
2884                 if (!cur_queue) {
2885                         /* If the queue no longer exists, remove it from the
2886                          * database */
2887                         ast_db_del(pm_family, queue_name);
2888                         continue;
2889                 } else
2890                         ast_mutex_unlock(&cur_queue->lock);
2891
2892                 if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
2893                         continue;
2894
2895                 cur_ptr = queue_data;
2896                 while ((member = strsep(&cur_ptr, "|"))) {
2897                         if (ast_strlen_zero(member))