103 static char *
app =
"FollowMe";
106 #define MAX_YN_STRING 20
151 unsigned int pending_in_connected_update:1;
153 unsigned int pending_out_connected_update:1;
156 char namerecloc[PATH_MAX];
158 char nextindp[MAX_YN_STRING];
159 char callfromprompt[PATH_MAX];
160 char norecordingprompt[PATH_MAX];
161 char optionsprompt[PATH_MAX];
162 char plsholdprompt[PATH_MAX];
163 char statusprompt[PATH_MAX];
164 char sorryprompt[PATH_MAX];
179 unsigned int cleared:1;
181 unsigned int pending_connected_update:1;
207 static char callfromprompt[PATH_MAX] =
"followme/call-from";
208 static char norecordingprompt[PATH_MAX] =
"followme/no-recording";
209 static char optionsprompt[PATH_MAX] =
"followme/options";
210 static char plsholdprompt[PATH_MAX] =
"followme/pls-hold-while-try";
211 static char statusprompt[PATH_MAX] =
"followme/status";
212 static char sorryprompt[PATH_MAX] =
"followme/sorry";
243 struct call_followme *
f;
275 static void profile_set_param(
struct call_followme *
f,
const char *param,
const char *
val,
int linenum,
int failunknown)
278 if (!strcasecmp(param,
"musicclass") || !strcasecmp(param,
"musiconhold") || !strcasecmp(param,
"music"))
280 else if (!strcasecmp(param,
"context"))
282 else if (!strcasecmp(param,
"takecall"))
284 else if (!strcasecmp(param,
"declinecall"))
286 else if (!strcasecmp(param,
"call-from-prompt") || !strcasecmp(param,
"call_from_prompt"))
288 else if (!strcasecmp(param,
"followme-norecording-prompt") || !strcasecmp(param,
"norecording_prompt"))
290 else if (!strcasecmp(param,
"followme-options-prompt") || !strcasecmp(param,
"options_prompt"))
292 else if (!strcasecmp(param,
"followme-pls-hold-prompt") || !strcasecmp(param,
"pls_hold_prompt"))
294 else if (!strcasecmp(param,
"followme-status-prompt") || !strcasecmp(param,
"status_prompt"))
296 else if (!strcasecmp(param,
"followme-sorry-prompt") || !strcasecmp(param,
"sorry_prompt"))
298 else if (failunknown) {
300 ast_log(
LOG_WARNING,
"Unknown keyword in profile '%s': %s at line %d of followme.conf\n", f->
name, param, linenum);
317 if ((tmp = strchr(buf,
',')))
320 cur->
order = numorder;
329 struct call_followme *
f;
331 char *cat = NULL, *tmp;
337 const char *takecallstr;
338 const char *declinecallstr;
348 ast_log(
LOG_ERROR,
"Config file followme.conf is in an invalid format. Aborting.\n");
355 featuredigittimeout = 5000;
365 if (!sscanf(featuredigittostr,
"%30d", &featuredigittimeout))
366 featuredigittimeout = 5000;
418 if (!strcasecmp(cat,
"general"))
423 if (!strcasecmp(f->
name, cat))
446 if (!strcasecmp(var->
name,
"number")) {
451 if ((tmp = strchr(numberstr,
','))) {
457 if ((tmp = strchr(tmp,
','))) {
459 numorder = atoi(tmp);
503 if (tmpuser && tmpuser->
ochan && tmpuser->
state >= 0) {
504 outbound = tmpuser->
ochan;
506 if (!outbound->
cdr) {
515 snprintf(tmp,
sizeof(tmp),
"%s/%s",
"Local", tmpuser->
dialarg);
529 tmpuser->
ochan = NULL;
535 struct findme_user *tmpuser;
545 struct findme_user *fmuser;
566 struct findme_user *tmpuser;
568 int livechannels = 0;
570 long totalwait = 0, wtd = 0, towas = 0;
572 char *pressbuttonname;
580 ast_verb(3,
"couldn't reach at this number.\n");
585 ast_verb(3,
"Original caller hungup. Cleanup.\n");
590 totalwait = nm->
timeout * 1000;
596 watchers[0] = caller;
602 if (tmpuser->
state == 3)
603 tmpuser->
digts += (towas - wtd);
604 if (tmpuser->
digts && (tmpuser->
digts > featuredigittimeout)) {
605 ast_verb(3,
"We've been waiting for digits longer than we should have.\n");
629 if (tmpto > 0 && tmpto < to)
631 else if (tmpto < 0 && !tmpuser->ochan->
timingfunc) {
633 if (tmpuser->
state == 1) {
634 ast_verb(3,
"Playback of the call-from file appears to be done.\n");
638 ast_log(
LOG_NOTICE,
"Unable to playback %s. Maybe the caller didn't record their name?\n", namerecloc);
639 memset(tmpuser->
yn, 0,
sizeof(tmpuser->
yn));
648 }
else if (tmpuser->
state == 2) {
649 ast_verb(3,
"Playback of name file appears to be done.\n");
650 memset(tmpuser->
yn, 0,
sizeof(tmpuser->
yn));
657 }
else if (tmpuser->
state == 3) {
658 ast_verb(3,
"Playback of the next step file appears to be done.\n");
663 watchers[pos++] = tmpuser->
ochan;
678 if (totalwait <= 0) {
679 ast_verb(3,
"We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
685 for (dg = 0; dg <
ARRAY_LEN(watchers); ++dg) {
686 if (winner == watchers[dg]) {
693 if (tmpuser->
ochan == winner) {
705 ast_verb(3,
"%s received a hangup frame.\n", winner->
name);
710 ast_verb(3,
"The calling channel hungup. Need to drop everyone else.\n");
720 ast_verb(3,
"Starting playback of %s\n", callfromname);
756 ast_verb(3,
"%s requested a video update\n", winner->
name);
759 ast_verb(3,
"%s requested a source update\n", winner->
name);
768 ast_verb(3,
"%s removed call from hold\n", winner->
name);
781 "%s connected line has changed. Saving it until we have a winner.\n",
793 ast_verb(3,
"Connected line update from %s prevented.\n",
797 "%s connected line has changed. Saving it until answer.\n",
818 ast_debug(1,
"Dunno what to do with control type %d from %s\n",
828 if (tmpuser->
ynidx < ARRAY_LEN(tmpuser->
yn) - 1) {
833 ast_debug(1,
"Match to take the call!\n");
835 return tmpuser->
ochan;
838 ast_debug(1,
"Next in dial plan step requested.\n");
846 ast_debug(1,
"we didn't get a frame. hanging up. dg is %d\n", dg);
854 tmpuser->
ochan = NULL;
857 ast_debug(1,
"live channels left %d\n", livechannels);
859 ast_verb(3,
"no live channels left. exiting.\n");
865 ast_debug(1,
"timed out waiting for action\n");
883 struct findme_user *tmpuser;
884 struct findme_user *fmuser;
887 findme_user_list =
ast_calloc(1,
sizeof(*findme_user_list));
888 if (!findme_user_list) {
894 caller = tpargs->
chan;
898 if (nm->
order == idx) {
909 for (number = num;
number; number = rest) {
910 rest = strchr(number,
'&');
921 if (!strcmp(tpargs->
context,
"")) {
922 snprintf(dialarg,
sizeof(dialarg),
"%s", number);
924 snprintf(dialarg,
sizeof(dialarg),
"%s@%s", number, tpargs->
context);
943 ast_verb(3,
"calling Local/%s\n", dialarg);
944 if (!
ast_call(outbound, dialarg, 0)) {
945 tmpuser->
ochan = outbound;
951 ast_verb(3,
"couldn't reach at this number.\n");
953 if (!outbound->
cdr) {
960 snprintf(tmp,
sizeof(tmp),
"%s/%s",
"Local", dialarg);
993 if (fmuser->
ochan == winner) {
1025 struct call_followme *new_follower;
1045 for (v = var; v; v = v->
next) {
1046 if (!strcasecmp(v->
name,
"active")) {
1074 const char *timeoutstr;
1083 || sscanf(timeoutstr,
"%30d", &timeout) != 1
1097 return new_follower;
1110 snprintf(buf,
sizeof(buf),
"%ld", (
long) end - chan->
cdr->
answer.tv_sec);
1115 snprintf(buf,
sizeof(buf),
"%ld", (
long) end - chan->
cdr->
start.tv_sec);
1128 struct fm_args targs = { 0, };
1130 struct call_followme *
f;
1131 struct number *nm, *newnm;
1239 if (targs.
status != 100) {
1249 memset(&config, 0,
sizeof(config));
1307 struct call_followme *
f;
static void free_numbers(struct call_followme *f)
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
Save the result of the call based on the AST_CAUSE_*.
int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path)
Record a file based on input from a channel. Use default accept and cancel DTMF. This function will p...
static char musicclass[MAX_MUSICCLASS]
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
union ast_frame_subclass subclass
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
static char accountcode[AST_MAX_ACCOUNT_CODE]
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
char norecordingprompt[PATH_MAX]
char * str
Subscriber phone number (Malloced)
struct ast_party_connected_line connected
Channel Connected Line ID information.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
void(* end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
struct ast_party_caller caller
Channel Caller ID information.
unsigned int pending_out_connected_update
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static void init_profile(struct call_followme *f)
const ast_string_field uniqueid
struct ast_flags features_callee
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
#define ast_test_flag(p, flag)
Support for translation of data formats. translate.c.
struct ast_channel * outbound
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
char norecordingprompt[PATH_MAX]
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define ast_set_flag(p, flag)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
static struct number * create_followme_number(const char *number, int timeout, int numorder)
Add a new number.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
struct fm_args::cnumbers cnumbers
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Structure for variables, used for configurations and for channel variables.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
char callfromprompt[PATH_MAX]
struct ast_party_connected_line connected_out
Configuration File Parser.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define ast_mutex_lock(a)
struct call_followme::numbers numbers
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
char context[AST_MAX_CONTEXT]
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel's connected line information.
char namerecloc[PATH_MAX]
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char plsholdprompt[PATH_MAX]
int ast_unregister_application(const char *app)
Unregister an application.
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
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.
char nextindp[MAX_YN_STRING]
char callfromprompt[PATH_MAX]
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
struct ast_party_id id
Caller party ID.
static void destroy_calling_tree(struct findme_user_listptr *findme_user_list)
static void clear_caller(struct findme_user *tmpuser)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static int reload_followme(int reload)
Reload followme application module.
#define AST_RWLIST_INSERT_HEAD
#define ast_debug(level,...)
Log a DEBUG message.
static char callfromprompt[PATH_MAX]
struct call_followme::wlnumbers wlnumbers
Data structure for followme scripts.
static int featuredigittimeout
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
static char optionsprompt[PATH_MAX]
#define ast_config_load(filename, flags)
Load a config file.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
unsigned int pending_in_connected_update
#define AST_MAX_EXTENSION
#define AST_RWLIST_TRAVERSE
struct ast_party_connected_line connected
#define AST_CAUSE_NORMAL_CLEARING
void * end_bridge_callback_data
char sorryprompt[PATH_MAX]
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static struct ast_app_option followme_opts[128]
static void end_bridge_callback(void *data)
struct sched_context * sched
static char language[MAX_LANGUAGE]
char context[AST_MAX_CONTEXT]
int(* timingfunc)(const void *data)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static char statusprompt[PATH_MAX]
Core PBX routines and definitions.
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
static char nextindp[MAX_YN_STRING]
struct ast_flags features_caller
static int load_module(void)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
char nextindp[MAX_YN_STRING]
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
char optionsprompt[PATH_MAX]
static void clear_calling_tree(struct findme_user_listptr *findme_user_list)
void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update)
Set the connected line information based on another connected line source.
enum ast_channel_state _state
Connected Line/Party information.
const ast_string_field name
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
struct call_followme::blnumbers blnumbers
static char norecordingprompt[PATH_MAX]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
char name[AST_MAX_EXTENSION]
#define ast_channel_unlock(chan)
struct ast_flags followmeflags
const char * ast_cause2str(int state) attribute_pure
Gives the string form of a given cause code.
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
#define AST_RWLIST_REMOVE_HEAD
char statusprompt[PATH_MAX]
void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data)
Set the last executed application.
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
const char * ast_config_AST_SPOOL_DIR
Structure used to handle boolean flags.
static struct call_followme * alloc_profile(const char *fmname)
Allocate and initialize followme profile.
static struct ast_channel * wait_for_winner(struct findme_user_listptr *findme_user_list, struct number *nm, struct ast_channel *caller, char *namerecloc, struct fm_args *tpargs)
int ast_sched_runq(struct sched_context *con)
Runs the queue.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static void findmeexec(struct fm_args *tpargs)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
void ast_deactivate_generator(struct ast_channel *chan)
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
static const char * featuredigittostr
static int app_exec(struct ast_channel *chan, const char *data)
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Standard Command Line Interface.
struct ast_channel * ochan
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
char plsholdprompt[PATH_MAX]
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
int ast_answer(struct ast_channel *chan)
Answer a channel.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
const ast_string_field musicclass
const ast_string_field accountcode
Data structure associated with a single frame of data.
char takecall[MAX_YN_STRING]
Internal Asterisk hangup causes.
static int unload_module(void)
#define AST_APP_ARG(name)
Define an application argument.
enum ast_frame_type frametype
struct ast_variable * next
struct ast_channel * chan
#define ast_mutex_init(pmutex)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static const char * defaultmoh
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define ast_mutex_destroy(a)
char sorryprompt[PATH_MAX]
char takecall[MAX_YN_STRING]
void(* end_bridge_callback)(void *)
struct ast_filestream * stream
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
static char plsholdprompt[PATH_MAX]
char optionsprompt[PATH_MAX]
static struct call_followme * find_realtime(const char *name)
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Asterisk module definitions.
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
union ast_frame::@172 data
static char takecall[MAX_YN_STRING]
static char sorryprompt[PATH_MAX]
Persistant data storage (akin to *doze registry)
unsigned char valid
TRUE if the number information is valid/present.
struct ast_party_connected_line connected_in
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
const ast_string_field language
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Structure for mutex and tracking information.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define CONFIG_STATUS_FILEUNCHANGED
#define ast_mutex_unlock(a)
unsigned int pending_connected_update
char statusprompt[PATH_MAX]
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
struct ast_party_number number
Subscriber phone number.