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