#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/config.h"
#include "asterisk/monitor.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astdb.h"
#include "asterisk/app.h"
Include dependency graph for app_followme.c:
Go to the source code of this file.
Data Structures | |
struct | call_followme |
Data structure for followme scripts. More... | |
struct | findme_user |
struct | fm_args |
struct | number |
Number structure. More... | |
Enumerations | |
enum | { FOLLOWMEFLAG_STATUSMSG = (1 << 0), FOLLOWMEFLAG_RECORDNAME = (1 << 1), FOLLOWMEFLAG_UNREACHABLEMSG = (1 << 2) } |
Functions | |
static struct call_followme * | alloc_profile (const char *fmname) |
Allocate and initialize followme profile. | |
static int | app_exec (struct ast_channel *chan, void *data) |
AST_APP_OPTIONS (followme_opts,{AST_APP_OPTION('s', FOLLOWMEFLAG_STATUSMSG), AST_APP_OPTION('a', FOLLOWMEFLAG_RECORDNAME), AST_APP_OPTION('n', FOLLOWMEFLAG_UNREACHABLEMSG),}) | |
AST_LIST_HEAD_NOLOCK (findme_user_listptr, findme_user) | |
static | AST_LIST_HEAD_STATIC (followmes, call_followme) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Find-Me/Follow-Me Application",.load=load_module,.unload=unload_module,.reload=reload,) | |
static void | clear_caller (struct findme_user *tmpuser) |
static void | clear_calling_tree (struct findme_user_listptr *findme_user_list) |
static struct number * | create_followme_number (char *number, int timeout, int numorder) |
Add a new number. | |
static void | findmeexec (struct fm_args *tpargs) |
static void | free_numbers (struct call_followme *f) |
static void | init_profile (struct call_followme *f) |
static int | load_module (void) |
static void | profile_set_param (struct call_followme *f, const char *param, const char *val, int linenum, int failunknown) |
Set parameter in profile from configuration file. | |
static int | reload (void) |
static int | reload_followme (void) |
Reload followme application module. | |
static int | unload_module (void) |
static struct ast_channel * | wait_for_winner (struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, char *namerecloc, int *status, struct fm_args *tpargs) |
Variables | |
static time_t | answer_time |
static char * | app = "FollowMe" |
static char | callfromprompt [PATH_MAX] = "followme/call-from" |
static const char * | defaultmoh = "default" |
static char * | descrip |
static time_t | end_time |
static int | featuredigittimeout = 5000 |
static const char * | featuredigittostr |
static char | nextindp [20] = "2" |
static char | norecordingprompt [PATH_MAX] = "followme/no-recording" |
static char | optionsprompt [PATH_MAX] = "followme/options" |
static char | plsholdprompt [PATH_MAX] = "followme/pls-hold-while-try" |
static char | sorryprompt [PATH_MAX] = "followme/sorry" |
static time_t | start_time |
static char | statusprompt [PATH_MAX] = "followme/status" |
static char * | synopsis = "Find-Me/Follow-Me application" |
static char | takecall [20] = "1" |
static int | ynlongest = 0 |
Definition in file app_followme.c.
anonymous enum |
Definition at line 137 of file app_followme.c.
00137 { 00138 FOLLOWMEFLAG_STATUSMSG = (1 << 0), 00139 FOLLOWMEFLAG_RECORDNAME = (1 << 1), 00140 FOLLOWMEFLAG_UNREACHABLEMSG = (1 << 2) 00141 };
static struct call_followme* alloc_profile | ( | const char * | fmname | ) | [static] |
Allocate and initialize followme profile.
Definition at line 192 of file app_followme.c.
References ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, ast_mutex_init(), and f.
Referenced by reload_followme().
00193 { 00194 struct call_followme *f; 00195 00196 if (!(f = ast_calloc(1, sizeof(*f)))) 00197 return NULL; 00198 00199 ast_mutex_init(&f->lock); 00200 ast_copy_string(f->name, fmname, sizeof(f->name)); 00201 f->moh[0] = '\0'; 00202 f->context[0] = '\0'; 00203 ast_copy_string(f->takecall, takecall, sizeof(f->takecall)); 00204 ast_copy_string(f->nextindp, nextindp, sizeof(f->nextindp)); 00205 ast_copy_string(f->callfromprompt, callfromprompt, sizeof(f->callfromprompt)); 00206 ast_copy_string(f->norecordingprompt, norecordingprompt, sizeof(f->norecordingprompt)); 00207 ast_copy_string(f->optionsprompt, optionsprompt, sizeof(f->optionsprompt)); 00208 ast_copy_string(f->plsholdprompt, plsholdprompt, sizeof(f->plsholdprompt)); 00209 ast_copy_string(f->statusprompt, statusprompt, sizeof(f->statusprompt)); 00210 ast_copy_string(f->sorryprompt, sorryprompt, sizeof(f->sorryprompt)); 00211 AST_LIST_HEAD_INIT_NOLOCK(&f->numbers); 00212 AST_LIST_HEAD_INIT_NOLOCK(&f->blnumbers); 00213 AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers); 00214 return f; 00215 }
static int app_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 909 of file app_followme.c.
References AST_APP_ARG, ast_app_parse_options(), ast_bridge_call(), ast_channel_make_compatible(), ast_config_AST_SPOOL_DIR, ast_deactivate_generator(), AST_DECLARE_APP_ARGS, AST_FEATURE_AUTOMON, AST_FEATURE_REDIRECT, ast_hangup(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_module_user_add, ast_module_user_remove, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_play_and_record(), ast_set_flag, AST_STANDARD_APP_ARGS, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), fm_args::chan, config, create_followme_number(), f, findmeexec(), FOLLOWMEFLAG_RECORDNAME, FOLLOWMEFLAG_STATUSMSG, FOLLOWMEFLAG_UNREACHABLEMSG, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, fm_args::mohclass, ast_format::name, number::number, option_debug, number::order, pbx_builtin_setvar_helper(), S_OR, and number::timeout.
00910 { 00911 struct fm_args targs; 00912 struct ast_bridge_config config; 00913 struct call_followme *f; 00914 struct number *nm, *newnm; 00915 int res = 0; 00916 struct ast_module_user *u; 00917 char *argstr; 00918 char namerecloc[255]; 00919 int duration = 0; 00920 struct ast_channel *caller; 00921 struct ast_channel *outbound; 00922 static char toast[80]; 00923 00924 AST_DECLARE_APP_ARGS(args, 00925 AST_APP_ARG(followmeid); 00926 AST_APP_ARG(options); 00927 ); 00928 00929 if (!(argstr = ast_strdupa((char *)data))) { 00930 ast_log(LOG_ERROR, "Out of memory!\n"); 00931 return -1; 00932 } 00933 00934 if (!data) { 00935 ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n",app); 00936 return -1; 00937 } 00938 00939 u = ast_module_user_add(chan); 00940 00941 AST_STANDARD_APP_ARGS(args, argstr); 00942 00943 if (!ast_strlen_zero(args.followmeid)) 00944 AST_LIST_LOCK(&followmes); 00945 AST_LIST_TRAVERSE(&followmes, f, entry) { 00946 if (!strcasecmp(f->name, args.followmeid) && (f->active)) 00947 break; 00948 } 00949 AST_LIST_UNLOCK(&followmes); 00950 00951 if (option_debug) 00952 ast_log(LOG_DEBUG, "New profile %s.\n", args.followmeid); 00953 if (!f) { 00954 ast_log(LOG_WARNING, "Profile requested, %s, not found in the configuration.\n", args.followmeid); 00955 res = 0; 00956 } else { 00957 /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */ 00958 00959 00960 if (args.options) 00961 ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options); 00962 00963 /* Lock the profile lock and copy out everything we need to run with before unlocking it again */ 00964 ast_mutex_lock(&f->lock); 00965 targs.mohclass = ast_strdupa(f->moh); 00966 ast_copy_string(targs.context, f->context, sizeof(targs.context)); 00967 ast_copy_string(targs.takecall, f->takecall, sizeof(targs.takecall)); 00968 ast_copy_string(targs.nextindp, f->nextindp, sizeof(targs.nextindp)); 00969 ast_copy_string(targs.callfromprompt, f->callfromprompt, sizeof(targs.callfromprompt)); 00970 ast_copy_string(targs.norecordingprompt, f->norecordingprompt, sizeof(targs.norecordingprompt)); 00971 ast_copy_string(targs.optionsprompt, f->optionsprompt, sizeof(targs.optionsprompt)); 00972 ast_copy_string(targs.plsholdprompt, f->plsholdprompt, sizeof(targs.plsholdprompt)); 00973 ast_copy_string(targs.statusprompt, f->statusprompt, sizeof(targs.statusprompt)); 00974 ast_copy_string(targs.sorryprompt, f->sorryprompt, sizeof(targs.sorryprompt)); 00975 /* Copy the numbers we're going to use into another list in case the master list should get modified 00976 (and locked) while we're trying to do a follow-me */ 00977 AST_LIST_HEAD_INIT_NOLOCK(&targs.cnumbers); 00978 AST_LIST_TRAVERSE(&f->numbers, nm, entry) { 00979 newnm = create_followme_number(nm->number, nm->timeout, nm->order); 00980 AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry); 00981 } 00982 ast_mutex_unlock(&f->lock); 00983 00984 if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG)) 00985 ast_stream_and_wait(chan, targs.statusprompt, chan->language, ""); 00986 00987 snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid); 00988 duration = 5; 00989 00990 if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME)) 00991 if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, 128, 0, NULL) < 0) 00992 goto outrun; 00993 00994 /* The following call looks like we're going to playback the file, but we're actually */ 00995 /* just checking to see if we *can* play it. */ 00996 if (ast_streamfile(chan, namerecloc, chan->language)) 00997 ast_copy_string(namerecloc, "", sizeof(namerecloc)); 00998 else 00999 ast_stopstream(chan); 01000 01001 if (ast_streamfile(chan, targs.plsholdprompt, chan->language)) 01002 goto outrun; 01003 if (ast_waitstream(chan, "") < 0) 01004 goto outrun; 01005 ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL); 01006 01007 targs.status = 0; 01008 targs.chan = chan; 01009 ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc)); 01010 01011 findmeexec(&targs); 01012 01013 AST_LIST_TRAVERSE_SAFE_BEGIN(&targs.cnumbers, nm, entry) { 01014 AST_LIST_REMOVE_CURRENT(&targs.cnumbers, entry); 01015 free(nm); 01016 } 01017 AST_LIST_TRAVERSE_SAFE_END 01018 01019 if (!ast_strlen_zero(namerecloc)) 01020 unlink(namerecloc); 01021 01022 if (targs.status != 100) { 01023 ast_moh_stop(chan); 01024 if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG)) 01025 ast_stream_and_wait(chan, targs.sorryprompt, chan->language, ""); 01026 res = 0; 01027 } else { 01028 caller = chan; 01029 outbound = targs.outbound; 01030 /* Bridge the two channels. */ 01031 01032 memset(&config,0,sizeof(struct ast_bridge_config)); 01033 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 01034 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 01035 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 01036 01037 ast_moh_stop(caller); 01038 /* Be sure no generators are left on it */ 01039 ast_deactivate_generator(caller); 01040 /* Make sure channels are compatible */ 01041 res = ast_channel_make_compatible(caller, outbound); 01042 if (res < 0) { 01043 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", caller->name, outbound->name); 01044 ast_hangup(outbound); 01045 goto outrun; 01046 } 01047 time(&answer_time); 01048 res = ast_bridge_call(caller,outbound,&config); 01049 time(&end_time); 01050 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time)); 01051 pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast); 01052 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time)); 01053 pbx_builtin_setvar_helper(caller, "ANSWEREDTIME", toast); 01054 if (outbound) 01055 ast_hangup(outbound); 01056 res = 1; 01057 } 01058 } 01059 outrun: 01060 01061 ast_module_user_remove(u); 01062 01063 return res; 01064 }
AST_APP_OPTIONS | ( | followme_opts | ) |
AST_LIST_HEAD_NOLOCK | ( | findme_user_listptr | , | |
findme_user | ||||
) |
static AST_LIST_HEAD_STATIC | ( | followmes | , | |
call_followme | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Find-Me/Follow-Me Application" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static void clear_caller | ( | struct findme_user * | tmpuser | ) | [static] |
Definition at line 428 of file app_followme.c.
References ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), ast_hangup(), ast_log(), ast_channel::cdr, findme_user::dialarg, ast_channel::hangupcause, LOG_WARNING, findme_user::ochan, and findme_user::state.
Referenced by clear_calling_tree(), and findmeexec().
00429 { 00430 struct ast_channel *outbound; 00431 00432 if (tmpuser && tmpuser->ochan && tmpuser->state >= 0) { 00433 outbound = tmpuser->ochan; 00434 if (!outbound->cdr) { 00435 outbound->cdr = ast_cdr_alloc(); 00436 if (outbound->cdr) 00437 ast_cdr_init(outbound->cdr, outbound); 00438 } 00439 if (outbound->cdr) { 00440 char tmp[256]; 00441 00442 snprintf(tmp, sizeof(tmp), "%s/%s", "Local", tmpuser->dialarg); 00443 ast_cdr_setapp(outbound->cdr, "FollowMe", tmp); 00444 ast_cdr_update(outbound); 00445 ast_cdr_start(outbound->cdr); 00446 ast_cdr_end(outbound->cdr); 00447 /* If the cause wasn't handled properly */ 00448 if (ast_cdr_disposition(outbound->cdr, outbound->hangupcause)) 00449 ast_cdr_failed(outbound->cdr); 00450 } else 00451 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 00452 ast_hangup(tmpuser->ochan); 00453 } 00454 00455 }
static void clear_calling_tree | ( | struct findme_user_listptr * | findme_user_list | ) | [static] |
Definition at line 457 of file app_followme.c.
References AST_LIST_TRAVERSE, clear_caller(), and findme_user::cleared.
Referenced by wait_for_winner().
00458 { 00459 struct findme_user *tmpuser; 00460 00461 AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) { 00462 clear_caller(tmpuser); 00463 tmpuser->cleared = 1; 00464 } 00465 00466 }
static struct number* create_followme_number | ( | char * | number, | |
int | timeout, | |||
int | numorder | |||
) | [static] |
Add a new number.
Definition at line 258 of file app_followme.c.
References ast_calloc, ast_log(), LOG_DEBUG, option_debug, and number::timeout.
Referenced by app_exec(), and reload_followme().
00259 { 00260 struct number *cur; 00261 char *tmp; 00262 00263 00264 if (!(cur = ast_calloc(1, sizeof(*cur)))) 00265 return NULL; 00266 00267 cur->timeout = timeout; 00268 if ((tmp = strchr(number, ','))) 00269 *tmp = '\0'; 00270 ast_copy_string(cur->number, number, sizeof(cur->number)); 00271 cur->order = numorder; 00272 if (option_debug) 00273 ast_log(LOG_DEBUG, "Created a number, %s, order of , %d, with a timeout of %ld.\n", cur->number, cur->order, cur->timeout); 00274 00275 return cur; 00276 }
static void findmeexec | ( | struct fm_args * | tpargs | ) | [static] |
Definition at line 763 of file app_followme.c.
References ast_best_codec(), ast_call(), ast_calloc, ast_cause2str(), ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), ast_channel_inherit_variables(), ast_hangup(), AST_LIST_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_request(), ast_set_callerid(), ast_strdupa, ast_verbose(), fm_args::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, clear_caller(), findme_user::cleared, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_channel::nativeformats, number::number, findme_user::ochan, option_debug, option_verbose, number::order, number::timeout, VERBOSE_PREFIX_3, and wait_for_winner().
Referenced by app_exec().
00764 { 00765 struct number *nm; 00766 struct ast_channel *outbound; 00767 struct ast_channel *caller; 00768 struct ast_channel *winner = NULL; 00769 char dialarg[512]; 00770 int dg, idx; 00771 char *rest, *number; 00772 struct findme_user *tmpuser; 00773 struct findme_user *fmuser; 00774 struct findme_user *headuser; 00775 struct findme_user_listptr *findme_user_list; 00776 int status; 00777 00778 findme_user_list = ast_calloc(1, sizeof(*findme_user_list)); 00779 AST_LIST_HEAD_INIT_NOLOCK(findme_user_list); 00780 00781 /* We're going to figure out what the longest possible string of digits to collect is */ 00782 ynlongest = 0; 00783 if (strlen(tpargs->takecall) > ynlongest) 00784 ynlongest = strlen(tpargs->takecall); 00785 if (strlen(tpargs->nextindp) > ynlongest) 00786 ynlongest = strlen(tpargs->nextindp); 00787 00788 idx = 1; 00789 caller = tpargs->chan; 00790 AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) 00791 if (nm->order == idx) 00792 break; 00793 00794 while (nm) { 00795 00796 if (option_debug > 1) 00797 ast_log(LOG_DEBUG, "Number %s timeout %ld\n", nm->number,nm->timeout); 00798 time(&start_time); 00799 00800 number = ast_strdupa(nm->number); 00801 if (option_debug > 2) 00802 ast_log(LOG_DEBUG, "examining %s\n", number); 00803 do { 00804 rest = strchr(number, '&'); 00805 if (rest) { 00806 *rest = 0; 00807 rest++; 00808 } 00809 00810 if (!strcmp(tpargs->context, "")) 00811 sprintf(dialarg, "%s", number); 00812 else 00813 sprintf(dialarg, "%s@%s", number, tpargs->context); 00814 00815 tmpuser = ast_calloc(1, sizeof(*tmpuser)); 00816 if (!tmpuser) { 00817 ast_log(LOG_WARNING, "Out of memory!\n"); 00818 free(findme_user_list); 00819 return; 00820 } 00821 00822 outbound = ast_request("Local", ast_best_codec(caller->nativeformats), dialarg, &dg); 00823 if (outbound) { 00824 ast_set_callerid(outbound, caller->cid.cid_num, caller->cid.cid_name, caller->cid.cid_num); 00825 ast_channel_inherit_variables(tpargs->chan, outbound); 00826 if (option_verbose > 2) 00827 ast_verbose(VERBOSE_PREFIX_3 "calling %s\n", dialarg); 00828 if (!ast_call(outbound,dialarg,0)) { 00829 tmpuser->ochan = outbound; 00830 tmpuser->state = 0; 00831 tmpuser->cleared = 0; 00832 ast_copy_string(tmpuser->dialarg, dialarg, sizeof(dialarg)); 00833 AST_LIST_INSERT_TAIL(findme_user_list, tmpuser, entry); 00834 } else { 00835 if (option_verbose > 2) 00836 ast_verbose(VERBOSE_PREFIX_3 "couldn't reach at this number.\n"); 00837 if (outbound) { 00838 if (!outbound->cdr) 00839 outbound->cdr = ast_cdr_alloc(); 00840 if (outbound->cdr) { 00841 char tmp[256]; 00842 00843 ast_cdr_init(outbound->cdr, outbound); 00844 snprintf(tmp, sizeof(tmp), "%s/%s", "Local", dialarg); 00845 ast_cdr_setapp(outbound->cdr, "FollowMe", tmp); 00846 ast_cdr_update(outbound); 00847 ast_cdr_start(outbound->cdr); 00848 ast_cdr_end(outbound->cdr); 00849 /* If the cause wasn't handled properly */ 00850 if (ast_cdr_disposition(outbound->cdr,outbound->hangupcause)) 00851 ast_cdr_failed(outbound->cdr); 00852 } else { 00853 ast_log(LOG_ERROR, "Unable to create Call Detail Record\n"); 00854 ast_hangup(outbound); 00855 outbound = NULL; 00856 } 00857 } 00858 00859 } 00860 } else 00861 ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", dialarg, ast_cause2str(dg)); 00862 00863 number = rest; 00864 } while (number); 00865 00866 status = 0; 00867 if (!AST_LIST_EMPTY(findme_user_list)) 00868 winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs); 00869 00870 00871 AST_LIST_TRAVERSE_SAFE_BEGIN(findme_user_list, fmuser, entry) { 00872 if (!fmuser->cleared && fmuser->ochan != winner) 00873 clear_caller(fmuser); 00874 AST_LIST_REMOVE_CURRENT(findme_user_list, entry); 00875 free(fmuser); 00876 } 00877 AST_LIST_TRAVERSE_SAFE_END 00878 fmuser = NULL; 00879 tmpuser = NULL; 00880 headuser = NULL; 00881 if (winner) 00882 break; 00883 00884 if (!caller) { 00885 tpargs->status = 1; 00886 free(findme_user_list); 00887 return; 00888 } 00889 00890 idx++; 00891 AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) 00892 if (nm->order == idx) 00893 break; 00894 00895 } 00896 free(findme_user_list); 00897 if (!winner) 00898 tpargs->status = 1; 00899 else { 00900 tpargs->status = 100; 00901 tpargs->outbound = winner; 00902 } 00903 00904 00905 return; 00906 00907 }
static void free_numbers | ( | struct call_followme * | f | ) | [static] |
Definition at line 168 of file app_followme.c.
References AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_REMOVE_HEAD, f, and free.
Referenced by reload_followme(), and unload_module().
00169 { 00170 /* Free numbers attached to the profile */ 00171 struct number *prev; 00172 00173 while ((prev = AST_LIST_REMOVE_HEAD(&f->numbers, entry))) 00174 /* Free the number */ 00175 free(prev); 00176 AST_LIST_HEAD_INIT_NOLOCK(&f->numbers); 00177 00178 while ((prev = AST_LIST_REMOVE_HEAD(&f->blnumbers, entry))) 00179 /* Free the blacklisted number */ 00180 free(prev); 00181 AST_LIST_HEAD_INIT_NOLOCK(&f->blnumbers); 00182 00183 while ((prev = AST_LIST_REMOVE_HEAD(&f->wlnumbers, entry))) 00184 /* Free the whitelisted number */ 00185 free(prev); 00186 AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers); 00187 00188 }
static void init_profile | ( | struct call_followme * | f | ) | [static] |
Definition at line 217 of file app_followme.c.
References f.
Referenced by reload_followme().
00218 { 00219 f->active = 1; 00220 ast_copy_string(f->moh, defaultmoh, sizeof(f->moh)); 00221 }
static int load_module | ( | void | ) | [static] |
Definition at line 1086 of file app_followme.c.
References app_exec, AST_MODULE_LOAD_DECLINE, ast_register_application(), and reload_followme().
01087 { 01088 if(!reload_followme()) 01089 return AST_MODULE_LOAD_DECLINE; 01090 01091 return ast_register_application(app, app_exec, synopsis, descrip); 01092 }
static void profile_set_param | ( | struct call_followme * | f, | |
const char * | param, | |||
const char * | val, | |||
int | linenum, | |||
int | failunknown | |||
) | [static] |
Set parameter in profile from configuration file.
Definition at line 226 of file app_followme.c.
References ast_log(), f, LOG_WARNING, and ast_format::name.
Referenced by reload_followme().
00227 { 00228 00229 if (!strcasecmp(param, "musicclass") || !strcasecmp(param, "musiconhold") || !strcasecmp(param, "music")) 00230 ast_copy_string(f->moh, val, sizeof(f->moh)); 00231 else if (!strcasecmp(param, "context")) 00232 ast_copy_string(f->context, val, sizeof(f->context)); 00233 else if (!strcasecmp(param, "takecall")) 00234 ast_copy_string(f->takecall, val, sizeof(f->takecall)); 00235 else if (!strcasecmp(param, "declinecall")) 00236 ast_copy_string(f->nextindp, val, sizeof(f->nextindp)); 00237 else if (!strcasecmp(param, "call-from-prompt")) 00238 ast_copy_string(f->callfromprompt, val, sizeof(f->callfromprompt)); 00239 else if (!strcasecmp(param, "followme-norecording-prompt")) 00240 ast_copy_string(f->norecordingprompt, val, sizeof(f->norecordingprompt)); 00241 else if (!strcasecmp(param, "followme-options-prompt")) 00242 ast_copy_string(f->optionsprompt, val, sizeof(f->optionsprompt)); 00243 else if (!strcasecmp(param, "followme-pls-hold-prompt")) 00244 ast_copy_string(f->plsholdprompt, val, sizeof(f->plsholdprompt)); 00245 else if (!strcasecmp(param, "followme-status-prompt")) 00246 ast_copy_string(f->statusprompt, val, sizeof(f->statusprompt)); 00247 else if (!strcasecmp(param, "followme-sorry-prompt")) 00248 ast_copy_string(f->sorryprompt, val, sizeof(f->sorryprompt)); 00249 else if (failunknown) { 00250 if (linenum >= 0) 00251 ast_log(LOG_WARNING, "Unknown keyword in profile '%s': %s at line %d of followme.conf\n", f->name, param, linenum); 00252 else 00253 ast_log(LOG_WARNING, "Unknown keyword in profile '%s': %s\n", f->name, param); 00254 } 00255 }
static int reload | ( | void | ) | [static] |
Definition at line 1094 of file app_followme.c.
References reload_followme().
01095 { 01096 reload_followme(); 01097 01098 return 0; 01099 }
static int reload_followme | ( | void | ) | [static] |
Reload followme application module.
Definition at line 279 of file app_followme.c.
References alloc_profile(), ast_category_browse(), ast_config_destroy(), ast_config_load(), AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), create_followme_number(), f, free_numbers(), init_profile(), LOG_DEBUG, LOG_WARNING, ast_format::name, option_debug, profile_set_param(), number::timeout, and var.
Referenced by load_module(), and reload().
00280 { 00281 struct call_followme *f; 00282 struct ast_config *cfg; 00283 char *cat = NULL, *tmp; 00284 struct ast_variable *var; 00285 struct number *cur, *nm; 00286 int new, idx; 00287 char numberstr[90]; 00288 int timeout; 00289 char *timeoutstr; 00290 int numorder; 00291 const char *takecallstr; 00292 const char *declinecallstr; 00293 const char *tmpstr; 00294 00295 cfg = ast_config_load("followme.conf"); 00296 if (!cfg) { 00297 ast_log(LOG_WARNING, "No follow me config file (followme.conf), so no follow me\n"); 00298 return 0; 00299 } 00300 00301 AST_LIST_LOCK(&followmes); 00302 00303 /* Reset Global Var Values */ 00304 featuredigittimeout = 5000; 00305 00306 /* Mark all profiles as inactive for the moment */ 00307 AST_LIST_TRAVERSE(&followmes, f, entry) { 00308 f->active = 0; 00309 } 00310 featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout"); 00311 00312 if (!ast_strlen_zero(featuredigittostr)) { 00313 if (!sscanf(featuredigittostr, "%d", &featuredigittimeout)) 00314 featuredigittimeout = 5000; 00315 } 00316 00317 takecallstr = ast_variable_retrieve(cfg, "general", "takecall"); 00318 if (!ast_strlen_zero(takecallstr)) 00319 ast_copy_string(takecall, takecallstr, sizeof(takecall)); 00320 00321 declinecallstr = ast_variable_retrieve(cfg, "general", "declinecall"); 00322 if (!ast_strlen_zero(declinecallstr)) 00323 ast_copy_string(nextindp, declinecallstr, sizeof(nextindp)); 00324 00325 tmpstr = ast_variable_retrieve(cfg, "general", "call-from-prompt"); 00326 if (!ast_strlen_zero(tmpstr)) 00327 ast_copy_string(callfromprompt, tmpstr, sizeof(callfromprompt)); 00328 00329 tmpstr = ast_variable_retrieve(cfg, "general", "norecording-prompt"); 00330 if (!ast_strlen_zero(tmpstr)) 00331 ast_copy_string(norecordingprompt, tmpstr, sizeof(norecordingprompt)); 00332 00333 tmpstr = ast_variable_retrieve(cfg, "general", "options-prompt"); 00334 if (!ast_strlen_zero(tmpstr)) 00335 ast_copy_string(optionsprompt, tmpstr, sizeof(optionsprompt)); 00336 00337 tmpstr = ast_variable_retrieve(cfg, "general", "pls-hold-prompt"); 00338 if (!ast_strlen_zero(tmpstr)) 00339 ast_copy_string(plsholdprompt, tmpstr, sizeof(plsholdprompt)); 00340 00341 tmpstr = ast_variable_retrieve(cfg, "general", "status-prompt"); 00342 if (!ast_strlen_zero(tmpstr)) 00343 ast_copy_string(statusprompt, tmpstr, sizeof(statusprompt)); 00344 00345 tmpstr = ast_variable_retrieve(cfg, "general", "sorry-prompt"); 00346 if (!ast_strlen_zero(tmpstr)) 00347 ast_copy_string(sorryprompt, tmpstr, sizeof(sorryprompt)); 00348 00349 /* Chug through config file */ 00350 while ((cat = ast_category_browse(cfg, cat))) { 00351 if (!strcasecmp(cat, "general")) 00352 continue; 00353 /* Define a new profile */ 00354 /* Look for an existing one */ 00355 AST_LIST_TRAVERSE(&followmes, f, entry) { 00356 if (!strcasecmp(f->name, cat)) 00357 break; 00358 } 00359 if (option_debug) 00360 ast_log(LOG_DEBUG, "New profile %s.\n", cat); 00361 if (!f) { 00362 /* Make one then */ 00363 f = alloc_profile(cat); 00364 new = 1; 00365 } else 00366 new = 0; 00367 00368 if (f) { 00369 if (!new) 00370 ast_mutex_lock(&f->lock); 00371 /* Re-initialize the profile */ 00372 init_profile(f); 00373 free_numbers(f); 00374 var = ast_variable_browse(cfg, cat); 00375 while(var) { 00376 if (!strcasecmp(var->name, "number")) { 00377 /* Add a new number */ 00378 ast_copy_string(numberstr, var->value, sizeof(numberstr)); 00379 if ((tmp = strchr(numberstr, ','))) { 00380 *tmp = '\0'; 00381 tmp++; 00382 timeoutstr = ast_strdupa(tmp); 00383 if ((tmp = strchr(timeoutstr, ','))) { 00384 *tmp = '\0'; 00385 tmp++; 00386 numorder = atoi(tmp); 00387 if (numorder < 0) 00388 numorder = 0; 00389 } else 00390 numorder = 0; 00391 timeout = atoi(timeoutstr); 00392 if (timeout < 0) 00393 timeout = 25; 00394 } else { 00395 timeout = 25; 00396 numorder = 0; 00397 } 00398 00399 if (!numorder) { 00400 idx = 1; 00401 AST_LIST_TRAVERSE(&f->numbers, nm, entry) 00402 idx++; 00403 numorder = idx; 00404 } 00405 cur = create_followme_number(numberstr, timeout, numorder); 00406 AST_LIST_INSERT_TAIL(&f->numbers, cur, entry); 00407 } else { 00408 profile_set_param(f, var->name, var->value, var->lineno, 1); 00409 if (option_debug > 1) 00410 ast_log(LOG_DEBUG, "Logging parameter %s with value %s from lineno %d\n", var->name, var->value, var->lineno); 00411 } 00412 var = var->next; 00413 } /* End while(var) loop */ 00414 00415 if (!new) 00416 ast_mutex_unlock(&f->lock); 00417 else 00418 AST_LIST_INSERT_HEAD(&followmes, f, entry); 00419 } 00420 } 00421 ast_config_destroy(cfg); 00422 00423 AST_LIST_UNLOCK(&followmes); 00424 00425 return 1; 00426 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1066 of file app_followme.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_module_user_hangup_all, ast_unregister_application(), f, free, and free_numbers().
01067 { 01068 struct call_followme *f; 01069 01070 ast_module_user_hangup_all(); 01071 01072 ast_unregister_application(app); 01073 01074 /* Free Memory. Yeah! I'm free! */ 01075 AST_LIST_LOCK(&followmes); 01076 while ((f = AST_LIST_REMOVE_HEAD(&followmes, entry))) { 01077 free_numbers(f); 01078 free(f); 01079 } 01080 01081 AST_LIST_UNLOCK(&followmes); 01082 01083 return 0; 01084 }
static struct ast_channel* wait_for_winner | ( | struct findme_user_listptr * | findme_user_list, | |
struct number * | nm, | |||
struct ast_channel * | caller, | |||
char * | namerecloc, | |||
int * | status, | |||
struct fm_args * | tpargs | |||
) | [static] |
Definition at line 470 of file app_followme.c.
References AST_CAUSE_NORMAL_CLEARING, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_hangup(), AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor_n(), clear_calling_tree(), findme_user::digts, f, ast_channel::hangupcause, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, findme_user::ochan, option_debug, option_verbose, ast_channel::sched, findme_user::state, ast_channel::stream, number::timeout, ast_channel::timingfunc, VERBOSE_PREFIX_3, findme_user::yn, and findme_user::ynidx.
Referenced by findmeexec().
00471 { 00472 struct ast_channel *watchers[256]; 00473 int pos; 00474 struct ast_channel *winner; 00475 struct ast_frame *f; 00476 int ctstatus; 00477 int dg; 00478 struct findme_user *tmpuser; 00479 int to = 0; 00480 int livechannels = 0; 00481 int tmpto; 00482 long totalwait = 0, wtd, towas = 0; 00483 char *callfromname; 00484 char *pressbuttonname; 00485 00486 /* ------------ wait_for_winner_channel start --------------- */ 00487 00488 callfromname = ast_strdupa(tpargs->callfromprompt); 00489 pressbuttonname = ast_strdupa(tpargs->optionsprompt); 00490 00491 if (!AST_LIST_EMPTY(findme_user_list)) { 00492 if (!caller) { 00493 if (option_verbose > 2) 00494 ast_verbose(VERBOSE_PREFIX_3 "Original caller hungup. Cleanup.\n"); 00495 clear_calling_tree(findme_user_list); 00496 return NULL; 00497 } 00498 ctstatus = 0; 00499 totalwait = nm->timeout * 1000; 00500 wtd = 0; 00501 while (!ctstatus) { 00502 to = 1000; 00503 pos = 1; 00504 livechannels = 0; 00505 watchers[0] = caller; 00506 00507 dg = 0; 00508 winner = NULL; 00509 AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) { 00510 if (tmpuser->state >= 0 && tmpuser->ochan) { 00511 if (tmpuser->state == 3) 00512 tmpuser->digts += (towas - wtd); 00513 if (tmpuser->digts && (tmpuser->digts > featuredigittimeout)) { 00514 if (option_verbose > 2) 00515 ast_verbose(VERBOSE_PREFIX_3 "We've been waiting for digits longer than we should have.\n"); 00516 if (!ast_strlen_zero(namerecloc)) { 00517 tmpuser->state = 1; 00518 tmpuser->digts = 0; 00519 if (!ast_streamfile(tmpuser->ochan, callfromname, tmpuser->ochan->language)) { 00520 ast_sched_runq(tmpuser->ochan->sched); 00521 } else { 00522 ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname); 00523 return NULL; 00524 } 00525 } else { 00526 tmpuser->state = 2; 00527 tmpuser->digts = 0; 00528 if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language)) 00529 ast_sched_runq(tmpuser->ochan->sched); 00530 else { 00531 ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt); 00532 return NULL; 00533 } 00534 } 00535 } 00536 if (tmpuser->ochan->stream) { 00537 ast_sched_runq(tmpuser->ochan->sched); 00538 tmpto = ast_sched_wait(tmpuser->ochan->sched); 00539 if (tmpto > 0 && tmpto < to) 00540 to = tmpto; 00541 else if (tmpto < 0 && !tmpuser->ochan->timingfunc) { 00542 ast_stopstream(tmpuser->ochan); 00543 if (tmpuser->state == 1) { 00544 if (option_verbose > 2) 00545 ast_verbose(VERBOSE_PREFIX_3 "Playback of the call-from file appears to be done.\n"); 00546 if (!ast_streamfile(tmpuser->ochan, namerecloc, tmpuser->ochan->language)) { 00547 tmpuser->state = 2; 00548 } else { 00549 ast_log(LOG_NOTICE, "Unable to playback %s. Maybe the caller didn't record their name?\n", namerecloc); 00550 memset(tmpuser->yn, 0, sizeof(tmpuser->yn)); 00551 tmpuser->ynidx = 0; 00552 if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) 00553 tmpuser->state = 3; 00554 else { 00555 ast_log(LOG_WARNING, "Unable to playback %s.\n", pressbuttonname); 00556 return NULL; 00557 } 00558 } 00559 } else if (tmpuser->state == 2) { 00560 if (option_verbose > 2) 00561 ast_verbose(VERBOSE_PREFIX_3 "Playback of name file appears to be done.\n"); 00562 memset(tmpuser->yn, 0, sizeof(tmpuser->yn)); 00563 tmpuser->ynidx = 0; 00564 if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) { 00565 tmpuser->state = 3; 00566 00567 } else { 00568 return NULL; 00569 } 00570 } else if (tmpuser->state == 3) { 00571 if (option_verbose > 2) 00572 ast_verbose(VERBOSE_PREFIX_3 "Playback of the next step file appears to be done.\n"); 00573 tmpuser->digts = 0; 00574 } 00575 } 00576 } 00577 watchers[pos++] = tmpuser->ochan; 00578 livechannels++; 00579 } 00580 } 00581 00582 tmpto = to; 00583 if (to < 0) { 00584 to = 1000; 00585 tmpto = 1000; 00586 } 00587 towas = to; 00588 winner = ast_waitfor_n(watchers, pos, &to); 00589 tmpto -= to; 00590 totalwait -= tmpto; 00591 wtd = to; 00592 if (totalwait <= 0) { 00593 if (option_verbose > 2) 00594 ast_verbose(VERBOSE_PREFIX_3 "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait); 00595 clear_calling_tree(findme_user_list); 00596 return NULL; 00597 } 00598 if (winner) { 00599 /* Need to find out which channel this is */ 00600 dg = 0; 00601 while ((winner != watchers[dg]) && (dg < 256)) 00602 dg++; 00603 AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) 00604 if (tmpuser->ochan == winner) 00605 break; 00606 f = ast_read(winner); 00607 if (f) { 00608 if (f->frametype == AST_FRAME_CONTROL) { 00609 switch(f->subclass) { 00610 case AST_CONTROL_HANGUP: 00611 if (option_verbose > 2) 00612 ast_verbose( VERBOSE_PREFIX_3 "%s received a hangup frame.\n", winner->name); 00613 if (dg == 0) { 00614 if (option_verbose > 2) 00615 ast_verbose( VERBOSE_PREFIX_3 "The calling channel hungup. Need to drop everyone else.\n"); 00616 clear_calling_tree(findme_user_list); 00617 ctstatus = -1; 00618 } 00619 break; 00620 case AST_CONTROL_ANSWER: 00621 if (option_verbose > 2) 00622 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", winner->name, caller->name); 00623 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 00624 winner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00625 caller->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00626 if (option_verbose > 2) 00627 ast_verbose( VERBOSE_PREFIX_3 "Starting playback of %s\n", callfromname); 00628 if (dg > 0) { 00629 if (!ast_strlen_zero(namerecloc)) { 00630 if (!ast_streamfile(winner, callfromname, winner->language)) { 00631 ast_sched_runq(winner->sched); 00632 tmpuser->state = 1; 00633 } else { 00634 ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname); 00635 ast_frfree(f); 00636 return NULL; 00637 } 00638 } else { 00639 tmpuser->state = 2; 00640 if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language)) 00641 ast_sched_runq(tmpuser->ochan->sched); 00642 else { 00643 ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt); 00644 ast_frfree(f); 00645 return NULL; 00646 } 00647 } 00648 } 00649 break; 00650 case AST_CONTROL_BUSY: 00651 if (option_verbose > 2) 00652 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", winner->name); 00653 break; 00654 case AST_CONTROL_CONGESTION: 00655 if (option_verbose > 2) 00656 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", winner->name); 00657 break; 00658 case AST_CONTROL_RINGING: 00659 if (option_verbose > 2) 00660 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", winner->name); 00661 break; 00662 case AST_CONTROL_PROGRESS: 00663 if (option_verbose > 2) 00664 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", winner->name, caller->name); 00665 break; 00666 case AST_CONTROL_VIDUPDATE: 00667 if (option_verbose > 2) 00668 ast_verbose ( VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", winner->name, caller->name); 00669 break; 00670 case AST_CONTROL_PROCEEDING: 00671 if (option_verbose > 2) 00672 ast_verbose ( VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", winner->name,caller->name); 00673 break; 00674 case AST_CONTROL_HOLD: 00675 if (option_verbose > 2) 00676 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", winner->name); 00677 break; 00678 case AST_CONTROL_UNHOLD: 00679 if (option_verbose > 2) 00680 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", winner->name); 00681 break; 00682 case AST_CONTROL_OFFHOOK: 00683 case AST_CONTROL_FLASH: 00684 /* Ignore going off hook and flash */ 00685 break; 00686 case -1: 00687 if (option_verbose > 2) 00688 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", winner->name); 00689 break; 00690 default: 00691 if (option_debug) 00692 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); 00693 break; 00694 } 00695 } 00696 if (tmpuser && tmpuser->state == 3 && f->frametype == AST_FRAME_DTMF) { 00697 if (winner->stream) 00698 ast_stopstream(winner); 00699 tmpuser->digts = 0; 00700 if (option_debug) 00701 ast_log(LOG_DEBUG, "DTMF received: %c\n",(char) f->subclass); 00702 tmpuser->yn[tmpuser->ynidx] = (char) f->subclass; 00703 tmpuser->ynidx++; 00704 if (option_debug) 00705 ast_log(LOG_DEBUG, "DTMF string: %s\n", tmpuser->yn); 00706 if (tmpuser->ynidx >= ynlongest) { 00707 if (option_debug) 00708 ast_log(LOG_DEBUG, "reached longest possible match - doing evals\n"); 00709 if (!strcmp(tmpuser->yn, tpargs->takecall)) { 00710 if (option_debug) 00711 ast_log(LOG_DEBUG, "Match to take the call!\n"); 00712 ast_frfree(f); 00713 return tmpuser->ochan; 00714 } 00715 if (!strcmp(tmpuser->yn, tpargs->nextindp)) { 00716 if (option_debug) 00717 ast_log(LOG_DEBUG, "Next in dial plan step requested.\n"); 00718 *status = 1; 00719 ast_frfree(f); 00720 return NULL; 00721 } 00722 00723 } 00724 } 00725 00726 ast_frfree(f); 00727 } else { 00728 if (winner) { 00729 if (option_debug) 00730 ast_log(LOG_DEBUG, "we didn't get a frame. hanging up. dg is %d\n",dg); 00731 if (!dg) { 00732 clear_calling_tree(findme_user_list); 00733 return NULL; 00734 } else { 00735 tmpuser->state = -1; 00736 ast_hangup(winner); 00737 livechannels--; 00738 if (option_debug) 00739 ast_log(LOG_DEBUG, "live channels left %d\n", livechannels); 00740 if (!livechannels) { 00741 if (option_verbose > 2) 00742 ast_verbose(VERBOSE_PREFIX_3 "no live channels left. exiting.\n"); 00743 return NULL; 00744 } 00745 } 00746 } 00747 } 00748 00749 } else 00750 if (option_debug) 00751 ast_log(LOG_DEBUG, "timed out waiting for action\n"); 00752 } 00753 00754 } else { 00755 if (option_verbose > 2) 00756 ast_verbose(VERBOSE_PREFIX_3 "couldn't reach at this number.\n"); 00757 } 00758 00759 /* --- WAIT FOR WINNER NUMBER END! -----------*/ 00760 return NULL; 00761 }
time_t answer_time [static] |
Definition at line 150 of file app_followme.c.
char* app = "FollowMe" [static] |
Definition at line 61 of file app_followme.c.
char callfromprompt[PATH_MAX] = "followme/call-from" [static] |
Definition at line 157 of file app_followme.c.
const char* defaultmoh = "default" [static] |
Default Music-On-Hold Class
Definition at line 154 of file app_followme.c.
char* descrip [static] |
Definition at line 63 of file app_followme.c.
time_t end_time [static] |
Definition at line 150 of file app_followme.c.
int featuredigittimeout = 5000 [static] |
const char* featuredigittostr [static] |
Definition at line 152 of file app_followme.c.
char nextindp[20] = "2" [static] |
Definition at line 156 of file app_followme.c.
char norecordingprompt[PATH_MAX] = "followme/no-recording" [static] |
Definition at line 158 of file app_followme.c.
char optionsprompt[PATH_MAX] = "followme/options" [static] |
Definition at line 159 of file app_followme.c.
char plsholdprompt[PATH_MAX] = "followme/pls-hold-while-try" [static] |
Definition at line 160 of file app_followme.c.
char sorryprompt[PATH_MAX] = "followme/sorry" [static] |
Definition at line 162 of file app_followme.c.
time_t start_time [static] |
Definition at line 150 of file app_followme.c.
char statusprompt[PATH_MAX] = "followme/status" [static] |
Definition at line 161 of file app_followme.c.
char* synopsis = "Find-Me/Follow-Me application" [static] |
Definition at line 62 of file app_followme.c.
char takecall[20] = "1" [static] |
Definition at line 156 of file app_followme.c.
int ynlongest = 0 [static] |
Definition at line 149 of file app_followme.c.