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