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