b380dd4e5149597308e6feabec4131e3cf8d148b
[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 static void free_members(struct ast_call_queue *q, int all)
791 {
792         /* Free non-dynamic members */
793         struct member *curm, *next, *prev = NULL;
794
795         for (curm = q->members; curm; curm = next) {
796                 next = curm->next;
797                 if (all || !curm->dynamic) {
798                         if (prev)
799                                 prev->next = next;
800                         else
801                                 q->members = next;
802                         free(curm);
803                 } else 
804                         prev = curm;
805         }
806 }
807
808 static void destroy_queue(struct ast_call_queue *q)
809 {
810         free_members(q, 1);
811         ast_mutex_destroy(&q->lock);
812         free(q);
813 }
814
815 /*!\brief Reload a single queue via realtime.
816    \return Return the queue, or NULL if it doesn't exist.
817    \note Should be called with the global qlock locked. */
818 static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
819 {
820         struct ast_variable *v;
821         struct ast_call_queue *q;
822         struct member *m, *prev_m, *next_m;
823         char *interface;
824         char *tmp, *tmp_name;
825         char tmpbuf[64];        /* Must be longer than the longest queue param name. */
826
827         /* Find the queue in the in-core list (we will create a new one if not found). */
828         AST_LIST_TRAVERSE(&queues, q, list) {
829                 if (!strcasecmp(q->name, queuename)) {
830                         break;
831                 }
832         }
833
834         /* Static queues override realtime. */
835         if (q) {
836                 ast_mutex_lock(&q->lock);
837                 if (!q->realtime) {
838                         if (q->dead) {
839                                 ast_mutex_unlock(&q->lock);
840                                 return NULL;
841                         } else {
842                                 ast_mutex_unlock(&q->lock);
843                                 return q;
844                         }
845                 }
846         } else if (!member_config)
847                 /* Not found in the list, and it's not realtime ... */
848                 return NULL;
849
850         /* Check if queue is defined in realtime. */
851         if (!queue_vars) {
852                 /* Delete queue from in-core list if it has been deleted in realtime. */
853                 if (q) {
854                         /*! \note Hmm, can't seem to distinguish a DB failure from a not
855                            found condition... So we might delete an in-core queue
856                            in case of DB failure. */
857                         ast_log(LOG_DEBUG, "Queue %s not found in realtime.\n", queuename);
858
859                         q->dead = 1;
860                         /* Delete if unused (else will be deleted when last caller leaves). */
861                         if (!q->count) {
862                                 /* Delete. */
863                                 AST_LIST_REMOVE(&queues, q, list);
864                                 ast_mutex_unlock(&q->lock);
865                                 destroy_queue(q);
866                         } else
867                                 ast_mutex_unlock(&q->lock);
868                 }
869                 return NULL;
870         }
871
872         /* Create a new queue if an in-core entry does not exist yet. */
873         if (!q) {
874                 if (!(q = alloc_queue(queuename)))
875                         return NULL;
876                 ast_mutex_lock(&q->lock);
877                 clear_queue(q);
878                 q->realtime = 1;
879                 AST_LIST_INSERT_HEAD(&queues, q, list);
880         }
881         init_queue(q);          /* Ensure defaults for all parameters not set explicitly. */
882
883         v = queue_vars;
884         memset(tmpbuf, 0, sizeof(tmpbuf));
885         while(v) {
886                 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
887                 if((tmp = strchr(v->name, '_')) != NULL) {
888                         ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
889                         tmp_name = tmpbuf;
890                         tmp = tmp_name;
891                         while((tmp = strchr(tmp, '_')) != NULL)
892                                 *tmp++ = '-';
893                 } else
894                         tmp_name = v->name;
895                 queue_set_param(q, tmp_name, v->value, -1, 0);
896                 v = v->next;
897         }
898
899         /* Temporarily set non-dynamic members dead so we can detect deleted ones. */
900         m = q->members;
901         while (m) {
902                 if (!m->dynamic)
903                         m->dead = 1;
904                 m = m->next;
905         }
906
907         interface = ast_category_browse(member_config, NULL);
908         while (interface) {
909                 rt_handle_member_record(q, interface, ast_variable_retrieve(member_config, interface, "penalty"));
910                 interface = ast_category_browse(member_config, interface);
911         }
912
913         /* Delete all realtime members that have been deleted in DB. */
914         m = q->members;
915         prev_m = NULL;
916         while (m) {
917                 next_m = m->next;
918                 if (m->dead) {
919                         if (prev_m) {
920                                 prev_m->next = next_m;
921                         } else {
922                                 q->members = next_m;
923                         }
924                         free(m);
925                 } else {
926                         prev_m = m;
927                 }
928                 m = next_m;
929         }
930
931         ast_mutex_unlock(&q->lock);
932
933         return q;
934 }
935
936 static struct ast_call_queue *load_realtime_queue(char *queuename)
937 {
938         struct ast_variable *queue_vars = NULL;
939         struct ast_config *member_config = NULL;
940         struct ast_call_queue *q;
941
942         /* Find the queue in the in-core list first. */
943         AST_LIST_LOCK(&queues);
944         AST_LIST_TRAVERSE(&queues, q, list) {
945                 if (!strcasecmp(q->name, queuename)) {
946                         break;
947                 }
948         }
949         AST_LIST_UNLOCK(&queues);
950
951         if (!q) {
952                 /*! \note Load from realtime before taking the global qlock, to avoid blocking all
953                    queue operations while waiting for the DB.
954
955                    This will be two separate database transactions, so we might
956                    see queue parameters as they were before another process
957                    changed the queue and member list as it was after the change.
958                    Thus we might see an empty member list when a queue is
959                    deleted. In practise, this is unlikely to cause a problem. */
960
961                 queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
962                 if (queue_vars) {
963                         member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
964                         if (!member_config) {
965                                 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
966                                 return NULL;
967                         }
968                 }
969
970                 AST_LIST_LOCK(&queues);
971
972                 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
973                 if (member_config)
974                         ast_config_destroy(member_config);
975                 if (queue_vars)
976                         ast_variables_destroy(queue_vars);
977
978                 AST_LIST_UNLOCK(&queues);
979         }
980         return q;
981 }
982
983 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
984 {
985         struct ast_call_queue *q;
986         struct queue_ent *cur, *prev = NULL;
987         int res = -1;
988         int pos = 0;
989         int inserted = 0;
990         enum queue_member_status stat;
991
992         q = load_realtime_queue(queuename);
993         if (!q)
994                 return res;
995
996         AST_LIST_LOCK(&queues);
997         ast_mutex_lock(&q->lock);
998
999         /* This is our one */
1000         stat = get_member_status(q, qe->max_penalty);
1001         if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
1002                 *reason = QUEUE_JOINEMPTY;
1003         else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
1004                 *reason = QUEUE_JOINUNAVAIL;
1005         else if (q->maxlen && (q->count >= q->maxlen))
1006                 *reason = QUEUE_FULL;
1007         else {
1008                 /* There's space for us, put us at the right position inside
1009                  * the queue. 
1010                  * Take into account the priority of the calling user */
1011                 inserted = 0;
1012                 prev = NULL;
1013                 cur = q->head;
1014                 while(cur) {
1015                         /* We have higher priority than the current user, enter
1016                          * before him, after all the other users with priority
1017                          * higher or equal to our priority. */
1018                         if ((!inserted) && (qe->prio > cur->prio)) {
1019                                 insert_entry(q, prev, qe, &pos);
1020                                 inserted = 1;
1021                         }
1022                         cur->pos = ++pos;
1023                         prev = cur;
1024                         cur = cur->next;
1025                 }
1026                 /* No luck, join at the end of the queue */
1027                 if (!inserted)
1028                         insert_entry(q, prev, qe, &pos);
1029                 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
1030                 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
1031                 ast_copy_string(qe->context, q->context, sizeof(qe->context));
1032                 q->count++;
1033                 res = 0;
1034                 manager_event(EVENT_FLAG_CALL, "Join", 
1035                               "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\n",
1036                               qe->chan->name, 
1037                               qe->chan->cid.cid_num ? qe->chan->cid.cid_num : "unknown",
1038                               qe->chan->cid.cid_name ? qe->chan->cid.cid_name : "unknown",
1039                               q->name, qe->pos, q->count );
1040 #if 0
1041 ast_log(LOG_NOTICE, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
1042 #endif
1043         }
1044         ast_mutex_unlock(&q->lock);
1045         AST_LIST_UNLOCK(&queues);
1046         return res;
1047 }
1048
1049 static int play_file(struct ast_channel *chan, char *filename)
1050 {
1051         int res;
1052
1053         ast_stopstream(chan);
1054         res = ast_streamfile(chan, filename, chan->language);
1055
1056         if (!res)
1057                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1058         else
1059                 res = 0;
1060
1061         ast_stopstream(chan);
1062
1063         return res;
1064 }
1065
1066 static int valid_exit(struct queue_ent *qe, char digit)
1067 {
1068         int digitlen = strlen(qe->digits);
1069
1070         /* Prevent possible buffer overflow */
1071         if (digitlen < sizeof(qe->digits) - 2) {
1072                 qe->digits[digitlen] = digit;
1073                 qe->digits[digitlen + 1] = '\0';
1074         } else {
1075                 qe->digits[0] = '\0';
1076                 return 0;
1077         }
1078
1079         /* If there's no context to goto, short-circuit */
1080         if (ast_strlen_zero(qe->context))
1081                 return 0;
1082
1083         /* If the extension is bad, then reset the digits to blank */
1084         if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
1085                 qe->digits[0] = '\0';
1086                 return 0;
1087         }
1088
1089         /* We have an exact match */
1090         if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
1091                 /* Return 1 on a successful goto */
1092                 return 1;
1093         }
1094         return 0;
1095 }
1096
1097 static int say_position(struct queue_ent *qe)
1098 {
1099         int res = 0, avgholdmins, avgholdsecs;
1100         time_t now;
1101
1102         /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/
1103         time(&now);
1104         if ( (now - qe->last_pos) < 15 )
1105                 return 0;
1106
1107         /* If either our position has changed, or we are over the freq timer, say position */
1108         if ( (qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency) )
1109                 return 0;
1110
1111         ast_moh_stop(qe->chan);
1112         /* Say we're next, if we are */
1113         if (qe->pos == 1) {
1114                 res = play_file(qe->chan, qe->parent->sound_next);
1115                 if (res && valid_exit(qe, res))
1116                         goto playout;
1117                 else
1118                         goto posout;
1119         } else {
1120                 res = play_file(qe->chan, qe->parent->sound_thereare);
1121                 if (res && valid_exit(qe, res))
1122                         goto playout;
1123                 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
1124                 if (res && valid_exit(qe, res))
1125                         goto playout;
1126                 res = play_file(qe->chan, qe->parent->sound_calls);
1127                 if (res && valid_exit(qe, res))
1128                         goto playout;
1129         }
1130         /* Round hold time to nearest minute */
1131         avgholdmins = abs(( (qe->parent->holdtime + 30) - (now - qe->start) ) / 60);
1132
1133         /* If they have specified a rounding then round the seconds as well */
1134         if(qe->parent->roundingseconds) {
1135                 avgholdsecs = (abs(( (qe->parent->holdtime + 30) - (now - qe->start) )) - 60 * avgholdmins) / qe->parent->roundingseconds;
1136                 avgholdsecs*= qe->parent->roundingseconds;
1137         } else {
1138                 avgholdsecs=0;
1139         }
1140
1141         if (option_verbose > 2)
1142                 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
1143
1144         /* If the hold time is >1 min, if it's enabled, and if it's not
1145            supposed to be only once and we have already said it, say it */
1146         if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
1147             (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
1148                 res = play_file(qe->chan, qe->parent->sound_holdtime);
1149                 if (res && valid_exit(qe, res))
1150                         goto playout;
1151
1152                 if (avgholdmins>0) {
1153                         if (avgholdmins < 2) {
1154                                 res = play_file(qe->chan, qe->parent->sound_lessthan);
1155                                 if (res && valid_exit(qe, res))
1156                                         goto playout;
1157
1158                                 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, (char *)NULL);
1159                                 if (res && valid_exit(qe, res))
1160                                         goto playout;
1161                         } else {
1162                                 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, (char*) NULL);
1163                                 if (res && valid_exit(qe, res))
1164                                         goto playout;
1165                         }
1166                         
1167                         res = play_file(qe->chan, qe->parent->sound_minutes);
1168                         if (res && valid_exit(qe, res))
1169                                 goto playout;
1170                 }
1171                 if (avgholdsecs>0) {
1172                         res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, (char*) NULL);
1173                         if (res && valid_exit(qe, res))
1174                                 goto playout;
1175
1176                         res = play_file(qe->chan, qe->parent->sound_seconds);
1177                         if (res && valid_exit(qe, res))
1178                                 goto playout;
1179                 }
1180
1181         }
1182
1183  posout:
1184         if (option_verbose > 2)
1185                 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n",
1186                             qe->chan->name, qe->parent->name, qe->pos);
1187         res = play_file(qe->chan, qe->parent->sound_thanks);
1188
1189  playout:
1190         /* Set our last_pos indicators */
1191         qe->last_pos = now;
1192         qe->last_pos_said = qe->pos;
1193         ast_moh_start(qe->chan, qe->moh);
1194
1195         return res;
1196 }
1197
1198 static void recalc_holdtime(struct queue_ent *qe)
1199 {
1200         int oldvalue, newvalue;
1201
1202         /* Calculate holdtime using a recursive boxcar filter */
1203         /* Thanks to SRT for this contribution */
1204         /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
1205
1206         newvalue = time(NULL) - qe->start;
1207
1208         ast_mutex_lock(&qe->parent->lock);
1209         if (newvalue <= qe->parent->servicelevel)
1210                 qe->parent->callscompletedinsl++;
1211         oldvalue = qe->parent->holdtime;
1212         qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2;
1213         ast_mutex_unlock(&qe->parent->lock);
1214 }
1215
1216
1217 static void leave_queue(struct queue_ent *qe)
1218 {
1219         struct ast_call_queue *q;
1220         struct queue_ent *cur, *prev = NULL;
1221         int pos = 0;
1222
1223         q = qe->parent;
1224         if (!q)
1225                 return;
1226         ast_mutex_lock(&q->lock);
1227
1228         prev = NULL;
1229         cur = q->head;
1230         while(cur) {
1231                 if (cur == qe) {
1232                         q->count--;
1233
1234                         /* Take us out of the queue */
1235                         manager_event(EVENT_FLAG_CALL, "Leave",
1236                                 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\n",
1237                                 qe->chan->name, q->name,  q->count);
1238 #if 0
1239 ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
1240 #endif
1241                         /* Take us out of the queue */
1242                         if (prev)
1243                                 prev->next = cur->next;
1244                         else
1245                                 q->head = cur->next;
1246                 } else {
1247                         /* Renumber the people after us in the queue based on a new count */
1248                         cur->pos = ++pos;
1249                         prev = cur;
1250                 }
1251                 cur = cur->next;
1252         }
1253         ast_mutex_unlock(&q->lock);
1254         if (q->dead && !q->count) {     
1255                 /* It's dead and nobody is in it, so kill it */
1256                 AST_LIST_LOCK(&queues);
1257                 AST_LIST_REMOVE(&queues, q, list);
1258                 AST_LIST_UNLOCK(&queues);
1259                 destroy_queue(q);
1260         }
1261 }
1262
1263 /* Hang up a list of outgoing calls */
1264 static void hangupcalls(struct localuser *outgoing, struct ast_channel *exception)
1265 {
1266         struct localuser *oo;
1267
1268         while(outgoing) {
1269                 /* Hangup any existing lines we have open */
1270                 if (outgoing->chan && (outgoing->chan != exception))
1271                         ast_hangup(outgoing->chan);
1272                 oo = outgoing;
1273                 outgoing=outgoing->next;
1274                 free(oo);
1275         }
1276 }
1277
1278 static int update_status(struct ast_call_queue *q, struct member *member, int status)
1279 {
1280         struct member *cur;
1281
1282         /* Since a reload could have taken place, we have to traverse the list to
1283                 be sure it's still valid */
1284         ast_mutex_lock(&q->lock);
1285         cur = q->members;
1286         while(cur) {
1287                 if (member == cur) {
1288                         cur->status = status;
1289                         if (!q->maskmemberstatus) {
1290                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1291                                         "Queue: %s\r\n"
1292                                         "Location: %s\r\n"
1293                                         "Membership: %s\r\n"
1294                                         "Penalty: %d\r\n"
1295                                         "CallsTaken: %d\r\n"
1296                                         "LastCall: %d\r\n"
1297                                         "Status: %d\r\n"
1298                                         "Paused: %d\r\n",
1299                                 q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
1300                                 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
1301                         }
1302                         break;
1303                 }
1304                 cur = cur->next;
1305         }
1306         ast_mutex_unlock(&q->lock);
1307         return 0;
1308 }
1309
1310 static int update_dial_status(struct ast_call_queue *q, struct member *member, int status)
1311 {
1312         if (status == AST_CAUSE_BUSY)
1313                 status = AST_DEVICE_BUSY;
1314         else if (status == AST_CAUSE_UNREGISTERED)
1315                 status = AST_DEVICE_UNAVAILABLE;
1316         else if (status == AST_CAUSE_NOSUCHDRIVER)
1317                 status = AST_DEVICE_INVALID;
1318         else
1319                 status = AST_DEVICE_UNKNOWN;
1320         return update_status(q, member, status);
1321 }
1322
1323 /* traverse all defined queues which have calls waiting and contain this member
1324    return 0 if no other queue has precedence (higher weight) or 1 if found  */
1325 static int compare_weight(struct ast_call_queue *rq, struct member *member)
1326 {
1327         struct ast_call_queue *q;
1328         struct member *mem;
1329         int found = 0;
1330         
1331         /* &qlock and &rq->lock already set by try_calling()
1332          * to solve deadlock */
1333         AST_LIST_TRAVERSE(&queues, q, list) {
1334                 if (q == rq) /* don't check myself, could deadlock */
1335                         continue; 
1336                 ast_mutex_lock(&q->lock);
1337                 if (q->count && q->members) {
1338                         for (mem = q->members; mem; mem = mem->next) {
1339                                 if (!strcmp(mem->interface, member->interface)) {
1340                                         ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1341                                         if (q->weight > rq->weight) {
1342                                                 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);
1343                                                 found = 1;
1344                                                 break;
1345                                         }
1346                                 }
1347                         }
1348                 }
1349                 ast_mutex_unlock(&q->lock);
1350                 if (found) 
1351                         break;
1352         }
1353         return found;
1354 }
1355
1356 static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
1357 {
1358         int res;
1359         int status;
1360         char tech[256];
1361         char *location;
1362
1363         if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1364                 if (option_debug)
1365                         ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
1366                 if (qe->chan->cdr)
1367                         ast_cdr_busy(qe->chan->cdr);
1368                 tmp->stillgoing = 0;
1369                 (*busies)++;
1370                 return 0;
1371         }
1372         
1373         if (tmp->member->paused) {
1374                 if (option_debug)
1375                         ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
1376                 if (qe->chan->cdr)
1377                         ast_cdr_busy(qe->chan->cdr);
1378                 tmp->stillgoing = 0;
1379                 return 0;
1380         }
1381         if (use_weight && compare_weight(qe->parent,tmp->member)) {
1382                 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1383                 if (qe->chan->cdr)
1384                         ast_cdr_busy(qe->chan->cdr);
1385                 tmp->stillgoing = 0;
1386                 (*busies)++;
1387                 return 0;
1388         }
1389
1390         ast_copy_string(tech, tmp->interface, sizeof(tech));
1391         if ((location = strchr(tech, '/')))
1392                 *location++ = '\0';
1393         else
1394                 location = "";
1395
1396         /* Request the peer */
1397         tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1398         if (!tmp->chan) {                       /* If we can't, just go on to the next call */
1399 #if 0
1400                 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
1401 #endif                  
1402                 if (qe->chan->cdr)
1403                         ast_cdr_busy(qe->chan->cdr);
1404                 tmp->stillgoing = 0;
1405                 update_dial_status(qe->parent, tmp->member, status);
1406                 (*busies)++;
1407                 return 0;
1408         } else if (status != tmp->oldstatus) 
1409                 update_dial_status(qe->parent, tmp->member, status);
1410         
1411         tmp->chan->appl = "AppQueue";
1412         tmp->chan->data = "(Outgoing Line)";
1413         tmp->chan->whentohangup = 0;
1414         if (tmp->chan->cid.cid_num)
1415                 free(tmp->chan->cid.cid_num);
1416         tmp->chan->cid.cid_num = NULL;
1417         if (tmp->chan->cid.cid_name)
1418                 free(tmp->chan->cid.cid_name);
1419         tmp->chan->cid.cid_name = NULL;
1420         if (tmp->chan->cid.cid_ani)
1421                 free(tmp->chan->cid.cid_ani);
1422         tmp->chan->cid.cid_ani = NULL;
1423         if (qe->chan->cid.cid_num)
1424                 tmp->chan->cid.cid_num = strdup(qe->chan->cid.cid_num);
1425         if (qe->chan->cid.cid_name)
1426                 tmp->chan->cid.cid_name = strdup(qe->chan->cid.cid_name);
1427         if (qe->chan->cid.cid_ani)
1428                 tmp->chan->cid.cid_ani = strdup(qe->chan->cid.cid_ani);
1429
1430         /* Inherit specially named variables from parent channel */
1431         ast_channel_inherit_variables(qe->chan, tmp->chan);
1432
1433         /* Presense of ADSI CPE on outgoing channel follows ours */
1434         tmp->chan->adsicpe = qe->chan->adsicpe;
1435
1436         /* Place the call, but don't wait on the answer */
1437         res = ast_call(tmp->chan, location, 0);
1438         if (res) {
1439                 /* Again, keep going even if there's an error */
1440                 if (option_debug)
1441                         ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1442                 else if (option_verbose > 2)
1443                         ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
1444                 ast_hangup(tmp->chan);
1445                 tmp->chan = NULL;
1446                 tmp->stillgoing = 0;
1447                 (*busies)++;
1448                 return 0;
1449         } else {
1450                 if (qe->parent->eventwhencalled) {
1451                         manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1452                                                 "AgentCalled: %s\r\n"
1453                                                 "ChannelCalling: %s\r\n"
1454                                                 "CallerID: %s\r\n"
1455                                                 "CallerIDName: %s\r\n"
1456                                                 "Context: %s\r\n"
1457                                                 "Extension: %s\r\n"
1458                                                 "Priority: %d\r\n",
1459                                                 tmp->interface, qe->chan->name,
1460                                                 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1461                                                 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1462                                                 qe->chan->context, qe->chan->exten, qe->chan->priority);
1463                 }
1464                 if (option_verbose > 2)
1465                         ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
1466         }
1467         return 1;
1468 }
1469
1470 static int ring_one(struct queue_ent *qe, struct localuser *outgoing, int *busies)
1471 {
1472         struct localuser *cur;
1473         struct localuser *best;
1474         int bestmetric=0;
1475
1476         do {
1477                 best = NULL;
1478                 cur = outgoing;
1479                 while(cur) {
1480                         if (cur->stillgoing &&                                  /* Not already done */
1481                                 !cur->chan &&                                   /* Isn't already going */
1482                                 (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
1483                                         bestmetric = cur->metric;
1484                                         best = cur;
1485                         }
1486                         cur = cur->next;
1487                 }
1488                 if (best) {
1489                         if (!qe->parent->strategy) {
1490                                 /* Ring everyone who shares this best metric (for ringall) */
1491                                 cur = outgoing;
1492                                 while(cur) {
1493                                         if (cur->stillgoing && !cur->chan && (cur->metric <= bestmetric)) {
1494                                                 if (option_debug)
1495                                                         ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1496                                                 ring_entry(qe, cur, busies);
1497                                         }
1498                                         cur = cur->next;
1499                                 }
1500                         } else {
1501                                 /* Ring just the best channel */
1502                                 if (option_debug)
1503                                         ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
1504                                 ring_entry(qe, best, busies);
1505                         }
1506                 }
1507         } while (best && !best->chan);
1508         if (!best) {
1509                 if (option_debug)
1510                         ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
1511                 return 0;
1512         }
1513         return 1;
1514 }
1515
1516 static int store_next(struct queue_ent *qe, struct localuser *outgoing)
1517 {
1518         struct localuser *cur;
1519         struct localuser *best;
1520         int bestmetric=0;
1521
1522         best = NULL;
1523         cur = outgoing;
1524         while(cur) {
1525                 if (cur->stillgoing &&                                  /* Not already done */
1526                         !cur->chan &&                                   /* Isn't already going */
1527                         (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
1528                                 bestmetric = cur->metric;
1529                                 best = cur;
1530                 }
1531                 cur = cur->next;
1532         }
1533         if (best) {
1534                 /* Ring just the best channel */
1535                 if (option_debug)
1536                         ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
1537                 qe->parent->rrpos = best->metric % 1000;
1538         } else {
1539                 /* Just increment rrpos */
1540                 if (qe->parent->wrapped) {
1541                         /* No more channels, start over */
1542                         qe->parent->rrpos = 0;
1543                 } else {
1544                         /* Prioritize next entry */
1545                         qe->parent->rrpos++;
1546                 }
1547         }
1548         qe->parent->wrapped = 0;
1549         return 0;
1550 }
1551
1552 static int background_file(struct queue_ent *qe, struct ast_channel *chan, char *filename)
1553 {
1554         int res;
1555
1556         ast_stopstream(chan);
1557         res = ast_streamfile(chan, filename, chan->language);
1558
1559         if (!res) {
1560                 /* Wait for a keypress */
1561                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1562                 if (res <= 0 || !valid_exit(qe, res))
1563                         res = 0;
1564
1565                 /* Stop playback */
1566                 ast_stopstream(chan);
1567         } else {
1568                 res = 0;
1569         }
1570         
1571         /*if (res) {
1572                 ast_log(LOG_WARNING, "ast_streamfile failed on %s \n", chan->name);
1573                 res = 0;
1574         }*/
1575
1576         return res;
1577 }
1578
1579 static int say_periodic_announcement(struct queue_ent *qe)
1580 {
1581         int res = 0;
1582         time_t now;
1583
1584         /* Get the current time */
1585         time(&now);
1586
1587         /* Check to see if it is time to announce */
1588         if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
1589                 return 0;
1590
1591         /* Stop the music on hold so we can play our own file */
1592         ast_moh_stop(qe->chan);
1593
1594         if (option_verbose > 2)
1595                 ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n");
1596
1597         /* Check to make sure we have a sound file. If not, reset to the first sound file */
1598         if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || !strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
1599                 qe->last_periodic_announce_sound = 0;
1600         }
1601         
1602         /* play the announcement */
1603         res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
1604
1605         /* Resume Music on Hold */
1606         ast_moh_start(qe->chan, qe->moh);
1607
1608         /* update last_periodic_announce_time */
1609         qe->last_periodic_announce_time = now;
1610
1611         /* Update the current periodic announcement to the next announcement */
1612         qe->last_periodic_announce_sound++;
1613         
1614         return res;
1615 }
1616
1617 static void record_abandoned(struct queue_ent *qe)
1618 {
1619         ast_mutex_lock(&qe->parent->lock);
1620         qe->parent->callsabandoned++;
1621         ast_mutex_unlock(&qe->parent->lock);
1622 }
1623
1624
1625 #define AST_MAX_WATCHERS 256
1626
1627 #define BUILD_WATCHERS do { \
1628                 o = outgoing; \
1629                 found = -1; \
1630                 pos = 1; \
1631                 numlines = 0; \
1632                 watchers[0] = in; \
1633                 while(o) { \
1634                         /* Keep track of important channels */ \
1635                         if (o->stillgoing) { \
1636                                 stillgoing = 1; \
1637                                 if (o->chan) { \
1638                                         watchers[pos++] = o->chan; \
1639                                         found = 1; \
1640                                 } \
1641                         } \
1642                         o = o->next; \
1643                         numlines++; \
1644                 } \
1645         } while(0)
1646         
1647 static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, char *digit, int prebusies, int caller_disconnect)
1648 {
1649         char *queue = qe->parent->name;
1650         char on[256] = "";
1651         struct localuser *o;
1652         int found;
1653         int numlines;
1654         int status;
1655         int sentringing = 0;
1656         int numbusies = prebusies;
1657         int numnochan = 0;
1658         int stillgoing = 0;
1659         int orig = *to;
1660         struct ast_frame *f;
1661         struct localuser *peer = NULL;
1662         struct ast_channel *watchers[AST_MAX_WATCHERS];
1663         int pos;
1664         struct ast_channel *winner;
1665         struct ast_channel *in = qe->chan;
1666         
1667         while(*to && !peer) {
1668                 BUILD_WATCHERS;
1669                 if ((found < 0) && stillgoing && !qe->parent->strategy) {
1670                         /* On "ringall" strategy we only move to the next penalty level
1671                            when *all* ringing phones are done in the current penalty level */
1672                         ring_one(qe, outgoing, &numbusies);
1673                         BUILD_WATCHERS;
1674                 }
1675                 if (found < 0) {
1676                         if (numlines == (numbusies + numnochan)) {
1677                                 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1678                         } else {
1679                                 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1680                         }
1681                         *to = 0;
1682                         return NULL;
1683                 }
1684                 winner = ast_waitfor_n(watchers, pos, to);
1685                 o = outgoing;
1686                 while(o) {
1687                         if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
1688                                 if (!peer) {
1689                                         if (option_verbose > 2)
1690                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1691                                         peer = o;
1692                                 }
1693                         } else if (o->chan && (o->chan == winner)) {
1694                                 ast_copy_string(on, o->member->interface, sizeof(on));
1695                                 if (!ast_strlen_zero(o->chan->call_forward)) {
1696                                         char tmpchan[256]="";
1697                                         char *stuff;
1698                                         char *tech;
1699                                         ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
1700                                         if ((stuff = strchr(tmpchan, '/'))) {
1701                                                 *stuff = '\0';
1702                                                 stuff++;
1703                                                 tech = tmpchan;
1704                                         } else {
1705                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1706                                                 stuff = tmpchan;
1707                                                 tech = "Local";
1708                                         }
1709                                         /* Before processing channel, go ahead and check for forwarding */
1710                                         if (option_verbose > 2)
1711                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1712                                         /* Setup parameters */
1713                                         o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1714                                         if (status != o->oldstatus) 
1715                                                 update_dial_status(qe->parent, o->member, status);                                              
1716                                         if (!o->chan) {
1717                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
1718                                                 o->stillgoing = 0;
1719                                                 numnochan++;
1720                                         } else {
1721                                                 if (o->chan->cid.cid_num)
1722                                                         free(o->chan->cid.cid_num);
1723                                                 o->chan->cid.cid_num = NULL;
1724                                                 if (o->chan->cid.cid_name)
1725                                                         free(o->chan->cid.cid_name);
1726                                                 o->chan->cid.cid_name = NULL;
1727
1728                                                 if (in->cid.cid_num) {
1729                                                         o->chan->cid.cid_num = strdup(in->cid.cid_num);
1730                                                         if (!o->chan->cid.cid_num)
1731                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1732                                                 }
1733                                                 if (in->cid.cid_name) {
1734                                                         o->chan->cid.cid_name = strdup(in->cid.cid_name);
1735                                                         if (!o->chan->cid.cid_name)
1736                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1737                                                 }
1738                                                 ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode));
1739                                                 o->chan->cdrflags = in->cdrflags;
1740
1741                                                 if (in->cid.cid_ani) {
1742                                                         if (o->chan->cid.cid_ani)
1743                                                                 free(o->chan->cid.cid_ani);
1744                                                         o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
1745                                                 }
1746                                                 if (o->chan->cid.cid_rdnis) 
1747                                                         free(o->chan->cid.cid_rdnis);
1748                                                 if (!ast_strlen_zero(in->macroexten))
1749                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
1750                                                 else
1751                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
1752                                                 if (ast_call(o->chan, tmpchan, 0)) {
1753                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
1754                                                         o->stillgoing = 0;
1755                                                         ast_hangup(o->chan);
1756                                                         o->chan = NULL;
1757                                                         numnochan++;
1758                                                 }
1759                                         }
1760                                         /* Hangup the original channel now, in case we needed it */
1761                                         ast_hangup(winner);
1762                                         continue;
1763                                 }
1764                                 f = ast_read(winner);
1765                                 if (f) {
1766                                         if (f->frametype == AST_FRAME_CONTROL) {
1767                                                 switch(f->subclass) {
1768                                         case AST_CONTROL_ANSWER:
1769                                                         /* This is our guy if someone answered. */
1770                                                         if (!peer) {
1771                                                                 if (option_verbose > 2)
1772                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1773                                                                 peer = o;
1774                                                         }
1775                                                         break;
1776                                                 case AST_CONTROL_BUSY:
1777                                                         if (option_verbose > 2)
1778                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
1779                                                         o->stillgoing = 0;
1780                                                         if (in->cdr)
1781                                                                 ast_cdr_busy(in->cdr);
1782                                                         ast_hangup(o->chan);
1783                                                         o->chan = NULL;
1784                                                         if (qe->parent->strategy) {
1785                                                                 if (qe->parent->timeoutrestart)
1786                                                                         *to = orig;
1787                                                                 ring_one(qe, outgoing, &numbusies);
1788                                                         }
1789                                                         numbusies++;
1790                                                         break;
1791                                                 case AST_CONTROL_CONGESTION:
1792                                                         if (option_verbose > 2)
1793                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
1794                                                         o->stillgoing = 0;
1795                                                         if (in->cdr)
1796                                                                 ast_cdr_busy(in->cdr);
1797                                                         ast_hangup(o->chan);
1798                                                         o->chan = NULL;
1799                                                         if (qe->parent->strategy) {
1800                                                                 if (qe->parent->timeoutrestart)
1801                                                                         *to = orig;
1802                                                                 ring_one(qe, outgoing, &numbusies);
1803                                                         }
1804                                                         numbusies++;
1805                                                         break;
1806                                                 case AST_CONTROL_RINGING:
1807                                                         if (option_verbose > 2)
1808                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1809                                                         if (!sentringing) {
1810 #if 0
1811                                                                 ast_indicate(in, AST_CONTROL_RINGING);
1812 #endif                                                          
1813                                                                 sentringing++;
1814                                                         }
1815                                                         break;
1816                                                 case AST_CONTROL_OFFHOOK:
1817                                                         /* Ignore going off hook */
1818                                                         break;
1819                                                 default:
1820                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
1821                                                 }
1822                                         }
1823                                         ast_frfree(f);
1824                                 } else {
1825                                         o->stillgoing = 0;
1826                                         ast_hangup(o->chan);
1827                                         o->chan = NULL;
1828                                         if (qe->parent->strategy) {
1829                                                 if (qe->parent->timeoutrestart)
1830                                                         *to = orig;
1831                                                 ring_one(qe, outgoing, &numbusies);
1832                                         }
1833                                 }
1834                         }
1835                         o = o->next;
1836                 }
1837                 if (winner == in) {
1838                         f = ast_read(in);
1839 #if 0
1840                         if (f && (f->frametype != AST_FRAME_VOICE))
1841                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
1842                         else if (!f || (f->frametype != AST_FRAME_VOICE))
1843                                 printf("Hangup received on %s\n", in->name);
1844 #endif
1845                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
1846                                 /* Got hung up */
1847                                 *to=-1;
1848                                 if (f)
1849                                         ast_frfree(f);
1850                                 return NULL;
1851                         }
1852                         if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
1853                                 if (option_verbose > 3)
1854                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
1855                                 *to=0;
1856                                 ast_frfree(f);
1857                                 return NULL;
1858                         }
1859                         if ((f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) {
1860                                 if (option_verbose > 3)
1861                                         ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass);
1862                                 *to=0;
1863                                 *digit=f->subclass;
1864                                 ast_frfree(f);
1865                                 return NULL;
1866                         }
1867                         ast_frfree(f);
1868                 }
1869                 if (!*to) {
1870                         if (option_verbose > 2)
1871                                 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
1872                         if (qe->parent->autopause) {
1873                                 if (!set_member_paused(qe->parent->name, on, 1)) {
1874                                         if (option_verbose > 2)
1875                                                 ast_verbose( VERBOSE_PREFIX_3 "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", on, qe->parent->name);
1876                                 } else {
1877                                         if (option_verbose > 2)
1878                                                 ast_verbose( VERBOSE_PREFIX_3 "Failed to pause Queue Member %s in queue %s!\n", on, qe->parent->name);
1879                                 }
1880                         }
1881                 }
1882         }
1883
1884         return peer;
1885         
1886 }
1887
1888 static int is_our_turn(struct queue_ent *qe)
1889 {
1890         struct queue_ent *ch;
1891         int res;
1892
1893         /* Atomically read the parent head -- does not need a lock */
1894         ch = qe->parent->head;
1895         /* If we are now at the top of the head, break out */
1896         if ((ch == qe) || (qe->parent->autofill)) {
1897                 if (option_debug)
1898                         ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
1899                 res = 1;
1900         } else {
1901                 if (option_debug)
1902                         ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
1903                 res = 0;
1904         }
1905         return res;
1906 }
1907
1908 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
1909 {
1910         int res = 0;
1911
1912         /* This is the holding pen for callers 2 through maxlen */
1913         for (;;) {
1914                 enum queue_member_status stat;
1915
1916                 if (is_our_turn(qe))
1917                         break;
1918
1919                 /* If we have timed out, break out */
1920                 if (qe->expire && (time(NULL) > qe->expire)) {
1921                         *reason = QUEUE_TIMEOUT;
1922                         ast_queue_log(qe->parent->name, qe->chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d", qe->pos);
1923                         break;
1924                 }
1925
1926                 stat = get_member_status(qe->parent, qe->max_penalty);
1927
1928                 /* leave the queue if no agents, if enabled */
1929                 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
1930                         *reason = QUEUE_LEAVEEMPTY;
1931                         leave_queue(qe);
1932                         break;
1933                 }
1934
1935                 /* leave the queue if no reachable agents, if enabled */
1936                 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
1937                         *reason = QUEUE_LEAVEUNAVAIL;
1938                         leave_queue(qe);
1939                         break;
1940                 }
1941
1942                 /* Make a position announcement, if enabled */
1943                 if (qe->parent->announcefrequency && !ringing)
1944                         res = say_position(qe);
1945                 if (res)
1946                         break;
1947
1948                 /* Make a periodic announcement, if enabled */
1949                 if (qe->parent->periodicannouncefrequency && !ringing)
1950                         res = say_periodic_announcement(qe);
1951
1952                 /* Wait a second before checking again */
1953                 if (!res) res = ast_waitfordigit(qe->chan, RECHECK * 1000);
1954                 if (res)
1955                         break;
1956         }
1957         return res;
1958 }
1959
1960 static int update_queue(struct ast_call_queue *q, struct member *member)
1961 {
1962         struct member *cur;
1963
1964         /* Since a reload could have taken place, we have to traverse the list to
1965                 be sure it's still valid */
1966         ast_mutex_lock(&q->lock);
1967         cur = q->members;
1968         while(cur) {
1969                 if (member == cur) {
1970                         time(&cur->lastcall);
1971                         cur->calls++;
1972                         break;
1973                 }
1974                 cur = cur->next;
1975         }
1976         q->callscompleted++;
1977         ast_mutex_unlock(&q->lock);
1978         return 0;
1979 }
1980
1981 static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp)
1982 {
1983         if (mem->penalty > qe->max_penalty)
1984                 return -1;
1985
1986         switch (q->strategy) {
1987         case QUEUE_STRATEGY_RINGALL:
1988                 /* Everyone equal, except for penalty */
1989                 tmp->metric = mem->penalty * 1000000;
1990                 break;
1991         case QUEUE_STRATEGY_ROUNDROBIN:
1992                 if (!pos) {
1993                         if (!q->wrapped) {
1994                                 /* No more channels, start over */
1995                                 q->rrpos = 0;
1996                         } else {
1997                                 /* Prioritize next entry */
1998                                 q->rrpos++;
1999                         }
2000                         q->wrapped = 0;
2001                 }
2002                 /* Fall through */
2003         case QUEUE_STRATEGY_RRMEMORY:
2004                 if (pos < q->rrpos) {
2005                         tmp->metric = 1000 + pos;
2006                 } else {
2007                         if (pos > q->rrpos)
2008                                 /* Indicate there is another priority */
2009                                 q->wrapped = 1;
2010                         tmp->metric = pos;
2011                 }
2012                 tmp->metric += mem->penalty * 1000000;
2013                 break;
2014         case QUEUE_STRATEGY_RANDOM:
2015                 tmp->metric = rand() % 1000;
2016                 tmp->metric += mem->penalty * 1000000;
2017                 break;
2018         case QUEUE_STRATEGY_FEWESTCALLS:
2019                 tmp->metric = mem->calls;
2020                 tmp->metric += mem->penalty * 1000000;
2021                 break;
2022         case QUEUE_STRATEGY_LEASTRECENT:
2023                 if (!mem->lastcall)
2024                         tmp->metric = 0;
2025                 else
2026                         tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
2027                 tmp->metric += mem->penalty * 1000000;
2028                 break;
2029         default:
2030                 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
2031                 break;
2032         }
2033         return 0;
2034 }
2035
2036 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on)
2037 {
2038         struct member *cur;
2039         struct localuser *outgoing=NULL, *tmp = NULL;
2040         int to;
2041         char restofit[AST_MAX_EXTENSION];
2042         char oldexten[AST_MAX_EXTENSION]="";
2043         char oldcontext[AST_MAX_CONTEXT]="";
2044         char queuename[256]="";
2045         char *newnum;
2046         struct ast_channel *peer;
2047         struct ast_channel *which;
2048         struct localuser *lpeer;
2049         struct member *member;
2050         int res = 0, bridge = 0;
2051         int numbusies = 0;
2052         int x=0;
2053         char *announce = NULL;
2054         char digit = 0;
2055         time_t callstart;
2056         time_t now = time(NULL);
2057         struct ast_bridge_config bridge_config;
2058         char nondataquality = 1;
2059
2060         memset(&bridge_config, 0, sizeof(bridge_config));
2061         time(&now);
2062                 
2063         for (; options && *options; options++)
2064                 switch (*options) {
2065                 case 't':
2066                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
2067                         break;
2068                 case 'T':
2069                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
2070                         break;
2071                 case 'w':
2072                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
2073                         break;
2074                 case 'W':
2075                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
2076                         break;
2077                 case 'd':
2078                         nondataquality = 0;
2079                         break;
2080                 case 'h':
2081                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
2082                         break;
2083                 case 'H':
2084                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
2085                         break;
2086                 case 'n':
2087                         if ((now - qe->start >= qe->parent->timeout))
2088                                 *go_on = 1;
2089                         break;
2090                 }
2091
2092         /* Hold the lock while we setup the outgoing calls */
2093         if (use_weight) 
2094                 AST_LIST_LOCK(&queues);
2095         ast_mutex_lock(&qe->parent->lock);
2096         if (option_debug)
2097                 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n", 
2098                                                         qe->chan->name);
2099         ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
2100         cur = qe->parent->members;
2101         if (!ast_strlen_zero(qe->announce))
2102                 announce = qe->announce;
2103         if (!ast_strlen_zero(announceoverride))
2104                 announce = announceoverride;
2105
2106         while(cur) {
2107                 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
2108                         ast_mutex_unlock(&qe->parent->lock);
2109                         if (use_weight) 
2110                                 AST_LIST_UNLOCK(&queues);
2111                         goto out;
2112                 }
2113                 tmp->stillgoing = -1;
2114                 if (option_debug) {
2115                         if (url)
2116                                 ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
2117                         else 
2118                                 ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
2119                 }
2120
2121                 tmp->member = cur;              /* Never directly dereference!  Could change on reload */
2122                 tmp->oldstatus = cur->status;
2123                 tmp->lastcall = cur->lastcall;
2124                 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2125                 /* If we're dialing by extension, look at the extension to know what to dial */
2126                 if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
2127                         newnum++;
2128                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1);
2129                         snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit);
2130                         if (option_debug)
2131                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface);
2132                 }
2133                 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2134                    just calculate their metric for the appropriate strategy */
2135                 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
2136                         /* Put them in the list of outgoing thingies...  We're ready now. 
2137                            XXX If we're forcibly removed, these outgoing calls won't get
2138                            hung up XXX */
2139                         tmp->next = outgoing;
2140                         outgoing = tmp;         
2141                         /* If this line is up, don't try anybody else */
2142                         if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2143                                 break;
2144                 } else {
2145                         free(tmp);
2146                 }
2147
2148                 cur = cur->next;
2149         }
2150         if (qe->parent->timeout)
2151                 to = qe->parent->timeout * 1000;
2152         else
2153                 to = -1;
2154         ring_one(qe, outgoing, &numbusies);
2155         ast_mutex_unlock(&qe->parent->lock);
2156         if (use_weight) 
2157                 AST_LIST_UNLOCK(&queues);
2158         lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
2159         ast_mutex_lock(&qe->parent->lock);
2160         if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2161                 store_next(qe, outgoing);
2162         }
2163         ast_mutex_unlock(&qe->parent->lock);
2164         if (lpeer)
2165                 peer = lpeer->chan;
2166         else
2167                 peer = NULL;
2168         if (!peer) {
2169                 if (to) {
2170                         /* Must gotten hung up */
2171                         record_abandoned(qe);
2172                         res = -1;
2173                 } else {
2174                         res = digit;
2175                 }
2176                 if (option_debug)
2177                         ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
2178                 goto out;
2179         }
2180         if (peer) {
2181                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
2182                    we will always return with -1 so that it is hung up properly after the 
2183                    conversation.  */
2184                 qe->handled++;
2185                 if (!strcmp(qe->chan->type,"Zap"))
2186                         ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2187                 if (!strcmp(peer->type,"Zap"))
2188                         ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2189                 /* Update parameters for the queue */
2190                 recalc_holdtime(qe);
2191                 member = lpeer->member;
2192                 hangupcalls(outgoing, peer);
2193                 outgoing = NULL;
2194                 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2195                         int res2;
2196                         res2 = ast_autoservice_start(qe->chan);
2197                         if (!res2) {
2198                                 if (qe->parent->memberdelay) {
2199                                         ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2200                                         res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2201                                 }
2202                                 if (!res2 && announce) {
2203                                         if (play_file(peer, announce))
2204                                                 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2205                                 }
2206                                 if (!res2 && qe->parent->reportholdtime) {
2207                                         if (!play_file(peer, qe->parent->sound_reporthold)) {
2208                                                 int holdtime;
2209
2210                                                 time(&now);
2211                                                 holdtime = abs((now - qe->start) / 60);
2212                                                 if (holdtime < 2) {
2213                                                         play_file(peer, qe->parent->sound_lessthan);
2214                                                         ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2215                                                 } else 
2216                                                         ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2217                                                 play_file(peer, qe->parent->sound_minutes);
2218                                         }
2219                                 }
2220                         }
2221                         res2 |= ast_autoservice_stop(qe->chan);
2222                         if (peer->_softhangup) {
2223                                 /* Agent must have hung up */
2224                                 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
2225                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
2226                                 record_abandoned(qe);
2227                                 if (qe->parent->eventwhencalled) {
2228                                         manager_event(EVENT_FLAG_AGENT, "AgentDump",
2229                                                       "Queue: %s\r\n"
2230                                                       "Uniqueid: %s\r\n"
2231                                                       "Channel: %s\r\n"
2232                                                       "Member: %s\r\n",
2233                                                       queuename, qe->chan->uniqueid, peer->name, member->interface);
2234                                 }
2235                                 ast_hangup(peer);
2236                                 goto out;
2237                         } else if (res2) {
2238                                 /* Caller must have hung up just before being connected*/
2239                                 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2240                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2241                                 record_abandoned(qe);
2242                                 ast_hangup(peer);
2243                                 return -1;
2244                         }
2245                 }
2246                 /* Stop music on hold */
2247                 ast_moh_stop(qe->chan);
2248                 /* If appropriate, log that we have a destination channel */
2249                 if (qe->chan->cdr)
2250                         ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2251                 /* Make sure channels are compatible */
2252                 res = ast_channel_make_compatible(qe->chan, peer);
2253                 if (res < 0) {
2254                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "SYSCOMPAT", "%s", "");
2255                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2256                         record_abandoned(qe);
2257                         ast_hangup(peer);
2258                         return -1;
2259                 }
2260                 /* Begin Monitoring */
2261                 if (qe->parent->monfmt && *qe->parent->monfmt) {
2262                         const char *monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2263                         if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2264                                 which = qe->chan;
2265                         else
2266                                 which = peer;
2267                         if (monitorfilename)
2268                                 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2269                         else if (qe->chan->cdr) 
2270                                 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2271                         else {
2272                                 /* Last ditch effort -- no CDR, make up something */
2273                                 char tmpid[256];
2274                                 snprintf(tmpid, sizeof(tmpid), "chan-%x", rand());
2275                                 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2276                         }
2277                         if (qe->parent->monjoin)
2278                                 ast_monitor_setjoinfiles(which, 1);
2279                 }
2280                 /* Drop out of the queue at this point, to prepare for next caller */
2281                 leave_queue(qe);                        
2282                 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2283                         if (option_debug)
2284                                 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2285                         ast_channel_sendurl(peer, url);
2286                 }
2287                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
2288                 if (qe->parent->eventwhencalled)
2289                         manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2290                                       "Queue: %s\r\n"
2291                                       "Uniqueid: %s\r\n"
2292                                       "Channel: %s\r\n"
2293                                       "Member: %s\r\n"
2294                                       "Holdtime: %ld\r\n",
2295                                       queuename, qe->chan->uniqueid, peer->name, member->interface,
2296                                       (long)time(NULL) - qe->start);
2297                 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2298                 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2299                 time(&callstart);
2300
2301                 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2302
2303                 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2304                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
2305                 } else if (qe->chan->_softhangup) {
2306                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
2307                                       (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2308                         if (qe->parent->eventwhencalled)
2309                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2310                                               "Queue: %s\r\n"
2311                                               "Uniqueid: %s\r\n"
2312                                               "Channel: %s\r\n"
2313                                               "Member: %s\r\n"
2314                                               "HoldTime: %ld\r\n"
2315                                               "TalkTime: %ld\r\n"
2316                                               "Reason: caller\r\n",
2317                                               queuename, qe->chan->uniqueid, peer->name, member->interface,
2318                                               (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2319                 } else {
2320                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2321                         if (qe->parent->eventwhencalled)
2322                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2323                                               "Queue: %s\r\n"
2324                                               "Uniqueid: %s\r\n"
2325                                               "Channel: %s\r\n"
2326                                               "HoldTime: %ld\r\n"
2327                                               "TalkTime: %ld\r\n"
2328                                               "Reason: agent\r\n",
2329                                               queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start),
2330                                               (long)(time(NULL) - callstart));
2331                 }
2332
2333                 if(bridge != AST_PBX_NO_HANGUP_PEER)
2334                         ast_hangup(peer);
2335                 update_queue(qe->parent, member);
2336                 if (bridge == 0) 
2337                         res = 1; /* JDG: bridge successfully, leave app_queue */
2338                 else 
2339                         res = bridge; /* bridge error, stay in the queue */
2340         }       
2341 out:
2342         hangupcalls(outgoing, NULL);
2343         return res;
2344 }
2345
2346 static int wait_a_bit(struct queue_ent *qe)
2347 {
2348         /* Don't need to hold the lock while we setup the outgoing calls */
2349         int retrywait = qe->parent->retry * 1000;
2350
2351         return ast_waitfordigit(qe->chan, retrywait);
2352 }
2353
2354 static struct member * interface_exists(struct ast_call_queue *q, char *interface)
2355 {
2356         struct member *mem;
2357
2358         if (q)
2359                 for (mem = q->members; mem; mem = mem->next)
2360                         if (!strcasecmp(interface, mem->interface))
2361                                 return mem;
2362
2363         return NULL;
2364 }
2365
2366
2367 /* Dump all members in a specific queue to the database
2368  *
2369  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2370  *
2371  */
2372 static void dump_queue_members(struct ast_call_queue *pm_queue)
2373 {
2374         struct member *cur_member;
2375         char value[PM_MAX_LEN];
2376         int value_len = 0;
2377         int res;
2378
2379         memset(value, 0, sizeof(value));
2380
2381         if (!pm_queue)
2382                 return;
2383
2384         for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2385                 if (!cur_member->dynamic)
2386                         continue;
2387
2388                 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d%s",
2389                                cur_member->interface, cur_member->penalty, cur_member->paused,
2390                                cur_member->next ? "|" : "");
2391                 if (res != strlen(value + value_len)) {
2392                         ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2393                         break;
2394                 }
2395                 value_len += res;
2396         }
2397         
2398         if (value_len && !cur_member) {
2399                 if (ast_db_put(pm_family, pm_queue->name, value))
2400                         ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2401         } else
2402                 /* Delete the entry if the queue is empty or there is an error */
2403                 ast_db_del(pm_family, pm_queue->name);
2404 }
2405
2406 static int remove_from_queue(char *queuename, char *interface)
2407 {
2408         struct ast_call_queue *q;
2409         struct member *last_member, *look;
2410         int res = RES_NOSUCHQUEUE;
2411
2412         AST_LIST_LOCK(&queues);
2413         AST_LIST_TRAVERSE(&queues, q, list) {
2414                 ast_mutex_lock(&q->lock);
2415                 if (!strcmp(q->name, queuename)) {
2416                         if ((last_member = interface_exists(q, interface))) {
2417                                 if ((look = q->members) == last_member) {
2418                                         q->members = last_member->next;
2419                                 } else {
2420                                         while (look != NULL) {
2421                                                 if (look->next == last_member) {
2422                                                         look->next = last_member->next;
2423                                                         break;
2424                                                 } else {
2425                                                          look = look->next;
2426                                                 }
2427                                         }
2428                                 }
2429                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
2430                                                 "Queue: %s\r\n"
2431                                                 "Location: %s\r\n",
2432                                         q->name, last_member->interface);
2433                                 free(last_member);
2434
2435                                 if (queue_persistent_members)
2436                                     dump_queue_members(q);
2437
2438                                 res = RES_OKAY;
2439                         } else {
2440                                 res = RES_EXISTS;
2441                         }
2442                         ast_mutex_unlock(&q->lock);
2443                         break;
2444                 }
2445                 ast_mutex_unlock(&q->lock);
2446         }
2447         AST_LIST_UNLOCK(&queues);
2448         return res;
2449 }
2450
2451 static int add_to_queue(char *queuename, char *interface, int penalty, int paused, int dump)
2452 {
2453         struct ast_call_queue *q;
2454         struct member *new_member;
2455         int res = RES_NOSUCHQUEUE;
2456
2457         /* \note Ensure the appropriate realtime queue is loaded.  Note that this
2458          * short-circuits if the queue is already in memory. */
2459         q = load_realtime_queue(queuename);
2460
2461         AST_LIST_LOCK(&queues);
2462
2463         if (q) {
2464                 ast_mutex_lock(&q->lock);
2465                 if (interface_exists(q, interface) == NULL) {
2466                         new_member = create_queue_member(interface, penalty, paused);
2467
2468                         if (new_member != NULL) {
2469                                 new_member->dynamic = 1;
2470                                 new_member->next = q->members;
2471                                 q->members = new_member;
2472                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
2473                                         "Queue: %s\r\n"
2474                                         "Location: %s\r\n"
2475                                         "Membership: %s\r\n"
2476                                         "Penalty: %d\r\n"
2477                                         "CallsTaken: %d\r\n"
2478                                         "LastCall: %d\r\n"
2479                                         "Status: %d\r\n"
2480                                         "Paused: %d\r\n",
2481                                 q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
2482                                 new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
2483                                         
2484                                 if (dump)
2485                                         dump_queue_members(q);
2486
2487                                 res = RES_OKAY;
2488                         } else {
2489                                 res = RES_OUTOFMEMORY;
2490                         }
2491                 } else {
2492                         res = RES_EXISTS;
2493                 }
2494                 ast_mutex_unlock(&q->lock);
2495         }
2496         AST_LIST_UNLOCK(&queues);
2497         return res;
2498 }
2499
2500 static int set_member_paused(char *queuename, char *interface, int paused)
2501 {
2502         int found = 0;
2503         struct ast_call_queue *q;
2504         struct member *mem;
2505
2506         /* Special event for when all queues are paused - individual events still generated */
2507
2508         if (ast_strlen_zero(queuename))
2509                 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
2510
2511         AST_LIST_LOCK(&queues);
2512         AST_LIST_TRAVERSE(&queues, q, list) {
2513                 ast_mutex_lock(&q->lock);
2514                 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
2515                         if ((mem = interface_exists(q, interface))) {
2516                                 found++;
2517                                 if (mem->paused == paused)
2518                                         ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
2519                                 mem->paused = paused;
2520
2521                                 if (queue_persistent_members)
2522                                     dump_queue_members(q);
2523
2524                                 ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
2525
2526                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
2527                                         "Queue: %s\r\n"
2528                                         "Location: %s\r\n"
2529                                         "Paused: %d\r\n",
2530                                                 q->name, mem->interface, paused);
2531                         }
2532                 }
2533                 ast_mutex_unlock(&q->lock);
2534         }
2535         AST_LIST_UNLOCK(&queues);
2536
2537         if (found)
2538                 return RESULT_SUCCESS;
2539         else
2540                 return RESULT_FAILURE;
2541 }
2542
2543 /* Reload dynamic queue members persisted into the astdb */
2544 static void reload_queue_members(void)
2545 {
2546         char *cur_ptr;  
2547         char *queue_name;
2548         char *member;
2549         char *interface;
2550         char *penalty_tok;
2551         int penalty = 0;
2552         char *paused_tok;
2553         int paused = 0;
2554         struct ast_db_entry *db_tree;
2555         struct ast_db_entry *entry;
2556         struct ast_call_queue *cur_queue;
2557         char queue_data[PM_MAX_LEN];
2558
2559         AST_LIST_LOCK(&queues);
2560
2561         /* Each key in 'pm_family' is the name of a queue */
2562         db_tree = ast_db_gettree(pm_family, NULL);
2563         for (entry = db_tree; entry; entry = entry->next) {
2564
2565                 queue_name = entry->key + strlen(pm_family) + 2;
2566
2567                 AST_LIST_TRAVERSE(&queues, cur_queue, list) {
2568                         ast_mutex_lock(&cur_queue->lock);
2569                         if (!strcmp(queue_name, cur_queue->name))
2570                                 break;
2571                         ast_mutex_unlock(&cur_queue->lock);
2572                 }
2573
2574                 if (!cur_queue) {
2575                         /* If the queue no longer exists, remove it from the
2576                          * database */
2577                         ast_db_del(pm_family, queue_name);
2578                         continue;
2579                 } else
2580                         ast_mutex_unlock(&cur_queue->lock);
2581
2582                 if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
2583                         continue;
2584
2585                 cur_ptr = queue_data;
2586                 while ((member = strsep(&cur_ptr, "|"))) {
2587                         if (ast_strlen_zero(member))
2588                                 continue;
2589
2590                         interface = strsep(&member, ";");
2591                         penalty_tok = strsep(&member, ";");
2592                         paused_tok = strsep(&member, ";");
2593
2594                         if (!penalty_tok) {
2595                                 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
2596                                 break;
2597                         }
2598                         penalty = strtol(penalty_tok, NULL, 10);
2599                         if (errno == ERANGE) {
2600                                 ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
2601                                 break;
2602                         }
2603                         
2604                         if (!paused_tok) {
2605                                 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
2606                                 break;
2607                         }
2608                         paused = strtol(paused_tok, NULL, 10);
2609                         if ((errno == ERANGE) || paused < 0 || paused > 1) {
2610                                 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
2611                                 break;
2612                         }
2613
2614                         if (option_debug)
2615                                 ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Penalty: %d  Paused: %d\n", queue_name, interface, penalty, paused);
2616                         
2617                         if (add_to_queue(queue_name, interface, penalty, paused, 0) == RES_OUTOFMEMORY) {
2618                                 ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
2619                                 break;
2620                         }
2621                 }
2622         }
2623
2624         AST_LIST_UNLOCK(&queues);
2625         if (db_tree) {
2626                 ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
2627                 ast_db_freetree(db_tree);
2628         }
2629 }
2630
2631 static int pqm_exec(struct ast_channel *chan, void *data)
2632 {
2633         struct localuser *u;
2634         char *parse;
2635         int priority_jump = 0;
2636         AST_DECLARE_APP_ARGS(args,
2637                 AST_APP_ARG(queuename);
2638                 AST_APP_ARG(interface);
2639                 AST_APP_ARG(options);
2640         );
2641
2642         if (ast_strlen_zero(data)) {
2643                 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface[|options])\n");
2644                 return -1;
2645         }
2646
2647         LOCAL_USER_ADD(u);
2648
2649         if (!(parse = ast_strdupa(data))) {
2650                 LOCAL_USER_REMOVE(u);
2651                 return -1;
2652         }
2653
2654         AST_STANDARD_APP_ARGS(args, parse);
2655
2656         if (args.options) {
2657                 if (strchr(args.options, 'j'))
2658                         priority_jump = 1;
2659         }
2660
2661         if (ast_strlen_zero(args.interface)) {
2662                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options])\n");
2663                 LOCAL_USER_REMOVE(u);
2664                 return -1;
2665         }
2666
2667         if (set_member_paused(args.queuename, args.interface, 1)) {
2668                 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
2669                 if (priority_jump || ast_opt_priority_jumping) {
2670                         if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
2671                                 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
2672                                 LOCAL_USER_REMOVE(u);
2673                                 return 0;
2674                         }
2675                 }
2676                 LOCAL_USER_REMOVE(u);
2677                 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
2678                 return -1;
2679         }
2680
2681         LOCAL_USER_REMOVE(u);
2682         pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
2683         return 0;
2684 }
2685
2686 static int upqm_exec(struct ast_channel *chan, void *data)
2687 {
2688         struct localuser *u;
2689         char *parse;
2690         int priority_jump = 0;
2691         AST_DECLARE_APP_ARGS(args,
2692                 AST_APP_ARG(queuename);
2693                 AST_APP_ARG(interface);
2694                 AST_APP_ARG(options);
2695         );
2696
2697         if (ast_strlen_zero(data)) {
2698                 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface[|options])\n");
2699                 return -1;
2700         }
2701
2702         LOCAL_USER_ADD(u);
2703
2704         if (!(parse = ast_strdupa(data))) {
2705                 LOCAL_USER_REMOVE(u);
2706                 return -1;      
2707         }
2708
2709         AST_STANDARD_APP_ARGS(args, parse);
2710
2711         if (args.options) {
2712                 if (strchr(args.options, 'j'))
2713                         priority_jump = 1;
2714         }
2715
2716         if (ast_strlen_zero(args.interface)) {
2717                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options])\n");
2718                 LOCAL_USER_REMOVE(u);
2719                 return -1;
2720         }
2721
2722         if (set_member_paused(args.queuename, args.interface, 0)) {
2723                 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
2724                 if (priority_jump || ast_opt_priority_jumping) {
2725                         if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
2726                                 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
2727                                 LOCAL_USER_REMOVE(u);
2728                                 return 0;
2729                         }
2730                 }
2731                 LOCAL_USER_REMOVE(u);
2732                 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
2733                 return -1;
2734         }
2735
2736         LOCAL_USER_REMOVE(u);
2737         pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
2738         return 0;
2739 }
2740
2741 static int rqm_exec(struct ast_channel *chan, void *data)
2742 {
2743         int res=-1;
2744         struct localuser *u;
2745         char *parse, *temppos = NULL;
2746         int priority_jump = 0;
2747         AST_DECLARE_APP_ARGS(args,
2748                 AST_APP_ARG(queuename);
2749                 AST_APP_ARG(interface);
2750                 AST_APP_ARG(options);
2751         );
2752
2753
2754         if (ast_strlen_zero(data)) {
2755                 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface[|options]])\n");
2756                 return -1;
2757         }
2758
2759         LOCAL_USER_ADD(u);
2760
2761         if (!(parse = ast_strdupa(data))) {
2762                 LOCAL_USER_REMOVE(u);
2763                 return -1;
2764         }
2765
2766         AST_STANDARD_APP_ARGS(args, parse);
2767
2768         if (ast_strlen_zero(args.interface)) {
2769                 args.interface = ast_strdupa(chan->name);
2770                 temppos = strrchr(args.interface, '-');
2771                 if (temppos)
2772                         *temppos = '\0';
2773         }
2774
2775         if (args.options) {
2776                 if (strchr(args.options, 'j'))
2777                         priority_jump = 1;
2778         }
2779
2780         switch (remove_from_queue(args.queuename, args.interface)) {
2781         case RES_OKAY:
2782                 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
2783                 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
2784                 res = 0;
2785                 break;
2786         case RES_EXISTS:
2787                 ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
2788                 if (priority_jump || ast_opt_priority_jumping) 
2789                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
2790                 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
2791                 res = 0;
2792                 break;
2793         case RES_NOSUCHQUEUE:
2794                 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
2795                 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
2796                 res = 0;
2797                 break;
2798         case RES_OUTOFMEMORY:
2799                 ast_log(LOG_ERROR, "Out of memory\n");
2800                 break;
2801         }
2802
2803         LOCAL_USER_REMOVE(u);
2804         return res;
2805 }
2806
2807 static int aqm_exec(struct ast_channel *chan, void *data)
2808 {
2809         int res=-1;
2810         struct localuser *u;
2811         char *parse, *temppos = NULL;
2812         int priority_jump = 0;
2813         AST_DECLARE_APP_ARGS(args,
2814                 AST_APP_ARG(queuename);
2815                 AST_APP_ARG(interface);
2816                 AST_APP_ARG(penalty);
2817                 AST_APP_ARG(options);
2818         );
2819         int penalty = 0;
2820
2821         if (ast_strlen_zero(data)) {
2822                 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface]|[penalty][|options]])\n");
2823                 return -1;
2824         }
2825
2826         LOCAL_USER_ADD(u);
2827
2828         parse = ast_strdupa(data);
2829
2830         AST_STANDARD_APP_ARGS(args, parse);
2831
2832         if (ast_strlen_zero(args.interface)) {
2833                 args.interface = ast_strdupa(chan->name);
2834                 temppos = strrchr(args.interface, '-');
2835                 if (temppos)
2836                         *temppos = '\0';
2837         }
2838
2839         if (!ast_strlen_zero(args.penalty)) {
2840                 if ((sscanf(args.penalty, "%d", &penalty) != 1) || penalty < 0) {
2841                         ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
2842                         penalty = 0;
2843                 }
2844         }
2845         
2846         if (args.options) {
2847                 if (strchr(args.options, 'j'))
2848                         priority_jump = 1;
2849         }
2850
2851
2852         switch (add_to_queue(args.queuename, args.interface, penalty, 0, queue_persistent_members)) {
2853         case RES_OKAY:
2854                 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
2855                 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
2856                 res = 0;
2857                 break;
2858         case RES_EXISTS:
2859                 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
2860                 if (priority_jump || ast_opt_priority_jumping) 
2861                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
2862                 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
2863                 res = 0;
2864                 break;
2865         case RES_NOSUCHQUEUE:
2866                 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
2867                 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
2868                 res = 0;
2869                 break;
2870         case RES_OUTOFMEMORY:
2871                 ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", args.interface, args.queuename);
2872                 break;
2873         }
2874
2875         LOCAL_USER_REMOVE(u);
2876         return res;
2877 }
2878
2879 static int queue_exec(struct ast_channel *chan, void *data)
2880 {
2881         int res=-1;
2882         int ringing=0;
2883         struct localuser *u;
2884         char *queuename;
2885         char info[512];
2886         char *info_ptr = info;
2887         char *options = NULL;
2888         char *url = NULL;
2889         char *announceoverride = NULL;
2890         const char *user_priority;
2891         const char *max_penalty_str;
2892         int prio;
2893         int max_penalty;
2894         char *queuetimeoutstr = NULL;
2895         enum queue_result reason = QUEUE_UNKNOWN;
2896
2897         /* whether to exit Queue application after the timeout hits */
2898         int go_on = 0;
2899
2900         /* Our queue entry */
2901         struct queue_ent qe;
2902         
2903         if (ast_strlen_zero(data)) {
2904                 ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n");
2905                 return -1;
2906         }
2907
2908         LOCAL_USER_ADD(u);
2909
2910         /* Setup our queue entry */
2911         memset(&qe, 0, sizeof(qe));
2912         qe.start = time(NULL);
2913         
2914         /* Parse our arguments XXX Check for failure XXX */
2915         ast_copy_string(info, (char *) data, sizeof(info));
2916         queuename = strsep(&info_ptr, "|");
2917         options = strsep(&info_ptr, "|");
2918         url = strsep(&info_ptr, "|");
2919         announceoverride = strsep(&info_ptr, "|");
2920         queuetimeoutstr = info_ptr;
2921
2922         /* set the expire time based on the supplied timeout; */
2923         if (queuetimeoutstr)
2924                 qe.expire = qe.start + atoi(queuetimeoutstr);
2925         else
2926                 qe.expire = 0;
2927
2928         /* Get the priority from the variable ${QUEUE_PRIO} */
2929         user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
2930         if (user_priority) {
2931                 if (sscanf(user_priority, "%d", &prio) == 1) {
2932                         if (option_debug)
2933                                 ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
2934                                         chan->name, prio);
2935                 } else {
2936                         ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
2937                                 user_priority, chan->name);
2938                         prio = 0;
2939                 }
2940         } else {
2941                 if (option_debug > 2)
2942                         ast_log(LOG_DEBUG, "NO QUEUE_PRIO variable found. Using default.\n");
2943                 prio = 0;
2944         }
2945
2946         /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
2947         if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
2948                 if (sscanf(max_penalty_str, "%d", &max_penalty) == 1) {
2949                         if (option_debug)
2950                                 ast_log(LOG_DEBUG, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n",
2951                                         chan->name, max_penalty);
2952                 } else {
2953                         ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
2954                                 max_penalty_str, chan->name);
2955                         max_penalty = 0;
2956                 }
2957         } else {
2958                 max_penalty = 0;
2959         }
2960
2961         if (options && (strchr(options, 'r')))
2962                 ringing = 1;
2963
2964         if (option_debug)  
2965                 ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
2966                         queuename, options, url, announceoverride, (long)qe.expire, prio);
2967
2968         qe.chan = chan;
2969         qe.prio = prio;
2970         qe.max_penalty = max_penalty;
2971         qe.last_pos_said = 0;
2972         qe.last_pos = 0;
2973         qe.last_periodic_announce_time = time(NULL);
2974         qe.last_periodic_announce_sound = 0;
2975         if (!join_queue(queuename, &qe, &reason)) {
2976                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "",
2977                               chan->cid.cid_num ? chan->cid.cid_num : "");
2978 check_turns:
2979                 if (ringing) {
2980                         ast_indicate(chan, AST_CONTROL_RINGING);
2981                 } else {              
2982                         ast_moh_start(chan, qe.moh);
2983                 }
2984                 for (;;) {
2985                         /* This is the wait loop for callers 2 through maxlen */
2986
2987                         res = wait_our_turn(&qe, ringing, &reason);
2988                         /* If they hungup, return immediately */
2989                         if (res < 0) {
2990                                 /* Record this abandoned call */
2991                                 record_abandoned(&qe);
2992                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2993                                 if (option_verbose > 2) {
2994                                         ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", queuename);
2995                                         res = -1;
2996                                 }
2997                                 break;
2998                         }
2999                         if (!res) 
3000                                 break;
3001                         if (valid_exit(&qe, res)) {
3002                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
3003                                 break;
3004                         }
3005                 }
3006                 if (!res) {
3007                         int makeannouncement = 0;
3008                         for (;;) {
3009                                 /* This is the wait loop for the head caller*/
3010                                 /* To exit, they may get their call answered; */
3011                                 /* they may dial a digit from the queue context; */
3012                                 /* or, they may timeout. */
3013
3014                                 enum queue_member_status stat;
3015
3016                                 /* Leave if we have exceeded our queuetimeout */
3017                                 if (qe.expire && (time(NULL) > qe.expire)) {
3018                                         record_abandoned(&qe);
3019                                         reason = QUEUE_TIMEOUT;
3020                                         res = 0;
3021                                         ast_queue_log(queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
3022                                         break;
3023                                 }
3024
3025                                 if (makeannouncement) {
3026                                         /* Make a position announcement, if enabled */
3027                                         if (qe.parent->announcefrequency && !ringing)
3028                                                 res = say_position(&qe);
3029                                         if (res && valid_exit(&qe, res)) {
3030                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
3031                                                 break;
3032                                         }
3033
3034                                 }
3035                                 makeannouncement = 1;
3036
3037                                 /* Make a periodic announcement, if enabled */
3038                                 if (qe.parent->periodicannouncefrequency && !ringing)
3039                                         res = say_periodic_announcement(&qe);
3040
3041                                 if (res && valid_exit(&qe, res)) {
3042                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
3043                                         break;
3044                                 }
3045
3046                                 /* Try calling all queue members for 'timeout' seconds */
3047                                 res = try_calling(&qe, options, announceoverride, url, &go_on);
3048                                 if (res) {
3049                                         if (res < 0) {
3050                                                 if (!qe.handled) {
3051                                                         record_abandoned(&qe);
3052                                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
3053                                                 }
3054                                         } else if (res > 0)
3055                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
3056                                         break;
3057                                 }
3058
3059                                 stat = get_member_status(qe.parent, qe.max_penalty);
3060
3061                                 /* leave the queue if no agents, if enabled */
3062                                 if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
3063                                         record_abandoned(&qe);
3064                                         reason = QUEUE_LEAVEEMPTY;
3065                                         res = 0;
3066                                         break;
3067                                 }
3068
3069                                 /* leave the queue if no reachable agents, if enabled */
3070                                 if ((qe.parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
3071                                         record_abandoned(&qe);
3072                                         reason = QUEUE_LEAVEUNAVAIL;
3073                                         res = 0;
3074                                         break;
3075                                 }
3076
3077                                 /* Leave if we have exceeded our queuetimeout */
3078                                 if (qe.expire && (time(NULL) > qe.expire)) {
3079                                         record_abandoned(&qe);
3080                                         reason = QUEUE_TIMEOUT;
3081                                         res = 0;
3082                                         ast_queue_log(queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d", qe.pos);       
3083                                         break;
3084                                 }
3085
3086                                 /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
3087                                 res = wait_a_bit(&qe);
3088                                 if (res < 0) {
3089                                         record_abandoned(&qe);
3090                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
3091                                         if (option_verbose > 2) {
3092                                                 ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s when they almost made it\n", queuename);
3093                                                 res = -1;
3094                                         }
3095                                         break;
3096                                 }
3097                                 if (res && valid_exit(&qe, res)) {
3098                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
3099                                         break;
3100                                 }
3101                                 /* exit after 'timeout' cycle if 'n' option enabled */
3102                                 if (go_on) {
3103                                         if (option_verbose > 2) {
3104                                                 ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n");
3105                                                 res = -1;
3106                                         }
3107                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
3108                                         record_abandoned(&qe);
3109                                         reason = QUEUE_TIMEOUT;
3110                                         res = 0;
3111                                         break;
3112                                 }
3113                                 /* Since this is a priority queue and 
3114                                  * it is not sure that we are still at the head
3115                                  * of the queue, go and check for our turn again.
3116                                  */
3117                                 if (!is_our_turn(&qe)) {
3118                                         if (option_debug)
3119                                                 ast_log(LOG_DEBUG, "Darn priorities, going back in queue (%s)!\n",
3120                                                                 qe.chan->name);
3121                                         goto check_turns;
3122                                 }
3123                         }
3124                 }
3125                 /* Don't allow return code > 0 */
3126                 if (res >= 0 && res != AST_PBX_KEEPALIVE) {
3127                         res = 0;        
3128                         if (ringing) {
3129                                 ast_indicate(chan, -1);
3130                         } else {
3131                                 ast_moh_stop(chan);
3132                         }                       
3133                         ast_stopstream(chan);
3134                 }
3135                 leave_queue(&qe);
3136                 if (reason != QUEUE_UNKNOWN)
3137                         set_queue_result(chan, reason);
3138         } else {
3139                 ast_log(LOG_WARNING, "Unable to join queue '%s'\n", queuename);
3140                 set_queue_result(chan, reason);
3141                 res = 0;
3142         }
3143         LOCAL_USER_REMOVE(u);
3144         return res;
3145 }
3146
3147 static char *queue_function_qac(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
3148 {
3149         int count = 0;
3150         struct ast_call_queue *q;
3151         struct localuser *u;
3152         struct member *m;
3153
3154         LOCAL_USER_ACF_ADD(u);
3155
3156         ast_copy_string(buf, "0", len);
3157         
3158         if (ast_strlen_zero(data)) {
3159                 ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
3160                 LOCAL_USER_REMOVE(u);
3161                 return buf;
3162         }
3163
3164         AST_LIST_LOCK(&queues);
3165
3166         /* Find the right queue */
3167         AST_LIST_TRAVERSE(&queues, q, list) {
3168                 if (!strcasecmp(q->name, data)) {
3169                         ast_mutex_lock(&q->lock);
3170                         break;
3171                 }
3172         }
3173
3174         AST_LIST_UNLOCK(&queues);
3175
3176         if (q) {
3177                 for (m = q->members; m; m = m->next) {
3178                         /* Count the agents who are logged in and presently answering calls */
3179                         if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
3180                                 count++;
3181                         }
3182                 }
3183                 ast_mutex_unlock(&q->lock);
3184         }
3185
3186         snprintf(buf, len, "%d", count);
3187         LOCAL_USER_REMOVE(u);
3188         return buf;
3189 }
3190
3191 static char *queue_function_queuememberlist(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
3192 {
3193         struct localuser *u;
3194         struct ast_call_queue *q;
3195         struct member *m;
3196
3197         /* Ensure an otherwise empty list doesn't return garbage */
3198         buf[0] = '\0';
3199
3200         if (!data || ast_strlen_zero(data)) {
3201                 ast_log(LOG_ERROR, "QUEUE_MEMBER_LIST requires an argument: queuename\n");
3202                 return buf;
3203         }
3204         
3205         LOCAL_USER_ACF_ADD(u);
3206
3207         AST_LIST_LOCK(&queues);
3208
3209         /* Find the right queue */
3210         AST_LIST_TRAVERSE(&queues, q, list) {
3211                 if (!strcasecmp(q->name, data)) {
3212                         ast_mutex_lock(&q->lock);
3213                         break;
3214                 }
3215         }
3216
3217         AST_LIST_UNLOCK(&queues);
3218
3219         if (q) {
3220                 int buflen = 0, count = 0;
3221                 for (m = q->members; m; m = m->next) {
3222                         /* strcat() is always faster than printf() */
3223                         if (count++) {
3224                                 strncat(buf + buflen, ",", len - buflen - 1);
3225                                 buflen++;
3226                         }
3227                         strncat(buf + buflen, m->interface, len - buflen - 1);
3228                         buflen += strlen(m->interface);
3229                         /* Safeguard against overflow (negative length) */
3230                         if (buflen >= len - 2) {
3231                                 ast_log(LOG_WARNING, "Truncating list\n");
3232                                 break;
3233                         }
3234                 }
3235                 ast_mutex_unlock(&q->lock);
3236         }
3237
3238         /* We should already be terminated, but let's make sure. */
3239         buf[len - 1] = '\0';
3240         LOCAL_USER_REMOVE(u);
3241         return buf;
3242 }
3243
3244 static struct ast_custom_function queueagentcount_function = {
3245         .name = "QUEUEAGENTCOUNT",
3246         .synopsis = "Count number of agents answering a queue",
3247         .syntax = "QUEUEAGENTCOUNT(<queuename>)",
3248         .desc =
3249 "Returns the number of members currently associated with the specified queue.\n"
3250 "This function is deprecated.  You should use QUEUE_MEMBER_COUNT() instead.\n",
3251         .read = queue_function_qac,
3252 };
3253
3254 static struct ast_custom_function queuemembercount_function = {
3255         .name = "QUEUE_MEMBER_COUNT",
3256         .synopsis = "Count number of members answering a queue",
3257         .syntax = "QUEUE_MEMBER_COUNT(<queuename>)",
3258         .desc =
3259 "Returns the number of members currently associated with the specified queue.\n",
3260         .read = queue_function_qac,
3261 };
3262
3263 static struct ast_custom_function queuememberlist_function = {
3264         .name = "QUEUE_MEMBER_LIST",
3265         .synopsis = "Returns a list of interfaces on a queue",
3266         .syntax = "QUEUE_MEMBER_LIST(<queuename>)",
3267         .desc =
3268 "Returns a comma-separated list of members associated with the specified queue.\n",
3269         .read = queue_function_queuememberlist,
3270 };
3271
3272 static void reload_queues(void)
3273 {
3274         struct ast_call_queue *q;
3275         struct ast_config *cfg;
3276         char *cat, *tmp;
3277         struct ast_variable *var;
3278         struct member *prev, *cur;
3279         int new;
3280         char *general_val = NULL;
3281         char interface[80];
3282         int penalty;
3283         
3284         cfg = ast_config_load("queues.conf");
3285         if (!cfg) {
3286                 ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
3287                 return;
3288         }
3289         memset(interface, 0, sizeof(interface));
3290         AST_LIST_LOCK(&queues);
3291         use_weight=0;
3292         /* Mark all queues as dead for the moment */
3293         AST_LIST_TRAVERSE(&queues, q, list) {
3294                 q->dead = 1;
3295         }
3296         /* Chug through config file */
3297         cat = ast_category_browse(cfg, NULL);
3298         while(cat) {
3299                 if (!strcasecmp(cat, "general")) {      
3300                         /* Initialize global settings */
3301                         queue_persistent_members = 0;
3302                         if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
3303                                 queue_persistent_members = ast_true(general_val);
3304                 } else {        /* Define queue */
3305                         /* Look for an existing one */
3306                         AST_LIST_TRAVERSE(&queues, q, list) {