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