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