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