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