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