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