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