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