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