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