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