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