Fix big flagification errors (bug #3414)
[asterisk/asterisk.git] / apps / app_queue.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * True call queues with optional send URL on answer
5  * 
6  * Copyright (C) 1999-2004, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * 2004-11-25: Persistent Dynamic Members added by:
11  *             NetNation Communications (www.netnation.com)
12  *             Kevin Lindsay <kevinl@netnation.com>
13  * 
14  *             Each dynamic agent in each queue is now stored in the astdb.
15  *             When asterisk is restarted, each agent will be automatically
16  *             readded into their recorded queues. This feature can be
17  *             configured with the 'peristent_members=<1|0>' KVP under the
18  *             '[general]' group in queues.conf. The default is on.
19  * 
20  * 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
21  *
22  * These features added by David C. Troy <dave@toad.net>:
23  *    - Per-queue holdtime calculation
24  *    - Estimated holdtime announcement
25  *    - Position announcement
26  *    - Abandoned/completed call counters
27  *    - Failout timer passed as optional app parameter
28  *    - Optional monitoring of calls, started when call is answered
29  *
30  * Patch Version 1.07 2003-12-24 01
31  *
32  * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
33  * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
34  *
35  * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
36  * by Matthew Enger <m.enger@xi.com.au>
37  *
38  * This program is free software, distributed under the terms of
39  * the GNU General Public License
40  */
41
42 #include <asterisk/lock.h>
43 #include <asterisk/file.h>
44 #include <asterisk/logger.h>
45 #include <asterisk/channel.h>
46 #include <asterisk/pbx.h>
47 #include <asterisk/options.h>
48 #include <asterisk/module.h>
49 #include <asterisk/translate.h>
50 #include <asterisk/say.h>
51 #include <asterisk/features.h>
52 #include <asterisk/musiconhold.h>
53 #include <asterisk/cli.h>
54 #include <asterisk/manager.h>
55 #include <asterisk/config.h>
56 #include <asterisk/monitor.h>
57 #include <asterisk/utils.h>
58 #include <asterisk/causes.h>
59 #include <asterisk/astdb.h>
60 #include <stdlib.h>
61 #include <errno.h>
62 #include <unistd.h>
63 #include <string.h>
64 #include <stdlib.h>
65 #include <stdio.h>
66 #include <sys/time.h>
67 #include <sys/signal.h>
68 #include <netinet/in.h>
69
70 #include "../astconf.h"
71
72 #define QUEUE_STRATEGY_RINGALL          0
73 #define QUEUE_STRATEGY_ROUNDROBIN       1
74 #define QUEUE_STRATEGY_LEASTRECENT      2
75 #define QUEUE_STRATEGY_FEWESTCALLS      3
76 #define QUEUE_STRATEGY_RANDOM           4
77 #define QUEUE_STRATEGY_RRMEMORY         5
78
79 static struct strategy {
80         int strategy;
81         char *name;
82 } strategies[] = {
83         { QUEUE_STRATEGY_RINGALL, "ringall" },
84         { QUEUE_STRATEGY_ROUNDROBIN, "roundrobin" },
85         { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
86         { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
87         { QUEUE_STRATEGY_RANDOM, "random" },
88         { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
89 };
90
91 #define DEFAULT_RETRY           5
92 #define DEFAULT_TIMEOUT         15
93 #define RECHECK                 1               /* Recheck every second to see we we're at the top yet */
94
95 #define RES_OKAY        0               /* Action completed */
96 #define RES_EXISTS      (-1)            /* Entry already exists */
97 #define RES_OUTOFMEMORY (-2)            /* Out of memory */
98 #define RES_NOSUCHQUEUE (-3)            /* No such queue */
99
100 static char *tdesc = "True Call Queueing";
101
102 static char *app = "Queue";
103
104 static char *synopsis = "Queue a call for a call queue";
105
106 static char *descrip =
107 "  Queue(queuename[|options[|URL][|announceoverride][|timeout]]):\n"
108 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
109 "  This application returns -1 if the originating channel hangs up, or if the\n"
110 "call is bridged and  either of the parties in the bridge terminate the call.\n"
111 "Returns 0 if the queue is full, nonexistant, or has no members.\n"
112 "The option string may contain zero or more of the following characters:\n"
113 "      't' -- allow the called user transfer the calling user\n"
114 "      'T' -- to allow the calling user to transfer the call.\n"
115 "      'd' -- data-quality (modem) call (minimum delay).\n"
116 "      'h' -- allow callee to hang up by hitting *.\n"
117 "      'H' -- allow caller to hang up by hitting *.\n"
118 "      'n' -- no retries on the timeout; will exit this application and \n"
119 "             go to the next step.\n"
120 "      'r' -- ring instead of playing MOH\n"
121 "  In addition to transferring the call, a call may be parked and then picked\n"
122 "up by another user.\n"
123 "  The optional URL will be sent to the called party if the channel supports\n"
124 "it.\n"
125 "  The timeout will cause the queue to fail out after a specified number of\n"
126 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n";
127
128 /* PHM 06/26/03 */
129 static char *app_aqm = "AddQueueMember" ;
130 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
131 static char *app_aqm_descrip =
132 "   AddQueueMember(queuename[|interface[|penalty]]):\n"
133 "Dynamically adds interface to an existing queue.\n"
134 "If the interface is already in the queue and there exists an n+101 priority\n"
135 "then it will then jump to this priority.  Otherwise it will return an error\n"
136 "Returns -1 if there is an error.\n"
137 "Example: AddQueueMember(techsupport|SIP/3000)\n"
138 "";
139
140 static char *app_rqm = "RemoveQueueMember" ;
141 static char *app_rqm_synopsis = "Dynamically removes queue members" ;
142 static char *app_rqm_descrip =
143 "   RemoveQueueMember(queuename[|interface]):\n"
144 "Dynamically removes interface to an existing queue\n"
145 "If the interface is NOT in the queue and there exists an n+101 priority\n"
146 "then it will then jump to this priority.  Otherwise it will return an error\n"
147 "Returns -1 if there is an error.\n"
148 "Example: RemoveQueueMember(techsupport|SIP/3000)\n"
149 "";
150
151 static char *app_pqm = "PauseQueueMember" ;
152 static char *app_pqm_synopsis = "Pauses a queue member" ;
153 static char *app_pqm_descrip =
154 "   PauseQueueMember([queuename]|interface):\n"
155 "Pauses (blocks calls for) a queue member.\n"
156 "The given interface will be paused in the given queue.  This prevents\n"
157 "any calls from being sent from the queue to the interface until it is\n"
158 "unpaused with UnpauseQueueMember or the manager interface.  If no\n"
159 "queuename is given, the interface is paused in every queue it is a\n"
160 "member of.  If the interface is not in the named queue, or if no queue\n"
161 "is given and the interface is not in any queue, it will jump to\n"
162 " priority n+101, if it exists.  Returns -1 if the interface is not\n"
163 "found and no extension to jump to exists, 0 otherwise.\n"
164 "Example: PauseQueueMember(|SIP/3000)\n";
165
166 static char *app_upqm = "UnpauseQueueMember" ;
167 static char *app_upqm_synopsis = "Unpauses a queue member" ;
168 static char *app_upqm_descrip =
169 "   UnpauseQueueMember([queuename]|interface):\n"
170 "Unpauses (resumes calls to) a queue member.\n"
171 "This is the counterpart to PauseQueueMember and operates exactly the\n"
172 "same way, except it unpauses instead of pausing the given interface.\n"
173 "Example: UnpauseQueueMember(|SIP/3000)\n";
174
175 /* Persistent Members astdb family */
176 static const char *pm_family = "/Queue/PersistentMembers";
177 /* The maximum lengh of each persistent member queue database entry */
178 #define PM_MAX_LEN 2048
179 /* queues.conf [general] option */
180 static int queue_persistent_members = 0;
181 /* queues.conf per-queue weight option */
182 static int use_weight = 0;
183
184
185 #define QUEUE_FLAG_RINGBACKONLY         (1 << 0)
186 #define QUEUE_FLAG_MUSICONHOLD          (1 << 1)
187 #define QUEUE_FLAG_DATAQUALITY          (1 << 2)
188 #define QUEUE_FLAG_REDIR_IN             (1 << 3)
189 #define QUEUE_FLAG_REDIR_OUT            (1 << 4)
190 #define QUEUE_FLAG_DISCON_IN            (1 << 5)
191 #define QUEUE_FLAG_DISCON_OUT           (1 << 6)
192 #define QUEUE_FLAG_MONJOIN              (1 << 7)        /* Should we join the two files when we are done with the call */
193 #define QUEUE_FLAG_DEAD                 (1 << 8)        /* Whether the queue is dead or not */
194 #define QUEUE_FLAG_JOINEMPTY            (1 << 9)        /* Do we care if the queue has no members? */
195 #define QUEUE_FLAG_EVENTWHENCALLED      (1 << 10)       /* Generate an event when the agent is called (before pickup) */
196 #define QUEUE_FLAG_LEAVEWHENEMPTY       (1 << 11)       /* If all agents leave the queue, remove callers from the queue */
197 #define QUEUE_FLAG_REPORTHOLDTIME       (1 << 12)       /* Should we report caller hold time to answering member? */
198 #define QUEUE_FLAG_WRAPPED              (1 << 13)       /* Round Robin - wrapped around? */
199
200 /* We define a custom "local user" structure because we
201    use it not only for keeping track of what is in use but
202    also for keeping track of who we're dialing. */
203
204 struct localuser {
205         struct ast_channel *chan;
206         char interface[256];
207         int stillgoing;
208         int metric;
209         int oldstatus;
210         unsigned int flags;             /* flag bits */
211         time_t lastcall;
212         struct member *member;
213         struct localuser *next;
214 };
215
216 LOCAL_USER_DECL;
217
218 struct queue_ent {
219         struct ast_call_queue *parent;  /* What queue is our parent */
220         char moh[80];                   /* Name of musiconhold to be used */
221         char announce[80];              /* Announcement to play for member when call is answered */
222         char context[80];               /* Context when user exits queue */
223         int pos;                        /* Where we are in the queue */
224         int prio;                       /* Our priority */
225         int last_pos_said;              /* Last position we told the user */
226         time_t last_pos;                /* Last time we told the user their position */
227         int opos;                       /* Where we started in the queue */
228         int handled;                    /* Whether our call was handled */
229         time_t start;                   /* When we started holding */
230         time_t expire;                  /* When this entry should expire (time out of queue) */
231         struct ast_channel *chan;       /* Our channel */
232         struct queue_ent *next;         /* The next queue entry */
233 };
234
235 struct member {
236         char interface[80];             /* Technology/Location */
237         int penalty;                    /* Are we a last resort? */
238         int calls;                      /* Number of calls serviced by this member */
239         int dynamic;                    /* Are we dynamically added? */
240         int status;                     /* Status of queue member */
241         int paused;                     /* Are we paused (not accepting calls)? */
242         time_t lastcall;                /* When last successful call was hungup */
243         struct member *next;            /* Next member */
244 };
245
246 struct ast_call_queue {
247         ast_mutex_t     lock;   
248         char name[80];                  /* Name of the queue */
249         char moh[80];                   /* Name of musiconhold to be used */
250         char announce[80];              /* Announcement to play when call is answered */
251         char context[80];               /* Context for this queue */
252         unsigned int flags;             /* flag bits */
253         int strategy;                   /* Queueing strategy */
254         int announcefrequency;          /* How often to announce their position */
255         int roundingseconds;            /* How many seconds do we round to? */
256         int announceholdtime;           /* When to announce holdtime: 0 = never, -1 = every announcement, 1 = only once */
257         int holdtime;                   /* Current avg holdtime for this queue, based on recursive boxcar filter */
258         int callscompleted;             /* Number of queue calls completed */
259         int callsabandoned;             /* Number of queue calls abandoned */
260         int servicelevel;               /* seconds setting for servicelevel*/
261         int callscompletedinsl;         /* Number of queue calls answered with servicelevel*/
262         char monfmt[8];                 /* Format to use when recording calls */
263         char sound_next[80];            /* Sound file: "Your call is now first in line" (def. queue-youarenext) */
264         char sound_thereare[80];        /* Sound file: "There are currently" (def. queue-thereare) */
265         char sound_calls[80];           /* Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/
266         char sound_holdtime[80];        /* Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
267         char sound_minutes[80];         /* Sound file: "minutes." (def. queue-minutes) */
268         char sound_lessthan[80];        /* Sound file: "less-than" (def. queue-lessthan) */
269         char sound_seconds[80];         /* Sound file: "seconds." (def. queue-seconds) */
270         char sound_thanks[80];          /* Sound file: "Thank you for your patience." (def. queue-thankyou) */
271         char sound_reporthold[80];      /* Sound file: "Hold time" (def. queue-reporthold) */
272
273         int count;                      /* How many entries are in the queue */
274         int maxlen;                     /* Max number of entries in queue */
275         int wrapuptime;                 /* Wrapup Time */
276
277         int retry;                      /* Retry calling everyone after this amount of time */
278         int timeout;                    /* How long to wait for an answer */
279         int weight;                     /* This queue's respective weight */
280         
281         /* Queue strategy things */
282         int rrpos;                      /* Round Robin - position */
283         int memberdelay;                /* Seconds to delay connecting member to caller */
284
285         struct member *members;         /* Member channels to be tried */
286         struct queue_ent *head;         /* Start of the actual queue */
287         struct ast_call_queue *next;    /* Next call queue */
288 };
289
290 static struct ast_call_queue *queues = NULL;
291 AST_MUTEX_DEFINE_STATIC(qlock);
292
293
294 static char *int2strat(int strategy)
295 {
296         int x;
297         for (x=0;x<sizeof(strategies) / sizeof(strategies[0]);x++) {
298                 if (strategy == strategies[x].strategy)
299                         return strategies[x].name;
300         }
301         return "<unknown>";
302 }
303
304 static int strat2int(char *strategy)
305 {
306         int x;
307         for (x=0;x<sizeof(strategies) / sizeof(strategies[0]);x++) {
308                 if (!strcasecmp(strategy, strategies[x].name))
309                         return strategies[x].strategy;
310         }
311         return -1;
312 }
313
314 /* Insert the 'new' entry after the 'prev' entry of queue 'q' */
315 static inline void insert_entry(struct ast_call_queue *q, 
316                                         struct queue_ent *prev, struct queue_ent *new, int *pos)
317 {
318         struct queue_ent *cur;
319
320         if (!q || !new)
321                 return;
322         if (prev) {
323                 cur = prev->next;
324                 prev->next = new;
325         } else {
326                 cur = q->head;
327                 q->head = new;
328         }
329         new->next = cur;
330         new->parent = q;
331         new->pos = ++(*pos);
332         new->opos = *pos;
333 }
334
335 static int has_no_members(struct ast_call_queue *q)
336 {
337         struct member *member;
338         int empty = 1;
339         member = q->members;
340         while(empty && member) {
341                 switch(member->status) {
342                 case AST_DEVICE_UNAVAILABLE:
343                 case AST_DEVICE_INVALID:
344                         /* Not logged on, etc */
345                         break;
346                 default:
347                         /* Not empty */
348                         empty = 0;
349                 }
350                 member = member->next;
351         }
352         return empty;
353 }
354
355 struct statechange {
356         int state;
357         char dev[0];
358 };
359
360 static void *changethread(void *data)
361 {
362         struct ast_call_queue *q;
363         struct statechange *sc = data;
364         struct member *cur;
365         char *loc;
366         char *technology;
367
368         technology = ast_strdupa(sc->dev);
369         loc = strchr(technology, '/');
370         if (loc) {
371                 *loc = '\0';
372                 loc++;
373         } else {
374                 ast_log(LOG_WARNING, "Can't change device '%s' with no technology!\n", sc->dev);
375                 free(sc);
376                 return NULL;
377         }
378         if (option_debug)
379                 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d'\n", technology, loc, sc->state);
380         ast_mutex_lock(&qlock);
381         for (q = queues; q; q = q->next) {
382                 ast_mutex_lock(&q->lock);
383                 cur = q->members;
384                 while(cur) {
385                         if (!strcasecmp(sc->dev, cur->interface)) {
386                                 if (cur->status != sc->state) {
387                                         cur->status = sc->state;
388                                         manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
389                                                 "Queue: %s\r\n"
390                                                 "Location: %s\r\n"
391                                                 "Membership: %s\r\n"
392                                                 "Penalty: %d\r\n"
393                                                 "CallsTaken: %d\r\n"
394                                                 "LastCall: %ld\r\n"
395                                                 "Status: %d\r\n"
396                                                 "Paused: %d\r\n",
397                                         q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
398                                         cur->penalty, cur->calls, cur->lastcall, cur->status, cur->paused);
399                                 }
400                         }
401                         cur = cur->next;
402                 }
403                 ast_mutex_unlock(&q->lock);
404         }
405         ast_mutex_unlock(&qlock);
406         if (option_debug)
407                 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d'\n", technology, loc, sc->state);
408         free(sc);
409         return NULL;
410 }
411
412 static int statechange_queue(const char *dev, int state, void *ign)
413 {
414         /* Avoid potential for deadlocks by spawning a new thread to handle
415            the event */
416         struct statechange *sc;
417         pthread_t t;
418         pthread_attr_t attr;
419
420         sc = malloc(sizeof(struct statechange) + strlen(dev) + 1);
421         if (sc) {
422                 sc->state = state;
423                 strcpy(sc->dev, dev);
424                 pthread_attr_init(&attr);
425                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
426                 if (ast_pthread_create(&t, &attr, changethread, sc)) {
427                         ast_log(LOG_WARNING, "Failed to create update thread!\n");
428                         free(sc);
429                 }
430         }
431         return 0;
432 }
433
434 static int join_queue(char *queuename, struct queue_ent *qe)
435 {
436         struct ast_call_queue *q;
437         struct queue_ent *cur, *prev = NULL;
438         int res = -1;
439         int pos = 0;
440         int inserted = 0;
441
442         ast_mutex_lock(&qlock);
443         for (q = queues; q; q = q->next) {
444                 if (!strcasecmp(q->name, queuename)) {
445                         /* This is our one */
446                         ast_mutex_lock(&q->lock);
447                         if ((!has_no_members(q) || ast_test_flag(q, QUEUE_FLAG_JOINEMPTY)) && (!q->maxlen || (q->count < q->maxlen))) {
448                                 /* There's space for us, put us at the right position inside
449                                  * the queue. 
450                                  * Take into account the priority of the calling user */
451                                 inserted = 0;
452                                 prev = NULL;
453                                 cur = q->head;
454                                 while(cur) {
455                                         /* We have higher priority than the current user, enter
456                                          * before him, after all the other users with priority
457                                          * higher or equal to our priority. */
458                                         if ((!inserted) && (qe->prio > cur->prio)) {
459                                                 insert_entry(q, prev, qe, &pos);
460                                                 inserted = 1;
461                                         }
462                                         cur->pos = ++pos;
463                                         prev = cur;
464                                         cur = cur->next;
465                                 }
466                                 /* No luck, join at the end of the queue */
467                                 if (!inserted)
468                                         insert_entry(q, prev, qe, &pos);
469                                 strncpy(qe->moh, q->moh, sizeof(qe->moh) - 1);
470                                 strncpy(qe->announce, q->announce, sizeof(qe->announce) - 1);
471                                 strncpy(qe->context, q->context, sizeof(qe->context) - 1);
472                                 q->count++;
473                                 res = 0;
474                                 manager_event(EVENT_FLAG_CALL, "Join", 
475                                         "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\n",
476                                         qe->chan->name, 
477                                         qe->chan->cid.cid_num ? qe->chan->cid.cid_num : "unknown",
478                                         qe->chan->cid.cid_name ? qe->chan->cid.cid_name : "unknown",
479                                         q->name, qe->pos, q->count );
480 #if 0
481 ast_log(LOG_NOTICE, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
482 #endif
483                         }
484                         ast_mutex_unlock(&q->lock);
485                         break;
486                 }
487         }
488         ast_mutex_unlock(&qlock);
489         return res;
490 }
491
492 static void free_members(struct ast_call_queue *q, int all)
493 {
494         /* Free non-dynamic members */
495         struct member *curm, *next, *prev;
496         curm = q->members;
497         prev = NULL;
498         while(curm) {
499                 next = curm->next;
500                 if (all || !curm->dynamic) {
501                         if (prev)
502                                 prev->next = next;
503                         else
504                                 q->members = next;
505                         free(curm);
506                 } else 
507                         prev = curm;
508                 curm = next;
509         }
510 }
511
512 static void destroy_queue(struct ast_call_queue *q)
513 {
514         struct ast_call_queue *cur, *prev = NULL;
515         ast_mutex_lock(&qlock);
516         for (cur = queues; cur; cur = cur->next) {
517                 if (cur == q) {
518                         if (prev)
519                                 prev->next = cur->next;
520                         else
521                                 queues = cur->next;
522                 } else {
523                         prev = cur;
524                 }
525         }
526         ast_mutex_unlock(&qlock);
527         free_members(q, 1);
528         ast_mutex_destroy(&q->lock);
529         free(q);
530 }
531
532 static int play_file(struct ast_channel *chan, char *filename)
533 {
534         int res;
535
536         ast_stopstream(chan);
537         res = ast_streamfile(chan, filename, chan->language);
538
539         if (!res)
540                 res = ast_waitstream(chan, "");
541         else
542                 res = 0;
543
544         if (res) {
545                 ast_log(LOG_WARNING, "ast_streamfile failed on %s \n", chan->name);
546                 res = 0;
547         }
548         ast_stopstream(chan);
549
550         return res;
551 }
552
553 static int say_position(struct queue_ent *qe)
554 {
555         int res = 0, avgholdmins, avgholdsecs;
556         time_t now;
557
558         /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/
559         time(&now);
560         if ( (now - qe->last_pos) < 15 )
561                 return -1;
562
563         /* If either our position has changed, or we are over the freq timer, say position */
564         if ( (qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency) )
565                 return -1;
566
567         ast_moh_stop(qe->chan);
568         /* Say we're next, if we are */
569         if (qe->pos == 1) {
570                 res += play_file(qe->chan, qe->parent->sound_next);
571                 goto posout;
572         } else {
573                 res += play_file(qe->chan, qe->parent->sound_thereare);
574                 res += ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */
575                 res += play_file(qe->chan, qe->parent->sound_calls);
576         }
577         /* Round hold time to nearest minute */
578         avgholdmins = abs(( (qe->parent->holdtime + 30) - (now - qe->start) ) / 60);
579
580         /* If they have specified a rounding then round the seconds as well */
581         if(qe->parent->roundingseconds) {
582                 avgholdsecs = (abs(( (qe->parent->holdtime + 30) - (now - qe->start) )) - 60 * avgholdmins) / qe->parent->roundingseconds;
583                 avgholdsecs*= qe->parent->roundingseconds;
584         } else {
585                 avgholdsecs=0;
586         }
587
588         if (option_verbose > 2)
589                 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
590
591         /* If the hold time is >1 min, if it's enabled, and if it's not
592            supposed to be only once and we have already said it, say it */
593         if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) && (!(qe->parent->announceholdtime==1 && qe->last_pos)) ) {
594                 res += play_file(qe->chan, qe->parent->sound_holdtime);
595                 if(avgholdmins>0) {
596                         if (avgholdmins < 2) {
597                                 res += play_file(qe->chan, qe->parent->sound_lessthan);
598                                 res += ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, (char *)NULL);
599                         } else 
600                                 res += ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, (char*) NULL);
601                         res += play_file(qe->chan, qe->parent->sound_minutes);
602                 }
603                 if(avgholdsecs>0) {
604                         res += ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, (char*) NULL);
605                         res += play_file(qe->chan, qe->parent->sound_seconds);
606                 }
607
608         }
609
610         posout:
611         /* Set our last_pos indicators */
612         qe->last_pos = now;
613         qe->last_pos_said = qe->pos;
614
615         if (option_verbose > 2)
616                 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n", qe->chan->name, qe->parent->name, qe->pos);
617         res += play_file(qe->chan, qe->parent->sound_thanks);
618         ast_moh_start(qe->chan, qe->moh);
619
620         return (res>0);
621 }
622
623 static void record_abandoned(struct queue_ent *qe)
624 {
625         ast_mutex_lock(&qe->parent->lock);
626         qe->parent->callsabandoned++;
627         ast_mutex_unlock(&qe->parent->lock);
628 }
629
630 static void recalc_holdtime(struct queue_ent *qe)
631 {
632         int oldvalue, newvalue;
633
634         /* Calculate holdtime using a recursive boxcar filter */
635         /* Thanks to SRT for this contribution */
636         /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
637
638         newvalue = time(NULL) - qe->start;
639
640         ast_mutex_lock(&qe->parent->lock);
641         if (newvalue <= qe->parent->servicelevel)
642                 qe->parent->callscompletedinsl++;
643         oldvalue = qe->parent->holdtime;
644         qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2;
645         ast_mutex_unlock(&qe->parent->lock);
646 }
647
648
649 static void leave_queue(struct queue_ent *qe)
650 {
651         struct ast_call_queue *q;
652         struct queue_ent *cur, *prev = NULL;
653         int pos = 0;
654         q = qe->parent;
655         if (!q)
656                 return;
657         ast_mutex_lock(&q->lock);
658
659         prev = NULL;
660         cur = q->head;
661         while(cur) {
662                 if (cur == qe) {
663                         q->count--;
664
665                         /* Take us out of the queue */
666                         manager_event(EVENT_FLAG_CALL, "Leave",
667                                 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\n",
668                                 qe->chan->name, q->name,  q->count);
669 #if 0
670 ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
671 #endif
672                         /* Take us out of the queue */
673                         if (prev)
674                                 prev->next = cur->next;
675                         else
676                                 q->head = cur->next;
677                 } else {
678                         /* Renumber the people after us in the queue based on a new count */
679                         cur->pos = ++pos;
680                         prev = cur;
681                 }
682                 cur = cur->next;
683         }
684         ast_mutex_unlock(&q->lock);
685         if (ast_test_flag(q, QUEUE_FLAG_DEAD) && !q->count) {   
686                 /* It's dead and nobody is in it, so kill it */
687                 destroy_queue(q);
688         }
689 }
690
691 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
692 {
693         /* Hang up a tree of stuff */
694         struct localuser *oo;
695         while(outgoing) {
696                 /* Hangup any existing lines we have open */
697                 if (outgoing->chan && (outgoing->chan != exception))
698                         ast_hangup(outgoing->chan);
699                 oo = outgoing;
700                 outgoing=outgoing->next;
701                 free(oo);
702         }
703 }
704
705 static int update_status(struct ast_call_queue *q, struct member *member, int status)
706 {
707         struct member *cur;
708         /* Since a reload could have taken place, we have to traverse the list to
709                 be sure it's still valid */
710         ast_mutex_lock(&q->lock);
711         cur = q->members;
712         while(cur) {
713                 if (member == cur) {
714                         cur->status = status;
715                         manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
716                                 "Queue: %s\r\n"
717                                 "Location: %s\r\n"
718                                 "Membership: %s\r\n"
719                                 "Penalty: %d\r\n"
720                                 "CallsTaken: %d\r\n"
721                                 "LastCall: %ld\r\n"
722                                 "Status: %d\r\n"
723                                 "Paused: %d\r\n",
724                                         q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
725                                         cur->penalty, cur->calls, cur->lastcall, cur->status, cur->paused);
726                         break;
727                 }
728                 cur = cur->next;
729         }
730         q->callscompleted++;
731         ast_mutex_unlock(&q->lock);
732         return 0;
733 }
734
735 static int update_dial_status(struct ast_call_queue *q, struct member *member, int status)
736 {
737         if (status == AST_CAUSE_BUSY)
738                 status = AST_DEVICE_BUSY;
739         else if (status == AST_CAUSE_UNREGISTERED)
740                 status = AST_DEVICE_UNAVAILABLE;
741         else if (status == AST_CAUSE_NOSUCHDRIVER)
742                 status = AST_DEVICE_INVALID;
743         else
744                 status = AST_DEVICE_UNKNOWN;
745         return update_status(q, member, status);
746 }
747
748 static int compare_weight(struct ast_call_queue *req_q, struct localuser *req_user, char *qname) 
749 {
750 /* traverse all defined queues which have calls waiting and contain this member
751    return 0 if no other queue has precedence (higher weight) or 1 if found  */
752         struct ast_call_queue *q;
753         struct member *mem;
754         int found = 0, weight = 0, calls = 0;
755         char name[80] = "";
756         
757         strncpy(name, req_q->name, sizeof(name) - 1);
758         weight = req_q->weight;
759         calls = req_q->count;
760         
761         ast_mutex_lock(&qlock);
762         for (q = queues; q; q = q->next) { /* spin queues */
763                 ast_mutex_lock(&q->lock);
764                 if (!strcasecmp(q->name, name)) { /* don't check myself */
765                         ast_mutex_unlock(&q->lock);
766                         continue; 
767                 }
768                 if (q->count && q->members) { /* check only if calls waiting and has members */
769                         for (mem = q->members; mem; mem = mem->next) {  /* spin members */
770                                 if (!strcasecmp(mem->interface, req_user->interface)) {
771                                         ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
772                                         if (q->weight > weight) {
773                                                 ast_log(LOG_DEBUG, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, name, weight, calls);
774                                                 found = 1;
775                                                 strncpy(qname, q->name, sizeof(qname) - 1);
776                                                 break;  /* stop looking for more members */
777                                         }
778                                 }
779                         }
780                 }
781                 ast_mutex_unlock(&q->lock);
782                 if (found) 
783                         break;
784         }
785         ast_mutex_unlock(&qlock);
786         return found;
787 }
788
789
790
791 static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
792 {
793         int res;
794         int status;
795         char tech[256];
796         char *location;
797         char qname[80] = "";
798
799         if (use_weight) { /* fast path */
800                 if (compare_weight(qe->parent,tmp,qname)) {
801                         ast_verbose(VERBOSE_PREFIX_3 "Attempt (%s: %s) delayed by higher priority queue (%s).\n", qe->parent->name, tmp->interface, qname);
802                         if (qe->chan->cdr)
803                                 ast_cdr_busy(qe->chan->cdr);
804                         tmp->stillgoing = 0;
805                         (*busies)++;
806                         return 0;
807                 }
808         }
809         if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
810                 if (option_debug)
811                         ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
812                 if (qe->chan->cdr)
813                         ast_cdr_busy(qe->chan->cdr);
814                 tmp->stillgoing = 0;
815                 (*busies)++;
816                 return 0;
817         }
818         
819         if (tmp->member->paused) {
820                 if (option_debug)
821                         ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface);
822                 if (qe->chan->cdr)
823                         ast_cdr_busy(qe->chan->cdr);
824                 tmp->stillgoing = 0;
825                 return 0;
826         }
827
828         strncpy(tech, tmp->interface, sizeof(tech) - 1);
829         if ((location = strchr(tech, '/')))
830                 *location++ = '\0';
831         else
832                 location = "";
833
834         /* Request the peer */
835         tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
836         if (!tmp->chan) {                       /* If we can't, just go on to the next call */
837 #if 0
838                 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
839 #endif                  
840                 if (qe->chan->cdr)
841                         ast_cdr_busy(qe->chan->cdr);
842                 tmp->stillgoing = 0;
843                 update_dial_status(qe->parent, tmp->member, status);
844                 (*busies)++;
845                 return 0;
846         } else if (status != tmp->oldstatus) 
847                 update_dial_status(qe->parent, tmp->member, status);
848         
849         tmp->chan->appl = "AppQueue";
850         tmp->chan->data = "(Outgoing Line)";
851         tmp->chan->whentohangup = 0;
852         if (tmp->chan->cid.cid_num)
853                 free(tmp->chan->cid.cid_num);
854         tmp->chan->cid.cid_num = NULL;
855         if (tmp->chan->cid.cid_name)
856                 free(tmp->chan->cid.cid_name);
857         tmp->chan->cid.cid_name = NULL;
858         if (tmp->chan->cid.cid_ani)
859                 free(tmp->chan->cid.cid_ani);
860         tmp->chan->cid.cid_ani = NULL;
861         if (qe->chan->cid.cid_num)
862                 tmp->chan->cid.cid_num = strdup(qe->chan->cid.cid_num);
863         if (qe->chan->cid.cid_name)
864                 tmp->chan->cid.cid_name = strdup(qe->chan->cid.cid_name);
865         if (qe->chan->cid.cid_ani)
866                 tmp->chan->cid.cid_ani = strdup(qe->chan->cid.cid_ani);
867
868         /* Inherit specially named variables from parent channel */
869         ast_channel_inherit_variables(qe->chan, tmp->chan);
870
871         /* Presense of ADSI CPE on outgoing channel follows ours */
872         tmp->chan->adsicpe = qe->chan->adsicpe;
873
874         /* Place the call, but don't wait on the answer */
875         res = ast_call(tmp->chan, location, 0);
876         if (res) {
877                 /* Again, keep going even if there's an error */
878                 if (option_debug)
879                         ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
880                 else if (option_verbose > 2)
881                         ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
882                 ast_hangup(tmp->chan);
883                 tmp->chan = NULL;
884                 tmp->stillgoing = 0;
885                 (*busies)++;
886                 return 0;
887         } else {
888                 if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
889                         manager_event(EVENT_FLAG_AGENT, "AgentCalled",
890                                                 "AgentCalled: %s\r\n"
891                                                 "ChannelCalling: %s\r\n"
892                                                 "CallerID: %s\r\n"
893                                                 "CallerIDName: %s\r\n"
894                                                 "Context: %s\r\n"
895                                                 "Extension: %s\r\n"
896                                                 "Priority: %d\r\n",
897                                                 tmp->interface, qe->chan->name,
898                                                 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
899                                                 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
900                                                 qe->chan->context, qe->chan->exten, qe->chan->priority);
901                 }
902                 if (option_verbose > 2)
903                         ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
904         }
905         return 1;
906 }
907
908 static int ring_one(struct queue_ent *qe, struct localuser *outgoing, int *busies)
909 {
910         struct localuser *cur;
911         struct localuser *best;
912         int bestmetric=0;
913         do {
914                 best = NULL;
915                 cur = outgoing;
916                 while(cur) {
917                         if (cur->stillgoing &&                                  /* Not already done */
918                                 !cur->chan &&                                   /* Isn't already going */
919                                 (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
920                                         bestmetric = cur->metric;
921                                         best = cur;
922                         }
923                         cur = cur->next;
924                 }
925                 if (best) {
926                         if (!qe->parent->strategy) {
927                                 /* Ring everyone who shares this best metric (for ringall) */
928                                 cur = outgoing;
929                                 while(cur) {
930                                         if (cur->stillgoing && !cur->chan && (cur->metric <= bestmetric)) {
931                                                 if (option_debug)
932                                                         ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
933                                                 ring_entry(qe, cur, busies);
934                                         }
935                                         cur = cur->next;
936                                 }
937                         } else {
938                                 /* Ring just the best channel */
939                                 if (option_debug)
940                                         ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
941                                 ring_entry(qe, best, busies);
942                         }
943                 }
944         } while (best && !best->chan);
945         if (!best) {
946                 if (option_debug)
947                         ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n");
948                 return 0;
949         }
950         return 1;
951 }
952
953 static int store_next(struct queue_ent *qe, struct localuser *outgoing)
954 {
955         struct localuser *cur;
956         struct localuser *best;
957         int bestmetric=0;
958         best = NULL;
959         cur = outgoing;
960         while(cur) {
961                 if (cur->stillgoing &&                                  /* Not already done */
962                         !cur->chan &&                                   /* Isn't already going */
963                         (!best || (cur->metric < bestmetric))) {        /* We haven't found one yet, or it's better */
964                                 bestmetric = cur->metric;
965                                 best = cur;
966                 }
967                 cur = cur->next;
968         }
969         if (best) {
970                 /* Ring just the best channel */
971                 if (option_debug)
972                         ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
973                 qe->parent->rrpos = best->metric % 1000;
974         } else {
975                 /* Just increment rrpos */
976                 if (!ast_test_flag(qe->parent, QUEUE_FLAG_WRAPPED)) {
977                         /* No more channels, start over */
978                         qe->parent->rrpos = 0;
979                 } else {
980                         /* Prioritize next entry */
981                         qe->parent->rrpos++;
982                 }
983         }
984         ast_clear_flag(qe->parent, QUEUE_FLAG_WRAPPED);
985         return 0;
986 }
987
988 static int valid_exit(struct queue_ent *qe, char digit)
989 {
990         char tmp[2];
991         if (ast_strlen_zero(qe->context))
992                 return 0;
993         tmp[0] = digit;
994         tmp[1] = '\0';
995         if (ast_exists_extension(qe->chan, qe->context, tmp, 1, qe->chan->cid.cid_num)) {
996                 strncpy(qe->chan->context, qe->context, sizeof(qe->chan->context) - 1);
997                 strncpy(qe->chan->exten, tmp, sizeof(qe->chan->exten) - 1);
998                 qe->chan->priority = 0;
999                 return 1;
1000         }
1001         return 0;
1002 }
1003
1004 #define AST_MAX_WATCHERS 256
1005
1006 #define BUILD_STATS do { \
1007                 o = outgoing; \
1008                 found = -1; \
1009                 pos = 1; \
1010                 numlines = 0; \
1011                 watchers[0] = in; \
1012                 while(o) { \
1013                         /* Keep track of important channels */ \
1014                         if (o->stillgoing) { \
1015                                 stillgoing = 1; \
1016                                 if (o->chan) { \
1017                                         watchers[pos++] = o->chan; \
1018                                         found = 1; \
1019                                 } \
1020                         } \
1021                         o = o->next; \
1022                         numlines++; \
1023                 } \
1024         } while(0)
1025         
1026 static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, struct ast_flags *flags, char *digit, int prebusies)
1027 {
1028         char *queue = qe->parent->name;
1029         struct localuser *o;
1030         int found;
1031         int numlines;
1032         int status;
1033         int sentringing = 0;
1034         int numbusies = prebusies;
1035         int numnochan = 0;
1036         int stillgoing = 0;
1037         int orig = *to;
1038         struct ast_frame *f;
1039         struct localuser *peer = NULL;
1040         struct ast_channel *watchers[AST_MAX_WATCHERS];
1041         int pos;
1042         struct ast_channel *winner;
1043         struct ast_channel *in = qe->chan;
1044         
1045         while(*to && !peer) {
1046                 BUILD_STATS;
1047                 if ((found < 0) && stillgoing && !qe->parent->strategy) {
1048                         /* On "ringall" strategy we only move to the next penalty level
1049                            when *all* ringing phones are done in the current penalty level */
1050                         ring_one(qe, outgoing, &numbusies);
1051                         BUILD_STATS;
1052                 }
1053                 if (found < 0) {
1054                         if (numlines == (numbusies + numnochan)) {
1055                                 ast_log(LOG_DEBUG, "Everyone is busy at this time\n");
1056                         } else {
1057                                 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan);
1058                         }
1059                         *to = 0;
1060                         return NULL;
1061                 }
1062                 winner = ast_waitfor_n(watchers, pos, to);
1063                 o = outgoing;
1064                 while(o) {
1065                         if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
1066                                 if (!peer) {
1067                                         if (option_verbose > 2)
1068                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1069                                         peer = o;
1070                                         ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN | QUEUE_FLAG_REDIR_OUT | QUEUE_FLAG_DISCON_IN | QUEUE_FLAG_DISCON_OUT);
1071                                 }
1072                         } else if (o->chan && (o->chan == winner)) {
1073                                 if (!ast_strlen_zero(o->chan->call_forward)) {
1074                                         char tmpchan[256]="";
1075                                         char *stuff;
1076                                         char *tech;
1077                                         strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
1078                                         if ((stuff = strchr(tmpchan, '/'))) {
1079                                                 *stuff = '\0';
1080                                                 stuff++;
1081                                                 tech = tmpchan;
1082                                         } else {
1083                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
1084                                                 stuff = tmpchan;
1085                                                 tech = "Local";
1086                                         }
1087                                         /* Before processing channel, go ahead and check for forwarding */
1088                                         if (option_verbose > 2)
1089                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1090                                         /* Setup parameters */
1091                                         o->chan = ast_request(tech, in->nativeformats, stuff, &status);
1092                                         if (status != o->oldstatus) 
1093                                                 update_dial_status(qe->parent, o->member, status);                                              
1094                                         if (!o->chan) {
1095                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
1096                                                 o->stillgoing = 0;
1097                                                 numnochan++;
1098                                         } else {
1099                                                 if (o->chan->cid.cid_num)
1100                                                         free(o->chan->cid.cid_num);
1101                                                 o->chan->cid.cid_num = NULL;
1102                                                 if (o->chan->cid.cid_name)
1103                                                         free(o->chan->cid.cid_name);
1104                                                 o->chan->cid.cid_name = NULL;
1105
1106                                                 if (in->cid.cid_num) {
1107                                                         o->chan->cid.cid_num = strdup(in->cid.cid_num);
1108                                                         if (!o->chan->cid.cid_num)
1109                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1110                                                 }
1111                                                 if (in->cid.cid_name) {
1112                                                         o->chan->cid.cid_name = strdup(in->cid.cid_name);
1113                                                         if (!o->chan->cid.cid_name)
1114                                                                 ast_log(LOG_WARNING, "Out of memory\n");        
1115                                                 }
1116                                                 strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
1117                                                 o->chan->cdrflags = in->cdrflags;
1118
1119                                                 if (in->cid.cid_ani) {
1120                                                         if (o->chan->cid.cid_ani)
1121                                                                 free(o->chan->cid.cid_ani);
1122                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
1123                                                         if (o->chan->cid.cid_ani)
1124                                                                 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
1125                                                         else
1126                                                                 ast_log(LOG_WARNING, "Out of memory\n");
1127                                                 }
1128                                                 if (o->chan->cid.cid_rdnis) 
1129                                                         free(o->chan->cid.cid_rdnis);
1130                                                 if (!ast_strlen_zero(in->macroexten))
1131                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
1132                                                 else
1133                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
1134                                                 if (ast_call(o->chan, tmpchan, 0)) {
1135                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
1136                                                         o->stillgoing = 0;
1137                                                         ast_hangup(o->chan);
1138                                                         o->chan = NULL;
1139                                                         numnochan++;
1140                                                 }
1141                                         }
1142                                         /* Hangup the original channel now, in case we needed it */
1143                                         ast_hangup(winner);
1144                                         continue;
1145                                 }
1146                                 f = ast_read(winner);
1147                                 if (f) {
1148                                         if (f->frametype == AST_FRAME_CONTROL) {
1149                                                 switch(f->subclass) {
1150                                                 case AST_CONTROL_ANSWER:
1151                                                         /* This is our guy if someone answered. */
1152                                                         if (!peer) {
1153                                                                 if (option_verbose > 2)
1154                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
1155                                                                 peer = o;
1156                                                                 ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN & QUEUE_FLAG_REDIR_OUT & QUEUE_FLAG_DISCON_IN & QUEUE_FLAG_DISCON_OUT);
1157                                                         }
1158                                                         break;
1159                                                 case AST_CONTROL_BUSY:
1160                                                         if (option_verbose > 2)
1161                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
1162                                                         o->stillgoing = 0;
1163                                                         if (in->cdr)
1164                                                                 ast_cdr_busy(in->cdr);
1165                                                         ast_hangup(o->chan);
1166                                                         o->chan = NULL;
1167                                                         if (qe->parent->strategy)
1168                                                                 ring_one(qe, outgoing, &numbusies);
1169                                                         numbusies++;
1170                                                         break;
1171                                                 case AST_CONTROL_CONGESTION:
1172                                                         if (option_verbose > 2)
1173                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
1174                                                         o->stillgoing = 0;
1175                                                         if (in->cdr)
1176                                                                 ast_cdr_busy(in->cdr);
1177                                                         ast_hangup(o->chan);
1178                                                         o->chan = NULL;
1179                                                         if (qe->parent->strategy)
1180                                                                 ring_one(qe, outgoing, &numbusies);
1181                                                         numbusies++;
1182                                                         break;
1183                                                 case AST_CONTROL_RINGING:
1184                                                         if (option_verbose > 2)
1185                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1186                                                         if (!sentringing) {
1187 #if 0
1188                                                                 ast_indicate(in, AST_CONTROL_RINGING);
1189 #endif                                                          
1190                                                                 sentringing++;
1191                                                         }
1192                                                         break;
1193                                                 case AST_CONTROL_OFFHOOK:
1194                                                         /* Ignore going off hook */
1195                                                         break;
1196                                                 default:
1197                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
1198                                                 }
1199                                         }
1200                                         ast_frfree(f);
1201                                 } else {
1202                                         o->stillgoing = 0;
1203                                         ast_hangup(o->chan);
1204                                         o->chan = NULL;
1205                                         if (qe->parent->strategy)
1206                                                 ring_one(qe, outgoing, &numbusies);
1207                                 }
1208                         }
1209                         o = o->next;
1210                 }
1211                 if (winner == in) {
1212                         f = ast_read(in);
1213 #if 0
1214                         if (f && (f->frametype != AST_FRAME_VOICE))
1215                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
1216                         else if (!f || (f->frametype != AST_FRAME_VOICE))
1217                                 printf("Hangup received on %s\n", in->name);
1218 #endif
1219                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
1220                                 /* Got hung up */
1221                                 *to=-1;
1222                                 return NULL;
1223                         }
1224                         if (f && (f->frametype == AST_FRAME_DTMF) && ast_test_flag(flags, QUEUE_FLAG_DISCON_OUT) && (f->subclass == '*')) {
1225                                 if (option_verbose > 3)
1226                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
1227                                 *to=0;
1228                                 return NULL;
1229                         }
1230                         if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) {
1231                                 if (option_verbose > 3)
1232                                         ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c", f->subclass);
1233                                 *to=0;
1234                                 *digit=f->subclass;
1235                                 return NULL;
1236                         }
1237                 }
1238                 if (!*to && (option_verbose > 2))
1239                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
1240         }
1241
1242         return peer;
1243         
1244 }
1245
1246 static int is_our_turn(struct queue_ent *qe)
1247 {
1248         struct queue_ent *ch;
1249         int res;
1250
1251         /* Atomically read the parent head -- does not need a lock */
1252         ch = qe->parent->head;
1253         /* If we are now at the top of the head, break out */
1254         if (ch == qe) {
1255                 if (option_debug)
1256                         ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
1257                 res = 1;
1258         } else {
1259                 if (option_debug)
1260                         ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
1261                 res = 0;
1262         }
1263         return res;
1264 }
1265
1266 static int wait_our_turn(struct queue_ent *qe, int ringing)
1267 {
1268         int res = 0;
1269
1270         /* This is the holding pen for callers 2 through maxlen */
1271         for (;;) {
1272                 if (is_our_turn(qe))
1273                         break;
1274
1275                 /* If we have timed out, break out */
1276                 if (qe->expire && (time(NULL) > qe->expire))
1277                         break;
1278
1279                 /* leave the queue if no agents, if enabled */
1280                 if (ast_test_flag(qe->parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe->parent)) {
1281                         leave_queue(qe);
1282                         break;
1283                 }
1284
1285                 /* Make a position announcement, if enabled */
1286                 if (qe->parent->announcefrequency && !ringing)
1287                         say_position(qe);
1288
1289                 /* Wait a second before checking again */
1290                 res = ast_waitfordigit(qe->chan, RECHECK * 1000);
1291                 if (res)
1292                         break;
1293         }
1294         return res;
1295 }
1296
1297 static int update_queue(struct ast_call_queue *q, struct member *member)
1298 {
1299         struct member *cur;
1300         /* Since a reload could have taken place, we have to traverse the list to
1301                 be sure it's still valid */
1302         ast_mutex_lock(&q->lock);
1303         cur = q->members;
1304         while(cur) {
1305                 if (member == cur) {
1306                         time(&cur->lastcall);
1307                         cur->calls++;
1308                         break;
1309                 }
1310                 cur = cur->next;
1311         }
1312         q->callscompleted++;
1313         ast_mutex_unlock(&q->lock);
1314         return 0;
1315 }
1316
1317 static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp)
1318 {
1319         switch (q->strategy) {
1320         case QUEUE_STRATEGY_RINGALL:
1321                 /* Everyone equal, except for penalty */
1322                 tmp->metric = mem->penalty * 1000000;
1323                 break;
1324         case QUEUE_STRATEGY_ROUNDROBIN:
1325                 if (!pos) {
1326                         if (!ast_test_flag(q, QUEUE_FLAG_WRAPPED)) {
1327                                 /* No more channels, start over */
1328                                 q->rrpos = 0;
1329                         } else {
1330                                 /* Prioritize next entry */
1331                                 q->rrpos++;
1332                         }
1333                         ast_clear_flag(q, QUEUE_FLAG_WRAPPED);
1334                 }
1335                 /* Fall through */
1336         case QUEUE_STRATEGY_RRMEMORY:
1337                 if (pos < q->rrpos) {
1338                         tmp->metric = 1000 + pos;
1339                 } else {
1340                         if (pos > q->rrpos) {
1341                                 /* Indicate there is another priority */
1342                                 ast_set_flag(q, QUEUE_FLAG_WRAPPED);
1343                         }
1344                         tmp->metric = pos;
1345                 }
1346                 tmp->metric += mem->penalty * 1000000;
1347                 break;
1348         case QUEUE_STRATEGY_RANDOM:
1349                 tmp->metric = rand() % 1000;
1350                 tmp->metric += mem->penalty * 1000000;
1351                 break;
1352         case QUEUE_STRATEGY_FEWESTCALLS:
1353                 tmp->metric = mem->calls;
1354                 tmp->metric += mem->penalty * 1000000;
1355                 break;
1356         case QUEUE_STRATEGY_LEASTRECENT:
1357                 if (!mem->lastcall)
1358                         tmp->metric = 0;
1359                 else
1360                         tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
1361                 tmp->metric += mem->penalty * 1000000;
1362                 break;
1363         default:
1364                 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
1365                 break;
1366         }
1367         return 0;
1368 }
1369
1370 static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverride, char *url, int *go_on)
1371 {
1372         struct member *cur;
1373         struct localuser *outgoing=NULL, *tmp = NULL;
1374         int to;
1375         struct ast_flags flags;
1376         char restofit[AST_MAX_EXTENSION];
1377         char oldexten[AST_MAX_EXTENSION]="";
1378         char oldcontext[AST_MAX_EXTENSION]="";
1379         char queuename[256]="";
1380         char *newnum;
1381         char *options;
1382         char *monitorfilename;
1383         struct ast_channel *peer;
1384         struct ast_channel *which;
1385         struct localuser *lpeer;
1386         struct member *member;
1387         int res = 0, bridge = 0;
1388         int zapx = 2;
1389         int numbusies = 0;
1390         int x=0;
1391         char *announce = NULL;
1392         char digit = 0;
1393         time_t callstart;
1394         time_t now;
1395         struct ast_bridge_config config;
1396         /* Hold the lock while we setup the outgoing calls */
1397         ast_mutex_lock(&qe->parent->lock);
1398         if (option_debug)
1399                 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n", 
1400                                                         qe->chan->name);
1401         strncpy(queuename, qe->parent->name, sizeof(queuename) - 1);
1402         time(&now);
1403         cur = qe->parent->members;
1404         if (!ast_strlen_zero(qe->announce))
1405                 announce = qe->announce;
1406         if (announceoverride && !ast_strlen_zero(announceoverride))
1407                 announce = announceoverride;
1408         while(cur) {
1409                 /* Get a technology/[device:]number pair */
1410                 tmp = malloc(sizeof(struct localuser));
1411                 if (!tmp) {
1412                         ast_mutex_unlock(&qe->parent->lock);
1413                         ast_log(LOG_WARNING, "Out of memory\n");
1414                         goto out;
1415                 }
1416                 memset(tmp, 0, sizeof(struct localuser));
1417                 tmp->stillgoing = -1;
1418                 options = ooptions;
1419                 for (; options && *options; options++)
1420                         switch (*options) {
1421                         case 't':
1422                                 ast_set_flag(tmp, QUEUE_FLAG_REDIR_IN);
1423                                 break;
1424                         case 'T':
1425                                 ast_set_flag(tmp, QUEUE_FLAG_REDIR_OUT);
1426                                 break;
1427                         case 'r':
1428                                 ast_set_flag(tmp, QUEUE_FLAG_RINGBACKONLY);
1429                                 break;
1430                         case 'm':
1431                                 ast_set_flag(tmp, QUEUE_FLAG_MUSICONHOLD);
1432                                 break;
1433                         case 'd':
1434                                 ast_set_flag(tmp, QUEUE_FLAG_DATAQUALITY);
1435                                 break;
1436                         case 'h':
1437                                 ast_set_flag(tmp, QUEUE_FLAG_DISCON_IN);
1438                                 break;
1439                         case 'H':
1440                                 ast_set_flag(tmp, QUEUE_FLAG_DISCON_OUT);
1441                                 break;
1442                         case 'n':
1443                                 if ((now - qe->start >= qe->parent->timeout))
1444                                         *go_on = 1;
1445                                 break;
1446                         }
1447                 if (option_debug) {
1448                         if (url)
1449                                 ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
1450                         else 
1451                                 ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
1452                 }
1453
1454                 tmp->member = cur;              /* Never directly dereference!  Could change on reload */
1455                 tmp->oldstatus = cur->status;
1456                 tmp->lastcall = cur->lastcall;
1457                 strncpy(tmp->interface, cur->interface, sizeof(tmp->interface)-1);
1458                 /* If we're dialing by extension, look at the extension to know what to dial */
1459                 if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
1460                         newnum++;
1461                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1);
1462                         snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit);
1463                         if (option_debug)
1464                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface);
1465                 }
1466                 /* Special case: If we ring everyone, go ahead and ring them, otherwise
1467                    just calculate their metric for the appropriate strategy */
1468                 calc_metric(qe->parent, cur, x++, qe, tmp);
1469                 /* Put them in the list of outgoing thingies...  We're ready now. 
1470                    XXX If we're forcibly removed, these outgoing calls won't get
1471                    hung up XXX */
1472                 tmp->next = outgoing;
1473                 outgoing = tmp;         
1474                 /* If this line is up, don't try anybody else */
1475                 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
1476                         break;
1477
1478                 cur = cur->next;
1479         }
1480         if (qe->parent->timeout)
1481                 to = qe->parent->timeout * 1000;
1482         else
1483                 to = -1;
1484         ring_one(qe, outgoing, &numbusies);
1485         ast_mutex_unlock(&qe->parent->lock);
1486         lpeer = wait_for_answer(qe, outgoing, &to, &flags, &digit, numbusies);
1487         ast_mutex_lock(&qe->parent->lock);
1488         if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
1489                 store_next(qe, outgoing);
1490         }
1491         ast_mutex_unlock(&qe->parent->lock);
1492         if (lpeer)
1493                 peer = lpeer->chan;
1494         else
1495                 peer = NULL;
1496         if (!peer) {
1497                 if (to) {
1498                         /* Musta gotten hung up */
1499                         record_abandoned(qe);
1500                         res = -1;
1501                 } else {
1502                         if (digit && valid_exit(qe, digit))
1503                                 res=digit;
1504                         else
1505                                 /* Nobody answered, next please? */
1506                                 res=0;
1507                 }
1508                 if (option_debug)
1509                         ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name);
1510                 goto out;
1511         }
1512         if (peer) {
1513                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1514                    we will always return with -1 so that it is hung up properly after the 
1515                    conversation.  */
1516                 qe->handled++;
1517                 if (!strcmp(qe->chan->type,"Zap")) {
1518                         zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
1519                         ast_channel_setoption(qe->chan,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
1520                 }                       
1521                 if (!strcmp(peer->type,"Zap")) {
1522                         zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
1523                         ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
1524                 }
1525                 /* Update parameters for the queue */
1526                 recalc_holdtime(qe);
1527                 member = lpeer->member;
1528                 hanguptree(outgoing, peer);
1529                 outgoing = NULL;
1530                 if (announce || ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME) || qe->parent->memberdelay) {
1531                         int res2;
1532                         res2 = ast_autoservice_start(qe->chan);
1533                         if (!res2) {
1534                                 if (qe->parent->memberdelay) {
1535                                         ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
1536                                         res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
1537                                 }
1538                                 if (!res2 && announce) {
1539                                         if (play_file(peer, announce))
1540                                                 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
1541                                 }
1542                                 if (!res2 && ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME)) {
1543                                         if (!play_file(peer, qe->parent->sound_reporthold)) {
1544                                                 int holdtime;
1545                                                 time_t now;
1546
1547                                                 time(&now);
1548                                                 holdtime = abs((now - qe->start) / 60);
1549                                                 if (holdtime < 2) {
1550                                                         play_file(peer, qe->parent->sound_lessthan);
1551                                                         ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL);
1552                                                 } else 
1553                                                         ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
1554                                                 play_file(peer, qe->parent->sound_minutes);
1555                                         }
1556                                 }
1557                         }
1558                         res2 |= ast_autoservice_stop(qe->chan);
1559                         if (res2) {
1560                                 /* Agent must have hung up */
1561                                 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
1562                                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
1563                                 if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
1564                                         manager_event(EVENT_FLAG_AGENT, "AgentDump",
1565                                                         "Queue: %s\r\n"
1566                                                         "Uniqueid: %s\r\n"
1567                                                         "Channel: %s\r\n"
1568                                                         "Member: %s\r\n",
1569                                                 queuename, qe->chan->uniqueid, peer->name, member->interface);
1570                                 }
1571                                 ast_hangup(peer);
1572                                 return -1;
1573                         }
1574                 }
1575                 /* Stop music on hold */
1576                 ast_moh_stop(qe->chan);
1577                 /* If appropriate, log that we have a destination channel */
1578                 if (qe->chan->cdr)
1579                         ast_cdr_setdestchan(qe->chan->cdr, peer->name);
1580                 /* Make sure channels are compatible */
1581                 res = ast_channel_make_compatible(qe->chan, peer);
1582                 if (res < 0) {
1583                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "SYSCOMPAT", "%s", "");
1584                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
1585                         ast_hangup(peer);
1586                         return -1;
1587                 }
1588                 /* Begin Monitoring */
1589                 if (qe->parent->monfmt && *qe->parent->monfmt) {
1590                         monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
1591                         if(pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper( qe->chan, "MONITOR_EXEC_ARGS"))
1592                                 which = qe->chan;
1593                         else
1594                                 which = peer;
1595                         if(monitorfilename) {
1596                                 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
1597                         } else {
1598                                 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
1599                         }
1600                         if(ast_test_flag(qe->parent, QUEUE_FLAG_MONJOIN)) {
1601                                 ast_monitor_setjoinfiles(which, 1);
1602                         }
1603                 }
1604                 /* Drop out of the queue at this point, to prepare for next caller */
1605                 leave_queue(qe);                        
1606                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1607                         if (option_debug)
1608                                 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
1609                         ast_channel_sendurl( peer, url );
1610                 }
1611                 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
1612                 if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
1613                         manager_event(EVENT_FLAG_AGENT, "AgentConnect",
1614                                         "Queue: %s\r\n"
1615                                         "Uniqueid: %s\r\n"
1616                                         "Channel: %s\r\n"
1617                                         "Member: %s\r\n"
1618                                         "Holdtime: %ld\r\n",
1619                                 queuename, qe->chan->uniqueid, peer->name, member->interface, (long)time(NULL) - qe->start);
1620                 }
1621                 strncpy(oldcontext, qe->chan->context, sizeof(oldcontext) - 1);
1622                 strncpy(oldexten, qe->chan->exten, sizeof(oldexten) - 1);
1623                 time(&callstart);
1624
1625                 memset(&config,0,sizeof(struct ast_bridge_config));
1626                 
1627                 if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_IN))
1628                         ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1629                 if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_OUT))
1630                         ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1631                 if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_IN))
1632                         ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1633                 if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_OUT))
1634                         ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1635                 bridge = ast_bridge_call(qe->chan,peer,&config);
1636
1637                 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
1638                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
1639                 } else if (qe->chan->_softhangup) {
1640                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
1641                         if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
1642                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
1643                                                 "Queue: %s\r\n"
1644                                                 "Uniqueid: %s\r\n"
1645                                                 "Channel: %s\r\n"
1646                                                 "Member: %s\r\n"
1647                                                 "HoldTime: %ld\r\n"
1648                                                 "TalkTime: %ld\r\n"
1649                                                 "Reason: caller\r\n",
1650                                                 queuename, qe->chan->uniqueid, peer->name, member->interface, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
1651                         }
1652                 } else {
1653                         ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
1654                         if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
1655                                 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
1656                                                 "Queue: %s\r\n"
1657                                                 "Uniqueid: %s\r\n"
1658                                                 "Channel: %s\r\n"
1659                                                 "HoldTime: %ld\r\n"
1660                                                 "TalkTime: %ld\r\n"
1661                                                 "Reason: agent\r\n",
1662                                         queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
1663                         }
1664
1665                 }
1666
1667                 if(bridge != AST_PBX_NO_HANGUP_PEER)
1668                         ast_hangup(peer);
1669                 update_queue(qe->parent, member);
1670                 if (bridge == 0) 
1671                         res = 1; /* JDG: bridge successfull, leave app_queue */
1672                 else 
1673                         res = bridge; /* bridge error, stay in the queue */
1674         }       
1675 out:
1676         hanguptree(outgoing, NULL);
1677         return res;
1678 }
1679
1680 static int wait_a_bit(struct queue_ent *qe)
1681 {
1682         /* Don't need to hold the lock while we setup the outgoing calls */
1683         int retrywait = qe->parent->retry * 1000;
1684         return ast_waitfordigit(qe->chan, retrywait);
1685 }
1686
1687 /* [PHM 06/26/03] */
1688
1689 static struct member * interface_exists(struct ast_call_queue *q, char *interface)
1690 {
1691         struct member *mem;
1692
1693         if (q)
1694                 for (mem = q->members; mem; mem = mem->next)
1695                         if (!strcmp(interface, mem->interface))
1696                                 return mem;
1697
1698         return NULL;
1699 }
1700
1701
1702 static struct member *create_queue_node(char *interface, int penalty, int paused)
1703 {
1704         struct member *cur;
1705         
1706         /* Add a new member */
1707
1708         cur = malloc(sizeof(struct member));
1709
1710         if (cur) {
1711                 memset(cur, 0, sizeof(struct member));
1712                 cur->penalty = penalty;
1713                 cur->paused = paused;
1714                 strncpy(cur->interface, interface, sizeof(cur->interface) - 1);
1715                 if (!strchr(cur->interface, '/'))
1716                         ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
1717                 cur->status = ast_device_state(interface);
1718         }
1719
1720         return cur;
1721 }
1722
1723 /* Dump all members in a specific queue to the databse
1724  *
1725  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>;...
1726  *
1727  */
1728 static void dump_queue_members(struct ast_call_queue *pm_queue)
1729 {
1730         struct member *cur_member = NULL;
1731         char value[PM_MAX_LEN];
1732         int value_len = 0;
1733         int res;
1734
1735         memset(value, 0, sizeof(value));
1736
1737         if (pm_queue) {
1738                 cur_member = pm_queue->members;
1739                 while (cur_member) {
1740                         if (cur_member->dynamic) {
1741                                 value_len = strlen(value);
1742                                 res = snprintf(value+value_len, sizeof(value)-value_len, "%s;%d;%d;", cur_member->interface, cur_member->penalty, cur_member->paused);
1743                                 if (res != strlen(value + value_len)) {
1744                                         ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
1745                                         break;
1746                                 }
1747                         }                                       
1748                         cur_member = cur_member->next;
1749                 }
1750
1751                 if (!ast_strlen_zero(value) && !cur_member) {
1752                         if (ast_db_put(pm_family, pm_queue->name, value))
1753                             ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
1754                 } else {
1755                         /* Delete the entry if the queue is empty or there is an error */
1756                     ast_db_del(pm_family, pm_queue->name);
1757                 }
1758
1759         }
1760
1761 }
1762
1763 static int remove_from_queue(char *queuename, char *interface)
1764 {
1765         struct ast_call_queue *q;
1766         struct member *last_member, *look;
1767         int res = RES_NOSUCHQUEUE;
1768
1769         ast_mutex_lock(&qlock);
1770         for (q = queues ; q ; q = q->next) {
1771                 ast_mutex_lock(&q->lock);
1772                 if (!strcmp(q->name, queuename)) {
1773                         if ((last_member = interface_exists(q, interface))) {
1774                                 if ((look = q->members) == last_member) {
1775                                         q->members = last_member->next;
1776                                 } else {
1777                                         while (look != NULL) {
1778                                                 if (look->next == last_member) {
1779                                                         look->next = last_member->next;
1780                                                         break;
1781                                                 } else {
1782                                                          look = look->next;
1783                                                 }
1784                                         }
1785                                 }
1786                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
1787                                                 "Queue: %s\r\n"
1788                                                 "Location: %s\r\n",
1789                                         q->name, last_member->interface);
1790                                 free(last_member);
1791
1792                                 if (queue_persistent_members)
1793                                     dump_queue_members(q);
1794
1795                                 res = RES_OKAY;
1796                         } else {
1797                                 res = RES_EXISTS;
1798                         }
1799                         ast_mutex_unlock(&q->lock);
1800                         break;
1801                 }
1802                 ast_mutex_unlock(&q->lock);
1803         }
1804         ast_mutex_unlock(&qlock);
1805         return res;
1806 }
1807
1808 static int add_to_queue(char *queuename, char *interface, int penalty, int paused)
1809 {
1810         struct ast_call_queue *q;
1811         struct member *new_member;
1812         int res = RES_NOSUCHQUEUE;
1813
1814         ast_mutex_lock(&qlock);
1815         for (q = queues ; q ; q = q->next) {
1816                 ast_mutex_lock(&q->lock);
1817                 if (!strcmp(q->name, queuename)) {
1818                         if (interface_exists(q, interface) == NULL) {
1819                                 new_member = create_queue_node(interface, penalty, paused);
1820
1821                                 if (new_member != NULL) {
1822                                         new_member->dynamic = 1;
1823                                         new_member->next = q->members;
1824                                         q->members = new_member;
1825                                         manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
1826                                                 "Queue: %s\r\n"
1827                                                 "Location: %s\r\n"
1828                                                 "Membership: %s\r\n"
1829                                                 "Penalty: %d\r\n"
1830                                                 "CallsTaken: %d\r\n"
1831                                                 "LastCall: %ld\r\n"
1832                                                 "Status: %d\r\n"
1833                                                 "Paused: %d\r\n",
1834                                         q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
1835                                         new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused);
1836                                         
1837                                         if (queue_persistent_members)
1838                                                 dump_queue_members(q);
1839
1840                                         res = RES_OKAY;
1841                                 } else {
1842                                         res = RES_OUTOFMEMORY;
1843                                 }
1844                         } else {
1845                                 res = RES_EXISTS;
1846                         }
1847                         ast_mutex_unlock(&q->lock);
1848                         break;
1849                 }
1850                 ast_mutex_unlock(&q->lock);
1851         }
1852         ast_mutex_unlock(&qlock);
1853         return res;
1854 }
1855
1856 static int set_member_paused(char *queuename, char *interface, int paused)
1857 {
1858         int found = 0;
1859         struct ast_call_queue *q;
1860         struct member *mem;
1861
1862         /* Special event for when all queues are paused - individual events still generated */
1863
1864         if (ast_strlen_zero(queuename))
1865                 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
1866
1867         ast_mutex_lock(&qlock);
1868         for (q = queues ; q ; q = q->next) {
1869                 ast_mutex_lock(&q->lock);
1870                 if (ast_strlen_zero(queuename) || !strcmp(q->name, queuename)) {
1871                         if ((mem = interface_exists(q, interface))) {
1872                                 found++;
1873                                 if (mem->paused == paused)
1874                                         ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
1875                                 mem->paused = paused;
1876
1877                                 if (queue_persistent_members)
1878                                     dump_queue_members(q);
1879
1880                                 ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", "");
1881
1882                                 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
1883                                         "Queue: %s\r\n"
1884                                         "Location: %s\r\n"
1885                                         "Paused: %d\r\n",
1886                                                 q->name, mem->interface, paused);
1887                         }
1888                 }
1889                 ast_mutex_unlock(&q->lock);
1890         }
1891         ast_mutex_unlock(&qlock);
1892
1893         if (found)
1894                 return RESULT_SUCCESS;
1895         else
1896                 return RESULT_FAILURE;
1897 }
1898
1899 /* Add members saved in the queue members DB file saves
1900  * created by dump_queue_members(), back into the queues */
1901 static void reload_queue_members(void)
1902 {
1903         char *cur_pm_ptr;       
1904         char *pm_queue_name;
1905         char *pm_interface;
1906         char *pm_penalty_tok;
1907         int pm_penalty = 0;
1908         char *pm_paused_tok;
1909         int pm_paused = 0;
1910         struct ast_db_entry *pm_db_tree = NULL;
1911         int pm_family_len = 0;
1912         struct ast_call_queue *cur_queue = NULL;
1913         char queue_data[PM_MAX_LEN];
1914
1915         pm_db_tree = ast_db_gettree(pm_family, NULL);
1916
1917         pm_family_len = strlen(pm_family);
1918         ast_mutex_lock(&qlock);
1919         /* Each key in 'pm_family' is the name of a specific queue in which
1920          * we will reload members into. */
1921         while (pm_db_tree) {
1922                 pm_queue_name = pm_db_tree->key+pm_family_len+2;
1923
1924                 cur_queue = queues;
1925                 while (cur_queue) {
1926                         ast_mutex_lock(&cur_queue->lock);
1927                         
1928                         if (strcmp(pm_queue_name, cur_queue->name) == 0)
1929                                 break;
1930                         
1931                         ast_mutex_unlock(&cur_queue->lock);
1932                         
1933                         cur_queue = cur_queue->next;
1934                 }
1935
1936                 if (!cur_queue) {
1937                         /* If the queue no longer exists, remove it from the
1938                          * database */
1939                         ast_db_del(pm_family, pm_queue_name);
1940                         pm_db_tree = pm_db_tree->next;
1941                         continue;
1942                 } else
1943                         ast_mutex_unlock(&cur_queue->lock);
1944
1945                 if (!ast_db_get(pm_family, pm_queue_name, queue_data, PM_MAX_LEN)) {
1946                         cur_pm_ptr = queue_data;
1947                         while ((pm_interface = strsep(&cur_pm_ptr, ";"))) {
1948                                 /* On the last iteration, pm_interface is a pointer to an empty string. Don't report a spurious error. */
1949                                 if (pm_interface[0] == 0)
1950                                         break;
1951                                 if (!(pm_penalty_tok = strsep(&cur_pm_ptr, ";"))) {
1952                                         ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (penalty)\n", pm_queue_name);
1953                                         break;
1954                                 }
1955                                 pm_penalty = strtol(pm_penalty_tok, NULL, 10);
1956                                 if (errno == ERANGE) {
1957                                         ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", pm_penalty_tok);
1958                                         break;
1959                                 }
1960
1961                                 /* If ptr[1] is ';', the string is 1 char long and can't be an interface */
1962
1963                                 if (cur_pm_ptr[1] == ';') {
1964                                         if (!(pm_paused_tok = strsep(&cur_pm_ptr, ";"))) {
1965                                                 ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (paused)\n", pm_queue_name);
1966                                                 break;
1967                                         }
1968                                         pm_paused = strtol(pm_paused_tok, NULL, 10);
1969                                         if ((errno == ERANGE) || (pm_paused < 0 || pm_paused > 1)) {
1970                                                 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", pm_paused_tok);
1971                                                 break;
1972                                         }
1973                                 } else if (option_debug)
1974                                         ast_verbose(VERBOSE_PREFIX_3 "Found old-format queue member %s:%s\n", pm_queue_name, pm_interface);
1975         
1976                                 if (option_debug)
1977                                         ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Penalty: %d  Paused: %d\n", pm_queue_name, pm_interface, pm_penalty, pm_paused);
1978         
1979                                 if (add_to_queue(pm_queue_name, pm_interface, pm_penalty, pm_paused) == RES_OUTOFMEMORY) {
1980                                         ast_log(LOG_ERROR, "Out of Memory when loading queue member from astdb\n");
1981                                         break;
1982                                 }
1983                         }
1984                 }
1985                 
1986                 pm_db_tree = pm_db_tree->next;
1987         }
1988
1989         ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
1990         ast_mutex_unlock(&qlock);
1991         if (pm_db_tree) {
1992                 ast_db_freetree(pm_db_tree);
1993                 pm_db_tree = NULL;
1994         }
1995 }
1996
1997 static int pqm_exec(struct ast_channel *chan, void *data)
1998 {
1999         struct localuser *u;
2000         char *queuename, *interface;
2001
2002         if (!data) {
2003                 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface])\n");
2004                 return -1;
2005         }
2006
2007         queuename = ast_strdupa((char *)data);
2008         if (!queuename) {
2009                 ast_log(LOG_ERROR, "Out of memory\n");
2010                 return -1;
2011         }
2012
2013         interface = strchr(queuename, '|');
2014         if (!interface) {
2015                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2016                 return -1;
2017         }
2018
2019         LOCAL_USER_ADD(u);
2020
2021         *interface = '\0';
2022         interface++;
2023
2024         if (set_member_paused(queuename, interface, 1)) {
2025                 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", interface);
2026                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2027                         chan->priority += 100;
2028                         LOCAL_USER_REMOVE(u);
2029                         return 0;
2030                 }
2031                 return -1;
2032         }
2033
2034         LOCAL_USER_REMOVE(u);
2035
2036         return 0;
2037 }
2038
2039 static int upqm_exec(struct ast_channel *chan, void *data)
2040 {
2041         struct localuser *u;
2042         char *queuename, *interface;
2043
2044         if (!data) {
2045                 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface])\n");
2046                 return -1;
2047         }
2048
2049         queuename = ast_strdupa((char *)data);
2050         if (!queuename) {
2051                 ast_log(LOG_ERROR, "Out of memory\n");
2052                 return -1;
2053         }
2054
2055         interface = strchr(queuename, '|');
2056         if (!interface) {
2057                 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface])\n");
2058                 return -1;
2059         }
2060
2061         LOCAL_USER_ADD(u);
2062
2063         *interface = '\0';
2064         interface++;
2065
2066         if (set_member_paused(queuename, interface, 0)) {
2067                 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", interface);
2068                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2069                         chan->priority += 100;
2070                         LOCAL_USER_REMOVE(u);
2071                         return 0;
2072                 }
2073                 return -1;
2074         }
2075
2076         LOCAL_USER_REMOVE(u);
2077
2078         return 0;
2079 }
2080
2081 static int rqm_exec(struct ast_channel *chan, void *data)
2082 {
2083         int res=-1;
2084         struct localuser *u;
2085         char *info, *queuename;
2086         char tmpchan[256]="";
2087         char *interface = NULL;
2088
2089         if (!data) {
2090                 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface])\n");
2091                 return -1;
2092         }
2093
2094         info = ast_strdupa((char *)data);
2095         if (!info) {
2096                 ast_log(LOG_ERROR, "Out of memory\n");
2097                 return -1;
2098         }
2099
2100         LOCAL_USER_ADD(u);
2101
2102         queuename = info;
2103         if (queuename) {
2104                 interface = strchr(queuename, '|');
2105                 if (interface) {
2106                         *interface = '\0';
2107                         interface++;
2108                 }
2109                 else {
2110                         strncpy(tmpchan, chan->name, sizeof(tmpchan) - 1);
2111                         interface = strrchr(tmpchan, '-');
2112                         if (interface)
2113                                 *interface = '\0';
2114                         interface = tmpchan;
2115                 }
2116         }
2117
2118         switch (remove_from_queue(queuename, interface)) {
2119         case RES_OKAY:
2120                 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", interface, queuename);
2121                 res = 0;
2122                 break;
2123         case RES_EXISTS:
2124                 ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
2125                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2126                         chan->priority += 100;
2127                 }
2128                 res = 0;
2129                 break;
2130         case RES_NOSUCHQUEUE:
2131                 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", queuename);
2132                 res = 0;
2133                 break;
2134         case RES_OUTOFMEMORY:
2135                 ast_log(LOG_ERROR, "Out of memory\n");
2136                 break;
2137         }
2138
2139         LOCAL_USER_REMOVE(u);
2140         return res;
2141 }
2142
2143 static int aqm_exec(struct ast_channel *chan, void *data)
2144 {
2145         int res=-1;
2146         struct localuser *u;
2147         char *queuename;
2148         char *info;
2149         char tmpchan[512]="";
2150         char *interface=NULL;
2151         char *penaltys=NULL;
2152         int penalty = 0;
2153
2154         if (!data) {
2155                 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface][|penalty]])\n");
2156                 return -1;
2157         }
2158
2159         info = ast_strdupa((char *)data);
2160         if (!info) {
2161                 ast_log(LOG_ERROR, "Out of memory\n");
2162                 return -1;
2163         }
2164         LOCAL_USER_ADD(u);
2165
2166         queuename = info;
2167         if (queuename) {
2168                 interface = strchr(queuename, '|');
2169                 if (interface) {
2170                         *interface = '\0';
2171                         interface++;
2172                 }
2173                 if (interface) {
2174                         penaltys = strchr(interface, '|');
2175                         if (penaltys) {
2176                                 *penaltys = '\0';
2177                                 penaltys++;
2178                         }
2179                 }
2180                 if (!interface || ast_strlen_zero(interface)) {
2181                         strncpy(tmpchan, chan->name, sizeof(tmpchan) - 1);
2182                         interface = strrchr(tmpchan, '-');
2183                         if (interface)
2184                                 *interface = '\0';
2185                         interface = tmpchan;
2186                 }
2187                 if (penaltys && !ast_strlen_zero(penaltys)) {
2188                         if ((sscanf(penaltys, "%d", &penalty) != 1) || penalty < 0) {
2189                                 ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", penaltys);
2190                                 penalty = 0;
2191                         }
2192                 }
2193         }
2194
2195         switch (add_to_queue(queuename, interface, penalty, 0)) {
2196         case RES_OKAY:
2197                 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
2198                 res = 0;
2199                 break;
2200         case RES_EXISTS:
2201                 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
2202                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
2203                         chan->priority += 100;
2204                 }
2205                 res = 0;
2206                 break;
2207         case RES_NOSUCHQUEUE:
2208                 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", queuename);
2209                 res = 0;
2210                 break;
2211         case RES_OUTOFMEMORY:
2212                 ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", interface, queuename);
2213                 break;
2214         }
2215
2216         LOCAL_USER_REMOVE(u);
2217         return res;
2218 }
2219
2220 static int queue_exec(struct ast_channel *chan, void *data)
2221 {
2222         int res=-1;
2223         int ringing=0;
2224         struct localuser *u;
2225         char *queuename;
2226         char info[512];
2227         char *info_ptr = info;
2228         char *options = NULL;
2229         char *url = NULL;
2230         char *announceoverride = NULL;
2231         char *user_priority;
2232         int prio;
2233         char *queuetimeoutstr = NULL;
2234
2235         /* whether to exit Queue application after the timeout hits */
2236         int go_on = 0;
2237
2238         /* Our queue entry */
2239         struct queue_ent qe;
2240         
2241         if (!data || ast_strlen_zero(data)) {
2242                 ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n");
2243                 return -1;
2244         }
2245         
2246         LOCAL_USER_ADD(u);
2247
2248         /* Setup our queue entry */
2249         memset(&qe, 0, sizeof(qe));
2250         qe.start = time(NULL);
2251         
2252         /* Parse our arguments XXX Check for failure XXX */
2253         strncpy(info, (char *) data, sizeof(info) - 1);
2254         queuename = strsep(&info_ptr, "|");
2255         options = strsep(&info_ptr, "|");
2256         url = strsep(&info_ptr, "|");
2257         announceoverride = strsep(&info_ptr, "|");
2258         queuetimeoutstr = info_ptr;
2259
2260         /* set the expire time based on the supplied timeout; */
2261         if (queuetimeoutstr)
2262                 qe.expire = qe.start + atoi(queuetimeoutstr);
2263         else
2264                 qe.expire = 0;
2265
2266         /* Get the priority from the variable ${QUEUE_PRIO} */
2267         user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
2268         if (user_priority) {
2269                 if (sscanf(user_priority, "%d", &prio) == 1) {
2270                         if (option_debug)
2271                                 ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
2272                                                                 chan->name, prio);
2273                 } else {
2274                         ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
2275                                                         user_priority, chan->name);
2276                         prio = 0;
2277                 }
2278         } else {
2279                 if (option_debug > 2)
2280                         ast_log(LOG_DEBUG, "NO QUEUE_PRIO variable found. Using default.\n");
2281                 prio = 0;
2282         }
2283
2284         if (options) {
2285                 if (strchr(options, 'r')) {
2286                         ringing = 1;
2287                 }
2288         }
2289
2290         if (option_debug)  
2291                 ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
2292                                 queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
2293
2294         qe.chan = chan;
2295         qe.prio = (int)prio;
2296         qe.last_pos_said = 0;
2297         qe.last_pos = 0;
2298         if (!join_queue(queuename, &qe)) {
2299                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "", chan->cid.cid_num ? chan->cid.cid_num : "");
2300                 /* Start music on hold */
2301 check_turns:
2302                 if (ringing) {
2303                         ast_indicate(chan, AST_CONTROL_RINGING);
2304                 } else {              
2305                         ast_moh_start(chan, qe.moh);
2306                 }
2307                 for (;;) {
2308                         /* This is the wait loop for callers 2 through maxlen */
2309
2310                         res = wait_our_turn(&qe, ringing);
2311                         /* If they hungup, return immediately */
2312                         if (res < 0) {
2313                                 /* Record this abandoned call */
2314                                 record_abandoned(&qe);
2315                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2316                                 if (option_verbose > 2) {
2317                                         ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", queuename);
2318                                         res = -1;
2319                                 }
2320                                 break;
2321                         }
2322                         if (!res) 
2323                                 break;
2324                         if (valid_exit(&qe, res)) {
2325                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2326                                 break;
2327                         }
2328                 }
2329                 if (!res) {
2330                         int makeannouncement = 0;
2331                         for (;;) {
2332                                 /* This is the wait loop for the head caller*/
2333                                 /* To exit, they may get their call answered; */
2334                                 /* they may dial a digit from the queue context; */
2335                                 /* or, they may timeout. */
2336
2337                                 /* Leave if we have exceeded our queuetimeout */
2338                                 if (qe.expire && (time(NULL) > qe.expire)) {
2339                                         res = 0;
2340                                         break;
2341                                 }
2342
2343                                 if (makeannouncement) {
2344                                         /* Make a position announcement, if enabled */
2345                                         if (qe.parent->announcefrequency && !ringing)
2346                                                 say_position(&qe);
2347                                 }
2348                                 makeannouncement = 1;
2349
2350                                 /* Try calling all queue members for 'timeout' seconds */
2351                                 res = try_calling(&qe, options, announceoverride, url, &go_on);
2352                                 if (res) {
2353                                         if (res < 0) {
2354                                                 if (!qe.handled)
2355                                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2356                                         } else if (res > 0)
2357                                                 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2358                                         break;
2359                                 }
2360
2361                                 /* leave the queue if no agents, if enabled */
2362                                 if (ast_test_flag(qe.parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe.parent)) {
2363                                         res = 0;
2364                                         break;
2365                                 }
2366
2367                                 /* Leave if we have exceeded our queuetimeout */
2368                                 if (qe.expire && (time(NULL) > qe.expire)) {
2369                                         res = 0;
2370                                         break;
2371                                 }
2372
2373                                 /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
2374                                 res = wait_a_bit(&qe);
2375                                 if (res < 0) {
2376                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
2377                                         if (option_verbose > 2) {
2378                                                 ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s when they almost made it\n", queuename);
2379                                                 res = -1;
2380                                         }
2381                                         break;
2382                                 }
2383                                 if (res && valid_exit(&qe, res)) {
2384                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos);
2385                                         break;
2386                                 }
2387                                 /* exit after 'timeout' cycle if 'n' option enabled */
2388                                 if (go_on) {
2389                                         if (option_verbose > 2) {
2390                                                 ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n");
2391                                                 res = -1;
2392                                         }
2393                                         ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
2394                                         res = 0;
2395                                         break;
2396                                 }
2397                                 /* Since this is a priority queue and 
2398                                  * it is not sure that we are still at the head
2399                                  * of the queue, go and check for our turn again.
2400                                  */
2401                                 if (!is_our_turn(&qe)) {
2402                                         if (option_debug)
2403                                                 ast_log(LOG_DEBUG, "Darn priorities, going back in queue (%s)!\n",
2404                                                                 qe.chan->name);
2405                                         goto check_turns;
2406                                 }
2407                         }
2408                 }
2409                 /* Don't allow return code > 0 */
2410                 if (res >= 0 && res != AST_PBX_KEEPALIVE) {
2411                         res = 0;        
2412                         if (ringing) {
2413                                 ast_indicate(chan, -1);
2414                         } else {
2415                                 ast_moh_stop(chan);
2416                         }                       
2417                         ast_stopstream(chan);
2418                 }
2419                 leave_queue(&qe);
2420         } else {
2421                 ast_log(LOG_WARNING, "Unable to join queue '%s'\n", queuename);
2422                 res =  0;
2423         }
2424         LOCAL_USER_REMOVE(u);
2425         return res;
2426 }
2427
2428 static void reload_queues(void)
2429 {
2430         struct ast_call_queue *q, *ql, *qn;
2431         struct ast_config *cfg;
2432         char *cat, *tmp;
2433         struct ast_variable *var;
2434         struct member *prev, *cur;
2435         int new;
2436         char *general_val = NULL;
2437         
2438         cfg = ast_config_load("queues.conf");
2439         if (!cfg) {
2440                 ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
2441                 return;
2442         }
2443         ast_mutex_lock(&qlock);
2444         use_weight=0;
2445         /* Mark all queues as dead for the moment */
2446         q = queues;
2447         while(q) {
2448                 ast_set_flag(q, QUEUE_FLAG_DEAD);
2449                 q = q->next;
2450         }
2451         /* Chug through config file */
2452         cat = ast_category_browse(cfg, NULL);
2453         while(cat) {
2454                 if (strcasecmp(cat, "general")) {       /* Define queue */
2455                         /* Look for an existing one */
2456                         q = queues;
2457                         while(q) {
2458                                 if (!strcmp(q->name, cat))
2459                                         break;
2460                                 q = q->next;
2461                         }
2462                         if (!q) {
2463                                 /* Make one then */
2464                                 q = malloc(sizeof(struct ast_call_queue));
2465                                 if (q) {
2466                                         /* Initialize it */
2467                                         memset(q, 0, sizeof(struct ast_call_queue));
2468                                         ast_mutex_init(&q->lock);
2469                                         strncpy(q->name, cat, sizeof(q->name) - 1);
2470                                         new = 1;
2471                                 } else new = 0;
2472                         } else
2473                                         new = 0;
2474                         if (q) {
2475                                 if (!new) 
2476                                         ast_mutex_lock(&q->lock);
2477                                 /* Re-initialize the queue */
2478                                 ast_clear_flag(q, QUEUE_FLAG_DEAD);
2479                                 q->retry = 0;
2480                                 q->timeout = -1;
2481                                 q->maxlen = 0;
2482                                 q->announcefrequency = 0;
2483                                 q->announceholdtime = 0;
2484                                 q->roundingseconds = 0; /* Default - don't announce seconds */
2485                                 q->holdtime = 0;
2486                                 q->callscompleted = 0;
2487                                 q->callsabandoned = 0;
2488                                 q->callscompletedinsl = 0;
2489                                 q->servicelevel = 0;
2490                                 q->wrapuptime = 0;
2491                                 free_members(q, 0);
2492                                 q->moh[0] = '\0';
2493                                 q->announce[0] = '\0';
2494                                 q->context[0] = '\0';
2495                                 q->monfmt[0] = '\0';
2496                                 strncpy(q->sound_next, "queue-youarenext", sizeof(q->sound_next) - 1);
2497                                 strncpy(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare) - 1);
2498                                 strncpy(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls) - 1);
2499                                 strncpy(q->sound_holdtime, "queue-holdtime", sizeof(q->sound_holdtime) - 1);
2500                                 strncpy(q->sound_minutes, "queue-minutes", sizeof(q->sound_minutes) - 1);
2501                                 strncpy(q->sound_seconds, "queue-seconds", sizeof(q->sound_seconds) - 1);
2502                                 strncpy(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks) - 1);
2503                                 strncpy(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan) - 1);
2504                                 strncpy(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold) - 1);
2505                                 prev = q->members;
2506                                 if (prev) {
2507                                         /* find the end of any dynamic members */
2508                                         while(prev->next)
2509                                                 prev = prev->next;
2510                                 }
2511                                 var = ast_variable_browse(cfg, cat);
2512                                 while(var) {
2513                                         if (!strcasecmp(var->name, "member")) {
2514                                                 /* Add a new member */
2515                                                 cur = malloc(sizeof(struct member));
2516                                                 if (cur) {
2517                                                         memset(cur, 0, sizeof(struct member));
2518                                                         strncpy(cur->interface, var->value, sizeof(cur->interface) - 1);
2519                                                         if ((tmp = strchr(cur->interface, ','))) {
2520                                                                 *tmp = '\0';
2521                                                                 tmp++;
2522                                                                 cur->penalty = atoi(tmp);
2523                                                                 if (cur->penalty < 0)
2524                                                                         cur->penalty = 0;
2525                                                         }
2526                                                         if (!strchr(cur->interface, '/'))
2527                                                                 ast_log(LOG_WARNING, "No location at line %d of queue.conf\n", var->lineno);
2528                                                         if (prev)
2529                                                                 prev->next = cur;
2530                                                         else
2531                                                                 q->members = cur;
2532                                                         prev = cur;
2533                                                 }
2534                                         } else if (!strcasecmp(var->name, "music") || !strcasecmp(var->name, "musiconhold")) {
2535                                                 strncpy(q->moh, var->value, sizeof(q->moh) - 1);
2536                                         } else if (!strcasecmp(var->name, "announce")) {
2537                                                 strncpy(q->announce, var->value, sizeof(q->announce) - 1);
2538                                         } else if (!strcasecmp(var->name, "context")) {
2539                                                 strncpy(q->context, var->value, sizeof(q->context) - 1);
2540                                         } else if (!strcasecmp(var->name, "timeout")) {
2541                                                 q->timeout = atoi(var->value);
2542                                         } else if (!strcasecmp(var->name, "monitor-join")) {
2543                                                 ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_MONJOIN);
2544                                         } else if (!strcasecmp(var->name, "monitor-format")) {
2545                                                 strncpy(q->monfmt, var->value, sizeof(q->monfmt) - 1);
2546                                         } else if (!strcasecmp(var->name, "queue-youarenext")) {
2547                                                 strncpy(q->sound_next, var->value, sizeof(q->sound_next) - 1);
2548                                         } else if (!strcasecmp(var->name, "queue-thereare")) {
2549                                                 strncpy(q->sound_thereare, var->value, sizeof(q->sound_thereare) - 1);
2550                                         } else if (!strcasecmp(var->name, "queue-callswaiting")) {
2551                                                 strncpy(q->sound_calls, var->value, sizeof(q->sound_calls) - 1);
2552                                         } else if (!strcasecmp(var->name, "queue-holdtime")) {
2553                                                 strncpy(q->sound_holdtime, var->value, sizeof(q->sound_holdtime) - 1);
2554                                         } else if (!strcasecmp(var->name, "queue-minutes")) {
2555                                                 strncpy(q->sound_minutes, var->value, sizeof(q->sound_minutes) - 1);
2556                                         } else if (!strcasecmp(var->name, "queue-seconds")) {
2557                                                 strncpy(q->sound_seconds, var->value, sizeof(q->sound_seconds) - 1);
2558                                         } else if (!strcasecmp(var->name, "queue-lessthan")) {
2559                                                 strncpy(q->sound_lessthan, var->value, sizeof(q->sound_lessthan) - 1);
2560                                         } else if (!strcasecmp(var->name, "queue-thankyou")) {
2561                                                 strncpy(q->sound_thanks, var->value, sizeof(q->sound_thanks) - 1);
2562                                         } else if (!strcasecmp(var->name, "queue-reporthold")) {
2563                                                 strncpy(q->sound_reporthold, var->value, sizeof(q->sound_reporthold) - 1);
2564                                         } else if (!strcasecmp(var->name, "announce-frequency")) {
2565                                                 q->announcefrequency = atoi(var->value);
2566                                         } else if (!strcasecmp(var->name, "announce-round-seconds")) {
2567                                                 q->roundingseconds = atoi(var->value);
2568                                                 if(q->roundingseconds>60 || q->roundingseconds<0) {
2569                                                         ast_log(LOG_WARNING, "'%s' isn't a valid value for queue-rounding-seconds using 0 instead at line %d of queue.conf\n", var->value, var->lineno);
2570                                                         q->roundingseconds=0;
2571                                                 }
2572                                         } else if (!strcasecmp(var->name, "announce-holdtime")) {
2573                                                 q->announceholdtime = (!strcasecmp(var->value,"once")) ? 1 : ast_true(var->value);
2574                                         } else if (!strcasecmp(var->name, "retry")) {
2575                                                 q->retry = atoi(var->value);
2576                                         } else if (!strcasecmp(var->name, "wrapuptime")) {
2577                                                 q->wrapuptime = atoi(var->value);
2578                                         } else if (!strcasecmp(var->name, "maxlen")) {
2579                                                 q->maxlen = atoi(var->value);
2580                                         } else if (!strcasecmp(var->name, "servicelevel")) {
2581                                                 q->servicelevel= atoi(var->value);
2582                                         } else if (!strcasecmp(var->name, "strategy")) {
2583                                                 q->strategy = strat2int(var->value);
2584                                                 if (q->strategy < 0) {
2585                                                         ast_log(LOG_WARNING, "'%s' isn't a valid strategy, using ringall instead\n", var->value);
2586                                                         q->strategy = 0;
2587                                                 }
2588                                         } else if (!strcasecmp(var->name, "joinempty")) {
2589                                                 ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_JOINEMPTY);
2590                                         } else if (!strcasecmp(var->name, "leavewhenempty")) {
2591                                                 ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_LEAVEWHENEMPTY);
2592                                         } else if (!strcasecmp(var->name, "eventwhencalled")) {
2593                                                 ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_EVENTWHENCALLED);
2594                                         } else if (!strcasecmp(var->name, "reportholdtime")) {
2595                                                 ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_REPORTHOLDTIME);
2596                                         } else if (!strcasecmp(var->name, "memberdelay")) {
2597                                                 q->memberdelay = atoi(var->value);
2598                                         } else if (!strcasecmp(var->name, "weight")) {
2599                                                 q->weight = atoi(var->value);
2600                                                 if (q->weight)
2601                                                         use_weight++;
2602                                         } else {
2603                                                 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno);
2604                                         }
2605                                         var = var->next;
2606                                 }
2607                                 if (q->retry < 1)
2608                                         q->retry = DEFAULT_RETRY;
2609                                 if (q->timeout < 0)
2610                                         q->timeout = DEFAULT_TIMEOUT;
2611                                 if (q->maxlen < 0)
2612                                         q->maxlen = 0;
2613                                 if (!new) 
2614                                         ast_mutex_unlock(&q->lock);
2615                                 if (new) {
2616                                         q->next = queues;
2617                                         queues = q;
2618                                 }
2619                         }
2620                 } else {        
2621                         /* Initialize global settings */
2622                         queue_persistent_members = 0;
2623                         if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
2624                             queue_persistent_members = ast_true(general_val);
2625                 }
2626                 cat = ast_category_browse(cfg, cat);
2627         }
2628         ast_config_destroy(cfg);
2629         q = queues;
2630         ql = NULL;
2631         while(q) {
2632                 qn = q->next;
2633                 if (ast_test_flag(q, QUEUE_FLAG_DEAD)) {
2634                         if (ql)
2635                                 ql->next = q->next;
2636                         else
2637                                 queues = q->next;
2638                         if (!q->count) {
2639                                 free(q);
2640                         } else
2641                                 ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n");
2642                 } else {
2643                         for (cur = q->members; cur; cur = cur->next)
2644                                 cur->status = ast_device_state(cur->interface);
2645                         ql = q;
2646                 }
2647                 q = qn;
2648         }
2649         ast_mutex_unlock(&qlock);
2650 }
2651
2652 static char *status2str(int status, char *buf, int buflen)
2653 {
2654         switch(status) {
2655         case AST_DEVICE_UNKNOWN:
2656                 strncpy(buf, "unknown", buflen - 1);
2657                 break;
2658         case AST_DEVICE_NOT_INUSE:
2659                 strncpy(buf, "notinuse", buflen - 1);
2660                 break;
2661         case AST_DEVICE_INUSE:
2662                 strncpy(buf, "inuse", buflen - 1);
2663                 break;
2664         case AST_DEVICE_BUSY:
2665                 strncpy(buf, "busy", buflen - 1);
2666                 break;
2667         case AST_DEVICE_INVALID:
2668                 strncpy(buf, "invalid", buflen - 1);
2669                 break;
2670         case AST_DEVICE_UNAVAILABLE:
2671                 strncpy(buf, "unavailable", buflen - 1);
2672                 break;
2673         default:
2674                 snprintf(buf, buflen, "unknown status %d", status);
2675         }
2676         return buf;
2677 }
2678
2679 static int __queues_show(int fd, int argc, char **argv, int queue_show)
2680 {
2681         struct ast_call_queue *q;
2682         struct queue_ent *qe;
2683         struct member *mem;
2684         int pos;
2685         time_t now;
2686         char max[80] = "";
2687         char calls[80] = "";
2688         char tmpbuf[80] = "";
2689         float sl = 0;
2690
2691         time(&now);
2692         if ((!queue_show && argc != 2) || (queue_show && argc != 3))
2693                 return RESULT_SHOWUSAGE;
2694         ast_mutex_lock(&qlock);
2695         q = queues;
2696         if (!q) {       
2697                 ast_mutex_unlock(&qlock);
2698                 if (queue_show)
2699                         ast_cli(fd, "No such queue: %s.\n",argv[2]);
2700                 else
2701                         ast_cli(fd, "No queues.\n");
2702                 return RESULT_SUCCESS;
2703         }
2704         while(q) {
2705                 ast_mutex_lock(&q->lock);
2706                 if (queue_show) {
2707                         if (strcasecmp(q->name, argv[2]) != 0) {
2708                                 ast_mutex_unlock(&q->lock);
2709                                 q = q->next;
2710                                 if (!q) {
2711                                         ast_cli(fd, "No such queue: %s.\n",argv[2]);
2712                                         break;
2713                                 }
2714                                 continue;
2715                         }
2716                 }
2717                 if (q->maxlen)
2718                         snprintf(max, sizeof(max), "%d", q->maxlen);
2719                 else
2720                         strncpy(max, "unlimited", sizeof(max) - 1);
2721                 sl = 0;
2722                 if(q->callscompleted > 0)
2723                         sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted);
2724                 ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds\n",
2725                         q->name, q->count, max, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel);
2726                 if (q->members) {
2727                         ast_cli(fd, "   Members: \n");
2728                         for (mem = q->members; mem; mem = mem->next) {
2729                                 if (mem->penalty)
2730                                         snprintf(max, sizeof(max) - 20, " with penalty %d", mem->penalty);
2731                                 else
2732                                         max[0] = '\0';
2733                                 if (mem->dynamic)
2734                                         strncat(max, " (dynamic)", sizeof(max) - strlen(max) - 1);
2735                                 if (mem->paused)
2736                                         strncat(max, " (paused)", sizeof(max) - strlen(max) - 1);
2737                                 if (mem->status)
2738                                         snprintf(max + strlen(max), sizeof(max) - strlen(max), " (%s)", status2str(mem->status, tmpbuf, sizeof(tmpbuf)));
2739                                 if (mem->calls) {
2740                                         snprintf(calls, sizeof(calls), " has taken %d calls (last was %ld secs ago)",
2741                                                         mem->calls, (long)(time(NULL) - mem->lastcall));
2742                                 } else
2743                                         strncpy(calls, " has taken no calls yet", sizeof(calls) - 1);
2744                                 ast_cli(fd, "      %s%s%s\n", mem->interface, max, calls);
2745                         }
2746                 } else
2747                         ast_cli(fd, "   No Members\n");
2748                 if (q->head) {
2749                         pos = 1;
2750                         ast_cli(fd, "   Callers: \n");
2751                         for (qe = q->head; qe; qe = qe->next) 
2752        &nbs