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