67#define REC_FORMAT "sln"
148static char *
app =
"FollowMe";
151#define MAX_YN_STRING 20
351 if (!strcasecmp(param,
"musicclass") || !strcasecmp(param,
"musiconhold") || !strcasecmp(param,
"music"))
353 else if (!strcasecmp(param,
"context"))
355 else if (!strcasecmp(param,
"enable_callee_prompt"))
357 else if (!strcasecmp(param,
"takecall"))
359 else if (!strcasecmp(param,
"declinecall"))
361 else if (!strcasecmp(param,
"call-from-prompt") || !strcasecmp(param,
"call_from_prompt"))
363 else if (!strcasecmp(param,
"followme-norecording-prompt") || !strcasecmp(param,
"norecording_prompt"))
365 else if (!strcasecmp(param,
"followme-options-prompt") || !strcasecmp(param,
"options_prompt"))
367 else if (!strcasecmp(param,
"followme-pls-hold-prompt") || !strcasecmp(param,
"pls_hold_prompt"))
369 else if (!strcasecmp(param,
"followme-status-prompt") || !strcasecmp(param,
"status_prompt"))
371 else if (!strcasecmp(param,
"followme-sorry-prompt") || !strcasecmp(param,
"sorry_prompt"))
373 else if (!strcasecmp(param,
"followme-connecting-prompt") || !strcasecmp(param,
"connecting_prompt")) {
375 }
else if (failunknown) {
377 ast_log(
LOG_WARNING,
"Unknown keyword in profile '%s': %s at line %d of followme.conf\n", f->
name, param, linenum);
394 if ((
tmp = strchr(
buf,
',')))
397 cur->
order = numorder;
413 const char* enable_callee_prompt_str;
414 const char *takecallstr;
415 const char *declinecallstr;
425 ast_log(
LOG_ERROR,
"Config file followme.conf is in an invalid format. Aborting.\n");
447 "enable_callee_prompt")) &&
508 if (!strcasecmp(cat,
"general"))
513 if (!strcasecmp(f->
name, cat))
536 if (!strcasecmp(
var->name,
"number")) {
538 char copy[strlen(
var->value) + 1];
544 if ((
tmp = strchr(numberstr,
','))) {
550 if ((
tmp = strchr(
tmp,
','))) {
552 numorder = atoi(
tmp);
574 ast_debug(2,
"Logging parameter %s with value %s from lineno %d\n",
var->name,
var->value,
var->lineno);
597 if (tmpuser->
ochan && tmpuser->
ochan != exception) {
607 if (!tmpuser->
ochan) {
612 outbound = tmpuser->
ochan;
655 long totalwait = 0, wtd = 0, towas = 0;
657 char *pressbuttonname;
664 totalwait = nm->
timeout * 1000;
670 watchers[0] = caller;
674 if (!tmpuser->
ochan) {
677 if (tmpuser->
state == 3) {
678 tmpuser->
digts += (towas - wtd);
681 ast_verb(3,
"<%s> We've been waiting for digits longer than we should have.\n",
712 if (tmpto > 0 && tmpto < to)
716 switch (tmpuser->
state) {
718 ast_verb(3,
"<%s> Playback of the call-from file appears to be done.\n",
723 ast_log(
LOG_NOTICE,
"<%s> Unable to playback %s. Maybe the caller didn't record their name?\n",
725 memset(tmpuser->
yn, 0,
sizeof(tmpuser->
yn));
737 ast_verb(3,
"<%s> Playback of name file appears to be done.\n",
739 memset(tmpuser->
yn, 0,
sizeof(tmpuser->
yn));
749 ast_verb(3,
"<%s> Playback of the next step file appears to be done.\n",
758 watchers[pos++] = tmpuser->
ochan;
762 ast_verb(3,
"No live channels left for this step.\n");
772 if (totalwait <= 0) {
773 ast_verb(3,
"We've hit our timeout for this step. Dropping unanswered calls and starting the next step.\n");
779 if (winner != caller) {
782 if (tmpuser->
ochan == winner) {
800 ast_verb(3,
"The calling channel hungup. Need to drop everyone.\n");
820 ast_verb(3,
"Starting playback of %s\n", callfromname);
839 ast_debug(1,
"Taking call with no prompt\n");
841 return tmpuser->
ochan;
918 ast_verb(3,
"Connected line update from %s prevented.\n",
928 "%s connected line has changed. Saving it until we have a winner.\n",
939 "%s connected line has changed. Saving it until answer.\n",
963 ast_debug(1,
"Dunno what to do with control type %d from %s\n",
979 memmove(tmpuser->
yn, tmpuser->
yn + 1,
980 sizeof(tmpuser->
yn) - 2 *
sizeof(tmpuser->
yn[0]));
985 if (cmp_len <= tmpuser->
ynidx
986 && !strcmp(tmpuser->
yn + (tmpuser->
ynidx - cmp_len), tpargs->
takecall)) {
987 ast_debug(1,
"Match to take the call!\n");
989 return tmpuser->
ochan;
992 if (cmp_len <= tmpuser->
ynidx
993 && !strcmp(tmpuser->
yn + (tmpuser->
ynidx - cmp_len), tpargs->
nextindp)) {
994 ast_debug(1,
"Declined to take the call.\n");
1001 ast_debug(1,
"we didn't get a frame. hanging up.\n");
1004 ast_verb(3,
"The calling channel hungup. Need to drop everyone.\n");
1012 ast_debug(1,
"timed out waiting for action\n");
1044 if (nm->
order == idx) {
1049 ast_verb(3,
"No more steps left.\n");
1062 if (tmpuser->
ochan) {
1073 rest = strchr(
number,
'&');
1128 tmpuser->
ochan = outbound;
1162 if (tmpuser->
ochan) {
1174 ast_verb(3,
"couldn't reach at this number.\n");
1208 if (!tmpuser->
ochan) {
1219 if (fmuser->
ochan == winner) {
1267 for (v =
var; v; v = v->
next) {
1268 if (!strcasecmp(v->
name,
"active")) {
1296 const char *timeoutstr;
1305 || sscanf(timeoutstr,
"%30d", &
timeout) != 1
1319 return new_follower;
1348 struct number *nm, *newnm;
1370 ast_log(
LOG_WARNING,
"Unable to execute FollowMe on channel %s. Max forwards exceeded\n",
1529 config.end_bridge_callback_data = chan;
1585 snprintf(fn,
sizeof(fn),
"%s.%s", targs->
namerecloc,
1592 ast_debug(2,
"deleted recorded prompt %s.\n", fn);
static char connprompt[PATH_MAX]
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.
@ FOLLOWMEFLAG_UNREACHABLEMSG
@ FOLLOWMEFLAG_DISABLEHOLDPROMPT
@ FOLLOWMEFLAG_PREDIAL_CALLER
@ FOLLOWMEFLAG_IGNORE_CONNECTEDLINE
@ FOLLOWMEFLAG_RECORDNAME
@ FOLLOWMEFLAG_DISABLEOPTIMIZATION
@ FOLLOWMEFLAG_PREDIAL_CALLEE
static char sorryprompt[PATH_MAX]
static int reload_followme(int reload)
Reload followme application module.
static char callfromprompt[PATH_MAX]
static char takecall[MAX_YN_STRING]
static struct call_followme * alloc_profile(const char *fmname)
Allocate and initialize followme profile.
static void clear_caller(struct findme_user *tmpuser)
static struct ast_channel * findmeexec(struct fm_args *tpargs, struct ast_channel *caller)
static void clear_unanswered_calls(struct findme_user_listptr *findme_user_list)
static char nextindp[MAX_YN_STRING]
static int featuredigittimeout
static char optionsprompt[PATH_MAX]
static void destroy_calling_tree(struct findme_user_listptr *findme_user_list)
static const struct ast_app_option followme_opts[128]
static void init_profile(struct call_followme *f, int activate)
static void publish_dial_end_event(struct ast_channel *in, struct findme_user_listptr *findme_user_list, struct ast_channel *exception, const char *status)
static char statusprompt[PATH_MAX]
static int app_exec(struct ast_channel *chan, const char *data)
static char plsholdprompt[PATH_MAX]
@ FOLLOWMEFLAG_ARG_ARRAY_SIZE
@ FOLLOWMEFLAG_ARG_PREDIAL_CALLER
@ FOLLOWMEFLAG_ARG_PREDIAL_CALLEE
static struct number * create_followme_number(const char *number, int timeout, int numorder)
Add a new number.
static int load_module(void)
Load the module.
static struct call_followme * find_realtime(const char *name)
static const char * featuredigittostr
static void end_bridge_callback(void *data)
static int unload_module(void)
static char norecordingprompt[PATH_MAX]
static void destroy_calling_node(struct findme_user *node)
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
static int enable_callee_prompt
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)
static const char * defaultmoh
static void free_numbers(struct call_followme *f)
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Persistent data storage (akin to *doze registry)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Internal Asterisk hangup causes.
#define AST_CAUSE_NORMAL_CLEARING
static const char config[]
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame)
Run a connected line interception subroutine and update a channel's connected line information.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
const char * ast_channel_musicclass(const struct ast_channel *chan)
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
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...
#define ast_channel_lock(chan)
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
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.
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
void ast_deactivate_generator(struct ast_channel *chan)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
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.
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
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.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan)
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
struct ast_sched_context * ast_channel_sched(const struct ast_channel *chan)
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.
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
int ast_pre_call(struct ast_channel *chan, const char *sub_args)
Execute a Gosub call on the channel before a call is placed.
int ast_channel_get_duration(struct ast_channel *chan)
Obtain how long the channel since the channel was created.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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.
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
void ast_autoservice_chan_hangup_peer(struct ast_channel *chan, struct ast_channel *peer)
Put chan into autoservice while hanging up peer.
int ast_answer(struct ast_channel *chan)
Answer a channel.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
ast_channel_state
ast_channel states
Standard Command Line Interface.
Convenient Signal Processing routines.
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_stopstream(struct ast_channel *c)
Stops a stream.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
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.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
const char * ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
Add missing context/exten to subroutine argument string.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
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...
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
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.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
@ CONFIG_FLAG_FILEUNCHANGED
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_PVT_CAUSE_CODE
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#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_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_RWLIST_TRAVERSE
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_RWLIST_INSERT_HEAD
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_APPEND_LIST(head, list, field)
Appends a whole list to the tail of a list.
Asterisk locking-related definitions:
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int ast_max_forwards_decrement(struct ast_channel *chan)
Decrement the max forwards count for a particular channel.
int ast_max_forwards_get(struct ast_channel *chan)
Get the current max forwards for a particular channel.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
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_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_SPOOL_DIR
Core PBX routines and definitions.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
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.
Say numbers and dates (maybe words one day too)
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
#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 force_inline int attribute_pure ast_strlen_zero(const char *s)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void * end_bridge_callback_data
Main Channel structure associated with a channel.
struct ast_party_caller caller
Channel Caller ID information.
Structure used to handle boolean flags.
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
Structure for mutex and tracking information.
Connected Line/Party information.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Data structure for followme scripts.
char connprompt[PATH_MAX]
struct call_followme::wlnumbers wlnumbers
unsigned int enable_callee_prompt
char name[AST_MAX_EXTENSION]
char sorryprompt[PATH_MAX]
char callfromprompt[PATH_MAX]
char takecall[MAX_YN_STRING]
char nextindp[MAX_YN_STRING]
char optionsprompt[PATH_MAX]
struct call_followme::blnumbers blnumbers
char statusprompt[PATH_MAX]
char plsholdprompt[PATH_MAX]
struct call_followme::@25 entry
char context[AST_MAX_CONTEXT]
struct call_followme::numbers numbers
char norecordingprompt[PATH_MAX]
struct findme_user::@26 entry
struct ast_channel * ochan
struct ast_party_connected_line connected
unsigned int pending_connected_update
char connprompt[PATH_MAX]
unsigned int pending_in_connected_update
char namerecloc[PATH_MAX]
struct fm_args::cnumbers cnumbers
unsigned int enable_callee_prompt
char sorryprompt[PATH_MAX]
char callfromprompt[PATH_MAX]
char takecall[MAX_YN_STRING]
unsigned int pending_hold
struct ast_party_connected_line connected_out
unsigned int pending_out_connected_update
char suggested_moh[MAX_MUSICCLASS]
char nextindp[MAX_YN_STRING]
char optionsprompt[PATH_MAX]
char statusprompt[PATH_MAX]
char plsholdprompt[PATH_MAX]
struct ast_flags followmeflags
char context[AST_MAX_CONTEXT]
char norecordingprompt[PATH_MAX]
const char * predial_callee
struct ast_party_connected_line connected_in
Channel datastore data for max forwards.
Support for translation of data formats. translate.c.
#define ast_test_flag(p, flag)
#define ast_clear_flag(p, flag)
#define ast_set_flag(p, flag)
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.