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