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