app_followme.c 54 KB

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