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