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