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