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