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