Put winning FollowMe outgoing call on hold if the caller put it on hold.
[asterisk/asterisk.git] / apps / app_followme.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * A full-featured Find-Me/Follow-Me Application
5  * 
6  * Copyright (C) 2005-2006, BJ Weschke All Rights Reserved.
7  *
8  * BJ Weschke <bweschke@btwtech.com>
9  *
10  * This code is released by the author with no restrictions on usage.
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  */
19
20 /*! \file
21  *
22  * \brief Find-Me Follow-Me application
23  *
24  * \author BJ Weschke <bweschke@btwtech.com>
25  *
26  * \arg See \ref Config_followme
27  *
28  * \ingroup applications
29  */
30
31 /*** MODULEINFO
32         <depend>chan_local</depend>
33         <support_level>core</support_level>
34  ***/
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include <signal.h>
41
42 #include "asterisk/paths.h"     /* use ast_config_AST_SPOOL_DIR */
43 #include "asterisk/lock.h"
44 #include "asterisk/file.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/say.h"
50 #include "asterisk/features.h"
51 #include "asterisk/musiconhold.h"
52 #include "asterisk/cli.h"
53 #include "asterisk/manager.h"
54 #include "asterisk/config.h"
55 #include "asterisk/utils.h"
56 #include "asterisk/causes.h"
57 #include "asterisk/astdb.h"
58 #include "asterisk/dsp.h"
59 #include "asterisk/app.h"
60
61 /*** DOCUMENTATION
62         <application name="FollowMe" language="en_US">
63                 <synopsis>
64                         Find-Me/Follow-Me application.
65                 </synopsis>
66                 <syntax>
67                         <parameter name="followmeid" required="true" />
68                         <parameter name="options">
69                                 <optionlist>
70                                         <option name="a">
71                                                 <para>Record the caller's name so it can be announced to the
72                                                 callee on each step.</para>
73                                         </option>
74                                         <option name="d">
75                                                 <para>Disable the 'Please hold while we try to connect your call' announcement.</para>
76                                         </option>
77                                         <option name="I">
78                                                 <para>Asterisk will ignore any connected line update requests
79                                                 it may receive on this dial attempt.</para>
80                                         </option>
81                                         <option name="l">
82                                                 <para>Disable local call optimization so that applications with
83                                                 audio hooks between the local bridge don't get dropped when the
84                                                 calls get joined directly.</para>
85                                         </option>
86                                         <option name="N">
87                                                 <para>Don't answer the incoming call until we're ready to
88                                                 connect the caller or give up.</para>
89                                                 <note>
90                                                         <para>This option is ignored if the call is already answered.</para>
91                                                 </note>
92                                                 <note>
93                                                         <para>If the call is not already answered, the 'a' and 's'
94                                                         options are ignored while the 'd' option is implicitly enabled.</para>
95                                                 </note>
96                                         </option>
97                                         <option name="n">
98                                                 <para>Playback the unreachable status message if we've run out
99                                                 of steps or the callee has elected not to be reachable.</para>
100                                         </option>
101                                         <option name="s">
102                                                 <para>Playback the incoming status message prior to starting
103                                                 the follow-me step(s)</para>
104                                         </option>
105                                 </optionlist>
106                         </parameter>
107                 </syntax>
108                 <description>
109                         <para>This application performs Find-Me/Follow-Me functionality for the caller
110                         as defined in the profile matching the <replaceable>followmeid</replaceable> parameter in
111                         <filename>followme.conf</filename>. If the specified <replaceable>followmeid</replaceable>
112                         profile doesn't exist in <filename>followme.conf</filename>, execution will be returned
113                         to the dialplan and call execution will continue at the next priority.</para>
114                         <para>Returns -1 on hangup.</para>
115                 </description>
116         </application>
117  ***/
118
119 static char *app = "FollowMe";
120
121 /*! Maximum accept/decline DTMF string plus terminator. */
122 #define MAX_YN_STRING           20
123
124 /*! \brief Number structure */
125 struct number {
126         char number[512];       /*!< Phone Number(s) and/or Extension(s) */
127         long timeout;           /*!< Dial Timeout, if used. */
128         int order;              /*!< The order to dial in */
129         AST_LIST_ENTRY(number) entry; /*!< Next Number record */
130 };
131
132 /*! \brief Data structure for followme scripts */
133 struct call_followme {
134         ast_mutex_t lock;
135         char name[AST_MAX_EXTENSION];   /*!< Name - FollowMeID */
136         char moh[MAX_MUSICCLASS];       /*!< Music On Hold Class to be used */
137         char context[AST_MAX_CONTEXT];  /*!< Context to dial from */
138         unsigned int active;            /*!< Profile is active (1), or disabled (0). */
139         int realtime;           /*!< Cached from realtime */
140         char takecall[MAX_YN_STRING];   /*!< Digit mapping to take a call */
141         char nextindp[MAX_YN_STRING];   /*!< Digit mapping to decline a call */
142         char callfromprompt[PATH_MAX];  /*!< Sound prompt name and path */
143         char norecordingprompt[PATH_MAX];       /*!< Sound prompt name and path */
144         char optionsprompt[PATH_MAX];   /*!< Sound prompt name and path */
145         char plsholdprompt[PATH_MAX];   /*!< Sound prompt name and path */
146         char statusprompt[PATH_MAX];    /*!< Sound prompt name and path */
147         char sorryprompt[PATH_MAX];     /*!< Sound prompt name and path */
148
149         AST_LIST_HEAD_NOLOCK(numbers, number) numbers;     /*!< Head of the list of follow-me numbers */
150         AST_LIST_HEAD_NOLOCK(blnumbers, number) blnumbers; /*!< Head of the list of black-listed numbers */
151         AST_LIST_HEAD_NOLOCK(wlnumbers, number) wlnumbers; /*!< Head of the list of white-listed numbers */
152         AST_LIST_ENTRY(call_followme) entry;           /*!< Next Follow-Me record */
153 };
154
155 struct fm_args {
156         char *mohclass;
157         AST_LIST_HEAD_NOLOCK(cnumbers, number) cnumbers;
158         /*! Accumulated connected line information from inbound call. */
159         struct ast_party_connected_line connected_in;
160         /*! Accumulated connected line information from outbound call. */
161         struct ast_party_connected_line connected_out;
162         /*! TRUE if connected line information from inbound call changed. */
163         unsigned int pending_in_connected_update:1;
164         /*! TRUE if connected line information from outbound call is available. */
165         unsigned int pending_out_connected_update:1;
166         /*! TRUE if caller has a pending hold request for the winning call. */
167         unsigned int pending_hold:1;
168         /*! Music On Hold Class suggested by caller hold for winning call. */
169         char suggested_moh[MAX_MUSICCLASS];
170         char context[AST_MAX_CONTEXT];
171         char namerecloc[PATH_MAX];
172         char takecall[MAX_YN_STRING];   /*!< Digit mapping to take a call */
173         char nextindp[MAX_YN_STRING];   /*!< Digit mapping to decline a call */
174         char callfromprompt[PATH_MAX];  /*!< Sound prompt name and path */
175         char norecordingprompt[PATH_MAX];       /*!< Sound prompt name and path */
176         char optionsprompt[PATH_MAX];   /*!< Sound prompt name and path */
177         char plsholdprompt[PATH_MAX];   /*!< Sound prompt name and path */
178         char statusprompt[PATH_MAX];    /*!< Sound prompt name and path */
179         char sorryprompt[PATH_MAX];     /*!< Sound prompt name and path */
180         struct ast_flags followmeflags;
181 };
182
183 struct findme_user {
184         struct ast_channel *ochan;
185         /*! Accumulated connected line information from outgoing call. */
186         struct ast_party_connected_line connected;
187         long digts;
188         int ynidx;
189         int state;
190         char dialarg[256];
191         /*! Collected digits to accept/decline the call. */
192         char yn[MAX_YN_STRING];
193         /*! TRUE if connected line information is available. */
194         unsigned int pending_connected_update:1;
195         AST_LIST_ENTRY(findme_user) entry;
196 };
197
198 enum {
199         FOLLOWMEFLAG_STATUSMSG = (1 << 0),
200         FOLLOWMEFLAG_RECORDNAME = (1 << 1),
201         FOLLOWMEFLAG_UNREACHABLEMSG = (1 << 2),
202         FOLLOWMEFLAG_DISABLEHOLDPROMPT = (1 << 3),
203         FOLLOWMEFLAG_NOANSWER = (1 << 4),
204         FOLLOWMEFLAG_DISABLEOPTIMIZATION = (1 << 5),
205         FOLLOWMEFLAG_IGNORE_CONNECTEDLINE = (1 << 6),
206 };
207
208 AST_APP_OPTIONS(followme_opts, {
209         AST_APP_OPTION('a', FOLLOWMEFLAG_RECORDNAME),
210         AST_APP_OPTION('d', FOLLOWMEFLAG_DISABLEHOLDPROMPT),
211         AST_APP_OPTION('I', FOLLOWMEFLAG_IGNORE_CONNECTEDLINE),
212         AST_APP_OPTION('l', FOLLOWMEFLAG_DISABLEOPTIMIZATION),
213         AST_APP_OPTION('N', FOLLOWMEFLAG_NOANSWER),
214         AST_APP_OPTION('n', FOLLOWMEFLAG_UNREACHABLEMSG),
215         AST_APP_OPTION('s', FOLLOWMEFLAG_STATUSMSG),
216 });
217
218 static const char *featuredigittostr;
219 static int featuredigittimeout = 5000;          /*!< Feature Digit Timeout */
220 static const char *defaultmoh = "default";      /*!< Default Music-On-Hold Class */
221
222 static char takecall[MAX_YN_STRING] = "1";
223 static char nextindp[MAX_YN_STRING] = "2";
224 static char callfromprompt[PATH_MAX] = "followme/call-from";
225 static char norecordingprompt[PATH_MAX] = "followme/no-recording";
226 static char optionsprompt[PATH_MAX] = "followme/options";
227 static char plsholdprompt[PATH_MAX] = "followme/pls-hold-while-try";
228 static char statusprompt[PATH_MAX] = "followme/status";
229 static char sorryprompt[PATH_MAX] = "followme/sorry";
230
231
232 static AST_RWLIST_HEAD_STATIC(followmes, call_followme);
233 AST_LIST_HEAD_NOLOCK(findme_user_listptr, findme_user);
234
235 static void free_numbers(struct call_followme *f)
236 {
237         /* Free numbers attached to the profile */
238         struct number *prev;
239
240         while ((prev = AST_LIST_REMOVE_HEAD(&f->numbers, entry)))
241                 /* Free the number */
242                 ast_free(prev);
243         AST_LIST_HEAD_INIT_NOLOCK(&f->numbers);
244
245         while ((prev = AST_LIST_REMOVE_HEAD(&f->blnumbers, entry)))
246                 /* Free the blacklisted number */
247                 ast_free(prev);
248         AST_LIST_HEAD_INIT_NOLOCK(&f->blnumbers);
249
250         while ((prev = AST_LIST_REMOVE_HEAD(&f->wlnumbers, entry)))
251                 /* Free the whitelisted number */
252                 ast_free(prev);
253         AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers);
254 }
255
256
257 /*! \brief Allocate and initialize followme profile */
258 static struct call_followme *alloc_profile(const char *fmname)
259 {
260         struct call_followme *f;
261
262         if (!(f = ast_calloc(1, sizeof(*f))))
263                 return NULL;
264
265         ast_mutex_init(&f->lock);
266         ast_copy_string(f->name, fmname, sizeof(f->name));
267         f->moh[0] = '\0';
268         f->context[0] = '\0';
269         ast_copy_string(f->takecall, takecall, sizeof(f->takecall));
270         ast_copy_string(f->nextindp, nextindp, sizeof(f->nextindp));
271         ast_copy_string(f->callfromprompt, callfromprompt, sizeof(f->callfromprompt));
272         ast_copy_string(f->norecordingprompt, norecordingprompt, sizeof(f->norecordingprompt));
273         ast_copy_string(f->optionsprompt, optionsprompt, sizeof(f->optionsprompt));
274         ast_copy_string(f->plsholdprompt, plsholdprompt, sizeof(f->plsholdprompt));
275         ast_copy_string(f->statusprompt, statusprompt, sizeof(f->statusprompt));
276         ast_copy_string(f->sorryprompt, sorryprompt, sizeof(f->sorryprompt));
277         AST_LIST_HEAD_INIT_NOLOCK(&f->numbers);
278         AST_LIST_HEAD_INIT_NOLOCK(&f->blnumbers);
279         AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers);
280         return f;
281 }
282
283 static void init_profile(struct call_followme *f)
284 {
285         f->active = 1;
286         ast_copy_string(f->moh, defaultmoh, sizeof(f->moh));
287 }
288
289    
290    
291 /*! \brief Set parameter in profile from configuration file */
292 static void profile_set_param(struct call_followme *f, const char *param, const char *val, int linenum, int failunknown)
293 {
294
295         if (!strcasecmp(param, "musicclass") || !strcasecmp(param, "musiconhold") || !strcasecmp(param, "music")) 
296                 ast_copy_string(f->moh, val, sizeof(f->moh));
297         else if (!strcasecmp(param, "context")) 
298                 ast_copy_string(f->context, val, sizeof(f->context));
299         else if (!strcasecmp(param, "takecall"))
300                 ast_copy_string(f->takecall, val, sizeof(f->takecall));
301         else if (!strcasecmp(param, "declinecall"))
302                 ast_copy_string(f->nextindp, val, sizeof(f->nextindp));
303         else if (!strcasecmp(param, "call-from-prompt") || !strcasecmp(param, "call_from_prompt"))
304                 ast_copy_string(f->callfromprompt, val, sizeof(f->callfromprompt));
305         else if (!strcasecmp(param, "followme-norecording-prompt") || !strcasecmp(param, "norecording_prompt")) 
306                 ast_copy_string(f->norecordingprompt, val, sizeof(f->norecordingprompt));
307         else if (!strcasecmp(param, "followme-options-prompt") || !strcasecmp(param, "options_prompt")) 
308                 ast_copy_string(f->optionsprompt, val, sizeof(f->optionsprompt));
309         else if (!strcasecmp(param, "followme-pls-hold-prompt") || !strcasecmp(param, "pls_hold_prompt"))
310                 ast_copy_string(f->plsholdprompt, val, sizeof(f->plsholdprompt));
311         else if (!strcasecmp(param, "followme-status-prompt") || !strcasecmp(param, "status_prompt")) 
312                 ast_copy_string(f->statusprompt, val, sizeof(f->statusprompt));
313         else if (!strcasecmp(param, "followme-sorry-prompt") || !strcasecmp(param, "sorry_prompt")) 
314                 ast_copy_string(f->sorryprompt, val, sizeof(f->sorryprompt));
315         else if (failunknown) {
316                 if (linenum >= 0)
317                         ast_log(LOG_WARNING, "Unknown keyword in profile '%s': %s at line %d of followme.conf\n", f->name, param, linenum);
318                 else
319                         ast_log(LOG_WARNING, "Unknown keyword in profile '%s': %s\n", f->name, param);
320         }
321 }
322
323 /*! \brief Add a new number */
324 static struct number *create_followme_number(const char *number, int timeout, int numorder)
325 {
326         struct number *cur;
327         char *buf = ast_strdupa(number);
328         char *tmp;
329
330         if (!(cur = ast_calloc(1, sizeof(*cur))))
331                 return NULL;
332
333         cur->timeout = timeout;
334         if ((tmp = strchr(buf, ',')))
335                 *tmp = '\0';
336         ast_copy_string(cur->number, buf, sizeof(cur->number));
337         cur->order = numorder;
338         ast_debug(1, "Created a number, %s, order of , %d, with a timeout of %ld.\n", cur->number, cur->order, cur->timeout);
339
340         return cur;
341 }
342
343 /*! \brief Reload followme application module */
344 static int reload_followme(int reload)
345 {
346         struct call_followme *f;
347         struct ast_config *cfg;
348         char *cat = NULL, *tmp;
349         struct ast_variable *var;
350         struct number *cur, *nm;
351         char numberstr[90];
352         int timeout;
353         int numorder;
354         const char *takecallstr;
355         const char *declinecallstr;
356         const char *tmpstr;
357         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
358
359         if (!(cfg = ast_config_load("followme.conf", config_flags))) {
360                 ast_log(LOG_WARNING, "No follow me config file (followme.conf), so no follow me\n");
361                 return 0;
362         } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
363                 return 0;
364         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
365                 ast_log(LOG_ERROR, "Config file followme.conf is in an invalid format.  Aborting.\n");
366                 return 0;
367         }
368
369         AST_RWLIST_WRLOCK(&followmes);
370
371         /* Reset Global Var Values */
372         featuredigittimeout = 5000;
373
374         /* Mark all profiles as inactive for the moment */
375         AST_RWLIST_TRAVERSE(&followmes, f, entry) {
376                 f->active = 0;
377         }
378
379         featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout");
380
381         if (!ast_strlen_zero(featuredigittostr)) {
382                 if (!sscanf(featuredigittostr, "%30d", &featuredigittimeout))
383                         featuredigittimeout = 5000;
384         }
385
386         if ((takecallstr = ast_variable_retrieve(cfg, "general", "takecall")) && !ast_strlen_zero(takecallstr)) {
387                 ast_copy_string(takecall, takecallstr, sizeof(takecall));
388         }
389
390         if ((declinecallstr = ast_variable_retrieve(cfg, "general", "declinecall")) && !ast_strlen_zero(declinecallstr)) {
391                 ast_copy_string(nextindp, declinecallstr, sizeof(nextindp));
392         }
393
394         if ((tmpstr = ast_variable_retrieve(cfg, "general", "call-from-prompt")) && !ast_strlen_zero(tmpstr)) {
395                 ast_copy_string(callfromprompt, tmpstr, sizeof(callfromprompt));
396         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "call_from_prompt")) && !ast_strlen_zero(tmpstr)) {
397                 ast_copy_string(callfromprompt, tmpstr, sizeof(callfromprompt));
398         }
399
400         if ((tmpstr = ast_variable_retrieve(cfg, "general", "norecording-prompt")) && !ast_strlen_zero(tmpstr)) {
401                 ast_copy_string(norecordingprompt, tmpstr, sizeof(norecordingprompt));
402         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "norecording_prompt")) && !ast_strlen_zero(tmpstr)) {
403                 ast_copy_string(norecordingprompt, tmpstr, sizeof(norecordingprompt));
404         }
405
406
407         if ((tmpstr = ast_variable_retrieve(cfg, "general", "options-prompt")) && !ast_strlen_zero(tmpstr)) {
408                 ast_copy_string(optionsprompt, tmpstr, sizeof(optionsprompt));
409         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "options_prompt")) && !ast_strlen_zero(tmpstr)) {
410                 ast_copy_string(optionsprompt, tmpstr, sizeof(optionsprompt));
411         }
412
413         if ((tmpstr = ast_variable_retrieve(cfg, "general", "pls-hold-prompt")) && !ast_strlen_zero(tmpstr)) {
414                 ast_copy_string(plsholdprompt, tmpstr, sizeof(plsholdprompt));
415         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "pls_hold_prompt")) && !ast_strlen_zero(tmpstr)) {
416                 ast_copy_string(plsholdprompt, tmpstr, sizeof(plsholdprompt));
417         }
418
419         if ((tmpstr = ast_variable_retrieve(cfg, "general", "status-prompt")) && !ast_strlen_zero(tmpstr)) {
420                 ast_copy_string(statusprompt, tmpstr, sizeof(statusprompt));
421         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "status_prompt")) && !ast_strlen_zero(tmpstr)) {
422                 ast_copy_string(statusprompt, tmpstr, sizeof(statusprompt));
423         }
424
425         if ((tmpstr = ast_variable_retrieve(cfg, "general", "sorry-prompt")) && !ast_strlen_zero(tmpstr)) {
426                 ast_copy_string(sorryprompt, tmpstr, sizeof(sorryprompt));
427         } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "sorry_prompt")) && !ast_strlen_zero(tmpstr)) {
428                 ast_copy_string(sorryprompt, tmpstr, sizeof(sorryprompt));
429         }
430
431         /* Chug through config file */
432         while ((cat = ast_category_browse(cfg, cat))) {
433                 int new = 0;
434
435                 if (!strcasecmp(cat, "general"))
436                         continue;
437
438                 /* Look for an existing one */
439                 AST_LIST_TRAVERSE(&followmes, f, entry) {
440                         if (!strcasecmp(f->name, cat))
441                                 break;
442                 }
443
444                 ast_debug(1, "New profile %s.\n", cat);
445
446                 if (!f) {
447                         /* Make one then */
448                         f = alloc_profile(cat);
449                         new = 1;
450                 }
451
452                 /* Totally fail if we fail to find/create an entry */
453                 if (!f)
454                         continue;
455
456                 if (!new)
457                         ast_mutex_lock(&f->lock);
458                 /* Re-initialize the profile */
459                 init_profile(f);
460                 free_numbers(f);
461                 var = ast_variable_browse(cfg, cat);
462                 while (var) {
463                         if (!strcasecmp(var->name, "number")) {
464                                 int idx = 0;
465
466                                 /* Add a new number */
467                                 ast_copy_string(numberstr, var->value, sizeof(numberstr));
468                                 if ((tmp = strchr(numberstr, ','))) {
469                                         *tmp++ = '\0';
470                                         timeout = atoi(tmp);
471                                         if (timeout < 0) {
472                                                 timeout = 25;
473                                         }
474                                         if ((tmp = strchr(tmp, ','))) {
475                                                 *tmp++ = '\0';
476                                                 numorder = atoi(tmp);
477                                                 if (numorder < 0)
478                                                         numorder = 0;
479                                         } else 
480                                                 numorder = 0;
481                                 } else {
482                                         timeout = 25;
483                                         numorder = 0;
484                                 }
485
486                                 if (!numorder) {
487                                         idx = 1;
488                                         AST_LIST_TRAVERSE(&f->numbers, nm, entry) 
489                                                 idx++;
490                                         numorder = idx;
491                                 }
492                                 cur = create_followme_number(numberstr, timeout, numorder);
493                                 if (cur) {
494                                         AST_LIST_INSERT_TAIL(&f->numbers, cur, entry);
495                                 }
496                         } else {
497                                 profile_set_param(f, var->name, var->value, var->lineno, 1);
498                                 ast_debug(2, "Logging parameter %s with value %s from lineno %d\n", var->name, var->value, var->lineno);
499                         }
500                         var = var->next;
501                 } /* End while(var) loop */
502
503                 if (!new) 
504                         ast_mutex_unlock(&f->lock);
505                 else
506                         AST_RWLIST_INSERT_HEAD(&followmes, f, entry);
507         }
508
509         ast_config_destroy(cfg);
510
511         AST_RWLIST_UNLOCK(&followmes);
512
513         return 1;
514 }
515
516 static void clear_caller(struct findme_user *tmpuser)
517 {
518         struct ast_channel *outbound;
519
520         if (!tmpuser->ochan) {
521                 /* Call already cleared. */
522                 return;
523         }
524
525         outbound = tmpuser->ochan;
526         ast_channel_lock(outbound);
527         if (!ast_channel_cdr(outbound)) {
528                 ast_channel_cdr_set(outbound, ast_cdr_alloc());
529                 if (ast_channel_cdr(outbound)) {
530                         ast_cdr_init(ast_channel_cdr(outbound), outbound);
531                 }
532         }
533         if (ast_channel_cdr(outbound)) {
534                 char tmp[256];
535
536                 snprintf(tmp, sizeof(tmp), "Local/%s", tmpuser->dialarg);
537                 ast_cdr_setapp(ast_channel_cdr(outbound), "FollowMe", tmp);
538                 ast_cdr_update(outbound);
539                 ast_cdr_start(ast_channel_cdr(outbound));
540                 ast_cdr_end(ast_channel_cdr(outbound));
541                 /* If the cause wasn't handled properly */
542                 if (ast_cdr_disposition(ast_channel_cdr(outbound), ast_channel_hangupcause(outbound))) {
543                         ast_cdr_failed(ast_channel_cdr(outbound));
544                 }
545         } else {
546                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
547         }
548         ast_channel_unlock(outbound);
549         ast_hangup(outbound);
550         tmpuser->ochan = NULL;
551 }
552
553 static void clear_calling_tree(struct findme_user_listptr *findme_user_list) 
554 {
555         struct findme_user *tmpuser;
556
557         AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
558                 clear_caller(tmpuser);
559         }
560 }
561
562 static void destroy_calling_node(struct findme_user *node)
563 {
564         clear_caller(node);
565         ast_party_connected_line_free(&node->connected);
566         ast_free(node);
567 }
568
569 static void destroy_calling_tree(struct findme_user_listptr *findme_user_list)
570 {
571         struct findme_user *fmuser;
572
573         while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
574                 destroy_calling_node(fmuser);
575         }
576 }
577
578 static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, struct fm_args *tpargs)
579 {
580         struct ast_party_connected_line connected;
581         struct ast_channel *watchers[256];
582         int pos;
583         struct ast_channel *winner;
584         struct ast_frame *f;
585         struct findme_user *tmpuser;
586         int to = 0;
587         int livechannels;
588         int tmpto;
589         long totalwait = 0, wtd = 0, towas = 0;
590         char *callfromname;
591         char *pressbuttonname;
592
593         /* ------------ wait_for_winner_channel start --------------- */ 
594
595         callfromname = ast_strdupa(tpargs->callfromprompt);
596         pressbuttonname = ast_strdupa(tpargs->optionsprompt);
597
598         totalwait = nm->timeout * 1000;
599
600         for (;;) {
601                 to = 1000;
602                 pos = 1; 
603                 livechannels = 0;
604                 watchers[0] = caller;
605
606                 winner = NULL;
607                 AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
608                         if (!tmpuser->ochan) {
609                                 continue;
610                         }
611                         if (tmpuser->state == 3) {
612                                 tmpuser->digts += (towas - wtd);
613                         }
614                         if (tmpuser->digts && (tmpuser->digts > featuredigittimeout)) {
615                                 ast_verb(3, "<%s> We've been waiting for digits longer than we should have.\n",
616                                         ast_channel_name(tmpuser->ochan));
617                                 if (!ast_strlen_zero(tpargs->namerecloc)) {
618                                         tmpuser->state = 1;
619                                         tmpuser->digts = 0;
620                                         if (!ast_streamfile(tmpuser->ochan, callfromname, ast_channel_language(tmpuser->ochan))) {
621                                                 ast_sched_runq(ast_channel_sched(tmpuser->ochan));
622                                         } else {
623                                                 ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
624                                                 clear_caller(tmpuser);
625                                                 continue;
626                                         }
627                                 } else {
628                                         tmpuser->state = 2;
629                                         tmpuser->digts = 0;
630                                         if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
631                                                 ast_sched_runq(ast_channel_sched(tmpuser->ochan));
632                                         else {
633                                                 ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
634                                                 clear_caller(tmpuser);
635                                                 continue;
636                                         }
637                                 }
638                         }
639                         if (ast_channel_stream(tmpuser->ochan)) {
640                                 ast_sched_runq(ast_channel_sched(tmpuser->ochan));
641                                 tmpto = ast_sched_wait(ast_channel_sched(tmpuser->ochan));
642                                 if (tmpto > 0 && tmpto < to)
643                                         to = tmpto;
644                                 else if (tmpto < 0 && !ast_channel_timingfunc(tmpuser->ochan)) {
645                                         ast_stopstream(tmpuser->ochan);
646                                         switch (tmpuser->state) {
647                                         case 1:
648                                                 ast_verb(3, "<%s> Playback of the call-from file appears to be done.\n",
649                                                         ast_channel_name(tmpuser->ochan));
650                                                 if (!ast_streamfile(tmpuser->ochan, tpargs->namerecloc, ast_channel_language(tmpuser->ochan))) {
651                                                         tmpuser->state = 2;
652                                                 } else {
653                                                         ast_log(LOG_NOTICE, "<%s> Unable to playback %s. Maybe the caller didn't record their name?\n",
654                                                                 ast_channel_name(tmpuser->ochan), tpargs->namerecloc);
655                                                         memset(tmpuser->yn, 0, sizeof(tmpuser->yn));
656                                                         tmpuser->ynidx = 0;
657                                                         if (!ast_streamfile(tmpuser->ochan, pressbuttonname, ast_channel_language(tmpuser->ochan)))
658                                                                 tmpuser->state = 3;
659                                                         else {
660                                                                 ast_log(LOG_WARNING, "Unable to playback %s.\n", pressbuttonname);
661                                                                 clear_caller(tmpuser);
662                                                                 continue;
663                                                         }
664                                                 }
665                                                 break;
666                                         case 2:
667                                                 ast_verb(3, "<%s> Playback of name file appears to be done.\n",
668                                                         ast_channel_name(tmpuser->ochan));
669                                                 memset(tmpuser->yn, 0, sizeof(tmpuser->yn));
670                                                 tmpuser->ynidx = 0;
671                                                 if (!ast_streamfile(tmpuser->ochan, pressbuttonname, ast_channel_language(tmpuser->ochan))) {
672                                                         tmpuser->state = 3;
673                                                 } else {
674                                                         clear_caller(tmpuser);
675                                                         continue;
676                                                 }
677                                                 break;
678                                         case 3:
679                                                 ast_verb(3, "<%s> Playback of the next step file appears to be done.\n",
680                                                         ast_channel_name(tmpuser->ochan));
681                                                 tmpuser->digts = 0;
682                                                 break;
683                                         default:
684                                                 break;
685                                         }
686                                 }
687                         }
688                         watchers[pos++] = tmpuser->ochan;
689                         livechannels++;
690                 }
691                 if (!livechannels) {
692                         ast_verb(3, "No live channels left for this step.\n");
693                         return NULL;
694                 }
695
696                 tmpto = to;
697                 if (to < 0) {
698                         to = 1000;
699                         tmpto = 1000;
700                 }
701                 towas = to;
702                 winner = ast_waitfor_n(watchers, pos, &to);
703                 tmpto -= to;
704                 totalwait -= tmpto;
705                 wtd = to;
706                 if (totalwait <= 0) {
707                         ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
708                         clear_calling_tree(findme_user_list);
709                         return NULL;
710                 }
711                 if (winner) {
712                         /* Need to find out which channel this is */
713                         if (winner != caller) {
714                                 /* The winner is an outgoing channel. */
715                                 AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
716                                         if (tmpuser->ochan == winner) {
717                                                 break;
718                                         }
719                                 }
720                         } else {
721                                 tmpuser = NULL;
722                         }
723
724                         f = ast_read(winner);
725                         if (f) {
726                                 if (f->frametype == AST_FRAME_CONTROL) {
727                                         switch (f->subclass.integer) {
728                                         case AST_CONTROL_HANGUP:
729                                                 ast_verb(3, "%s received a hangup frame.\n", ast_channel_name(winner));
730                                                 if (f->data.uint32) {
731                                                         ast_channel_hangupcause_set(winner, f->data.uint32);
732                                                 }
733                                                 if (!tmpuser) {
734                                                         ast_verb(3, "The calling channel hungup. Need to drop everyone.\n");
735                                                         ast_frfree(f);
736                                                         return NULL;
737                                                 }
738                                                 clear_caller(tmpuser);
739                                                 break;
740                                         case AST_CONTROL_ANSWER:
741                                                 if (!tmpuser) {
742                                                         /* The caller answered?  We want an outgoing channel to answer. */
743                                                         break;
744                                                 }
745                                                 ast_verb(3, "%s answered %s\n", ast_channel_name(winner), ast_channel_name(caller));
746                                                 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 
747                                                 ast_channel_hangupcause_set(winner, AST_CAUSE_NORMAL_CLEARING);
748                                                 ast_channel_hangupcause_set(caller, AST_CAUSE_NORMAL_CLEARING);
749                                                 ast_verb(3, "Starting playback of %s\n", callfromname);
750                                                 if (!ast_strlen_zero(tpargs->namerecloc)) {
751                                                         if (!ast_streamfile(winner, callfromname, ast_channel_language(winner))) {
752                                                                 ast_sched_runq(ast_channel_sched(winner));
753                                                                 tmpuser->state = 1;
754                                                         } else {
755                                                                 ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
756                                                                 clear_caller(tmpuser);
757                                                         }
758                                                 } else {
759                                                         tmpuser->state = 2;
760                                                         if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
761                                                                 ast_sched_runq(ast_channel_sched(tmpuser->ochan));
762                                                         else {
763                                                                 ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
764                                                                 clear_caller(tmpuser);
765                                                         }
766                                                 }
767                                                 break;
768                                         case AST_CONTROL_BUSY:
769                                                 ast_verb(3, "%s is busy\n", ast_channel_name(winner));
770                                                 if (tmpuser) {
771                                                         /* Outbound call was busy.  Drop it. */
772                                                         clear_caller(tmpuser);
773                                                 }
774                                                 break;
775                                         case AST_CONTROL_CONGESTION:
776                                                 ast_verb(3, "%s is circuit-busy\n", ast_channel_name(winner));
777                                                 if (tmpuser) {
778                                                         /* Outbound call was congested.  Drop it. */
779                                                         clear_caller(tmpuser);
780                                                 }
781                                                 break;
782                                         case AST_CONTROL_RINGING:
783                                                 ast_verb(3, "%s is ringing\n", ast_channel_name(winner));
784                                                 break;
785                                         case AST_CONTROL_PROGRESS:
786                                                 ast_verb(3, "%s is making progress\n", ast_channel_name(winner));
787                                                 break;
788                                         case AST_CONTROL_VIDUPDATE:
789                                                 ast_verb(3, "%s requested a video update\n", ast_channel_name(winner));
790                                                 break;
791                                         case AST_CONTROL_SRCUPDATE:
792                                                 ast_verb(3, "%s requested a source update\n", ast_channel_name(winner));
793                                                 break;
794                                         case AST_CONTROL_PROCEEDING:
795                                                 ast_verb(3, "%s is proceeding\n", ast_channel_name(winner));
796                                                 break;
797                                         case AST_CONTROL_HOLD:
798                                                 ast_verb(3, "%s placed call on hold\n", ast_channel_name(winner));
799                                                 if (!tmpuser) {
800                                                         /* Caller placed outgoing calls on hold. */
801                                                         tpargs->pending_hold = 1;
802                                                         if (f->data.ptr) {
803                                                                 ast_copy_string(tpargs->suggested_moh, f->data.ptr,
804                                                                         sizeof(tpargs->suggested_moh));
805                                                         } else {
806                                                                 tpargs->suggested_moh[0] = '\0';
807                                                         }
808                                                 } else {
809                                                         /*
810                                                          * Outgoing call placed caller on hold.
811                                                          *
812                                                          * Ignore because the outgoing call should not be able to place
813                                                          * the caller on hold until after they are bridged.
814                                                          */
815                                                 }
816                                                 break;
817                                         case AST_CONTROL_UNHOLD:
818                                                 ast_verb(3, "%s removed call from hold\n", ast_channel_name(winner));
819                                                 if (!tmpuser) {
820                                                         /* Caller removed outgoing calls from hold. */
821                                                         tpargs->pending_hold = 0;
822                                                 } else {
823                                                         /*
824                                                          * Outgoing call removed caller from hold.
825                                                          *
826                                                          * Ignore because the outgoing call should not be able to place
827                                                          * the caller on hold until after they are bridged.
828                                                          */
829                                                 }
830                                                 break;
831                                         case AST_CONTROL_OFFHOOK:
832                                         case AST_CONTROL_FLASH:
833                                                 /* Ignore going off hook and flash */
834                                                 break;
835                                         case AST_CONTROL_CONNECTED_LINE:
836                                                 if (!tmpuser) {
837                                                         /*
838                                                          * Hold connected line update from caller until we have a
839                                                          * winner.
840                                                          */
841                                                         ast_verb(3,
842                                                                 "%s connected line has changed. Saving it until we have a winner.\n",
843                                                                 ast_channel_name(winner));
844                                                         ast_party_connected_line_set_init(&connected, &tpargs->connected_in);
845                                                         if (!ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected)) {
846                                                                 ast_party_connected_line_set(&tpargs->connected_in,
847                                                                         &connected, NULL);
848                                                                 tpargs->pending_in_connected_update = 1;
849                                                         }
850                                                         ast_party_connected_line_free(&connected);
851                                                         break;
852                                                 }
853                                                 if (ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_IGNORE_CONNECTEDLINE)) {
854                                                         ast_verb(3, "Connected line update from %s prevented.\n",
855                                                                 ast_channel_name(winner));
856                                                 } else {
857                                                         ast_verb(3,
858                                                                 "%s connected line has changed. Saving it until answer.\n",
859                                                                 ast_channel_name(winner));
860                                                         ast_party_connected_line_set_init(&connected, &tmpuser->connected);
861                                                         if (!ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected)) {
862                                                                 ast_party_connected_line_set(&tmpuser->connected,
863                                                                         &connected, NULL);
864                                                                 tmpuser->pending_connected_update = 1;
865                                                         }
866                                                         ast_party_connected_line_free(&connected);
867                                                 }
868                                                 break;
869                                         case AST_CONTROL_REDIRECTING:
870                                                 /*
871                                                  * Ignore because we are masking the FollowMe search progress to
872                                                  * the caller.
873                                                  */
874                                                 break;
875                                         case -1:
876                                                 ast_verb(3, "%s stopped sounds\n", ast_channel_name(winner));
877                                                 break;
878                                         default:
879                                                 ast_debug(1, "Dunno what to do with control type %d from %s\n",
880                                                         f->subclass.integer, ast_channel_name(winner));
881                                                 break;
882                                         }
883                                 } 
884                                 if (tmpuser && tmpuser->state == 3 && f->frametype == AST_FRAME_DTMF) {
885                                         if (ast_channel_stream(winner))
886                                                 ast_stopstream(winner);
887                                         tmpuser->digts = 0;
888                                         ast_debug(1, "DTMF received: %c\n", (char) f->subclass.integer);
889                                         if (tmpuser->ynidx < ARRAY_LEN(tmpuser->yn) - 1) {
890                                                 tmpuser->yn[tmpuser->ynidx++] = (char) f->subclass.integer;
891                                         }
892                                         ast_debug(1, "DTMF string: %s\n", tmpuser->yn);
893                                         if (!strcmp(tmpuser->yn, tpargs->takecall)) {
894                                                 ast_debug(1, "Match to take the call!\n");
895                                                 ast_frfree(f);
896                                                 return tmpuser->ochan;
897                                         }
898                                         if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
899                                                 ast_debug(1, "Declined to take the call.\n");
900                                                 clear_caller(tmpuser);
901                                         }
902                                 }
903
904                                 ast_frfree(f);
905                         } else {
906                                 ast_debug(1, "we didn't get a frame. hanging up.\n");
907                                 if (!tmpuser) {
908                                         /* Caller hung up. */
909                                         ast_verb(3, "The calling channel hungup. Need to drop everyone.\n");
910                                         return NULL;
911                                 }
912                                 /* Outgoing channel hung up. */
913                                 clear_caller(tmpuser);
914                         }
915                 } else {
916                         ast_debug(1, "timed out waiting for action\n");
917                 }
918         }
919
920         /* Unreachable. */
921 }
922
923 /*!
924  * \internal
925  * \brief Find an extension willing to take the call.
926  *
927  * \param tpargs Active Followme config.
928  * \param caller Channel initiating the outgoing calls.
929  *
930  * \retval winner Winning outgoing call.
931  * \retval NULL if could not find someone to take the call.
932  */
933 static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel *caller)
934 {
935         struct number *nm;
936         struct ast_channel *winner = NULL;
937         char num[512];
938         int dg, idx;
939         char *rest, *number;
940         struct findme_user *tmpuser;
941         struct findme_user *fmuser;
942         struct findme_user_listptr findme_user_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
943         struct findme_user_listptr new_user_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
944
945         for (idx = 1; !ast_check_hangup(caller); ++idx) {
946                 /* Find next followme numbers to dial. */
947                 AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
948                         if (nm->order == idx) {
949                                 break;
950                         }
951                 }
952                 if (!nm) {
953                         ast_verb(3, "No more steps left.\n");
954                         break;
955                 }
956
957                 ast_debug(2, "Number(s) %s timeout %ld\n", nm->number, nm->timeout);
958
959                 ast_copy_string(num, nm->number, sizeof(num));
960                 for (number = num; number; number = rest) {
961                         struct ast_channel *outbound;
962
963                         rest = strchr(number, '&');
964                         if (rest) {
965                                 *rest++ = 0;
966                         }
967
968                         /* We check if the extension exists, before creating the ast_channel struct */
969                         if (!ast_exists_extension(caller, tpargs->context, number, 1, S_COR(ast_channel_caller(caller)->id.number.valid, ast_channel_caller(caller)->id.number.str, NULL))) {
970                                 ast_log(LOG_ERROR, "Extension '%s@%s' doesn't exist\n", number, tpargs->context);
971                                 continue;
972                         }
973
974                         tmpuser = ast_calloc(1, sizeof(*tmpuser));
975                         if (!tmpuser) {
976                                 continue;
977                         }
978
979                         if (ast_strlen_zero(tpargs->context)) {
980                                 snprintf(tmpuser->dialarg, sizeof(tmpuser->dialarg), "%s%s",
981                                         number,
982                                         ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_DISABLEOPTIMIZATION)
983                                                 ? "/n" : "/m");
984                         } else {
985                                 snprintf(tmpuser->dialarg, sizeof(tmpuser->dialarg), "%s@%s%s",
986                                         number, tpargs->context,
987                                         ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_DISABLEOPTIMIZATION)
988                                                 ? "/n" : "/m");
989                         }
990
991                         outbound = ast_request("Local", ast_channel_nativeformats(caller), caller,
992                                 tmpuser->dialarg, &dg);
993                         if (!outbound) {
994                                 ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n",
995                                         tmpuser->dialarg, ast_cause2str(dg));
996                                 ast_free(tmpuser);
997                                 continue;
998                         }
999
1000                         ast_channel_lock_both(caller, outbound);
1001                         ast_connected_line_copy_from_caller(ast_channel_connected(outbound), ast_channel_caller(caller));
1002                         ast_channel_inherit_variables(caller, outbound);
1003                         ast_channel_datastore_inherit(caller, outbound);
1004                         ast_channel_language_set(outbound, ast_channel_language(caller));
1005                         ast_channel_accountcode_set(outbound, ast_channel_accountcode(caller));
1006                         ast_channel_musicclass_set(outbound, ast_channel_musicclass(caller));
1007                         ast_channel_unlock(outbound);
1008                         ast_channel_unlock(caller);
1009
1010                         tmpuser->ochan = outbound;
1011                         tmpuser->state = 0;
1012
1013                         ast_verb(3, "calling Local/%s\n", tmpuser->dialarg);
1014                         if (!ast_call(tmpuser->ochan, tmpuser->dialarg, 0)) {
1015                                 AST_LIST_INSERT_TAIL(&new_user_list, tmpuser, entry);
1016                         } else {
1017                                 ast_verb(3, "couldn't reach at this number.\n");
1018
1019                                 /* Destroy this failed new outgoing call. */
1020                                 ast_channel_lock(tmpuser->ochan);
1021                                 if (ast_channel_cdr(tmpuser->ochan)) {
1022                                         ast_cdr_init(ast_channel_cdr(tmpuser->ochan), tmpuser->ochan);
1023                                 }
1024                                 ast_channel_unlock(tmpuser->ochan);
1025                                 destroy_calling_node(tmpuser);
1026                         }
1027                 }
1028
1029                 if (AST_LIST_EMPTY(&new_user_list)) {
1030                         /* No new channels remain at this order level.  If there were any at all. */
1031                         continue;
1032                 }
1033
1034                 /* Add new outgoing channels to the findme list. */
1035                 AST_LIST_APPEND_LIST(&findme_user_list, &new_user_list, entry);
1036
1037                 winner = wait_for_winner(&findme_user_list, nm, caller, tpargs);
1038                 if (!winner) {
1039                         continue;
1040                 }
1041
1042                 /* Destroy losing calls up to the winner.  The rest will be destroyed later. */
1043                 while ((fmuser = AST_LIST_REMOVE_HEAD(&findme_user_list, entry))) {
1044                         if (fmuser->ochan == winner) {
1045                                 /*
1046                                  * Pass any connected line info up.
1047                                  *
1048                                  * NOTE: This code must be in line with destroy_calling_node().
1049                                  */
1050                                 tpargs->connected_out = fmuser->connected;
1051                                 tpargs->pending_out_connected_update = fmuser->pending_connected_update;
1052                                 ast_free(fmuser);
1053                                 break;
1054                         } else {
1055                                 /* Destroy losing call. */
1056                                 destroy_calling_node(fmuser);
1057                         }
1058                 }
1059                 break;
1060         }
1061         destroy_calling_tree(&findme_user_list);
1062         return winner;
1063 }
1064
1065 static struct call_followme *find_realtime(const char *name)
1066 {
1067         struct ast_variable *var;
1068         struct ast_variable *v;
1069         struct ast_config *cfg;
1070         const char *catg;
1071         struct call_followme *new_follower;
1072         struct ast_str *str;
1073
1074         str = ast_str_create(16);
1075         if (!str) {
1076                 return NULL;
1077         }
1078
1079         var = ast_load_realtime("followme", "name", name, SENTINEL);
1080         if (!var) {
1081                 ast_free(str);
1082                 return NULL;
1083         }
1084
1085         if (!(new_follower = alloc_profile(name))) {
1086                 ast_variables_destroy(var);
1087                 ast_free(str);
1088                 return NULL;
1089         }
1090
1091         for (v = var; v; v = v->next) {
1092                 if (!strcasecmp(v->name, "active")) {
1093                         if (ast_false(v->value)) {
1094                                 ast_mutex_destroy(&new_follower->lock);
1095                                 ast_free(new_follower);
1096                                 ast_variables_destroy(var);
1097                                 ast_free(str);
1098                                 return NULL;
1099                         }
1100                 } else {
1101                         profile_set_param(new_follower, v->name, v->value, 0, 0);
1102                 }
1103         }
1104
1105         ast_variables_destroy(var);
1106         new_follower->realtime = 1;
1107
1108         /* Load numbers */
1109         cfg = ast_load_realtime_multientry("followme_numbers", "ordinal LIKE", "%", "name",
1110                 name, SENTINEL);
1111         if (!cfg) {
1112                 ast_mutex_destroy(&new_follower->lock);
1113                 ast_free(new_follower);
1114                 ast_free(str);
1115                 return NULL;
1116         }
1117
1118         for (catg = ast_category_browse(cfg, NULL); catg; catg = ast_category_browse(cfg, catg)) {
1119                 const char *numstr;
1120                 const char *timeoutstr;
1121                 const char *ordstr;
1122                 int timeout;
1123                 struct number *cur;
1124
1125                 if (!(numstr = ast_variable_retrieve(cfg, catg, "phonenumber"))) {
1126                         continue;
1127                 }
1128                 if (!(timeoutstr = ast_variable_retrieve(cfg, catg, "timeout"))
1129                         || sscanf(timeoutstr, "%30d", &timeout) != 1
1130                         || timeout < 1) {
1131                         timeout = 25;
1132                 }
1133                 /* This one has to exist; it was part of the query */
1134                 ordstr = ast_variable_retrieve(cfg, catg, "ordinal");
1135                 ast_str_set(&str, 0, "%s", numstr);
1136                 if ((cur = create_followme_number(ast_str_buffer(str), timeout, atoi(ordstr)))) {
1137                         AST_LIST_INSERT_TAIL(&new_follower->numbers, cur, entry);
1138                 }
1139         }
1140         ast_config_destroy(cfg);
1141
1142         ast_free(str);
1143         return new_follower;
1144 }
1145
1146 static void end_bridge_callback(void *data)
1147 {
1148         char buf[80];
1149         time_t end;
1150         struct ast_channel *chan = data;
1151
1152         time(&end);
1153
1154         ast_channel_lock(chan);
1155         if (ast_channel_cdr(chan)->answer.tv_sec) {
1156                 snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->answer.tv_sec);
1157                 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
1158         }
1159
1160         if (ast_channel_cdr(chan)->start.tv_sec) {
1161                 snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->start.tv_sec);
1162                 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
1163         }
1164         ast_channel_unlock(chan);
1165 }
1166
1167 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
1168 {
1169         bconfig->end_bridge_callback_data = originator;
1170 }
1171
1172 static int app_exec(struct ast_channel *chan, const char *data)
1173 {
1174         struct fm_args *targs;
1175         struct ast_bridge_config config;
1176         struct call_followme *f;
1177         struct number *nm, *newnm;
1178         int res = 0;
1179         char *argstr;
1180         struct ast_channel *caller;
1181         struct ast_channel *outbound;
1182         AST_DECLARE_APP_ARGS(args,
1183                 AST_APP_ARG(followmeid);
1184                 AST_APP_ARG(options);
1185         );
1186
1187         if (ast_strlen_zero(data)) {
1188                 ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
1189                 return -1;
1190         }
1191
1192         argstr = ast_strdupa((char *) data);
1193
1194         AST_STANDARD_APP_ARGS(args, argstr);
1195
1196         if (ast_strlen_zero(args.followmeid)) {
1197                 ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
1198                 return -1;
1199         }
1200
1201         targs = ast_calloc(1, sizeof(*targs));
1202         if (!targs) {
1203                 return -1;
1204         }
1205
1206         AST_RWLIST_RDLOCK(&followmes);
1207         AST_RWLIST_TRAVERSE(&followmes, f, entry) {
1208                 if (!strcasecmp(f->name, args.followmeid) && (f->active))
1209                         break;
1210         }
1211         AST_RWLIST_UNLOCK(&followmes);
1212
1213         ast_debug(1, "New profile %s.\n", args.followmeid);
1214
1215         if (!f) {
1216                 f = find_realtime(args.followmeid);
1217         }
1218
1219         if (!f) {
1220                 ast_log(LOG_WARNING, "Profile requested, %s, not found in the configuration.\n", args.followmeid);
1221                 ast_free(targs);
1222                 return 0;
1223         }
1224
1225         /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
1226         if (args.options) {
1227                 ast_app_parse_options(followme_opts, &targs->followmeflags, NULL, args.options);
1228         }
1229
1230         /* Lock the profile lock and copy out everything we need to run with before unlocking it again */
1231         ast_mutex_lock(&f->lock);
1232         targs->mohclass = ast_strdupa(f->moh);
1233         ast_copy_string(targs->context, f->context, sizeof(targs->context));
1234         ast_copy_string(targs->takecall, f->takecall, sizeof(targs->takecall));
1235         ast_copy_string(targs->nextindp, f->nextindp, sizeof(targs->nextindp));
1236         ast_copy_string(targs->callfromprompt, f->callfromprompt, sizeof(targs->callfromprompt));
1237         ast_copy_string(targs->norecordingprompt, f->norecordingprompt, sizeof(targs->norecordingprompt));
1238         ast_copy_string(targs->optionsprompt, f->optionsprompt, sizeof(targs->optionsprompt));
1239         ast_copy_string(targs->plsholdprompt, f->plsholdprompt, sizeof(targs->plsholdprompt));
1240         ast_copy_string(targs->statusprompt, f->statusprompt, sizeof(targs->statusprompt));
1241         ast_copy_string(targs->sorryprompt, f->sorryprompt, sizeof(targs->sorryprompt));
1242         /* Copy the numbers we're going to use into another list in case the master list should get modified 
1243            (and locked) while we're trying to do a follow-me */
1244         AST_LIST_HEAD_INIT_NOLOCK(&targs->cnumbers);
1245         AST_LIST_TRAVERSE(&f->numbers, nm, entry) {
1246                 newnm = create_followme_number(nm->number, nm->timeout, nm->order);
1247                 if (newnm) {
1248                         AST_LIST_INSERT_TAIL(&targs->cnumbers, newnm, entry);
1249                 }
1250         }
1251         ast_mutex_unlock(&f->lock);
1252
1253         /* Forget the 'N' option if the call is already up. */
1254         if (ast_channel_state(chan) == AST_STATE_UP) {
1255                 ast_clear_flag(&targs->followmeflags, FOLLOWMEFLAG_NOANSWER);
1256         }
1257
1258         if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_NOANSWER)) {
1259                 ast_indicate(chan, AST_CONTROL_RINGING);
1260         } else {
1261                 /* Answer the call */
1262                 if (ast_channel_state(chan) != AST_STATE_UP) {
1263                         ast_answer(chan);
1264                 }
1265
1266                 if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_STATUSMSG)) {
1267                         ast_stream_and_wait(chan, targs->statusprompt, "");
1268                 }
1269
1270                 if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_RECORDNAME)) {
1271                         int duration = 5;
1272
1273                         snprintf(targs->namerecloc, sizeof(targs->namerecloc), "%s/followme.%s",
1274                                 ast_config_AST_SPOOL_DIR, ast_channel_uniqueid(chan));
1275                         if (ast_play_and_record(chan, "vm-rec-name", targs->namerecloc, 5, "sln", &duration,
1276                                 NULL, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0) {
1277                                 goto outrun;
1278                         }
1279                         if (!ast_fileexists(targs->namerecloc, NULL, ast_channel_language(chan))) {
1280                                 targs->namerecloc[0] = '\0';
1281                         }
1282                 }
1283
1284                 if (!ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_DISABLEHOLDPROMPT)) {
1285                         if (ast_streamfile(chan, targs->plsholdprompt, ast_channel_language(chan))) {
1286                                 goto outrun;
1287                         }
1288                         if (ast_waitstream(chan, "") < 0)
1289                                 goto outrun;
1290                 }
1291                 ast_moh_start(chan, S_OR(targs->mohclass, NULL), NULL);
1292         }
1293
1294         ast_channel_lock(chan);
1295         ast_connected_line_copy_from_caller(&targs->connected_in, ast_channel_caller(chan));
1296         ast_channel_unlock(chan);
1297
1298         outbound = findmeexec(targs, chan);
1299         if (!outbound) {
1300                 if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_NOANSWER)) {
1301                         if (ast_channel_state(chan) != AST_STATE_UP) {
1302                                 ast_answer(chan);
1303                         }
1304                 } else {
1305                         ast_moh_stop(chan);
1306                 }
1307
1308                 if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG)) {
1309                         ast_stream_and_wait(chan, targs->sorryprompt, "");
1310                 }
1311                 res = 0;
1312         } else {
1313                 caller = chan;
1314                 /* Bridge the two channels. */
1315
1316                 memset(&config, 0, sizeof(config));
1317                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1318                 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1319                 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1320                 config.end_bridge_callback = end_bridge_callback;
1321                 config.end_bridge_callback_data = chan;
1322                 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
1323
1324                 /* Update connected line to caller if available. */
1325                 if (targs->pending_out_connected_update) {
1326                         if (ast_channel_connected_line_sub(outbound, caller, &targs->connected_out, 0) &&
1327                                 ast_channel_connected_line_macro(outbound, caller, &targs->connected_out, 1, 0)) {
1328                                 ast_channel_update_connected_line(caller, &targs->connected_out, NULL);
1329                         }
1330                 }
1331
1332                 if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_NOANSWER)) {
1333                         if (ast_channel_state(caller) != AST_STATE_UP) {
1334                                 ast_answer(caller);
1335                         }
1336                 } else {
1337                         ast_moh_stop(caller);
1338                 }
1339
1340                 /* Be sure no generators are left on it */
1341                 ast_deactivate_generator(caller);
1342                 /* Make sure channels are compatible */
1343                 res = ast_channel_make_compatible(caller, outbound);
1344                 if (res < 0) {
1345                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(caller), ast_channel_name(outbound));
1346                         ast_hangup(outbound);
1347                         goto outrun;
1348                 }
1349
1350                 /* Update connected line to winner if changed. */
1351                 if (targs->pending_in_connected_update) {
1352                         if (ast_channel_connected_line_sub(caller, outbound, &targs->connected_in, 0) &&
1353                                 ast_channel_connected_line_macro(caller, outbound, &targs->connected_in, 0, 0)) {
1354                                 ast_channel_update_connected_line(outbound, &targs->connected_in, NULL);
1355                         }
1356                 }
1357
1358                 /* Put winner on hold if caller requested. */
1359                 if (targs->pending_hold) {
1360                         if (ast_strlen_zero(targs->suggested_moh)) {
1361                                 ast_indicate_data(outbound, AST_CONTROL_HOLD, NULL, 0);
1362                         } else {
1363                                 ast_indicate_data(outbound, AST_CONTROL_HOLD,
1364                                         targs->suggested_moh, strlen(targs->suggested_moh) + 1);
1365                         }
1366                 }
1367
1368                 res = ast_bridge_call(caller, outbound, &config);
1369                 ast_hangup(outbound);
1370         }
1371
1372 outrun:
1373         while ((nm = AST_LIST_REMOVE_HEAD(&targs->cnumbers, entry))) {
1374                 ast_free(nm);
1375         }
1376         if (!ast_strlen_zero(targs->namerecloc)) {
1377                 unlink(targs->namerecloc);
1378         }
1379         ast_party_connected_line_free(&targs->connected_in);
1380         ast_party_connected_line_free(&targs->connected_out);
1381         ast_free(targs);
1382
1383         if (f->realtime) {
1384                 /* Not in list */
1385                 free_numbers(f);
1386                 ast_free(f);
1387         }
1388
1389         return res;
1390 }
1391
1392 static int unload_module(void)
1393 {
1394         struct call_followme *f;
1395
1396         ast_unregister_application(app);
1397
1398         /* Free Memory. Yeah! I'm free! */
1399         AST_RWLIST_WRLOCK(&followmes);
1400         while ((f = AST_RWLIST_REMOVE_HEAD(&followmes, entry))) {
1401                 free_numbers(f);
1402                 ast_free(f);
1403         }
1404
1405         AST_RWLIST_UNLOCK(&followmes);
1406
1407         return 0;
1408 }
1409
1410 static int load_module(void)
1411 {
1412         if(!reload_followme(0))
1413                 return AST_MODULE_LOAD_DECLINE;
1414
1415         return ast_register_application_xml(app, app_exec);
1416 }
1417
1418 static int reload(void)
1419 {
1420         reload_followme(1);
1421
1422         return 0;
1423 }
1424
1425 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Find-Me/Follow-Me Application",
1426                 .load = load_module,
1427                 .unload = unload_module,
1428                 .reload = reload,
1429                );