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