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