ensure that abandoned calls are recorded that way (bug #4644)
[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         q->callscompleted++;
1208         ast_mutex_unlock(&q->lock);
1209         return 0;
1210 }
1211
1212 static int update_dial_status(struct ast_call_queue *q, struct member *member, int status)
1213 {
1214         if (status == AST_CAUSE_BUSY)
1215                 status = AST_DEVICE_BUSY;
1216         else if (status == AST_CAUSE_UNREGISTERED)
1217                 status = AST_DEVICE_UNAVAILABLE;
1218         else if (status == AST_CAUSE_NOSUCHDRIVER)
1219                 status = AST_DEVICE_INVALID;
1220         else
1221                 status = AST_DEVICE_UNKNOWN;
1222         return update_status(q, member, status);
1223 }
1224
1225 /* traverse all defined queues which have calls waiting and contain this member
1226    return 0 if no other queue has precedence (higher weight) or 1 if found  */
1227 static int compare_weight(struct ast_call_queue *rq, struct member *member)
1228 {
1229         struct ast_call_queue *q;
1230         struct member *mem;
1231         int found = 0;
1232         
1233         /* &qlock and &rq->lock already set by try_calling()
1234          * to solve deadlock */
1235         for (q = queues; q; q = q->next) {
1236                 if (q == rq) /* don't check myself, could deadlock */
1237                         continue; 
1238                 ast_mutex_lock(&q->lock);
1239                 if (q->count && q->members) {
1240                         for (mem = q->members; mem; mem = mem->next) {
1241                                 if (mem == member) {
1242                                         ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
1243                                         if (q->weight > rq->weight) {
1244                                                 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);
1245                                                 found = 1;
1246                                                 break;
1247                                         }
1248                                 }
1249                         }
1250                 }
1251                 ast_mutex_unlock(&q->lock);
1252                 if (found) 
1253                         break;
1254         }
1255         ast_mutex_unlock(&qlock);
1256         return found;
1257 }
1258
1259 static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
1260 {
1261         int res;
1262         int status;
1263         char tech[256];
1264         char *location;
1265
1266         if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
1267                 if (option_debug)
1268                         ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
1269                 if (qe->chan->cdr)
1270                         ast_cdr_busy(qe->chan->cdr);
1271                 tmp->stillgoing = 0;
1272                 (*busies)++;
1273                 return 0;
1274         }
1275         
1276         if (tmp->member->paused) {
1277                 if (option_debug)
1278                         ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
1279                 if (qe->chan->cdr)
1280                         ast_cdr_busy(qe->chan->cdr);
1281                 tmp->stillgoing = 0;
1282                 return 0;
1283         }
1284         if (use_weight && compare_weight(qe->parent,tmp->member)) {
1285                 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
1286                 if (qe->chan->cdr)
1287                         ast_cdr_busy(qe->chan->cdr);
1288                 tmp->stillgoing = 0;
1289                 (*busies)++;
1290                 return 0;
1291         }
1292
1293         ast_copy_string(tech, tmp->interface, sizeof(tech));
1294         if ((location = strchr(tech, '/')))
1295                 *location++ = '\0';
1296         else
1297                 location = "";
1298
1299         /* Request the peer */
1300         tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
1301         if (!tmp->chan) {                       /* If we can't, just go on to the next call */
1302 #if 0
1303                 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
1304 #endif                  
1305                 if (qe->chan->cdr)
1306                         ast_cdr_busy(qe->chan->cdr);
1307                 tmp->stillgoing = 0;
1308                 update_dial_status(qe->parent, tmp->member, status);
1309                 (*busies)++;
1310                 return 0;
1311         } else if (status != tmp->oldstatus) 
1312                 update_dial_status(qe->parent, tmp->member, status);
1313         
1314         tmp->chan->appl = "AppQueue";
1315         tmp->chan->data = "(Outgoing Line)";
1316         tmp->chan->whentohangup = 0;
1317         if (tmp->chan->cid.cid_num)
1318                 free(tmp->chan->cid.cid_num);
1319         tmp->chan->cid.cid_num = NULL;
1320         if (tmp->chan->cid.cid_name)
1321                 free(tmp->chan->cid.cid_name);
1322         tmp->chan->cid.cid_name = NULL;
1323         if (tmp->chan->cid.cid_ani)
1324                 free(tmp->chan->cid.cid_ani);
1325         tmp->chan->cid.cid_ani = NULL;
1326         if (qe->chan->cid.cid_num)
1327                 tmp->chan->cid.cid_num = strdup(qe->chan->cid.cid_num);
1328         if (qe->chan->cid.cid_name)
1329                 tmp->chan->cid.cid_name = strdup(qe->chan->cid.cid_name);
1330         if (qe->chan->cid.cid_ani)
1331                 tmp->chan->cid.cid_ani = strdup(qe->chan->cid.cid_ani);
1332
1333         /* Inherit specially named variables from parent channel */
1334         ast_channel_inherit_variables(qe->chan, tmp->chan);
1335
1336         /* Presense of ADSI CPE on outgoing channel follows ours */
1337         tmp->chan->adsicpe = qe->chan->adsicpe;
1338
1339         /* Place the call, but don't wait on the answer */
1340         res = ast_call(tmp->chan, location, 0);
1341         if (res) {
1342                 /* Again, keep going even if there's an error */
1343                 if (option_debug)
1344                         ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1345                 else if (option_verbose > 2)
1346                         ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
1347                 ast_hangup(tmp->chan);
1348                 tmp->chan = NULL;
1349                 tmp->stillgoing = 0;
1350                 (*busies)++;
1351                 return 0;
1352         } else {
1353                 if (qe->parent->eventwhencalled) {
1354                         manager_event(EVENT_FLAG_AGENT, "AgentCalled",
1355                                                 "AgentCalled: %s\r\n"
1356                                                 "ChannelCalling: %s\r\n"
1357                                                 "CallerID: %s\r\n"
1358                                                 "CallerIDName: %s\r\n"
1359                                                 "Context: %s\r\n"
1360                                                 "Extension: %s\r\n"
1361                                                 "Priority: %d\r\n",
1362                                                 tmp->interface, qe->chan->name,
1363                                                 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
1364                                                 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
1365                                                 qe->chan->context, qe->chan->exten, qe->chan->priority);
1366                 }
1367                 if (option_verbose > 2)
1368                         ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
1369         }
1370         return 1;
1371 }
1372
1373 static int ring_one(struct queue_ent *qe, struct localuser *outgoing, int *busies)
1374 {
1375         struct localuser *cur;
1376         struct localuser *best;
1377         int bestmetric=0;
1378
1379         do {
1380                 best = NULL;
1381                 cur = outgoing;
1382                 while(cur) {
1383                         if (cur->stillgoing &&                                  /* Not already done */
1384                                 !cur->chan &&                                   /* Isn't already going */
1385                                 (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
1386                                         bestmetric = cur->metric;
1387                                         best = cur;
1388                         }
1389                         cur = cur->next;
1390                 }
1391                 if (best) {
1392                         if (!qe->parent->strategy) {
1393                                 /* Ring everyone who shares this best metric (for ringall) */
1394                                 cur = outgoing;
1395                                 while(cur) {
1396                                         if (cur->stillgoing && !cur->chan && (cur->metric <= bestmetric)) {
1397                                                 if (option_debug)
1398                                                         ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
1399                                                 ring_entry(qe, cur, busies);
1400                                         }
1401                                         cur = cur->next;
1402                                 }
1403                         } else {
1404                                 /* Ring just the best channel */
1405                                 if (option_debug)
1406                                         ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
1407                                 ring_entry(qe, best, busies);
1408                         }
1409                 }
1410         } while (best && !best->chan);
1411         if (!best) {
1412                 if (option_debug)
1413                         ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
1414                 return 0;
1415         }
1416         return 1;
1417 }
1418
1419 static int store_next(struct queue_ent *qe, struct localuser *outgoing)
1420 {
1421         struct localuser *cur;
1422         struct localuser *best;
1423         int bestmetric=0;
1424
1425         best = NULL;
1426         cur = outgoing;
1427         while(cur) {
1428                 if (cur->stillgoing &&                                  /* Not already done */
1429                         !cur->chan &&                                   /* Isn't already going */
1430                         (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
1431                                 bestmetric = cur->metric;
1432                                 best = cur;
1433                 }
1434                 cur = cur->next;
1435         }
1436         if (best) {
1437                 /* Ring just the best channel */
1438                 if (option_debug)
1439                         ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
1440                 qe->parent->rrpos = best->metric % 1000;
1441         } else {
1442                 /* Just increment rrpos */
1443                 if (qe->parent->wrapped) {
1444                         /* No more channels, start over */
1445                         qe->parent->rrpos = 0;
1446                 } else {
1447                         /* Prioritize next entry */
1448                         qe->parent->rrpos++;
1449                 }
1450         }
1451         qe->parent->wrapped = 0;
1452         return 0;
1453 }
1454
1455 #define AST_MAX_WATCHERS 256
1456
1457 #define BUILD_WATCHERS do { \
1458                 o = outgoing; \
1459                 found = -1; \
1460                 pos = 1; \
1461                 numlines = 0; \
1462                 watchers[0] = in; \
1463                 while(o) { \
1464                         /* Keep track of important channels */ \
1465                         if (o->stillgoing) { \
1466                                 stillgoing = 1; \
1467                                 if (o->chan) { \
1468                                         watchers[pos++] = o->chan; \
1469                                         found = 1; \
1470                                 } \
1471                         } \
1472                         o = o->next; \
1473                         numlines++; \
1474                 } \
1475         } while(0)
1476         
1477 static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, char *digit, int prebusies, int caller_disconnect)
1478 {
1479         char *queue = qe->parent->name;
1480         struct localuser *o;
1481         int found;
1482         int numlines;
1483         int status;
1484         int sentringing = 0;
1485         int numbusies = prebusies;
1486         int numnochan = 0;
1487         int stillgoing = 0;
1488         int orig = *to;
1489         struct ast_frame *f;
1490         struct localuser *peer = NULL;
1491         struct ast_channel *watchers[AST_MAX_WATCHERS];
1492         int pos;
1493         struct ast_channel *winner;
1494         struct ast_channel *in = qe->chan;
1495         
1496         while(*to && !peer) {
1497                 BUILD_WATCHERS;
1498                 if ((found < 0) && stillgoing && !qe->parent->strategy) {
1499                         /* On "ringall" strategy we only move to the next penalty level
1500                            when *all* ringing phones are done in the current penalty level */
1501                         ring_one(qe, outgoing, &numbusies);
1502                         BUILD_WATCHERS;
1503                 }
1504                 if (found < 0) {
1505                         if (numlines == (numbusies + numnochan)) {
1506                                 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1507                         } else {
1508                                 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1509                         }
1510                         *to = 0;
1511                         return NULL;
1512                 }
1513                 winner = ast_waitfor_n(watchers, pos, to);
1514                 o = outgoing;
1515                 while(o) {
1516                         if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
1517                                 if (!peer) {
1518                                         if (option_verbose > 2)
1519                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1520                                         peer = o;
1521                                 }
1522                         } else if (o->chan && (o->chan == winner)) {
1523                                 if (!ast_strlen_zero(o->chan->call_forward)) {
1524                                         char tmpchan[256]="";
1525                                         char *stuff;
1526                                         char *tech;
1527                                         ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
1528                                         if ((stuff = strchr(tmpchan, '/'))) {
1529                                                 *stuff = '\0';
1530                                                 stuff++;
1531                                                 tech = tmpchan;
1532                                         } else {
1533                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1534                                                 stuff = tmpchan;
1535                                                 tech = "Local";
1536                                         }
1537                                         /* Before processing channel, go ahead and check for forwarding */
1538                                         if (option_verbose > 2)
1539                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1540                                         /* Setup parameters */
1541                                         o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1542                                         if (status != o->oldstatus) 
1543                                                 update_dial_status(qe->parent, o->member, status);                                              
1544                                         if (!o->chan) {
1545                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
1546                                                 o->stillgoing = 0;
1547                                                 numnochan++;
1548                                         } else {
1549                                                 if (o->chan->cid.cid_num)
1550                                                         free(o->chan->cid.cid_num);
1551                                                 o->chan->cid.cid_num = NULL;
1552                                                 if (o->chan->cid.cid_name)
1553                                                         free(o->chan->cid.cid_name);
1554                                                 o->chan->cid.cid_name = NULL;
1555
1556                                                 if (in->cid.cid_num) {
1557                                                         o->chan->cid.cid_num = strdup(in->cid.cid_num);
1558                                                         if (!o->chan->cid.cid_num)
1559                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1560                                                 }
1561                                                 if (in->cid.cid_name) {
1562                                                         o->chan->cid.cid_name = strdup(in->cid.cid_name);
1563                                                         if (!o->chan->cid.cid_name)
1564                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1565                                                 }
1566                                                 ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode));
1567                                                 o->chan->cdrflags = in->cdrflags;
1568
1569                                                 if (in->cid.cid_ani) {
1570                                                         if (o->chan->cid.cid_ani)
1571                                                                 free(o->chan->cid.cid_ani);
1572                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
1573                                                         if (o->chan->cid.cid_ani)
1574                                                                 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
1575                                                         else
1576                                                                 ast_log(LOG_WARNING, "Out of memory\n");
1577                                                 }
1578                                                 if (o->chan->cid.cid_rdnis) 
1579                                                         free(o->chan->cid.cid_rdnis);
1580                                                 if (!ast_strlen_zero(in->macroexten))
1581                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
1582                                                 else
1583                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
1584                                                 if (ast_call(o->chan, tmpchan, 0)) {
1585                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
1586                                                         o->stillgoing = 0;
1587                                                         ast_hangup(o->chan);
1588                                                         o->chan = NULL;
1589                                                         numnochan++;
1590                                                 }
1591                                         }
1592                                         /* Hangup the original channel now, in case we needed it */
1593                                         ast_hangup(winner);
1594                                         continue;
1595                                 }
1596                                 f = ast_read(winner);
1597                                 if (f) {
1598                                         if (f->frametype == AST_FRAME_CONTROL) {
1599                                                 switch(f->subclass) {
1600                                         case AST_CONTROL_ANSWER:
1601                                                         /* This is our guy if someone answered. */
1602                                                         if (!peer) {
1603                                                                 if (option_verbose > 2)
1604                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1605                                                                 peer = o;
1606                                                         }
1607                                                         break;
1608                                                 case AST_CONTROL_BUSY:
1609                                                         if (option_verbose > 2)
1610                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
1611                                                         o->stillgoing = 0;
1612                                                         if (in->cdr)
1613                                                                 ast_cdr_busy(in->cdr);
1614                                                         ast_hangup(o->chan);
1615                                                         o->chan = NULL;
1616                                                         if (qe->parent->strategy) {
1617                                                                 if (qe->parent->timeoutrestart)
1618                                                                         *to = orig;
1619                                                                 ring_one(qe, outgoing, &numbusies);
1620                                                         }
1621                                                         numbusies++;
1622                                                         break;
1623                                                 case AST_CONTROL_CONGESTION:
1624                                                         if (option_verbose > 2)
1625                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
1626                                                         o->stillgoing = 0;
1627                                                         if (in->cdr)
1628                                                                 ast_cdr_busy(in->cdr);
1629                                                         ast_hangup(o->chan);
1630                                                         o->chan = NULL;
1631                                                         if (qe->parent->strategy) {
1632                                                                 if (qe->parent->timeoutrestart)
1633                                                                         *to = orig;
1634                                                                 ring_one(qe, outgoing, &numbusies);
1635                                                         }
1636                                                         numbusies++;
1637                                                         break;
1638                                                 case AST_CONTROL_RINGING:
1639                                                         if (option_verbose > 2)
1640                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1641                                                         if (!sentringing) {
1642 #if 0
1643                                                                 ast_indicate(in, AST_CONTROL_RINGING);
1644 #endif                                                          
1645                                                                 sentringing++;
1646                                                         }
1647                                                         break;
1648                                                 case AST_CONTROL_OFFHOOK:
1649                                                         /* Ignore going off hook */
1650                                                         break;
1651                                                 default:
1652                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
1653                                                 }
1654                                         }
1655                                         ast_frfree(f);
1656                                 } else {
1657                                         o->stillgoing = 0;
1658                                         ast_hangup(o->chan);
1659                                         o->chan = NULL;
1660                                         if (qe->parent->strategy) {
1661                                                 if (qe->parent->timeoutrestart)
1662                                                         *to = orig;
1663                                                 ring_one(qe, outgoing, &numbusies);
1664                                         }
1665                                 }
1666                         }
1667                         o = o->next;
1668                 }
1669                 if (winner == in) {
1670                         f = ast_read(in);
1671 #if 0
1672                         if (f && (f->frametype != AST_FRAME_VOICE))
1673                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
1674                         else if (!f || (f->frametype != AST_FRAME_VOICE))
1675                                 printf("Hangup received on %s\n", in->name);
1676 #endif
1677                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
1678                                 /* Got hung up */
1679                                 *to=-1;
1680                                 if (f)
1681                                         ast_frfree(f);
1682                                 return NULL;
1683                         }
1684                         if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
1685                                 if (option_verbose > 3)
1686                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
1687                                 *to=0;
1688                                 ast_frfree(f);
1689                                 return NULL;
1690                         }
1691                         if ((f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) {
1692                                 if (option_verbose > 3)
1693                                         ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass);
1694                                 *to=0;
1695                                 *digit=f->subclass;
1696                                 ast_frfree(f);
1697                                 return NULL;
1698                         }
1699                         ast_frfree(f);
1700                 }
1701                 if (!*to && (option_verbose > 2))
1702                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
1703         }
1704
1705         return peer;
1706         
1707 }
1708
1709 static int is_our_turn(struct queue_ent *qe)
1710 {
1711         struct queue_ent *ch;
1712         int res;
1713
1714         /* Atomically read the parent head -- does not need a lock */
1715         ch = qe->parent->head;
1716         /* If we are now at the top of the head, break out */
1717         if (ch == qe) {
1718                 if (option_debug)
1719                         ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
1720                 res = 1;
1721         } else {
1722                 if (option_debug)
1723                         ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
1724                 res = 0;
1725         }
1726         return res;
1727 }
1728
1729 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
1730 {
1731         int res = 0;
1732
1733         /* This is the holding pen for callers 2 through maxlen */
1734         for (;;) {
1735                 enum queue_member_status stat;
1736
1737                 if (is_our_turn(qe))
1738                         break;
1739
1740                 /* If we have timed out, break out */
1741                 if (qe->expire && (time(NULL) > qe->expire)) {
1742                         *reason = QUEUE_TIMEOUT;
1743                         break;
1744                 }
1745
1746                 stat = get_member_status(qe->parent);
1747
1748                 /* leave the queue if no agents, if enabled */
1749                 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
1750                         *reason = QUEUE_LEAVEEMPTY;
1751                         leave_queue(qe);
1752                         break;
1753                 }
1754
1755                 /* leave the queue if no reachable agents, if enabled */
1756                 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
1757                         *reason = QUEUE_LEAVEUNAVAIL;
1758                         leave_queue(qe);
1759                         break;
1760                 }
1761
1762                 /* Make a position announcement, if enabled */
1763                 if (qe->parent->announcefrequency && !ringing)
1764                         res = say_position(qe);
1765                 if (res)
1766                         break;
1767
1768                 /* Wait a second before checking again */
1769                 res = ast_waitfordigit(qe->chan, RECHECK * 1000);
1770                 if (res)
1771                         break;
1772         }
1773         return res;
1774 }
1775
1776 static int update_queue(struct ast_call_queue *q, struct member *member)
1777 {
1778         struct member *cur;
1779
1780         /* Since a reload could have taken place, we have to traverse the list to
1781                 be sure it's still valid */
1782         ast_mutex_lock(&q->lock);
1783         cur = q->members;
1784         while(cur) {
1785                 if (member == cur) {
1786                         time(&cur->lastcall);
1787                         cur->calls++;
1788                         break;
1789                 }
1790                 cur = cur->next;
1791         }
1792         q->callscompleted++;
1793         ast_mutex_unlock(&q->lock);
1794         return 0;
1795 }
1796
1797 static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp)
1798 {
1799         switch (q->strategy) {
1800         case QUEUE_STRATEGY_RINGALL:
1801                 /* Everyone equal, except for penalty */
1802                 tmp->metric = mem->penalty * 1000000;
1803                 break;
1804         case QUEUE_STRATEGY_ROUNDROBIN:
1805                 if (!pos) {
1806                         if (!q->wrapped) {
1807                                 /* No more channels, start over */
1808                                 q->rrpos = 0;
1809                         } else {
1810                                 /* Prioritize next entry */
1811                                 q->rrpos++;
1812                         }
1813                         q->wrapped = 0;
1814                 }
1815                 /* Fall through */
1816         case QUEUE_STRATEGY_RRMEMORY:
1817                 if (pos < q->rrpos) {
1818                         tmp->metric = 1000 + pos;
1819                 } else {
1820                         if (pos > q->rrpos)
1821                                 /* Indicate there is another priority */
1822                                 q->wrapped = 1;
1823                         tmp->metric = pos;
1824                 }
1825                 tmp->metric += mem->penalty * 1000000;
1826                 break;
1827         case QUEUE_STRATEGY_RANDOM:
1828                 tmp->metric = rand() % 1000;
1829                 tmp->metric += mem->penalty * 1000000;
1830                 break;
1831         case QUEUE_STRATEGY_FEWESTCALLS:
1832                 tmp->metric = mem->calls;
1833                 tmp->metric += mem->penalty * 1000000;
1834                 break;
1835         case QUEUE_STRATEGY_LEASTRECENT:
1836                 if (!mem->lastcall)
1837                         tmp->metric = 0;
1838                 else
1839                         tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
1840                 tmp->metric += mem->penalty * 1000000;
1841                 break;
1842         default:
1843                 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
1844                 break;
1845         }
1846         return 0;
1847 }
1848
1849 static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on)
1850 {
1851         struct member *cur;
1852         struct localuser *outgoing=NULL, *tmp = NULL;
1853         int to;
1854         char restofit[AST_MAX_EXTENSION];
1855         char oldexten[AST_MAX_EXTENSION]="";
1856         char oldcontext[AST_MAX_EXTENSION]="";
1857         char queuename[256]="";
1858         char *newnum;
1859         char *monitorfilename;
1860         struct ast_channel *peer;
1861         struct ast_channel *which;
1862         struct localuser *lpeer;
1863         struct member *member;
1864         int res = 0, bridge = 0;
1865         int numbusies = 0;
1866         int x=0;
1867         char *announce = NULL;
1868         char digit = 0;
1869         time_t callstart;
1870         time_t now;
1871         struct ast_bridge_config bridge_config;
1872         char nondataquality = 1;
1873
1874         memset(&bridge_config, 0, sizeof(bridge_config));
1875                 
1876         for (; options && *options; options++)
1877                 switch (*options) {
1878                 case 't':
1879                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
1880                         break;
1881                 case 'T':
1882                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
1883                         break;
1884                 case 'd':
1885                         nondataquality = 0;
1886                         break;
1887                 case 'h':
1888                         ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
1889                         break;
1890                 case 'H':
1891                         ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
1892                         break;
1893                 case 'n':
1894                         if ((now - qe->start >= qe->parent->timeout))
1895                                 *go_on = 1;
1896                         break;
1897                 }
1898
1899         /* Hold the lock while we setup the outgoing calls */
1900         if (use_weight) 
1901                 ast_mutex_lock(&qlock);
1902         ast_mutex_lock(&qe->parent->lock);
1903         if (option_debug)
1904                 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n", 
1905                                                         qe->chan->name);
1906         ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
1907         time(&now);
1908         cur = qe->parent->members;
1909         if (!ast_strlen_zero(qe->announce))
1910                 announce = qe->announce;
1911         if (announceoverride && !ast_strlen_zero(announceoverride))
1912                 announce = announceoverride;
1913
1914         while(cur) {
1915                 tmp = malloc(sizeof(*tmp));
1916                 if (!tmp) {
1917                         ast_mutex_unlock(&qe->parent->lock);
1918                         if (use_weight) 
1919                                 ast_mutex_unlock(&qlock);
1920                         ast_log(LOG_WARNING, "Out of memory\n");
1921                         goto out;
1922                 }
1923                 memset(tmp, 0, sizeof(*tmp));
1924                 tmp->stillgoing = -1;
1925                 if (option_debug) {
1926                         if (url)
1927                                 ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
1928                         else 
1929                                 ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
1930                 }
1931
1932                 tmp->member = cur;              /* Never directly dereference!  Could change on reload */
1933                 tmp->oldstatus = cur->status;
1934                 tmp->lastcall = cur->lastcall;
1935                 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface)-1);
1936                 /* If we're dialing by extension, look at the extension to know what to dial */
1937                 if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
1938                         newnum++;
1939                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1);
1940                         snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit);
1941                         if (option_debug)
1942                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface);
1943                 }
1944                 /* Special case: If we ring everyone, go ahead and ring them, otherwise
1945                    just calculate their metric for the appropriate strategy */
1946                 calc_metric(qe->parent, cur, x++, qe, tmp);
1947                 /* Put them in the list of outgoing thingies...  We're ready now. 
1948                    XXX If we're forcibly removed, these outgoing calls won't get
1949                    hung up XXX */
1950                 tmp->next = outgoing;
1951                 outgoing = tmp;         
1952                 /* If this line is up, don't try anybody else */
1953                 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
1954                         break;
1955
1956                 cur = cur->next;
1957         }
1958         if (qe->parent->timeout)
1959                 to = qe->parent->timeout * 1000;
1960         else
1961                 to = -1;
1962         ring_one(qe, outgoing, &numbusies);
1963         ast_mutex_unlock(&qe->parent->lock);
1964         if (use_weight) 
1965                 ast_mutex_unlock(&qlock);
1966         lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
1967         ast_mutex_lock(&qe->parent->lock);
1968         if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
1969                 store_next(qe, outgoing);
1970         }
1971         ast_mutex_unlock(&qe->parent->lock);
1972         if (lpeer)
1973                 peer = lpeer->chan;
1974         else
1975                 peer = NULL;
1976         if (!peer) {
1977                 if (to) {
1978                         /* Musta gotten hung up */
1979                         record_abandoned(qe);
1980                         res = -1;
1981                 } else {
1982                         if (digit && valid_exit(qe, digit))
1983                                 res=digit;
1984                         else
1985                                 /* Nobody answered, next please? */
1986                                 res=0;
1987                 }
1988                 if (option_debug)
1989                         ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
1990                 goto out;
1991         }
1992         if (peer) {
1993                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1994                    we will always return with -1 so that it is hung up properly after the 
1995                    conversation.  */
1996                 qe->handled++;
1997                 if (!strcmp(qe->chan->type,"Zap"))
1998                         ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
1999                 if (!strcmp(peer->type,"Zap"))
2000                         ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
2001                 /* Update parameters for the queue */
2002                 recalc_holdtime(qe);
2003                 member = lpeer->member;
2004                 hangupcalls(outgoing, peer);
2005                 outgoing = NULL;
2006                 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
2007                         int res2;
2008                         res2 = ast_autoservice_start(qe->chan);
2009                         if (!res2) {
2010                                 if (qe->parent->memberdelay) {
2011                                         ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
2012                                         res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
2013                                 }
2014                                 if (!res2 && announce) {
2015                                         if (play_file(peer, announce))
2016                                                 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
2017                                 }
2018                                 if (!res2 && qe->parent->reportholdtime) {
2019                                         if (!play_file(peer, qe->parent->sound_reporthold)) {
2020                                                 int holdtime;
2021                                                 time_t now;
2022
2023                                                 time(&now);
2024                                                 holdtime = abs((now - qe->start) / 60);
2025                                                 if (holdtime < 2) {
2026                                                         play_file(peer, qe->parent->sound_lessthan);
2027                                                         ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
2028                                                 } else 
2029                                                         ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
2030                                                 play_file(peer, qe->parent->sound_minutes);
2031                                         }
2032                                 }
2033                         }
2034                         res2 |= ast_autoservice_stop(qe->chan);
2035                         if (peer->_softhangup) {
2036                                 /* Agent must have hung up */
2037                                 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
2038                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
2039                                 record_abandoned(qe);
2040                                 if (qe->parent->eventwhencalled) {
2041                                         manager_event(EVENT_FLAG_AGENT, "AgentDump",
2042                                                       "Queue: %s\r\n"
2043                                                       "Uniqueid: %s\r\n"
2044                                                       "Channel: %s\r\n"
2045                                                       "Member: %s\r\n",
2046                                                       queuename, qe->chan->uniqueid, peer->name, member->interface);
2047                                 }
2048                                 ast_hangup(peer);
2049                                 goto out;
2050                         } else if (res2) {
2051                                 /* Caller must have hung up just before being connected*/
2052                                 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
2053                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
2054                                 record_abandoned(qe);
2055                                 ast_hangup(peer);
2056                                 return -1;
2057                         }
2058                 }
2059                 /* Stop music on hold */
2060                 ast_moh_stop(qe->chan);
2061                 /* If appropriate, log that we have a destination channel */
2062                 if (qe->chan->cdr)
2063                         ast_cdr_setdestchan(qe->chan->cdr, peer->name);
2064                 /* Make sure channels are compatible */
2065                 res = ast_channel_make_compatible(qe->chan, peer);
2066                 if (res < 0) {
2067                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "SYSCOMPAT", "%s", "");
2068                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
2069                         record_abandoned(qe);
2070                         ast_hangup(peer);
2071                         return -1;
2072                 }
2073                 /* Begin Monitoring */
2074                 if (qe->parent->monfmt && *qe->parent->monfmt) {
2075                         monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
2076                         if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
2077                                 which = qe->chan;
2078                         else
2079                                 which = peer;
2080                         if (monitorfilename)
2081                                 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2082                         else
2083                                 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2084                         if (qe->parent->monjoin)
2085                                 ast_monitor_setjoinfiles(which, 1);
2086                 }
2087                 /* Drop out of the queue at this point, to prepare for next caller */
2088                 leave_queue(qe);                        
2089                 if (url && !ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
2090                         if (option_debug)
2091                                 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
2092                         ast_channel_sendurl(peer, url);
2093                 }
2094                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
2095                 if (qe->parent->eventwhencalled)
2096                         manager_event(EVENT_FLAG_AGENT, "AgentConnect",
2097                                       "Queue: %s\r\n"
2098                                       "Uniqueid: %s\r\n"
2099                                       "Channel: %s\r\n"
2100                                       "Member: %s\r\n"
2101                                       "Holdtime: %ld\r\n",
2102                                       queuename, qe->chan->uniqueid, peer->name, member->interface,
2103                                       (long)time(NULL) - qe->start);
2104                 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
2105                 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
2106                 time(&callstart);
2107
2108                 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
2109
2110                 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
2111                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
2112                 } else if (qe->chan->_softhangup) {
2113                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
2114                                       (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2115                         if (qe->parent->eventwhencalled)
2116                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2117                                               "Queue: %s\r\n"
2118                                               "Uniqueid: %s\r\n"
2119                                               "Channel: %s\r\n"
2120                                               "Member: %s\r\n"
2121                                               "HoldTime: %ld\r\n"
2122                                               "TalkTime: %ld\r\n"
2123                                               "Reason: caller\r\n",
2124                                               queuename, qe->chan->uniqueid, peer->name, member->interface,
2125                                               (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2126                 } else {
2127                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
2128                         if (qe->parent->eventwhencalled)
2129                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
2130                                               "Queue: %s\r\n"
2131                                               "Uniqueid: %s\r\n"
2132                                               "Channel: %s\r\n"
2133                                               "HoldTime: %ld\r\n"
2134                                               "TalkTime: %ld\r\n"
2135                                               "Reason: agent\r\n",
2136                                               queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start),
2137                                               (long)(time(NULL) - callstart));
2138                 }
2139
2140                 if(bridge != AST_PBX_NO_HANGUP_PEER)
2141                         ast_hangup(peer);
2142                 update_queue(qe->parent, member);
2143                 if (bridge == 0) 
2144                         res = 1; /* JDG: bridge successfull, leave app_queue */
2145                 else 
2146                         res = bridge; /* bridge error, stay in the queue */
2147         }       
2148 out:
2149         hangupcalls(outgoing, NULL);
2150         return res;
2151 }
2152
2153 static int wait_a_bit(struct queue_ent *qe)
2154 {
2155         /* Don't need to hold the lock while we setup the outgoing calls */
2156         int retrywait = qe->parent->retry * 1000;
2157
2158         return ast_waitfordigit(qe->chan, retrywait);
2159 }
2160
2161 static struct member * interface_exists(struct ast_call_queue *q, char *interface)
2162 {
2163         struct member *mem;
2164
2165         if (q)
2166                 for (mem = q->members; mem; mem = mem->next)
2167                         if (!strcmp(interface, mem->interface))
2168                                 return mem;
2169
2170         return NULL;
2171 }
2172
2173
2174 /* Dump all members in a specific queue to the databse
2175  *
2176  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
2177  *
2178  */
2179 static void dump_queue_members(struct ast_call_queue *pm_queue)
2180 {
2181         struct member *cur_member;
2182         char value[PM_MAX_LEN];
2183         int value_len = 0;
2184         int res;
2185
2186         memset(value, 0, sizeof(value));
2187
2188         if (!pm_queue)
2189                 return;
2190
2191         for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
2192                 if (!cur_member->dynamic)
2193                         continue;
2194
2195                 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d%s",
2196                                cur_member->interface, cur_member->penalty, cur_member->paused,
2197                                cur_member->next ? "|" : "");
2198                 if (res != strlen(value + value_len)) {
2199                         ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
2200                         break;
2201                 }
2202                 value_len += res;
2203         }
2204         
2205         if (value_len && !cur_member) {
2206                 if (ast_db_put(pm_family, pm_queue->name, value))
2207                         ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
2208         } else
2209                 /* Delete the entry if the queue is empty or there is an error */
2210                 ast_db_del(pm_family, pm_queue->name);
2211 }
2212
2213 static int remove_from_queue(char *queuename, char *interface)
2214 {
2215         struct ast_call_queue *q;
2216         struct member *last_member, *look;
2217         int res = RES_NOSUCHQUEUE;
2218
2219         ast_mutex_lock(&qlock);
2220         for (q = queues ; q ; q = q->next) {
2221                 ast_mutex_lock(&q->lock);
2222                 if (!strcmp(q->name, queuename)) {
2223                         if ((last_member = interface_exists(q, interface))) {
2224                                 if ((look = q->members) == last_member) {
2225                                         q->members = last_member->next;
2226                                 } else {
2227                                         while (look != NULL) {
2228                                                 if (look->next == last_member) {
2229                                                         look->next = last_member->next;
2230                                                         break;
2231                                                 } else {
2232                                                          look = look->next;
2233                                                 }
2234                                         }
2235                                 }
2236                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
2237                                                 "Queue: %s\r\n"
2238                                                 "Location: %s\r\n",
2239                                         q->name, last_member->interface);
2240                                 free(last_member);
2241
2242                                 if (queue_persistent_members)
2243                                     dump_queue_members(q);
2244
2245                                 res = RES_OKAY;
2246                         } else {
2247                                 res = RES_EXISTS;
2248                         }
2249                         ast_mutex_unlock(&q->lock);
2250                         break;
2251                 }
2252                 ast_mutex_unlock(&q->lock);
2253         }
2254         ast_mutex_unlock(&qlock);
2255         return res;
2256 }
2257
2258 static int add_to_queue(char *queuename, char *interface, int penalty, int paused, int dump)
2259 {
2260         struct ast_call_queue *q;
2261         struct member *new_member;
2262         int res = RES_NOSUCHQUEUE;
2263
2264         ast_mutex_lock(&qlock);
2265         for (q = queues ; q ; q = q->next) {
2266                 ast_mutex_lock(&q->lock);
2267                 if (!strcmp(q->name, queuename)) {
2268                         if (interface_exists(q, interface) == NULL) {
2269                                 new_member = create_queue_member(interface, penalty, paused);
2270
2271                                 if (new_member != NULL) {
2272                                         new_member->dynamic = 1;
2273                                         new_member->next = q->members;
2274                                         q->members = new_member;
2275                                         manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
2276                                                 "Queue: %s\r\n"
2277                                                 "Location: %s\r\n"
2278                                                 "Membership: %s\r\n"
2279                                                 "Penalty: %d\r\n"
2280                                                 "CallsTaken: %d\r\n"
2281                                                 "LastCall: %ld\r\n"
2282                                                 "Status: %d\r\n"
2283                                                 "Paused: %d\r\n",
2284                                         q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
2285                                         new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused);
2286                                         
2287                                         if (dump)
2288                                                 dump_queue_members(q);
2289
2290                                         res = RES_OKAY;
2291                                 } else {
2292                                         res = RES_OUTOFMEMORY;
2293                                 }
2294                         } else {
2295                                 res = RES_EXISTS;
2296                         }
2297                         ast_mutex_unlock(&q->lock);
2298                         break;
2299                 }
2300                 ast_mutex_unlock(&q->lock);
2301         }
2302         ast_mutex_unlock(&qlock);
2303         return res;
2304 }
2305
2306 static int set_member_paused(char *queuename, char *interface, int paused)
2307 {
2308         int found = 0;
2309         struct ast_call_queue *q;
2310         struct member *mem;
2311
2312         /* Special event for when all queues are paused - individual events still generated */
2313
2314         if (ast_strlen_zero(queuename))
2315                 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
2316
2317         ast_mutex_lock(&qlock);
2318         for (q = queues ; q ; q = q->next) {
2319                 ast_mutex_lock(&q->lock);
2320                 if (ast_strlen_zero(queuename) || !strcmp(q->name, queuename)) {
2321                         if ((mem = interface_exists(q, interface))) {
2322                                 found++;
2323                                 if (mem->paused == paused)
2324                                         ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
2325                                 mem->paused = paused;
2326
2327                                 if (queue_persistent_members)
2328                                     dump_queue_members(q);
2329
2330                                 ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
2331
2332                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
2333                                         "Queue: %s\r\n"
2334                                         "Location: %s\r\n"
2335                                         "Paused: %d\r\n",
2336                                                 q->name, mem->interface, paused);
2337                         }
2338                 }
2339                 ast_mutex_unlock(&q->lock);
2340         }
2341         ast_mutex_unlock(&qlock);
2342
2343         if (found)
2344                 return RESULT_SUCCESS;
2345         else
2346                 return RESULT_FAILURE;
2347 }
2348
2349 /* Reload dynamic queue members persisted into the astdb */
2350 static void reload_queue_members(void)
2351 {
2352         char *cur_ptr;  
2353         char *queue_name;
2354         char *member;
2355         char *interface;
2356         char *penalty_tok;
2357         int penalty = 0;
2358         char *paused_tok;
2359         int paused = 0;
2360         struct ast_db_entry *db_tree;
2361         struct ast_db_entry *entry;
2362         struct ast_call_queue *cur_queue;
2363         char queue_data[PM_MAX_LEN];
2364
2365         ast_mutex_lock(&qlock);
2366
2367         /* Each key in 'pm_family' is the name of a queue */
2368         db_tree = ast_db_gettree(pm_family, NULL);
2369         for (entry = db_tree; entry; entry = entry->next) {
2370
2371                 queue_name = entry->key + strlen(pm_family) + 2;
2372
2373                 cur_queue = queues;
2374                 while (cur_queue) {
2375                         ast_mutex_lock(&cur_queue->lock);
2376                         if (!strcmp(queue_name, cur_queue->name))
2377                                 break;
2378                         ast_mutex_unlock(&cur_queue->lock);
2379                         cur_queue = cur_queue->next;
2380                 }
2381
2382                 if (!cur_queue) {
2383                         /* If the queue no longer exists, remove it from the
2384                          * database */
2385                         ast_db_del(pm_family, queue_name);
2386                         continue;
2387                 } else
2388                         ast_mutex_unlock(&cur_queue->lock);
2389
2390                 if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
2391                         continue;
2392
2393                 cur_ptr = queue_data;
2394                 while ((member = strsep(&cur_ptr, "|"))) {
2395                         if (ast_strlen_zero(member))
2396                                 continue;
2397
2398                         interface = strsep(&member, ";");
2399                         penalty_tok = strsep(&member, ";");
2400                         paused_tok = strsep(&member, ";");
2401
2402                         if (!penalty_tok) {
2403                                 ast_log(LOG_WARNING, "Error parsing persisent member string for '%s' (penalty)\n", queue_name);
2404                                 break;
2405                         }
2406                         penalty = strtol(penalty_tok, NULL, 10);
2407                         if (errno == ERANGE) {
2408                                 ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
2409                                 break;
2410                         }
2411                         
2412                         if (!paused_tok) {
2413                                 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
2414                                 break;
2415                         }
2416                         paused = strtol(paused_tok, NULL, 10);
2417                         if ((errno == ERANGE) || paused < 0 || paused > 1) {
2418                                 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
2419                                 break;
2420                         }
2421
2422                         if (option_debug)
2423                                 ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Penalty: %d  Paused: %d\n", queue_name, interface, penalty, paused);
2424                         
2425                         if (add_to_queue(queue_name, interface, penalty, paused, 0) == RES_OUTOFMEMORY) {
2426                                 ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
2427                                 break;
2428                         }
2429                 }
2430         }
2431
2432         ast_mutex_unlock(&qlock);
2433         if (db_tree) {
2434                 ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
2435                 ast_db_freetree(db_tree);
2436         }
2437 }
2438
2439 static int pqm_exec(struct ast_channel *chan, void *data)
2440 {
2441         struct localuser *u;
2442         char *queuename, *interface;
2443
2444         if (!data) {
2445                 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface])\n");
2446                 return -1;
2447         }
2448
2449         queuename = ast_strdupa((char *)data);
2450         if (!queuename) {
2451                 ast_log(LOG_ERROR, "Out of memory\n");
2452                 return -1;
2453         }
2454
2455         interface = strchr(queuename, '|');
2456         if (!interface) {
2457                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2458                 return -1;
2459         }
2460
2461         LOCAL_USER_ADD(u);
2462
2463         *interface = '\0';
2464         interface++;
2465
2466         if (set_member_paused(queuename, interface, 1)) {
2467                 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", interface);
2468                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2469                         chan->priority += 100;
2470                         LOCAL_USER_REMOVE(u);
2471                         return 0;
2472                 }
2473                 return -1;
2474         }
2475
2476         LOCAL_USER_REMOVE(u);
2477
2478         return 0;
2479 }
2480
2481 static int upqm_exec(struct ast_channel *chan, void *data)
2482 {
2483         struct localuser *u;
2484         char *queuename, *interface;
2485
2486         if (!data) {
2487                 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface])\n");
2488                 return -1;
2489         }
2490
2491         queuename = ast_strdupa((char *)data);
2492         if (!queuename) {
2493                 ast_log(LOG_ERROR, "Out of memory\n");
2494                 return -1;
2495         }
2496
2497         interface = strchr(queuename, '|');
2498         if (!interface) {
2499                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2500                 return -1;
2501         }
2502
2503         LOCAL_USER_ADD(u);
2504
2505         *interface = '\0';
2506         interface++;
2507
2508         if (set_member_paused(queuename, interface, 0)) {
2509                 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", interface);
2510                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2511                         chan->priority += 100;
2512                         LOCAL_USER_REMOVE(u);
2513                         return 0;
2514                 }
2515                 return -1;
2516         }
2517
2518         LOCAL_USER_REMOVE(u);
2519
2520         return 0;
2521 }
2522
2523 static int rqm_exec(struct ast_channel *chan, void *data)
2524 {
2525         int res=-1;
2526         struct localuser *u;
2527         char *info, *queuename;
2528         char tmpchan[256]="";
2529         char *interface = NULL;
2530
2531         if (!data) {
2532                 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface])\n");
2533                 return -1;
2534         }
2535
2536         info = ast_strdupa((char *)data);
2537         if (!info) {
2538                 ast_log(LOG_ERROR, "Out of memory\n");
2539                 return -1;
2540         }
2541
2542         LOCAL_USER_ADD(u);
2543
2544         queuename = info;
2545         if (queuename) {
2546                 interface = strchr(queuename, '|');
2547                 if (interface) {
2548                         *interface = '\0';
2549                         interface++;
2550                 }
2551                 else {
2552                         ast_copy_string(tmpchan, chan->name, sizeof(tmpchan));
2553                         interface = strrchr(tmpchan, '-');
2554                         if (interface)
2555                                 *interface = '\0';
2556                         interface = tmpchan;
2557                 }
2558         }
2559
2560         switch (remove_from_queue(queuename, interface)) {
2561         case RES_OKAY:
2562                 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", interface, queuename);
2563                 res = 0;
2564                 break;
2565         case RES_EXISTS:
2566                 ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
2567                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2568                         chan->priority += 100;
2569                 }
2570                 res = 0;
2571                 break;
2572         case RES_NOSUCHQUEUE:
2573                 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", queuename);
2574                 res = 0;
2575                 break;
2576         case RES_OUTOFMEMORY:
2577                 ast_log(LOG_ERROR, "Out of memory\n");
2578                 break;
2579         }
2580
2581         LOCAL_USER_REMOVE(u);
2582         return res;
2583 }
2584
2585 static int aqm_exec(struct ast_channel *chan, void *data)
2586 {
2587         int res=-1;
2588         struct localuser *u;
2589         char *queuename;
2590         char *info;
2591         char tmpchan[512]="";
2592         char *interface=NULL;
2593         char *penaltys=NULL;
2594         int penalty = 0;
2595
2596         if (!data) {
2597                 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface][|penalty]])\n");
2598                 return -1;
2599         }
2600
2601         info = ast_strdupa((char *)data);
2602         if (!info) {
2603                 ast_log(LOG_ERROR, "Out of memory\n");
2604                 return -1;
2605         }
2606         LOCAL_USER_ADD(u);
2607
2608         queuename = info;
2609         if (queuename) {
2610                 interface = strchr(queuename, '|');
2611                 if (interface) {
2612                         *interface = '\0';
2613                         interface++;
2614                 }
2615                 if (interface) {
2616                         penaltys = strchr(interface, '|');
2617                         if (penaltys) {
2618                                 *penaltys = '\0';
2619                                 penaltys++;
2620                         }
2621                 }
2622                 if (!interface || ast_strlen_zero(interface)) {
2623                         ast_copy_string(tmpchan, chan->name, sizeof(tmpchan));
2624                         interface = strrchr(tmpchan, '-');
2625                         if (interface)
2626                                 *interface = '\0';
2627                         interface = tmpchan;
2628                 }
2629                 if (penaltys && !ast_strlen_zero(penaltys)) {
2630                         if ((sscanf(penaltys, "%d", &penalty) != 1) || penalty < 0) {
2631                                 ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", penaltys);
2632                                 penalty = 0;
2633                         }
2634                 }
2635         }
2636
2637         switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
2638         case RES_OKAY:
2639                 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
2640                 res = 0;
2641                 break;
2642         case RES_EXISTS:
2643                 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
2644                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2645                         chan->priority += 100;
2646                 }
2647                 res = 0;
2648                 break;
2649         case RES_NOSUCHQUEUE:
2650                 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", queuename);
2651                 res = 0;
2652                 break;
2653         case RES_OUTOFMEMORY:
2654                 ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", interface, queuename);
2655                 break;
2656         }
2657
2658         LOCAL_USER_REMOVE(u);
2659         return res;
2660 }
2661
2662 static int queue_exec(struct ast_channel *chan, void *data)
2663 {
2664         int res=-1;
2665         int ringing=0;
2666         struct localuser *u;
2667         char *queuename;
2668         char info[512];
2669         char *info_ptr = info;
2670         char *options = NULL;
2671         char *url = NULL;
2672         char *announceoverride = NULL;
2673         char *user_priority;
2674         int prio;
2675         char *queuetimeoutstr = NULL;
2676         enum queue_result reason = QUEUE_UNKNOWN;
2677
2678         /* whether to exit Queue application after the timeout hits */
2679         int go_on = 0;
2680
2681         /* Our queue entry */
2682         struct queue_ent qe;
2683         
2684         if (!data || ast_strlen_zero(data)) {
2685                 ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n");
2686                 return -1;
2687         }
2688         
2689         LOCAL_USER_ADD(u);
2690
2691         /* Setup our queue entry */
2692         memset(&qe, 0, sizeof(qe));
2693         qe.start = time(NULL);
2694         
2695         /* Parse our arguments XXX Check for failure XXX */
2696         ast_copy_string(info, (char *) data, sizeof(info));
2697         queuename = strsep(&info_ptr, "|");
2698         options = strsep(&info_ptr, "|");
2699         url = strsep(&info_ptr, "|");
2700         announceoverride = strsep(&info_ptr, "|");
2701         queuetimeoutstr = info_ptr;
2702
2703         /* set the expire time based on the supplied timeout; */
2704         if (queuetimeoutstr)
2705                 qe.expire = qe.start + atoi(queuetimeoutstr);
2706         else
2707                 qe.expire = 0;
2708
2709         /* Get the priority from the variable ${QUEUE_PRIO} */
2710         user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
2711         if (user_priority) {
2712                 if (sscanf(user_priority, "%d", &prio) == 1) {
2713                         if (option_debug)
2714                                 ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
2715                                         chan->name, prio);
2716                 } else {
2717                         ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
2718                                 user_priority, chan->name);
2719                         prio = 0;
2720                 }
2721         } else {
2722                 if (option_debug > 2)
2723                         ast_log(LOG_DEBUG, "NO QUEUE_PRIO variable found. Using default.\n");
2724                 prio = 0;
2725         }
2726
2727         if (options && (strchr(options, 'r')))
2728                 ringing = 1;
2729
2730         if (option_debug)  
2731                 ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
2732                         queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
2733
2734         qe.chan = chan;
2735         qe.prio = (int)prio;
2736         qe.last_pos_said = 0;
2737         qe.last_pos = 0;
2738         if (!join_queue(queuename, &qe, &reason)) {
2739                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "",
2740                               chan->cid.cid_num ? chan->cid.cid_num : "");
2741 check_turns:
2742                 if (ringing) {
2743                         ast_indicate(chan, AST_CONTROL_RINGING);
2744                 } else {              
2745                         ast_moh_start(chan, qe.moh);
2746                 }
2747                 for (;;) {
2748                         /* This is the wait loop for callers 2 through maxlen */
2749
2750                         res = wait_our_turn(&qe, ringing, &reason);
2751                         /* If they hungup, return immediately */
2752                         if (res < 0) {
2753                                 /* Record this abandoned call */
2754                                 record_abandoned(&qe);
2755                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2756                                 if (option_verbose > 2) {
2757                                         ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", queuename);
2758                                         res = -1;
2759                                 }
2760                                 break;
2761                         }
2762                         if (!res) 
2763                                 break;
2764                         if (valid_exit(&qe, res)) {
2765                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2766                                 break;
2767                         }
2768                 }
2769                 if (!res) {
2770                         int makeannouncement = 0;
2771                         for (;;) {
2772                                 /* This is the wait loop for the head caller*/
2773                                 /* To exit, they may get their call answered; */
2774                                 /* they may dial a digit from the queue context; */
2775                                 /* or, they may timeout. */
2776
2777                                 enum queue_member_status stat;
2778
2779                                 /* Leave if we have exceeded our queuetimeout */
2780                                 if (qe.expire && (time(NULL) > qe.expire)) {
2781                                         record_abandoned(&qe);
2782                                         reason = QUEUE_TIMEOUT;
2783                                         res = 0;
2784                                         break;
2785                                 }
2786
2787                                 if (makeannouncement) {
2788                                         /* Make a position announcement, if enabled */
2789                                         if (qe.parent->announcefrequency && !ringing)
2790                                                 res = say_position(&qe);
2791                                         if (res && valid_exit(&qe, res)) {
2792                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2793                                                 break;
2794                                         }
2795
2796                                 }
2797                                 makeannouncement = 1;
2798
2799                                 /* Try calling all queue members for 'timeout' seconds */
2800                                 res = try_calling(&qe, options, announceoverride, url, &go_on);
2801                                 if (res) {
2802                                         if (res < 0) {
2803                                                 if (!qe.handled)
2804                                                         record_abandoned(&qe);
2805                                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2806                                         } else if (res > 0)
2807                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2808                                         break;
2809                                 }
2810
2811                                 stat = get_member_status(qe.parent);
2812
2813                                 /* leave the queue if no agents, if enabled */
2814                                 if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
2815                                         record_abandoned(&qe);
2816                                         reason = QUEUE_LEAVEEMPTY;
2817                                         res = 0;
2818                                         break;
2819                                 }
2820
2821                                 /* leave the queue if no reachable agents, if enabled */
2822                                 if ((qe.parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
2823                                         record_abandoned(&qe);
2824                                         reason = QUEUE_LEAVEUNAVAIL;
2825                                         res = 0;
2826                                         break;
2827                                 }
2828
2829                                 /* Leave if we have exceeded our queuetimeout */
2830                                 if (qe.expire && (time(NULL) > qe.expire)) {
2831                                         record_abandoned(&qe);
2832                                         reason = QUEUE_TIMEOUT;
2833                                         res = 0;
2834                                         break;
2835                                 }
2836
2837                                 /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
2838                                 res = wait_a_bit(&qe);
2839                                 if (res < 0) {
2840                                         record_abandoned(&qe);
2841                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2842                                         if (option_verbose > 2) {
2843                                                 ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s when they almost made it\n", queuename);
2844                                                 res = -1;
2845                                         }
2846                                         break;
2847                                 }
2848                                 if (res && valid_exit(&qe, res)) {
2849                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2850                                         break;
2851                                 }
2852                                 /* exit after 'timeout' cycle if 'n' option enabled */
2853                                 if (go_on) {
2854                                         if (option_verbose > 2) {
2855                                                 ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n");
2856                                                 res = -1;
2857                                         }
2858                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
2859                                         record_abandoned(&qe);
2860                                         reason = QUEUE_TIMEOUT;
2861                                         res = 0;
2862                                         break;
2863                                 }
2864                                 /* Since this is a priority queue and 
2865                                  * it is not sure that we are still at the head
2866                                  * of the queue, go and check for our turn again.
2867                                  */
2868     &nb