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