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