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