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