don't duplicate devicestate-to-string function (issue #5078)
[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         time(&now);
1962                 
1963         for (; options && *options; options++)
1964                 switch (*options) {
1965                 case 't':
1966                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
1967                         break;
1968                 case 'T':
1969                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
1970                         break;
1971                 case 'd':
1972                         nondataquality = 0;
1973                         break;
1974                 case 'h':
1975                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
1976                         break;
1977                 case 'H':
1978                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
1979                         break;
1980                 case 'n':
1981                         if ((now - qe->start >= qe->parent->timeout))
1982                                 *go_on = 1;
1983                         break;
1984                 }
1985
1986         /* Hold the lock while we setup the outgoing calls */
1987         if (use_weight) 
1988                 ast_mutex_lock(&qlock);
1989         ast_mutex_lock(&qe->parent->lock);
1990         if (option_debug)
1991                 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n", 
1992                                                         qe->chan->name);
1993         ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
1994         cur = qe->parent->members;
1995         if (!ast_strlen_zero(qe->announce))
1996                 announce = qe->announce;
1997         if (announceoverride && !ast_strlen_zero(announceoverride))
1998                 announce = announceoverride;
1999
2000         while(cur) {
2001                 tmp = malloc(sizeof(*tmp));
2002                 if (!tmp) {
2003                         ast_mutex_unlock(&qe->parent->lock);
2004                         if (use_weight) 
2005                                 ast_mutex_unlock(&qlock);
2006                         ast_log(LOG_WARNING, "Out of memory\n");
2007                         goto out;
2008                 }
2009                 memset(tmp, 0, sizeof(*tmp));
2010                 tmp->stillgoing = -1;
2011                 if (option_debug) {
2012                         if (url)
2013                                 ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
2014                         else 
2015                                 ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
2016                 }
2017
2018                 tmp->member = cur;              /* Never directly dereference!  Could change on reload */
2019                 tmp->oldstatus = cur->status;
2020                 tmp->lastcall = cur->lastcall;
2021                 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
2022                 /* If we're dialing by extension, look at the extension to know what to dial */
2023                 if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
2024                         newnum++;
2025                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1);
2026                         snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit);
2027                         if (option_debug)
2028                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface);
2029                 }
2030                 /* Special case: If we ring everyone, go ahead and ring them, otherwise
2031                    just calculate their metric for the appropriate strategy */
2032                 calc_metric(qe->parent, cur, x++, qe, tmp);
2033                 /* Put them in the list of outgoing thingies...  We're ready now. 
2034                    XXX If we're forcibly removed, these outgoing calls won't get
2035                    hung up XXX */
2036                 tmp->next = outgoing;
2037                 outgoing = tmp;         
2038                 /* If this line is up, don't try anybody else */
2039                 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
2040                         break;
2041
2042                 cur = cur->next;
2043         }
2044         if (qe->parent->timeout)
2045                 to = qe->parent->timeout * 1000;
2046         else
2047                 to = -1;
2048         ring_one(qe, outgoing, &numbusies);
2049         ast_mutex_unlock(&qe->parent->lock);
2050         if (use_weight) 
2051                 ast_mutex_unlock(&qlock);
2052         lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
2053         ast_mutex_lock(&qe->parent->lock);
2054         if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
2055                 store_next(qe, outgoing);
2056         }
2057         ast_mutex_unlock(&qe->parent->lock);
2058         if (lpeer)
2059                 peer = lpeer->chan;
2060         else
2061                 peer = NULL;
2062         if (!peer) {
2063                 if (to) {
2064                         /* Musta gotten hung up */
2065                         record_abandoned(qe);
2066                         res = -1;
2067                 } else {
2068                         res = digit;
2069                 }
2070                 if (option_debug)
2071                         ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
2072                 goto out;
2073         }
2074         if (peer) {
2075                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
2076                    we will always return with -1 so that it is hung up properly after the 
2077                    conversation.  */
2078                 qe->handled++;
2079                 if (!strcmp(qe->chan->type,"Zap"))
2080                         ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2081                 if (!strcmp(peer->type,"Zap"))
2082                         ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2083                 /* Update parameters for the queue */
2084                 recalc_holdtime(qe);
2085                 member = lpeer->member;
2086                 hangupcalls(outgoing, peer);
2087                 outgoing = NULL;
2088                 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2089                         int res2;
2090                         res2 = ast_autoservice_start(qe->chan);
2091                         if (!res2) {
2092                                 if (qe->parent->memberdelay) {
2093                                         ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2094                                         res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2095                                 }
2096                                 if (!res2 && announce) {
2097                                         if (play_file(peer, announce))
2098                                                 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2099                                 }
2100                                 if (!res2 && qe->parent->reportholdtime) {
2101                                         if (!play_file(peer, qe->parent->sound_reporthold)) {
2102                                                 int holdtime;
2103
2104                                                 time(&now);
2105                                                 holdtime = abs((now - qe->start) / 60);
2106                                                 if (holdtime < 2) {
2107                                                         play_file(peer, qe->parent->sound_lessthan);
2108                                                         ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2109                                                 } else 
2110                                                         ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2111                                                 play_file(peer, qe->parent->sound_minutes);
2112                                         }
2113                                 }
2114                         }
2115                         res2 |= ast_autoservice_stop(qe->chan);
2116                         if (peer->_softhangup) {
2117                                 /* Agent must have hung up */
2118                                 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
2119                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
2120                                 record_abandoned(qe);
2121                                 if (qe->parent->eventwhencalled) {
2122                                         manager_event(EVENT_FLAG_AGENT, "AgentDump",
2123                                                       "Queue: %s\r\n"
2124                                                       "Uniqueid: %s\r\n"
2125                                                       "Channel: %s\r\n"
2126                                                       "Member: %s\r\n",
2127                                                       queuename, qe->chan->uniqueid, peer->name, member->interface);
2128                                 }
2129                                 ast_hangup(peer);
2130                                 goto out;
2131                         } else if (res2) {
2132                                 /* Caller must have hung up just before being connected*/
2133                                 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2134                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2135                                 record_abandoned(qe);
2136                                 ast_hangup(peer);
2137                                 return -1;
2138                         }
2139                 }
2140                 /* Stop music on hold */
2141                 ast_moh_stop(qe->chan);
2142                 /* If appropriate, log that we have a destination channel */
2143                 if (qe->chan->cdr)
2144                         ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2145                 /* Make sure channels are compatible */
2146                 res = ast_channel_make_compatible(qe->chan, peer);
2147                 if (res < 0) {
2148                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "SYSCOMPAT", "%s", "");
2149                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2150                         record_abandoned(qe);
2151                         ast_hangup(peer);
2152                         return -1;
2153                 }
2154                 /* Begin Monitoring */
2155                 if (qe->parent->monfmt && *qe->parent->monfmt) {
2156                         monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2157                         if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2158                                 which = qe->chan;
2159                         else
2160                                 which = peer;
2161                         if (monitorfilename)
2162                                 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2163                         else
2164                                 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2165                         if (qe->parent->monjoin)
2166                                 ast_monitor_setjoinfiles(which, 1);
2167                 }
2168                 /* Drop out of the queue at this point, to prepare for next caller */
2169                 leave_queue(qe);                        
2170                 if (url && !ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2171                         if (option_debug)
2172                                 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2173                         ast_channel_sendurl(peer, url);
2174                 }
2175                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
2176                 if (qe->parent->eventwhencalled)
2177                         manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2178                                       "Queue: %s\r\n"
2179                                       "Uniqueid: %s\r\n"
2180                                       "Channel: %s\r\n"
2181                                       "Member: %s\r\n"
2182                                       "Holdtime: %ld\r\n",
2183                                       queuename, qe->chan->uniqueid, peer->name, member->interface,
2184                                       (long)time(NULL) - qe->start);
2185                 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2186                 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2187                 time(&callstart);
2188
2189                 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2190
2191                 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2192                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
2193                 } else if (qe->chan->_softhangup) {
2194                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
2195                                       (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2196                         if (qe->parent->eventwhencalled)
2197                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2198                                               "Queue: %s\r\n"
2199                                               "Uniqueid: %s\r\n"
2200                                               "Channel: %s\r\n"
2201                                               "Member: %s\r\n"
2202                                               "HoldTime: %ld\r\n"
2203                                               "TalkTime: %ld\r\n"
2204                                               "Reason: caller\r\n",
2205                                               queuename, qe->chan->uniqueid, peer->name, member->interface,
2206                                               (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2207                 } else {
2208                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2209                         if (qe->parent->eventwhencalled)
2210                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2211                                               "Queue: %s\r\n"
2212                                               "Uniqueid: %s\r\n"
2213                                               "Channel: %s\r\n"
2214                                               "HoldTime: %ld\r\n"
2215                                               "TalkTime: %ld\r\n"
2216                                               "Reason: agent\r\n",
2217                                               queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start),
2218                                               (long)(time(NULL) - callstart));
2219                 }
2220
2221                 if(bridge != AST_PBX_NO_HANGUP_PEER)
2222                         ast_hangup(peer);
2223                 update_queue(qe->parent, member);
2224                 if (bridge == 0) 
2225                         res = 1; /* JDG: bridge successfull, leave app_queue */
2226                 else 
2227                         res = bridge; /* bridge error, stay in the queue */
2228         }       
2229 out:
2230         hangupcalls(outgoing, NULL);
2231         return res;
2232 }
2233
2234 static int wait_a_bit(struct queue_ent *qe)
2235 {
2236         /* Don't need to hold the lock while we setup the outgoing calls */
2237         int retrywait = qe->parent->retry * 1000;
2238
2239         return ast_waitfordigit(qe->chan, retrywait);
2240 }
2241
2242 static struct member * interface_exists(struct ast_call_queue *q, char *interface)
2243 {
2244         struct member *mem;
2245
2246         if (q)
2247                 for (mem = q->members; mem; mem = mem->next)
2248                         if (!strcasecmp(interface, mem->interface))
2249                                 return mem;
2250
2251         return NULL;
2252 }
2253
2254
2255 /* Dump all members in a specific queue to the databse
2256  *
2257  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2258  *
2259  */
2260 static void dump_queue_members(struct ast_call_queue *pm_queue)
2261 {
2262         struct member *cur_member;
2263         char value[PM_MAX_LEN];
2264         int value_len = 0;
2265         int res;
2266
2267         memset(value, 0, sizeof(value));
2268
2269         if (!pm_queue)
2270                 return;
2271
2272         for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2273                 if (!cur_member->dynamic)
2274                         continue;
2275
2276                 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d%s",
2277                                cur_member->interface, cur_member->penalty, cur_member->paused,
2278                                cur_member->next ? "|" : "");
2279                 if (res != strlen(value + value_len)) {
2280                         ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2281                         break;
2282                 }
2283                 value_len += res;
2284         }
2285         
2286         if (value_len && !cur_member) {
2287                 if (ast_db_put(pm_family, pm_queue->name, value))
2288                         ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2289         } else
2290                 /* Delete the entry if the queue is empty or there is an error */
2291                 ast_db_del(pm_family, pm_queue->name);
2292 }
2293
2294 static int remove_from_queue(char *queuename, char *interface)
2295 {
2296         struct ast_call_queue *q;
2297         struct member *last_member, *look;
2298         int res = RES_NOSUCHQUEUE;
2299
2300         ast_mutex_lock(&qlock);
2301         for (q = queues ; q ; q = q->next) {
2302                 ast_mutex_lock(&q->lock);
2303                 if (!strcmp(q->name, queuename)) {
2304                         if ((last_member = interface_exists(q, interface))) {
2305                                 if ((look = q->members) == last_member) {
2306                                         q->members = last_member->next;
2307                                 } else {
2308                                         while (look != NULL) {
2309                                                 if (look->next == last_member) {
2310                                                         look->next = last_member->next;
2311                                                         break;
2312                                                 } else {
2313                                                          look = look->next;
2314                                                 }
2315                                         }
2316                                 }
2317                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
2318                                                 "Queue: %s\r\n"
2319                                                 "Location: %s\r\n",
2320                                         q->name, last_member->interface);
2321                                 free(last_member);
2322
2323                                 if (queue_persistent_members)
2324                                     dump_queue_members(q);
2325
2326                                 res = RES_OKAY;
2327                         } else {
2328                                 res = RES_EXISTS;
2329                         }
2330                         ast_mutex_unlock(&q->lock);
2331                         break;
2332                 }
2333                 ast_mutex_unlock(&q->lock);
2334         }
2335         ast_mutex_unlock(&qlock);
2336         return res;
2337 }
2338
2339 static int add_to_queue(char *queuename, char *interface, int penalty, int paused, int dump)
2340 {
2341         struct ast_call_queue *q;
2342         struct member *new_member;
2343         int res = RES_NOSUCHQUEUE;
2344
2345         ast_mutex_lock(&qlock);
2346         for (q = queues ; q ; q = q->next) {
2347                 ast_mutex_lock(&q->lock);
2348                 if (!strcmp(q->name, queuename)) {
2349                         if (interface_exists(q, interface) == NULL) {
2350                                 new_member = create_queue_member(interface, penalty, paused);
2351
2352                                 if (new_member != NULL) {
2353                                         new_member->dynamic = 1;
2354                                         new_member->next = q->members;
2355                                         q->members = new_member;
2356                                         manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
2357                                                 "Queue: %s\r\n"
2358                                                 "Location: %s\r\n"
2359                                                 "Membership: %s\r\n"
2360                                                 "Penalty: %d\r\n"
2361                                                 "CallsTaken: %d\r\n"
2362                                                 "LastCall: %ld\r\n"
2363                                                 "Status: %d\r\n"
2364                                                 "Paused: %d\r\n",
2365                                         q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
2366                                         new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused);
2367                                         
2368                                         if (dump)
2369                                                 dump_queue_members(q);
2370
2371                                         res = RES_OKAY;
2372                                 } else {
2373                                         res = RES_OUTOFMEMORY;
2374                                 }
2375                         } else {
2376                                 res = RES_EXISTS;
2377                         }
2378                         ast_mutex_unlock(&q->lock);
2379                         break;
2380                 }
2381                 ast_mutex_unlock(&q->lock);
2382         }
2383         ast_mutex_unlock(&qlock);
2384         return res;
2385 }
2386
2387 static int set_member_paused(char *queuename, char *interface, int paused)
2388 {
2389         int found = 0;
2390         struct ast_call_queue *q;
2391         struct member *mem;
2392
2393         /* Special event for when all queues are paused - individual events still generated */
2394
2395         if (ast_strlen_zero(queuename))
2396                 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
2397
2398         ast_mutex_lock(&qlock);
2399         for (q = queues ; q ; q = q->next) {
2400                 ast_mutex_lock(&q->lock);
2401                 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
2402                         if ((mem = interface_exists(q, interface))) {
2403                                 found++;
2404                                 if (mem->paused == paused)
2405                                         ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
2406                                 mem->paused = paused;
2407
2408                                 if (queue_persistent_members)
2409                                     dump_queue_members(q);
2410
2411                                 ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
2412
2413                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
2414                                         "Queue: %s\r\n"
2415                                         "Location: %s\r\n"
2416                                         "Paused: %d\r\n",
2417                                                 q->name, mem->interface, paused);
2418                         }
2419                 }
2420                 ast_mutex_unlock(&q->lock);
2421         }
2422         ast_mutex_unlock(&qlock);
2423
2424         if (found)
2425                 return RESULT_SUCCESS;
2426         else
2427                 return RESULT_FAILURE;
2428 }
2429
2430 /* Reload dynamic queue members persisted into the astdb */
2431 static void reload_queue_members(void)
2432 {
2433         char *cur_ptr;  
2434         char *queue_name;
2435         char *member;
2436         char *interface;
2437         char *penalty_tok;
2438         int penalty = 0;
2439         char *paused_tok;
2440         int paused = 0;
2441         struct ast_db_entry *db_tree;
2442         struct ast_db_entry *entry;
2443         struct ast_call_queue *cur_queue;
2444         char queue_data[PM_MAX_LEN];
2445
2446         ast_mutex_lock(&qlock);
2447
2448         /* Each key in 'pm_family' is the name of a queue */
2449         db_tree = ast_db_gettree(pm_family, NULL);
2450         for (entry = db_tree; entry; entry = entry->next) {
2451
2452                 queue_name = entry->key + strlen(pm_family) + 2;
2453
2454                 cur_queue = queues;
2455                 while (cur_queue) {
2456                         ast_mutex_lock(&cur_queue->lock);
2457                         if (!strcmp(queue_name, cur_queue->name))
2458                                 break;
2459                         ast_mutex_unlock(&cur_queue->lock);
2460                         cur_queue = cur_queue->next;
2461                 }
2462
2463                 if (!cur_queue) {
2464                         /* If the queue no longer exists, remove it from the
2465                          * database */
2466                         ast_db_del(pm_family, queue_name);
2467                         continue;
2468                 } else
2469                         ast_mutex_unlock(&cur_queue->lock);
2470
2471                 if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
2472                         continue;
2473
2474                 cur_ptr = queue_data;
2475                 while ((member = strsep(&cur_ptr, "|"))) {
2476                         if (ast_strlen_zero(member))
2477                                 continue;
2478
2479                         interface = strsep(&member, ";");
2480                         penalty_tok = strsep(&member, ";");
2481                         paused_tok = strsep(&member, ";");
2482
2483                         if (!penalty_tok) {
2484                                 ast_log(LOG_WARNING, "Error parsing persisent member string for '%s' (penalty)\n", queue_name);
2485                                 break;
2486                         }
2487                         penalty = strtol(penalty_tok, NULL, 10);
2488                         if (errno == ERANGE) {
2489                                 ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
2490                                 break;
2491                         }
2492                         
2493                         if (!paused_tok) {
2494                                 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
2495                                 break;
2496                         }
2497                         paused = strtol(paused_tok, NULL, 10);
2498                         if ((errno == ERANGE) || paused < 0 || paused > 1) {
2499                                 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
2500                                 break;
2501                         }
2502
2503                         if (option_debug)
2504                                 ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Penalty: %d  Paused: %d\n", queue_name, interface, penalty, paused);
2505                         
2506                         if (add_to_queue(queue_name, interface, penalty, paused, 0) == RES_OUTOFMEMORY) {
2507                                 ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
2508                                 break;
2509                         }
2510                 }
2511         }
2512
2513         ast_mutex_unlock(&qlock);
2514         if (db_tree) {
2515                 ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
2516                 ast_db_freetree(db_tree);
2517         }
2518 }
2519
2520 static int pqm_exec(struct ast_channel *chan, void *data)
2521 {
2522         struct localuser *u;
2523         char *queuename, *interface;
2524
2525         if (!data) {
2526                 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface])\n");
2527                 return -1;
2528         }
2529
2530         queuename = ast_strdupa((char *)data);
2531         if (!queuename) {
2532                 ast_log(LOG_ERROR, "Out of memory\n");
2533                 return -1;
2534         }
2535
2536         interface = strchr(queuename, '|');
2537         if (!interface) {
2538                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2539                 return -1;
2540         }
2541
2542         LOCAL_USER_ADD(u);
2543
2544         *interface = '\0';
2545         interface++;
2546
2547         if (set_member_paused(queuename, interface, 1)) {
2548                 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", interface);
2549                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2550                         chan->priority += 100;
2551                         LOCAL_USER_REMOVE(u);
2552                         return 0;
2553                 }
2554                 return -1;
2555         }
2556
2557         LOCAL_USER_REMOVE(u);
2558
2559         return 0;
2560 }
2561
2562 static int upqm_exec(struct ast_channel *chan, void *data)
2563 {
2564         struct localuser *u;
2565         char *queuename, *interface;
2566
2567         if (!data) {
2568                 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface])\n");
2569                 return -1;
2570         }
2571
2572         queuename = ast_strdupa((char *)data);
2573         if (!queuename) {
2574                 ast_log(LOG_ERROR, "Out of memory\n");
2575                 return -1;
2576         }
2577
2578         interface = strchr(queuename, '|');
2579         if (!interface) {
2580                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2581                 return -1;
2582         }
2583
2584         LOCAL_USER_ADD(u);
2585
2586         *interface = '\0';
2587         interface++;
2588
2589         if (set_member_paused(queuename, interface, 0)) {
2590                 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", interface);
2591                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2592                         chan->priority += 100;
2593                         LOCAL_USER_REMOVE(u);
2594                         return 0;
2595                 }
2596                 return -1;
2597         }
2598
2599         LOCAL_USER_REMOVE(u);
2600
2601         return 0;
2602 }
2603
2604 static int rqm_exec(struct ast_channel *chan, void *data)
2605 {
2606         int res=-1;
2607         struct localuser *u;
2608         char *info, *queuename;
2609         char tmpchan[256]="";
2610         char *interface = NULL;
2611
2612         if (!data) {
2613                 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface])\n");
2614                 return -1;
2615         }
2616
2617         info = ast_strdupa((char *)data);
2618         if (!info) {
2619                 ast_log(LOG_ERROR, "Out of memory\n");
2620                 return -1;
2621         }
2622
2623         LOCAL_USER_ADD(u);
2624
2625         queuename = info;
2626         if (queuename) {
2627                 interface = strchr(queuename, '|');
2628                 if (interface) {
2629                         *interface = '\0';
2630                         interface++;
2631                 }
2632                 else {
2633                         ast_copy_string(tmpchan, chan->name, sizeof(tmpchan));
2634                         interface = strrchr(tmpchan, '-');
2635                         if (interface)
2636                                 *interface = '\0';
2637                         interface = tmpchan;
2638                 }
2639         }
2640
2641         switch (remove_from_queue(queuename, interface)) {
2642         case RES_OKAY:
2643                 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", interface, queuename);
2644                 res = 0;
2645                 break;
2646         case RES_EXISTS:
2647                 ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
2648                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2649                         chan->priority += 100;
2650                 }
2651                 res = 0;
2652                 break;
2653         case RES_NOSUCHQUEUE:
2654                 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", queuename);
2655                 res = 0;
2656                 break;
2657         case RES_OUTOFMEMORY:
2658                 ast_log(LOG_ERROR, "Out of memory\n");
2659                 break;
2660         }
2661
2662         LOCAL_USER_REMOVE(u);
2663         return res;
2664 }
2665
2666 static int aqm_exec(struct ast_channel *chan, void *data)
2667 {
2668         int res=-1;
2669         struct localuser *u;
2670         char *queuename;
2671         char *info;
2672         char tmpchan[512]="";
2673         char *interface=NULL;
2674         char *penaltys=NULL;
2675         int penalty = 0;
2676
2677         if (!data) {
2678                 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface][|penalty]])\n");
2679                 return -1;
2680         }
2681
2682         info = ast_strdupa((char *)data);
2683         if (!info) {
2684                 ast_log(LOG_ERROR, "Out of memory\n");
2685                 return -1;
2686         }
2687         LOCAL_USER_ADD(u);
2688
2689         queuename = info;
2690         if (queuename) {
2691                 interface = strchr(queuename, '|');
2692                 if (interface) {
2693                         *interface = '\0';
2694                         interface++;
2695                 }
2696                 if (interface) {
2697                         penaltys = strchr(interface, '|');
2698                         if (penaltys) {
2699                                 *penaltys = '\0';
2700                                 penaltys++;
2701                         }
2702                 }
2703                 if (!interface || ast_strlen_zero(interface)) {
2704                         ast_copy_string(tmpchan, chan->name, sizeof(tmpchan));
2705                         interface = strrchr(tmpchan, '-');
2706                         if (interface)
2707                                 *interface = '\0';
2708                         interface = tmpchan;
2709                 }
2710                 if (penaltys && !ast_strlen_zero(penaltys)) {
2711                         if ((sscanf(penaltys, "%d", &penalty) != 1) || penalty < 0) {
2712                                 ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", penaltys);
2713                                 penalty = 0;
2714                         }
2715                 }
2716         }
2717
2718         switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
2719         case RES_OKAY:
2720                 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
2721                 res = 0;
2722                 break;
2723         case RES_EXISTS:
2724                 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
2725                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2726                         chan->priority += 100;
2727                 }
2728                 res = 0;
2729                 break;
2730         case RES_NOSUCHQUEUE:
2731                 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", queuename);
2732                 res = 0;
2733                 break;
2734         case RES_OUTOFMEMORY:
2735                 ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", interface, queuename);
2736                 break;
2737         }
2738
2739         LOCAL_USER_REMOVE(u);
2740         return res;
2741 }
2742
2743 static int queue_exec(struct ast_channel *chan, void *data)
2744 {
2745         int res=-1;
2746         int ringing=0;
2747         struct localuser *u;
2748         char *queuename;
2749         char info[512];
2750         char *info_ptr = info;
2751         char *options = NULL;
2752         char *url = NULL;
2753         char *announceoverride = NULL;
2754         char *user_priority;
2755         int prio;
2756         char *queuetimeoutstr = NULL;
2757         enum queue_result reason = QUEUE_UNKNOWN;
2758
2759         /* whether to exit Queue application after the timeout hits */
2760         int go_on = 0;
2761
2762         /* Our queue entry */
2763         struct queue_ent qe;
2764         
2765         if (!data || ast_strlen_zero(data)) {
2766                 ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n");
2767                 return -1;
2768         }
2769         
2770         LOCAL_USER_ADD(u);
2771
2772         /* Setup our queue entry */
2773         memset(&qe, 0, sizeof(qe));
2774         qe.start = time(NULL);
2775         
2776         /* Parse our arguments XXX Check for failure XXX */
2777         ast_copy_string(info, (char *) data, sizeof(info));
2778         queuename = strsep(&info_ptr, "|");
2779         options = strsep(&info_ptr, "|");
2780         url = strsep(&info_ptr, "|");
2781         announceoverride = strsep(&info_ptr, "|");
2782         queuetimeoutstr = info_ptr;
2783
2784         /* set the expire time based on the supplied timeout; */
2785         if (queuetimeoutstr)
2786                 qe.expire = qe.start + atoi(queuetimeoutstr);
2787         else
2788                 qe.expire = 0;
2789
2790         /* Get the priority from the variable ${QUEUE_PRIO} */
2791         user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
2792         if (user_priority) {
2793                 if (sscanf(user_priority, "%d", &prio) == 1) {
2794                         if (option_debug)
2795                                 ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
2796                                         chan->name, prio);
2797                 } else {
2798                         ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
2799                                 user_priority, chan->name);
2800                         prio = 0;
2801                 }
2802         } else {
2803                 if (option_debug > 2)
2804                         ast_log(LOG_DEBUG, "NO QUEUE_PRIO variable found. Using default.\n");
2805                 prio = 0;
2806         }
2807
2808         if (options && (strchr(options, 'r')))
2809                 ringing = 1;
2810
2811         if (option_debug)  
2812                 ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
2813                         queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
2814
2815         qe.chan = chan;
2816         qe.prio = (int)prio;
2817         qe.last_pos_said = 0;
2818         qe.last_pos = 0;
2819         qe.last_periodic_announce_time = time(NULL);
2820         if (!join_queue(queuename, &qe, &reason)) {
2821                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "",
2822                               chan->cid.cid_num ? chan->cid.cid_num : "");
2823 check_turns:
2824                 if (ringing) {
2825                         ast_indicate(chan, AST_CONTROL_RINGING);
2826                 } else {              
2827                         ast_moh_start(chan, qe.moh);
2828                 }
2829                 for (;;) {
2830                         /* This is the wait loop for callers 2 through maxlen */
2831
2832                         res = wait_our_turn(&qe, ringing, &reason);
2833                         /* If they hungup, return immediately */
2834                         if (res < 0) {
2835                                 /* Record this abandoned call */
2836                                 record_abandoned(&qe);
2837                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2838                                 if (option_verbose > 2) {
2839                                         ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", queuename);
2840                                         res = -1;
2841                                 }
2842                                 break;
2843                         }
2844                         if (!res) 
2845                                 break;
2846                         if (valid_exit(&qe, res)) {
2847                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
2848                                 break;
2849                         }
2850                 }
2851                 if (!res) {
2852                         int makeannouncement = 0;
2853                         for (;;) {
2854                                 /* This is the wait loop for the head caller*/
2855                                 /* To exit, they may get their call answered; */
2856                                 /* they may dial a digit from the queue context; */
2857                                 /* or, they may timeout. */
2858
2859                                 enum queue_member_status stat;
2860
2861                                 /* Leave if we have exceeded our queuetimeout */
2862                                 if (qe.expire && (time(NULL) > qe.expire)) {
2863                                         record_abandoned(&qe);
2864                                         reason = QUEUE_TIMEOUT;
2865                                         res = 0;
2866                                         break;
2867                                 }
2868
2869                                 if (makeannouncement) {
2870                                         /* Make a position announcement, if enabled */
2871                                         if (qe.parent->announcefrequency && !ringing)
2872                                                 res = say_position(&qe);
2873                                         if (res && valid_exit(&qe, res)) {
2874                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos);
2875                                                 break;
2876                                         }
2877
2878                                 }
2879                                 makeannouncement = 1;
2880
2881                                 /* Make a periodic announcement, if enabled */
2882                                 if (qe.parent->periodicannouncefrequency && !ringing)
2883                                         res = say_periodic_announcement(&qe);
2884
2885                                 if (res && valid_exit(&qe, res)) {
2886                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2887                                         break;
2888                                 }
2889
2890                                 /* Try calling all queue members for 'timeout' seconds */
2891                                 res = try_calling(&qe, options, announceoverride, url, &go_on);
2892                                 if (res) {
2893                                         if (res < 0) {
2894                                                 if (!qe.handled) {
2895                                                         record_abandoned(&qe);
2896                                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2897                                                 }
2898                                        &