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