#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include "asterisk.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/config.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/causes.h"
#include "asterisk/manager.h"
#include "asterisk/privacy.h"
Go to the source code of this file.
Data Structures | |
struct | localuser |
We define a custom "local user" structure because we use it not only for keeping track of what is in use but also for keeping track of who we're dialing. More... | |
Defines | |
#define | AST_MAX_FORWARDS 8 |
#define | AST_MAX_WATCHERS 256 |
#define | DIAL_NOFORWARDHTML (1 << 31) |
#define | DIAL_STILLGOING (1 << 30) |
#define | HANDLE_CAUSE(cause, chan) |
Enumerations | |
enum | { OPT_ANNOUNCE = (1 << 0), OPT_RESETCDR = (1 << 1), OPT_DTMF_EXIT = (1 << 2), OPT_SENDDTMF = (1 << 3), OPT_FORCECLID = (1 << 4), OPT_GO_ON = (1 << 5), OPT_CALLEE_HANGUP = (1 << 6), OPT_CALLER_HANGUP = (1 << 7), OPT_PRIORITY_JUMP = (1 << 8), OPT_DURATION_LIMIT = (1 << 9), OPT_MUSICBACK = (1 << 10), OPT_CALLEE_MACRO = (1 << 11), OPT_SCREEN_NOINTRO = (1 << 12), OPT_SCREEN_NOCLID = (1 << 13), OPT_ORIGINAL_CLID = (1 << 14), OPT_SCREENING = (1 << 15), OPT_PRIVACY = (1 << 16), OPT_RINGBACK = (1 << 17), OPT_DURATION_STOP = (1 << 18), OPT_CALLEE_TRANSFER = (1 << 19), OPT_CALLER_TRANSFER = (1 << 20), OPT_CALLEE_MONITOR = (1 << 21), OPT_CALLER_MONITOR = (1 << 22), OPT_GOTO = (1 << 23) } |
enum | { OPT_ARG_ANNOUNCE = 0, OPT_ARG_SENDDTMF, OPT_ARG_GOTO, OPT_ARG_DURATION_LIMIT, OPT_ARG_MUSICBACK, OPT_ARG_CALLEE_MACRO, OPT_ARG_PRIVACY, OPT_ARG_DURATION_STOP, OPT_ARG_ARRAY_SIZE } |
Functions | |
AST_APP_OPTIONS (dial_exec_options,{AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE), AST_APP_OPTION('C', OPT_RESETCDR), AST_APP_OPTION('d', OPT_DTMF_EXIT), AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF), AST_APP_OPTION('f', OPT_FORCECLID), AST_APP_OPTION('g', OPT_GO_ON), AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO), AST_APP_OPTION('h', OPT_CALLEE_HANGUP), AST_APP_OPTION('H', OPT_CALLER_HANGUP), AST_APP_OPTION('j', OPT_PRIORITY_JUMP), AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT), AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK), AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO), AST_APP_OPTION('n', OPT_SCREEN_NOINTRO), AST_APP_OPTION('N', OPT_SCREEN_NOCLID), AST_APP_OPTION('o', OPT_ORIGINAL_CLID), AST_APP_OPTION('p', OPT_SCREENING), AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY), AST_APP_OPTION('r', OPT_RINGBACK), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), AST_APP_OPTION('t', OPT_CALLEE_TRANSFER), AST_APP_OPTION('T', OPT_CALLER_TRANSFER), AST_APP_OPTION('w', OPT_CALLEE_MONITOR), AST_APP_OPTION('W', OPT_CALLER_MONITOR),}) | |
char * | description (void) |
Provides a description of the module. | |
static int | dial_exec (struct ast_channel *chan, void *data) |
static int | dial_exec_full (struct ast_channel *chan, void *data, struct ast_flags *peerflags) |
static char * | get_cid_name (char *name, int namelen, struct ast_channel *chan) |
static void | hanguptree (struct localuser *outgoing, struct ast_channel *exception) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static int | onedigit_goto (struct ast_channel *chan, char *context, char exten, int pri) |
static int | retrydial_exec (struct ast_channel *chan, void *data) |
static void | senddialevent (struct ast_channel *src, struct ast_channel *dst) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
static struct ast_channel * | wait_for_answer (struct ast_channel *in, struct localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int priority_jump, int *result) |
Variables | |
static char * | app = "Dial" |
static char * | descrip |
enum { ... } | dial_exec_option_args |
enum { ... } | dial_exec_option_flags |
LOCAL_USER_DECL | |
static char * | rapp = "RetryDial" |
static char * | rdescrip |
static char * | rsynopsis = "Place a call, retrying on failure allowing optional exit extension." |
static char * | synopsis = "Place a call and connect to the current channel" |
static char * | tdesc = "Dialing Application" |
Definition in file app_dial.c.
#define AST_MAX_FORWARDS 8 |
#define AST_MAX_WATCHERS 256 |
#define DIAL_NOFORWARDHTML (1 << 31) |
#define DIAL_STILLGOING (1 << 30) |
#define HANDLE_CAUSE | ( | cause, | |||
chan | ) |
anonymous enum |
Definition at line 193 of file app_dial.c.
00193 { 00194 OPT_ANNOUNCE = (1 << 0), 00195 OPT_RESETCDR = (1 << 1), 00196 OPT_DTMF_EXIT = (1 << 2), 00197 OPT_SENDDTMF = (1 << 3), 00198 OPT_FORCECLID = (1 << 4), 00199 OPT_GO_ON = (1 << 5), 00200 OPT_CALLEE_HANGUP = (1 << 6), 00201 OPT_CALLER_HANGUP = (1 << 7), 00202 OPT_PRIORITY_JUMP = (1 << 8), 00203 OPT_DURATION_LIMIT = (1 << 9), 00204 OPT_MUSICBACK = (1 << 10), 00205 OPT_CALLEE_MACRO = (1 << 11), 00206 OPT_SCREEN_NOINTRO = (1 << 12), 00207 OPT_SCREEN_NOCLID = (1 << 13), 00208 OPT_ORIGINAL_CLID = (1 << 14), 00209 OPT_SCREENING = (1 << 15), 00210 OPT_PRIVACY = (1 << 16), 00211 OPT_RINGBACK = (1 << 17), 00212 OPT_DURATION_STOP = (1 << 18), 00213 OPT_CALLEE_TRANSFER = (1 << 19), 00214 OPT_CALLER_TRANSFER = (1 << 20), 00215 OPT_CALLEE_MONITOR = (1 << 21), 00216 OPT_CALLER_MONITOR = (1 << 22), 00217 OPT_GOTO = (1 << 23), 00218 } dial_exec_option_flags;
anonymous enum |
OPT_ARG_ANNOUNCE | |
OPT_ARG_SENDDTMF | |
OPT_ARG_GOTO | |
OPT_ARG_DURATION_LIMIT | |
OPT_ARG_MUSICBACK | |
OPT_ARG_CALLEE_MACRO | |
OPT_ARG_PRIVACY | |
OPT_ARG_DURATION_STOP | |
OPT_ARG_ARRAY_SIZE |
Definition at line 223 of file app_dial.c.
00223 { 00224 OPT_ARG_ANNOUNCE = 0, 00225 OPT_ARG_SENDDTMF, 00226 OPT_ARG_GOTO, 00227 OPT_ARG_DURATION_LIMIT, 00228 OPT_ARG_MUSICBACK, 00229 OPT_ARG_CALLEE_MACRO, 00230 OPT_ARG_PRIVACY, 00231 OPT_ARG_DURATION_STOP, 00232 /* note: this entry _MUST_ be the last one in the enum */ 00233 OPT_ARG_ARRAY_SIZE, 00234 } dial_exec_option_args;
AST_APP_OPTIONS | ( | dial_exec_options | ) |
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 1794 of file app_dial.c.
01795 { 01796 return tdesc; 01797 }
static int dial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1659 of file app_dial.c.
References dial_exec_full().
Referenced by load_module().
01660 { 01661 struct ast_flags peerflags; 01662 memset(&peerflags, 0, sizeof(peerflags)); 01663 return dial_exec_full(chan, data, &peerflags); 01664 }
static int dial_exec_full | ( | struct ast_channel * | chan, | |
void * | data, | |||
struct ast_flags * | peerflags | |||
) | [static] |
Definition at line 745 of file app_dial.c.
References ast_channel::_softhangup, ast_channel::_state, ast_channel::accountcode, ast_channel::adsicpe, app, AST_APP_ARG, ast_app_group_set_channel(), ast_app_parse_options(), ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_call(), ast_call(), ast_cause2str(), AST_CAUSE_CONGESTION, ast_cdr_reset(), ast_cdr_setdestchan(), ast_channel_inherit_variables(), ast_channel_make_compatible(), ast_channel_sendurl(), ast_channel_supports_html(), ast_config_AST_VAR_DIR, AST_CONTROL_RINGING, ast_copy_flags, ast_deactivate_generator(), AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_dtmf_stream(), AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PLAY_WARNING, AST_FEATURE_REDIRECT, ast_filedelete(), ast_fileexists(), ast_goto_if_exists(), ast_hangup(), ast_indicate(), ast_log(), AST_MAX_EXTENSION, AST_MAX_FORWARDS, ast_moh_start(), ast_moh_stop(), ast_parseable_goto(), AST_PBX_KEEPALIVE, AST_PBX_NO_HANGUP_PEER, ast_pbx_start(), ast_play_and_record(), ast_play_and_wait(), AST_PRIVACY_ALLOW, ast_privacy_check(), AST_PRIVACY_DENY, AST_PRIVACY_KILL, ast_privacy_set(), AST_PRIVACY_TORTURE, AST_PRIVACY_UNKNOWN, ast_request(), ast_senddigit(), ast_set2_flag, ast_set_callerid(), ast_set_flag, ast_shrink_phone_number(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_verbose(), ast_waitstream(), ast_channel::cdr, ast_channel::cdrflags, localuser::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, config, ast_channel::context, DIAL_NOFORWARDHTML, DIAL_STILLGOING, ast_bridge_config::end_sound, ast_channel::exten, ast_flags::flags, free, get_cid_name(), HANDLE_CAUSE, ast_channel::hangupcause, hanguptree(), ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, malloc, moh, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, OPT_ANNOUNCE, OPT_ARG_ANNOUNCE, OPT_ARG_ARRAY_SIZE, OPT_ARG_CALLEE_MACRO, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_GOTO, OPT_ARG_MUSICBACK, OPT_ARG_PRIVACY, OPT_ARG_SENDDTMF, OPT_CALLEE_HANGUP, OPT_CALLEE_MACRO, OPT_CALLEE_MONITOR, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MONITOR, OPT_CALLER_TRANSFER, OPT_DTMF_EXIT, OPT_DURATION_LIMIT, OPT_DURATION_STOP, OPT_FORCECLID, OPT_GO_ON, OPT_GOTO, OPT_MUSICBACK, OPT_ORIGINAL_CLID, OPT_PRIORITY_JUMP, OPT_PRIVACY, OPT_RESETCDR, OPT_RINGBACK, OPT_SCREEN_NOCLID, OPT_SCREEN_NOINTRO, OPT_SCREENING, OPT_SENDDTMF, option_debug, option_priority_jumping, option_verbose, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), peers, ast_bridge_config::play_warning, ast_channel::priority, result, senddialevent(), ast_bridge_config::start_sound, ast_bridge_config::start_time, strdup, strsep(), ast_bridge_config::timelimit, ast_channel::transfercapability, var, VERBOSE_PREFIX_3, wait_for_answer(), ast_bridge_config::warning_freq, ast_bridge_config::warning_sound, and ast_channel::whentohangup.
Referenced by dial_exec(), and retrydial_exec().
00746 { 00747 int res=-1; 00748 struct localuser *u; 00749 char *tech, *number, *rest, *cur; 00750 char privcid[256]; 00751 char privintro[1024]; 00752 struct localuser *outgoing=NULL, *tmp; 00753 struct ast_channel *peer; 00754 int to; 00755 int numbusy = 0; 00756 int numcongestion = 0; 00757 int numnochan = 0; 00758 int cause; 00759 char numsubst[AST_MAX_EXTENSION]; 00760 char restofit[AST_MAX_EXTENSION]; 00761 char cidname[AST_MAX_EXTENSION]; 00762 char toast[80]; 00763 char *newnum; 00764 char *l; 00765 int privdb_val=0; 00766 unsigned int calldurationlimit=0; 00767 struct ast_bridge_config config; 00768 long timelimit = 0; 00769 long play_warning = 0; 00770 long warning_freq=0; 00771 char *warning_sound=NULL; 00772 char *end_sound=NULL; 00773 char *start_sound=NULL; 00774 char *dtmfcalled=NULL, *dtmfcalling=NULL; 00775 char *var; 00776 char status[256]; 00777 int play_to_caller=0,play_to_callee=0; 00778 int sentringing=0, moh=0; 00779 char *outbound_group = NULL; 00780 char *macro_result = NULL, *macro_transfer_dest = NULL; 00781 int digit = 0, result = 0; 00782 time_t start_time, answer_time, end_time; 00783 struct ast_app *app = NULL; 00784 00785 char *parse; 00786 AST_DECLARE_APP_ARGS(args, 00787 AST_APP_ARG(peers); 00788 AST_APP_ARG(timeout); 00789 AST_APP_ARG(options); 00790 AST_APP_ARG(url); 00791 ); 00792 struct ast_flags opts = { 0, }; 00793 char *opt_args[OPT_ARG_ARRAY_SIZE]; 00794 00795 if (ast_strlen_zero(data)) { 00796 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 00797 return -1; 00798 } 00799 00800 LOCAL_USER_ADD(u); 00801 00802 if (!(parse = ast_strdupa(data))) { 00803 ast_log(LOG_WARNING, "Memory allocation failure\n"); 00804 LOCAL_USER_REMOVE(u); 00805 return -1; 00806 } 00807 00808 AST_STANDARD_APP_ARGS(args, parse); 00809 00810 if (!ast_strlen_zero(args.options)) { 00811 if (ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) { 00812 LOCAL_USER_REMOVE(u); 00813 return -1; 00814 } 00815 } 00816 00817 if (ast_strlen_zero(args.peers)) { 00818 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 00819 LOCAL_USER_REMOVE(u); 00820 return -1; 00821 } 00822 00823 if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) { 00824 calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]); 00825 if (option_verbose > 2) 00826 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",calldurationlimit); 00827 } 00828 00829 if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { 00830 parse = opt_args[OPT_ARG_SENDDTMF]; 00831 dtmfcalled = strsep(&parse, ":"); 00832 dtmfcalling = parse; 00833 } 00834 00835 if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { 00836 char *limit_str, *warning_str, *warnfreq_str; 00837 00838 parse = opt_args[OPT_ARG_DURATION_LIMIT]; 00839 limit_str = strsep(&parse, ":"); 00840 warning_str = strsep(&parse, ":"); 00841 warnfreq_str = parse; 00842 00843 timelimit = atol(limit_str); 00844 if (warning_str) 00845 play_warning = atol(warning_str); 00846 if (warnfreq_str) 00847 warning_freq = atol(warnfreq_str); 00848 00849 if (!timelimit) { 00850 timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0; 00851 warning_sound = NULL; 00852 } else if (play_warning > timelimit) { 00853 /* If the first warning is requested _after_ the entire call would end, 00854 and no warning frequency is requested, then turn off the warning. If 00855 a warning frequency is requested, reduce the 'first warning' time by 00856 that frequency until it falls within the call's total time limit. 00857 */ 00858 00859 if (!warning_freq) { 00860 play_warning = 0; 00861 } else { 00862 while (play_warning > timelimit) 00863 play_warning -= warning_freq; 00864 if (play_warning < 1) 00865 play_warning = warning_freq = 0; 00866 } 00867 } 00868 00869 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER"); 00870 play_to_caller = var ? ast_true(var) : 1; 00871 00872 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE"); 00873 play_to_callee = var ? ast_true(var) : 0; 00874 00875 if (!play_to_caller && !play_to_callee) 00876 play_to_caller=1; 00877 00878 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE"); 00879 warning_sound = var ? var : "timeleft"; 00880 00881 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE"); 00882 end_sound = var ? var : NULL; 00883 00884 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE"); 00885 start_sound = var ? var : NULL; 00886 00887 /* undo effect of S(x) in case they are both used */ 00888 calldurationlimit = 0; 00889 /* more efficient do it like S(x) does since no advanced opts*/ 00890 if (!play_warning && !start_sound && !end_sound && timelimit) { 00891 calldurationlimit = timelimit/1000; 00892 timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0; 00893 } else if (option_verbose > 2) { 00894 ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n"); 00895 ast_verbose(VERBOSE_PREFIX_3 "- timelimit = %ld\n", timelimit); 00896 ast_verbose(VERBOSE_PREFIX_3 "- play_warning = %ld\n", play_warning); 00897 ast_verbose(VERBOSE_PREFIX_3 "- play_to_caller= %s\n", play_to_caller ? "yes" : "no"); 00898 ast_verbose(VERBOSE_PREFIX_3 "- play_to_callee= %s\n", play_to_callee ? "yes" : "no"); 00899 ast_verbose(VERBOSE_PREFIX_3 "- warning_freq = %ld\n", warning_freq); 00900 ast_verbose(VERBOSE_PREFIX_3 "- start_sound = %s\n", start_sound ? start_sound : "UNDEF"); 00901 ast_verbose(VERBOSE_PREFIX_3 "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 00902 ast_verbose(VERBOSE_PREFIX_3 "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 00903 } 00904 } 00905 00906 if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr) 00907 ast_cdr_reset(chan->cdr, NULL); 00908 if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) 00909 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten); 00910 if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) { 00911 char callerid[60]; 00912 00913 l = chan->cid.cid_num; 00914 if (!ast_strlen_zero(l)) { 00915 ast_shrink_phone_number(l); 00916 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 00917 if (option_verbose > 2) 00918 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB is '%s', clid is '%s'\n", 00919 opt_args[OPT_ARG_PRIVACY], l); 00920 privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l); 00921 } 00922 else { 00923 if (option_verbose > 2) 00924 ast_verbose( VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l); 00925 privdb_val = AST_PRIVACY_UNKNOWN; 00926 } 00927 } else { 00928 char *tnam, *tn2; 00929 00930 tnam = ast_strdupa(chan->name); 00931 /* clean the channel name so slashes don't try to end up in disk file name */ 00932 for(tn2 = tnam; *tn2; tn2++) { 00933 if( *tn2=='/') 00934 *tn2 = '='; /* any other chars to be afraid of? */ 00935 } 00936 if (option_verbose > 2) 00937 ast_verbose( VERBOSE_PREFIX_3 "Privacy-- callerid is empty\n"); 00938 00939 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); 00940 l = callerid; 00941 privdb_val = AST_PRIVACY_UNKNOWN; 00942 } 00943 00944 ast_copy_string(privcid,l,sizeof(privcid)); 00945 00946 if( strncmp(privcid,"NOCALLERID",10) != 0 && ast_test_flag(&opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */ 00947 if (option_verbose > 2) 00948 ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid); 00949 privdb_val = AST_PRIVACY_ALLOW; 00950 } 00951 else if( ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) { 00952 if (option_verbose > 2) 00953 ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val); 00954 } 00955 00956 if( privdb_val == AST_PRIVACY_DENY ) { 00957 strcpy(status, "NOANSWER"); 00958 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); 00959 res=0; 00960 goto out; 00961 } 00962 else if( privdb_val == AST_PRIVACY_KILL ) { 00963 strcpy(status, "DONTCALL"); 00964 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) { 00965 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201); 00966 } 00967 res = 0; 00968 goto out; /* Is this right? */ 00969 } 00970 else if( privdb_val == AST_PRIVACY_TORTURE ) { 00971 strcpy(status, "TORTURE"); 00972 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) { 00973 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301); 00974 } 00975 res = 0; 00976 goto out; /* is this right??? */ 00977 } 00978 else if( privdb_val == AST_PRIVACY_UNKNOWN ) { 00979 /* Get the user's intro, store it in priv-callerintros/$CID, 00980 unless it is already there-- this should be done before the 00981 call is actually dialed */ 00982 00983 /* make sure the priv-callerintros dir actually exists */ 00984 snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_VAR_DIR); 00985 if (mkdir(privintro, 0755) && errno != EEXIST) { 00986 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno)); 00987 res = -1; 00988 goto out; 00989 } 00990 00991 snprintf(privintro,sizeof(privintro),"priv-callerintros/%s", privcid); 00992 if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) { 00993 /* the DELUX version of this code would allow this caller the 00994 option to hear and retape their previously recorded intro. 00995 */ 00996 } 00997 else { 00998 int duration; /* for feedback from play_and_wait */ 00999 /* the file doesn't exist yet. Let the caller submit his 01000 vocal intro for posterity */ 01001 /* priv-recordintro script: 01002 01003 "At the tone, please say your name:" 01004 01005 */ 01006 res = ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to */ 01007 /* 4 sec don't think we'll need a lock removed, we 01008 took care of conflicts by naming the privintro file */ 01009 if (res == -1) { 01010 /* Delete the file regardless since they hung up during recording */ 01011 ast_filedelete(privintro, NULL); 01012 if( ast_fileexists(privintro,NULL,NULL ) > 0 ) 01013 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro); 01014 else if (option_verbose > 2) 01015 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro); 01016 goto out; 01017 } 01018 } 01019 } 01020 } 01021 01022 /* If a channel group has been specified, get it for use when we create peer channels */ 01023 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"); 01024 01025 ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP); 01026 cur = args.peers; 01027 do { 01028 /* Remember where to start next time */ 01029 rest = strchr(cur, '&'); 01030 if (rest) { 01031 *rest = 0; 01032 rest++; 01033 } 01034 /* Get a technology/[device:]number pair */ 01035 tech = cur; 01036 number = strchr(tech, '/'); 01037 if (!number) { 01038 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); 01039 goto out; 01040 } 01041 *number = '\0'; 01042 number++; 01043 tmp = malloc(sizeof(struct localuser)); 01044 if (!tmp) { 01045 ast_log(LOG_WARNING, "Out of memory\n"); 01046 goto out; 01047 } 01048 memset(tmp, 0, sizeof(struct localuser)); 01049 if (opts.flags) { 01050 ast_copy_flags(tmp, &opts, 01051 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01052 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01053 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01054 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID); 01055 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML); 01056 } 01057 ast_copy_string(numsubst, number, sizeof(numsubst)); 01058 /* If we're dialing by extension, look at the extension to know what to dial */ 01059 if ((newnum = strstr(numsubst, "BYEXTENSION"))) { 01060 /* strlen("BYEXTENSION") == 11 */ 01061 ast_copy_string(restofit, newnum + 11, sizeof(restofit)); 01062 snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit); 01063 if (option_debug) 01064 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst); 01065 } 01066 /* Request the peer */ 01067 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause); 01068 if (!tmp->chan) { 01069 /* If we can't, just go on to the next call */ 01070 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause)); 01071 HANDLE_CAUSE(cause, chan); 01072 cur = rest; 01073 if (!cur) 01074 chan->hangupcause = cause; 01075 continue; 01076 } 01077 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst); 01078 if (!ast_strlen_zero(tmp->chan->call_forward)) { 01079 char tmpchan[256]; 01080 char *stuff; 01081 char *tech; 01082 ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan)); 01083 if ((stuff = strchr(tmpchan, '/'))) { 01084 *stuff = '\0'; 01085 stuff++; 01086 tech = tmpchan; 01087 } else { 01088 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context); 01089 stuff = tmpchan; 01090 tech = "Local"; 01091 } 01092 tmp->forwards++; 01093 if (tmp->forwards < AST_MAX_FORWARDS) { 01094 if (option_verbose > 2) 01095 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name); 01096 ast_hangup(tmp->chan); 01097 /* Setup parameters */ 01098 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause); 01099 if (!tmp->chan) 01100 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); 01101 else 01102 ast_channel_inherit_variables(chan, tmp->chan); 01103 } else { 01104 if (option_verbose > 2) 01105 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name); 01106 ast_hangup(tmp->chan); 01107 tmp->chan = NULL; 01108 cause = AST_CAUSE_CONGESTION; 01109 } 01110 if (!tmp->chan) { 01111 HANDLE_CAUSE(cause, chan); 01112 cur = rest; 01113 continue; 01114 } 01115 } 01116 01117 /* Inherit specially named variables from parent channel */ 01118 ast_channel_inherit_variables(chan, tmp->chan); 01119 01120 tmp->chan->appl = "AppDial"; 01121 tmp->chan->data = "(Outgoing Line)"; 01122 tmp->chan->whentohangup = 0; 01123 if (tmp->chan->cid.cid_num) 01124 free(tmp->chan->cid.cid_num); 01125 tmp->chan->cid.cid_num = NULL; 01126 if (tmp->chan->cid.cid_name) 01127 free(tmp->chan->cid.cid_name); 01128 tmp->chan->cid.cid_name = NULL; 01129 if (tmp->chan->cid.cid_ani) 01130 free(tmp->chan->cid.cid_ani); 01131 tmp->chan->cid.cid_ani = NULL; 01132 01133 if (chan->cid.cid_num) 01134 tmp->chan->cid.cid_num = strdup(chan->cid.cid_num); 01135 if (chan->cid.cid_name) 01136 tmp->chan->cid.cid_name = strdup(chan->cid.cid_name); 01137 if (chan->cid.cid_ani) 01138 tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani); 01139 01140 /* Copy language from incoming to outgoing */ 01141 ast_copy_string(tmp->chan->language, chan->language, sizeof(tmp->chan->language)); 01142 ast_copy_string(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode)); 01143 tmp->chan->cdrflags = chan->cdrflags; 01144 if (ast_strlen_zero(tmp->chan->musicclass)) 01145 ast_copy_string(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass)); 01146 if (chan->cid.cid_rdnis) 01147 tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis); 01148 /* Pass callingpres setting */ 01149 tmp->chan->cid.cid_pres = chan->cid.cid_pres; 01150 /* Pass type of number */ 01151 tmp->chan->cid.cid_ton = chan->cid.cid_ton; 01152 /* Pass type of tns */ 01153 tmp->chan->cid.cid_tns = chan->cid.cid_tns; 01154 /* Presense of ADSI CPE on outgoing channel follows ours */ 01155 tmp->chan->adsicpe = chan->adsicpe; 01156 /* Pass the transfer capability */ 01157 tmp->chan->transfercapability = chan->transfercapability; 01158 01159 /* If we have an outbound group, set this peer channel to it */ 01160 if (outbound_group) 01161 ast_app_group_set_channel(tmp->chan, outbound_group); 01162 01163 /* Place the call, but don't wait on the answer */ 01164 res = ast_call(tmp->chan, numsubst, 0); 01165 01166 /* Save the info in cdr's that we called them */ 01167 if (chan->cdr) 01168 ast_cdr_setdestchan(chan->cdr, tmp->chan->name); 01169 01170 /* check the results of ast_call */ 01171 if (res) { 01172 /* Again, keep going even if there's an error */ 01173 if (option_debug) 01174 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res); 01175 else if (option_verbose > 2) 01176 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst); 01177 ast_hangup(tmp->chan); 01178 tmp->chan = NULL; 01179 cur = rest; 01180 continue; 01181 } else { 01182 senddialevent(chan, tmp->chan); 01183 if (option_verbose > 2) 01184 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst); 01185 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) 01186 ast_set_callerid(tmp->chan, ast_strlen_zero(chan->macroexten) ? chan->exten : chan->macroexten, get_cid_name(cidname, sizeof(cidname), chan), NULL); 01187 } 01188 /* Put them in the list of outgoing thingies... We're ready now. 01189 XXX If we're forcibly removed, these outgoing calls won't get 01190 hung up XXX */ 01191 ast_set_flag(tmp, DIAL_STILLGOING); 01192 tmp->next = outgoing; 01193 outgoing = tmp; 01194 /* If this line is up, don't try anybody else */ 01195 if (outgoing->chan->_state == AST_STATE_UP) 01196 break; 01197 cur = rest; 01198 } while (cur); 01199 01200 if (!ast_strlen_zero(args.timeout)) { 01201 to = atoi(args.timeout); 01202 if (to > 0) 01203 to *= 1000; 01204 else 01205 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 01206 } else 01207 to = -1; 01208 01209 if (outgoing) { 01210 /* Our status will at least be NOANSWER */ 01211 strcpy(status, "NOANSWER"); 01212 if (ast_test_flag(outgoing, OPT_MUSICBACK)) { 01213 moh=1; 01214 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]); 01215 } else if (ast_test_flag(outgoing, OPT_RINGBACK)) { 01216 ast_indicate(chan, AST_CONTROL_RINGING); 01217 sentringing++; 01218 } 01219 } else 01220 strcpy(status, "CHANUNAVAIL"); 01221 01222 time(&start_time); 01223 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result); 01224 01225 if (!peer) { 01226 if (result) { 01227 res = result; 01228 } else if (to) 01229 /* Musta gotten hung up */ 01230 res = -1; 01231 else 01232 /* Nobody answered, next please? */ 01233 res = 0; 01234 01235 goto out; 01236 } 01237 if (peer) { 01238 time(&answer_time); 01239 #ifdef OSP_SUPPORT 01240 /* Once call is answered, ditch the OSP Handle */ 01241 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", ""); 01242 #endif 01243 strcpy(status, "ANSWER"); 01244 /* Ah ha! Someone answered within the desired timeframe. Of course after this 01245 we will always return with -1 so that it is hung up properly after the 01246 conversation. */ 01247 hanguptree(outgoing, peer); 01248 outgoing = NULL; 01249 /* If appropriate, log that we have a destination channel */ 01250 if (chan->cdr) 01251 ast_cdr_setdestchan(chan->cdr, peer->name); 01252 if (peer->name) 01253 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name); 01254 01255 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 01256 if (!number) 01257 number = numsubst; 01258 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); 01259 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { 01260 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url); 01261 ast_channel_sendurl( peer, args.url ); 01262 } 01263 if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) { 01264 int res2; 01265 int loopcount = 0; 01266 if( privdb_val == AST_PRIVACY_UNKNOWN ) { 01267 01268 /* Get the user's intro, store it in priv-callerintros/$CID, 01269 unless it is already there-- this should be done before the 01270 call is actually dialed */ 01271 01272 /* all ring indications and moh for the caller has been halted as soon as the 01273 target extension was picked up. We are going to have to kill some 01274 time and make the caller believe the peer hasn't picked up yet */ 01275 01276 if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) { 01277 ast_indicate(chan, -1); 01278 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]); 01279 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01280 ast_indicate(chan, AST_CONTROL_RINGING); 01281 sentringing++; 01282 } 01283 01284 /* Start autoservice on the other chan ?? */ 01285 res2 = ast_autoservice_start(chan); 01286 /* Now Stream the File */ 01287 if (!res2) { 01288 do { 01289 if (!res2) 01290 res2 = ast_play_and_wait(peer,"priv-callpending"); 01291 if ( res2 < '1' || (ast_test_flag(&opts, OPT_PRIVACY) && res2>'5') || (ast_test_flag(&opts, OPT_SCREENING) && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */ 01292 res2 = 0; 01293 01294 /* priv-callpending script: 01295 "I have a caller waiting, who introduces themselves as:" 01296 */ 01297 if (!res2) 01298 res2 = ast_play_and_wait(peer, privintro); 01299 if ( res2 < '1' || (ast_test_flag(&opts, OPT_PRIVACY) && res2>'5') || (ast_test_flag(&opts, OPT_SCREENING) && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */ 01300 res2 = 0; 01301 /* now get input from the called party, as to their choice */ 01302 if (!res2) { 01303 if( ast_test_flag(&opts, OPT_PRIVACY) ) 01304 res2 = ast_play_and_wait(peer,"priv-callee-options"); 01305 if( ast_test_flag(&opts, OPT_SCREENING) ) 01306 res2 = ast_play_and_wait(peer,"screen-callee-options"); 01307 } 01308 /* priv-callee-options script: 01309 "Dial 1 if you wish this caller to reach you directly in the future, 01310 and immediately connect to their incoming call 01311 Dial 2 if you wish to send this caller to voicemail now and 01312 forevermore. 01313 Dial 3 to send this callerr to the torture menus, now and forevermore. 01314 Dial 4 to send this caller to a simple "go away" menu, now and forevermore. 01315 Dial 5 to allow this caller to come straight thru to you in the future, 01316 but right now, just this once, send them to voicemail." 01317 */ 01318 01319 /* screen-callee-options script: 01320 "Dial 1 if you wish to immediately connect to the incoming call 01321 Dial 2 if you wish to send this caller to voicemail. 01322 Dial 3 to send this callerr to the torture menus. 01323 Dial 4 to send this caller to a simple "go away" menu. 01324 */ 01325 if( !res2 || res2 < '1' || (ast_test_flag(&opts, OPT_PRIVACY) && res2 > '5') || (ast_test_flag(&opts, OPT_SCREENING) && res2 > '4') ) { 01326 /* invalid option */ 01327 res2 = ast_play_and_wait(peer,"vm-sorry"); 01328 } 01329 loopcount++; /* give the callee a couple chances to make a choice */ 01330 } while( (!res2 || res2 < '1' || (ast_test_flag(&opts, OPT_PRIVACY) && res2 > '5') || (ast_test_flag(&opts, OPT_SCREENING) && res2 > '4')) && loopcount < 2 ); 01331 } 01332 01333 switch(res2) { 01334 case '1': 01335 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 01336 if (option_verbose > 2) 01337 ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", 01338 opt_args[OPT_ARG_PRIVACY], privcid); 01339 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW); 01340 } 01341 break; 01342 case '2': 01343 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 01344 if (option_verbose > 2) 01345 ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n", 01346 opt_args[OPT_ARG_PRIVACY], privcid); 01347 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY); 01348 } 01349 strcpy(status,"NOANSWER"); 01350 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01351 ast_moh_stop(chan); 01352 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01353 ast_indicate(chan, -1); 01354 sentringing=0; 01355 } 01356 res2 = ast_autoservice_stop(chan); 01357 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ 01358 res=0; 01359 goto out; 01360 case '3': 01361 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 01362 if (option_verbose > 2) 01363 ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n", 01364 opt_args[OPT_ARG_PRIVACY], privcid); 01365 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE); 01366 } 01367 ast_copy_string(status, "TORTURE", sizeof(status)); 01368 01369 res = 0; 01370 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01371 ast_moh_stop(chan); 01372 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01373 ast_indicate(chan, -1); 01374 sentringing=0; 01375 } 01376 res2 = ast_autoservice_stop(chan); 01377 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ 01378 goto out; /* Is this right? */ 01379 case '4': 01380 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 01381 if (option_verbose > 2) 01382 ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n", 01383 opt_args[OPT_ARG_PRIVACY], privcid); 01384 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL); 01385 } 01386 01387 ast_copy_string(status, "DONTCALL", sizeof(status)); 01388 res = 0; 01389 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01390 ast_moh_stop(chan); 01391 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01392 ast_indicate(chan, -1); 01393 sentringing=0; 01394 } 01395 res2 = ast_autoservice_stop(chan); 01396 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ 01397 goto out; /* Is this right? */ 01398 case '5': 01399 if( ast_test_flag(&opts, OPT_PRIVACY) ) { 01400 if (option_verbose > 2) 01401 ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", 01402 opt_args[OPT_ARG_PRIVACY], privcid); 01403 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW); 01404 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01405 ast_moh_stop(chan); 01406 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01407 ast_indicate(chan, -1); 01408 sentringing=0; 01409 } 01410 res2 = ast_autoservice_stop(chan); 01411 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ 01412 res=0; 01413 goto out; 01414 } /* if not privacy, then 5 is the same as "default" case */ 01415 default: 01416 /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */ 01417 /* well, there seems basically two choices. Just patch the caller thru immediately, 01418 or,... put 'em thru to voicemail. */ 01419 /* since the callee may have hung up, let's do the voicemail thing, no database decision */ 01420 if (option_verbose > 2) 01421 ast_log(LOG_NOTICE,"privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n"); 01422 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01423 ast_moh_stop(chan); 01424 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01425 ast_indicate(chan, -1); 01426 sentringing=0; 01427 } 01428 res2 = ast_autoservice_stop(chan); 01429 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ 01430 res=0; 01431 goto out; 01432 } 01433 if (ast_test_flag(&opts, OPT_MUSICBACK)) { 01434 ast_moh_stop(chan); 01435 } else if (ast_test_flag(&opts, OPT_RINGBACK)) { 01436 ast_indicate(chan, -1); 01437 sentringing=0; 01438 } 01439 res2 = ast_autoservice_stop(chan); 01440 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 01441 just clog things up, and it's not useful information, not being tied to a CID */ 01442 if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) { 01443 ast_filedelete(privintro, NULL); 01444 if( ast_fileexists(privintro,NULL,NULL ) > 0 ) 01445 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro); 01446 else if (option_verbose > 2) 01447 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro); 01448 } 01449 } 01450 } 01451 if (ast_test_flag(&opts, OPT_ANNOUNCE) && !ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) { 01452 /* Start autoservice on the other chan */ 01453 res = ast_autoservice_start(chan); 01454 /* Now Stream the File */ 01455 if (!res) 01456 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language); 01457 if (!res) { 01458 digit = ast_waitstream(peer, AST_DIGIT_ANY); 01459 } 01460 /* Ok, done. stop autoservice */ 01461 res = ast_autoservice_stop(chan); 01462 if (digit > 0 && !res) 01463 res = ast_senddigit(chan, digit); 01464 else 01465 res = digit; 01466 01467 } else 01468 res = 0; 01469 01470 if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { 01471 char *ch; 01472 01473 for (ch = opt_args[OPT_ARG_GOTO]; *ch; ch++) { 01474 if (*ch == '^') 01475 *ch = '|'; 01476 } 01477 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); 01478 ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]); 01479 peer->priority++; 01480 ast_pbx_start(peer); 01481 hanguptree(outgoing, NULL); 01482 LOCAL_USER_REMOVE(u); 01483 return 0; 01484 } 01485 01486 if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) { 01487 char *ch; 01488 01489 res = ast_autoservice_start(chan); 01490 if (res) { 01491 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 01492 res = -1; 01493 } 01494 01495 app = pbx_findapp("Macro"); 01496 01497 if (app && !res) { 01498 for (ch = opt_args[OPT_ARG_CALLEE_MACRO]; *ch; ch++) { 01499 if (*ch == '^') 01500 *ch = '|'; 01501 } 01502 res = pbx_exec(peer, app, opt_args[OPT_ARG_CALLEE_MACRO], 1); 01503 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res); 01504 res = 0; 01505 } else { 01506 ast_log(LOG_ERROR, "Could not find application Macro\n"); 01507 res = -1; 01508 } 01509 01510 if (ast_autoservice_stop(chan) < 0) { 01511 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n"); 01512 res = -1; 01513 } 01514 01515 if (!res) { 01516 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) { 01517 if (!strcasecmp(macro_result, "BUSY")) { 01518 ast_copy_string(status, macro_result, sizeof(status)); 01519 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) { 01520 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) { 01521 ast_set_flag(peerflags, OPT_GO_ON); 01522 } 01523 } else 01524 ast_set_flag(peerflags, OPT_GO_ON); 01525 res = -1; 01526 } 01527 else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { 01528 ast_copy_string(status, macro_result, sizeof(status)); 01529 ast_set_flag(peerflags, OPT_GO_ON); 01530 res = -1; 01531 } 01532 else if (!strcasecmp(macro_result, "CONTINUE")) { 01533 /* hangup peer and keep chan alive assuming the macro has changed 01534 the context / exten / priority or perhaps 01535 the next priority in the current exten is desired. 01536 */ 01537 ast_set_flag(peerflags, OPT_GO_ON); 01538 res = -1; 01539 } else if (!strcasecmp(macro_result, "ABORT")) { 01540 /* Hangup both ends unless the caller has the g flag */ 01541 res = -1; 01542 } else if (!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { 01543 res = -1; 01544 /* perform a transfer to a new extension */ 01545 if (strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/ 01546 /* no brainer mode... substitute ^ with | and feed it to builtin goto */ 01547 for (res=0;res<strlen(macro_transfer_dest);res++) 01548 if (macro_transfer_dest[res] == '^') 01549 macro_transfer_dest[res] = '|'; 01550 01551 if (!ast_parseable_goto(chan, macro_transfer_dest)) 01552 ast_set_flag(peerflags, OPT_GO_ON); 01553 01554 } 01555 } 01556 } 01557 } 01558 } 01559 01560 if (!res) { 01561 if (calldurationlimit > 0) { 01562 time_t now; 01563 01564 time(&now); 01565 chan->whentohangup = now + calldurationlimit; 01566 } 01567 if (!ast_strlen_zero(dtmfcalled)) { 01568 if (option_verbose > 2) 01569 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n",dtmfcalled); 01570 res = ast_dtmf_stream(peer,chan,dtmfcalled,250); 01571 } 01572 if (!ast_strlen_zero(dtmfcalling)) { 01573 if (option_verbose > 2) 01574 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n",dtmfcalling); 01575 res = ast_dtmf_stream(chan,peer,dtmfcalling,250); 01576 } 01577 } 01578 01579 if (!res) { 01580 memset(&config,0,sizeof(struct ast_bridge_config)); 01581 if (play_to_caller) 01582 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING); 01583 if (play_to_callee) 01584 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING); 01585 if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER)) 01586 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 01587 if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER)) 01588 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 01589 if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP)) 01590 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT); 01591 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP)) 01592 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT); 01593 if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR)) 01594 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 01595 if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 01596 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 01597 01598 config.timelimit = timelimit; 01599 config.play_warning = play_warning; 01600 config.warning_freq = warning_freq; 01601 config.warning_sound = warning_sound; 01602 config.end_sound = end_sound; 01603 config.start_sound = start_sound; 01604 if (moh) { 01605 moh = 0; 01606 ast_moh_stop(chan); 01607 } else if (sentringing) { 01608 sentringing = 0; 01609 ast_indicate(chan, -1); 01610 } 01611 /* Be sure no generators are left on it */ 01612 ast_deactivate_generator(chan); 01613 /* Make sure channels are compatible */ 01614 res = ast_channel_make_compatible(chan, peer); 01615 if (res < 0) { 01616 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name); 01617 ast_hangup(peer); 01618 LOCAL_USER_REMOVE(u); 01619 return -1; 01620 } 01621 res = ast_bridge_call(chan,peer,&config); 01622 time(&end_time); 01623 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time)); 01624 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast); 01625 01626 } else { 01627 time(&end_time); 01628 res = -1; 01629 } 01630 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time)); 01631 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast); 01632 01633 if (res != AST_PBX_NO_HANGUP_PEER) { 01634 if (!chan->_softhangup) 01635 chan->hangupcause = peer->hangupcause; 01636 ast_hangup(peer); 01637 } 01638 } 01639 out: 01640 if (moh) { 01641 moh = 0; 01642 ast_moh_stop(chan); 01643 } else if (sentringing) { 01644 sentringing = 0; 01645 ast_indicate(chan, -1); 01646 } 01647 hanguptree(outgoing, NULL); 01648 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status); 01649 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status); 01650 01651 if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) 01652 res=0; 01653 01654 LOCAL_USER_REMOVE(u); 01655 01656 return res; 01657 }
static char* get_cid_name | ( | char * | name, | |
int | namelen, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 339 of file app_dial.c.
References ast_get_hint(), ast_strlen_zero(), localuser::chan, ast_channel::context, context, ast_channel::exten, exten, ast_channel::macrocontext, and ast_channel::macroexten.
Referenced by dial_exec_full(), and wait_for_answer().
00340 { 00341 char *context; 00342 char *exten; 00343 if (!ast_strlen_zero(chan->macrocontext)) 00344 context = chan->macrocontext; 00345 else 00346 context = chan->context; 00347 00348 if (!ast_strlen_zero(chan->macroexten)) 00349 exten = chan->macroexten; 00350 else 00351 exten = chan->exten; 00352 00353 if (ast_get_hint(NULL, 0, name, namelen, chan, context, exten)) 00354 return name; 00355 else 00356 return ""; 00357 }
static void hanguptree | ( | struct localuser * | outgoing, | |
struct ast_channel * | exception | |||
) | [static] |
Definition at line 276 of file app_dial.c.
References ast_hangup(), localuser::chan, free, and localuser::next.
Referenced by dial_exec_full().
00277 { 00278 /* Hang up a tree of stuff */ 00279 struct localuser *oo; 00280 while (outgoing) { 00281 /* Hangup any existing lines we have open */ 00282 if (outgoing->chan && (outgoing->chan != exception)) 00283 ast_hangup(outgoing->chan); 00284 oo = outgoing; 00285 outgoing=outgoing->next; 00286 free(oo); 00287 } 00288 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 1806 of file app_dial.c.
References ASTERISK_GPL_KEY.
01807 { 01808 return ASTERISK_GPL_KEY; 01809 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 1784 of file app_dial.c.
References ast_register_application(), dial_exec(), and retrydial_exec().
01785 { 01786 int res; 01787 01788 res = ast_register_application(app, dial_exec, synopsis, descrip); 01789 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); 01790 01791 return res; 01792 }
static int onedigit_goto | ( | struct ast_channel * | chan, | |
char * | context, | |||
char | exten, | |||
int | pri | |||
) | [static] |
Definition at line 320 of file app_dial.c.
References ast_goto_if_exists(), ast_strlen_zero(), localuser::chan, ast_channel::context, and ast_channel::macrocontext.
Referenced by retrydial_exec(), and wait_for_answer().
00321 { 00322 char rexten[2] = { exten, '\0' }; 00323 00324 if (context) { 00325 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00326 return 1; 00327 } else { 00328 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00329 return 1; 00330 else if (!ast_strlen_zero(chan->macrocontext)) { 00331 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00332 return 1; 00333 } 00334 } 00335 return 0; 00336 }
static int retrydial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1666 of file app_dial.c.
References AST_DIGIT_ANY, AST_FLAG_MOH, ast_log(), ast_moh_start(), ast_moh_stop(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_waitstream(), context, ast_channel::data, dial_exec_full(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, onedigit_goto(), OPT_DTMF_EXIT, and pbx_builtin_getvar_helper().
Referenced by load_module().
01667 { 01668 char *announce = NULL, *context = NULL, *dialdata = NULL; 01669 int sleep = 0, loops = 0, res = 0; 01670 struct localuser *u; 01671 struct ast_flags peerflags; 01672 01673 if (ast_strlen_zero(data)) { 01674 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 01675 return -1; 01676 } 01677 01678 LOCAL_USER_ADD(u); 01679 01680 announce = ast_strdupa(data); 01681 if (!announce) { 01682 ast_log(LOG_ERROR, "Out of memory!\n"); 01683 LOCAL_USER_REMOVE(u); 01684 return -1; 01685 } 01686 01687 memset(&peerflags, 0, sizeof(peerflags)); 01688 01689 if ((dialdata = strchr(announce, '|'))) { 01690 *dialdata = '\0'; 01691 dialdata++; 01692 if ((sleep = atoi(dialdata))) { 01693 sleep *= 1000; 01694 } else { 01695 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp); 01696 LOCAL_USER_REMOVE(u); 01697 return -1; 01698 } 01699 if ((dialdata = strchr(dialdata, '|'))) { 01700 *dialdata = '\0'; 01701 dialdata++; 01702 if (!(loops = atoi(dialdata))) { 01703 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp); 01704 LOCAL_USER_REMOVE(u); 01705 return -1; 01706 } 01707 } 01708 } 01709 01710 if ((dialdata = strchr(dialdata, '|'))) { 01711 *dialdata = '\0'; 01712 dialdata++; 01713 } else { 01714 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp); 01715 LOCAL_USER_REMOVE(u); 01716 return -1; 01717 } 01718 01719 if (sleep < 1000) 01720 sleep = 10000; 01721 01722 if (!loops) 01723 loops = -1; 01724 01725 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 01726 01727 while (loops) { 01728 chan->data = "Retrying"; 01729 if (ast_test_flag(chan, AST_FLAG_MOH)) 01730 ast_moh_stop(chan); 01731 01732 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) { 01733 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) { 01734 if (!(res = ast_streamfile(chan, announce, chan->language))) 01735 res = ast_waitstream(chan, AST_DIGIT_ANY); 01736 if (!res && sleep) { 01737 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01738 ast_moh_start(chan, NULL); 01739 res = ast_waitfordigit(chan, sleep); 01740 } 01741 } else { 01742 if (!(res = ast_streamfile(chan, announce, chan->language))) 01743 res = ast_waitstream(chan, ""); 01744 if (sleep) { 01745 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01746 ast_moh_start(chan, NULL); 01747 if (!res) 01748 res = ast_waitfordigit(chan, sleep); 01749 } 01750 } 01751 } 01752 01753 if (res < 0) 01754 break; 01755 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 01756 if (onedigit_goto(chan, context, (char) res, 1)) { 01757 res = 0; 01758 break; 01759 } 01760 } 01761 loops--; 01762 } 01763 01764 if (ast_test_flag(chan, AST_FLAG_MOH)) 01765 ast_moh_stop(chan); 01766 01767 LOCAL_USER_REMOVE(u); 01768 return loops ? res : 0; 01769 01770 }
static void senddialevent | ( | struct ast_channel * | src, | |
struct ast_channel * | dst | |||
) | [static] |
Definition at line 359 of file app_dial.c.
References ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, EVENT_FLAG_CALL, manager_event(), ast_channel::name, and ast_channel::uniqueid.
Referenced by dial_exec_full(), and wait_for_answer().
00360 { 00361 manager_event(EVENT_FLAG_CALL, "Dial", 00362 "Source: %s\r\n" 00363 "Destination: %s\r\n" 00364 "CallerID: %s\r\n" 00365 "CallerIDName: %s\r\n" 00366 "SrcUniqueID: %s\r\n" 00367 "DestUniqueID: %s\r\n", 00368 src->name, dst->name, src->cid.cid_num ? src->cid.cid_num : "<unknown>", 00369 src->cid.cid_name ? src->cid.cid_name : "<unknown>", src->uniqueid, 00370 dst->uniqueid); 00371 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 1772 of file app_dial.c.
References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.
01773 { 01774 int res; 01775 01776 res = ast_unregister_application(app); 01777 res |= ast_unregister_application(rapp); 01778 01779 STANDARD_HANGUP_LOCALUSERS; 01780 01781 return res; 01782 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 1799 of file app_dial.c.
References STANDARD_USECOUNT.
01800 { 01801 int res; 01802 STANDARD_USECOUNT(res); 01803 return res; 01804 }
static struct ast_channel* wait_for_answer | ( | struct ast_channel * | in, | |
struct localuser * | outgoing, | |||
int * | to, | |||
struct ast_flags * | peerflags, | |||
int * | sentringing, | |||
char * | status, | |||
size_t | statussize, | |||
int | busystart, | |||
int | nochanstart, | |||
int | congestionstart, | |||
int | priority_jump, | |||
int * | result | |||
) | [static] |
Definition at line 373 of file app_dial.c.
References ast_channel::accountcode, ast_call(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, ast_channel_inherit_variables(), ast_channel_make_compatible(), ast_channel_sendhtml(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_DISCONNECT, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_INBAND_INFO, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_copy_flags, ast_deactivate_generator(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree(), ast_goto_if_exists(), ast_hangup(), ast_indicate(), ast_log(), AST_MAX_EXTENSION, AST_MAX_FORWARDS, AST_MAX_WATCHERS, ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel::cdrflags, localuser::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, context, ast_frame::data, ast_frame::datalen, DIAL_NOFORWARDHTML, DIAL_STILLGOING, ast_channel::exten, ast_frame::frametype, free, get_cid_name(), HANDLE_CAUSE, ast_channel::hangupcause, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, ast_channel::name, ast_channel::nativeformats, ast_channel::next, localuser::next, onedigit_goto(), OPT_CALLEE_HANGUP, OPT_CALLEE_MONITOR, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MONITOR, OPT_CALLER_TRANSFER, OPT_DTMF_EXIT, OPT_FORCECLID, OPT_MUSICBACK, OPT_ORIGINAL_CLID, OPT_RINGBACK, option_priority_jumping, option_verbose, pbx_builtin_getvar_helper(), senddialevent(), strdup, ast_frame::subclass, ast_channel::tech, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by dial_exec_full(), and try_calling().
00374 { 00375 struct localuser *o; 00376 int found; 00377 int numlines; 00378 int numbusy = busystart; 00379 int numcongestion = congestionstart; 00380 int numnochan = nochanstart; 00381 int prestart = busystart + congestionstart + nochanstart; 00382 int cause; 00383 int orig = *to; 00384 struct ast_frame *f; 00385 struct ast_channel *peer = NULL; 00386 struct ast_channel *watchers[AST_MAX_WATCHERS]; 00387 int pos; 00388 int single; 00389 struct ast_channel *winner; 00390 char *context = NULL; 00391 char cidname[AST_MAX_EXTENSION]; 00392 00393 single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK)); 00394 00395 if (single) { 00396 /* Turn off hold music, etc */ 00397 ast_deactivate_generator(in); 00398 /* If we are calling a single channel, make them compatible for in-band tone purpose */ 00399 ast_channel_make_compatible(outgoing->chan, in); 00400 } 00401 00402 00403 while (*to && !peer) { 00404 o = outgoing; 00405 found = -1; 00406 pos = 1; 00407 numlines = prestart; 00408 watchers[0] = in; 00409 while (o) { 00410 /* Keep track of important channels */ 00411 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) { 00412 watchers[pos++] = o->chan; 00413 found = 1; 00414 } 00415 o = o->next; 00416 numlines++; 00417 } 00418 if (found < 0) { 00419 if (numlines == (numbusy + numcongestion + numnochan)) { 00420 if (option_verbose > 2) 00421 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00422 if (numbusy) 00423 strcpy(status, "BUSY"); 00424 else if (numcongestion) 00425 strcpy(status, "CONGESTION"); 00426 else if (numnochan) 00427 strcpy(status, "CHANUNAVAIL"); 00428 if (option_priority_jumping || priority_jump) 00429 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101); 00430 } else { 00431 if (option_verbose > 2) 00432 ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00433 } 00434 *to = 0; 00435 return NULL; 00436 } 00437 winner = ast_waitfor_n(watchers, pos, to); 00438 o = outgoing; 00439 while (o) { 00440 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) { 00441 if (!peer) { 00442 if (option_verbose > 2) 00443 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); 00444 peer = o->chan; 00445 ast_copy_flags(peerflags, o, 00446 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00447 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00448 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00449 DIAL_NOFORWARDHTML); 00450 } 00451 } else if (o->chan && (o->chan == winner)) { 00452 if (!ast_strlen_zero(o->chan->call_forward)) { 00453 char tmpchan[256]; 00454 char *stuff; 00455 char *tech; 00456 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan)); 00457 if ((stuff = strchr(tmpchan, '/'))) { 00458 *stuff = '\0'; 00459 stuff++; 00460 tech = tmpchan; 00461 } else { 00462 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context); 00463 stuff = tmpchan; 00464 tech = "Local"; 00465 } 00466 /* Before processing channel, go ahead and check for forwarding */ 00467 o->forwards++; 00468 if (o->forwards < AST_MAX_FORWARDS) { 00469 if (option_verbose > 2) 00470 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name); 00471 /* Setup parameters */ 00472 o->chan = ast_request(tech, in->nativeformats, stuff, &cause); 00473 if (!o->chan) 00474 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); 00475 else 00476 ast_channel_inherit_variables(in, o->chan); 00477 } else { 00478 if (option_verbose > 2) 00479 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name); 00480 cause = AST_CAUSE_CONGESTION; 00481 o->chan = NULL; 00482 } 00483 if (!o->chan) { 00484 ast_clear_flag(o, DIAL_STILLGOING); 00485 HANDLE_CAUSE(cause, in); 00486 } else { 00487 if (o->chan->cid.cid_num) 00488 free(o->chan->cid.cid_num); 00489 o->chan->cid.cid_num = NULL; 00490 if (o->chan->cid.cid_name) 00491 free(o->chan->cid.cid_name); 00492 o->chan->cid.cid_name = NULL; 00493 00494 if (ast_test_flag(o, OPT_FORCECLID)) { 00495 char *newcid = NULL; 00496 00497 if (!ast_strlen_zero(in->macroexten)) 00498 newcid = in->macroexten; 00499 else 00500 newcid = in->exten; 00501 o->chan->cid.cid_num = strdup(newcid); 00502 ast_copy_string(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode)); 00503 o->chan->cdrflags = winner->cdrflags; 00504 if (!o->chan->cid.cid_num) 00505 ast_log(LOG_WARNING, "Out of memory\n"); 00506 } else { 00507 if (in->cid.cid_num) { 00508 o->chan->cid.cid_num = strdup(in->cid.cid_num); 00509 if (!o->chan->cid.cid_num) 00510 ast_log(LOG_WARNING, "Out of memory\n"); 00511 } 00512 if (in->cid.cid_name) { 00513 o->chan->cid.cid_name = strdup(in->cid.cid_name); 00514 if (!o->chan->cid.cid_name) 00515 ast_log(LOG_WARNING, "Out of memory\n"); 00516 } 00517 ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode)); 00518 o->chan->cdrflags = in->cdrflags; 00519 } 00520 00521 if (in->cid.cid_ani) { 00522 if (o->chan->cid.cid_ani) 00523 free(o->chan->cid.cid_ani); 00524 o->chan->cid.cid_ani = strdup(in->cid.cid_ani); 00525 if (!o->chan->cid.cid_ani) 00526 ast_log(LOG_WARNING, "Out of memory\n"); 00527 } 00528 if (o->chan->cid.cid_rdnis) 00529 free(o->chan->cid.cid_rdnis); 00530 if (!ast_strlen_zero(in->macroexten)) 00531 o->chan->cid.cid_rdnis = strdup(in->macroexten); 00532 else 00533 o->chan->cid.cid_rdnis = strdup(in->exten); 00534 if (ast_call(o->chan, tmpchan, 0)) { 00535 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan); 00536 ast_clear_flag(o, DIAL_STILLGOING); 00537 ast_hangup(o->chan); 00538 o->chan = NULL; 00539 numnochan++; 00540 } else { 00541 senddialevent(in, o->chan); 00542 /* After calling, set callerid to extension */ 00543 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) 00544 ast_set_callerid(o->chan, ast_strlen_zero(in->macroexten) ? in->exten : in->macroexten, get_cid_name(cidname, sizeof(cidname), in), NULL); 00545 } 00546 } 00547 /* Hangup the original channel now, in case we needed it */ 00548 ast_hangup(winner); 00549 continue; 00550 } 00551 f = ast_read(winner); 00552 if (f) { 00553 if (f->frametype == AST_FRAME_CONTROL) { 00554 switch(f->subclass) { 00555 case AST_CONTROL_ANSWER: 00556 /* This is our guy if someone answered. */ 00557 if (!peer) { 00558 if (option_verbose > 2) 00559 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); 00560 peer = o->chan; 00561 ast_copy_flags(peerflags, o, 00562 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00563 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00564 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00565 DIAL_NOFORWARDHTML); 00566 ast_indicate(in, AST_CONTROL_ANSWER); 00567 00568 } 00569 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 00570 in->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00571 o->chan->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00572 00573 break; 00574 case AST_CONTROL_BUSY: 00575 if (option_verbose > 2) 00576 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name); 00577 in->hangupcause = o->chan->hangupcause; 00578 ast_hangup(o->chan); 00579 o->chan = NULL; 00580 ast_clear_flag(o, DIAL_STILLGOING); 00581 HANDLE_CAUSE(AST_CAUSE_BUSY, in); 00582 break; 00583 case AST_CONTROL_CONGESTION: 00584 if (option_verbose > 2) 00585 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name); 00586 in->hangupcause = o->chan->hangupcause; 00587 ast_hangup(o->chan); 00588 o->chan = NULL; 00589 ast_clear_flag(o, DIAL_STILLGOING); 00590 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in); 00591 break; 00592 case AST_CONTROL_RINGING: 00593 if (option_verbose > 2) 00594 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name); 00595 if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) { 00596 ast_indicate(in, AST_CONTROL_RINGING); 00597 (*sentringing)++; 00598 } 00599 break; 00600 case AST_CONTROL_PROGRESS: 00601 if (option_verbose > 2) 00602 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name); 00603 if (!ast_test_flag(outgoing, OPT_RINGBACK)) 00604 ast_indicate(in, AST_CONTROL_PROGRESS); 00605 break; 00606 case AST_CONTROL_VIDUPDATE: 00607 if (option_verbose > 2) 00608 ast_verbose ( VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", o->chan->name,in->name); 00609 ast_indicate(in, AST_CONTROL_VIDUPDATE); 00610 break; 00611 case AST_CONTROL_PROCEEDING: 00612 if (option_verbose > 2) 00613 ast_verbose ( VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", o->chan->name,in->name); 00614 if (!ast_test_flag(outgoing, OPT_RINGBACK)) 00615 ast_indicate(in, AST_CONTROL_PROCEEDING); 00616 break; 00617 case AST_CONTROL_HOLD: 00618 if (option_verbose > 2) 00619 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", o->chan->name); 00620 ast_indicate(in, AST_CONTROL_HOLD); 00621 break; 00622 case AST_CONTROL_UNHOLD: 00623 if (option_verbose > 2) 00624 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", o->chan->name); 00625 ast_indicate(in, AST_CONTROL_UNHOLD); 00626 break; 00627 case AST_CONTROL_INBAND_INFO: 00628 if (option_verbose > 2) 00629 ast_verbose(VERBOSE_PREFIX_3 "Inband information available\n", o->chan->name); 00630 ast_indicate(in, AST_CONTROL_INBAND_INFO); 00631 break; 00632 case AST_CONTROL_DISCONNECT: 00633 if (option_verbose > 2) 00634 ast_verbose(VERBOSE_PREFIX_3 "Call disconnected\n", o->chan->name); 00635 in->hangupcause = o->chan->hangupcause; 00636 ast_indicate(in, AST_CONTROL_DISCONNECT); 00637 break; 00638 case AST_CONTROL_OFFHOOK: 00639 case AST_CONTROL_FLASH: 00640 /* Ignore going off hook and flash */ 00641 break; 00642 case -1: 00643 if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) { 00644 if (option_verbose > 2) 00645 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name); 00646 ast_indicate(in, -1); 00647 (*sentringing) = 0; 00648 } 00649 break; 00650 default: 00651 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); 00652 } 00653 } else if (single && (f->frametype == AST_FRAME_VOICE) && 00654 !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { 00655 if (ast_write(in, f)) 00656 ast_log(LOG_DEBUG, "Unable to forward frame\n"); 00657 } else if (single && (f->frametype == AST_FRAME_IMAGE) && 00658 !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { 00659 if (ast_write(in, f)) 00660 ast_log(LOG_DEBUG, "Unable to forward image\n"); 00661 } else if (single && (f->frametype == AST_FRAME_TEXT) && 00662 !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { 00663 if (ast_write(in, f)) 00664 ast_log(LOG_DEBUG, "Unable to text\n"); 00665 } else if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 00666 ast_channel_sendhtml(in, f->subclass, f->data, f->datalen); 00667 00668 ast_frfree(f); 00669 } else { 00670 in->hangupcause = o->chan->hangupcause; 00671 ast_hangup(o->chan); 00672 o->chan = NULL; 00673 ast_clear_flag(o, DIAL_STILLGOING); 00674 HANDLE_CAUSE(in->hangupcause, in); 00675 } 00676 } 00677 o = o->next; 00678 } 00679 if (winner == in) { 00680 f = ast_read(in); 00681 #if 0 00682 if (f && (f->frametype != AST_FRAME_VOICE)) 00683 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 00684 else if (!f || (f->frametype != AST_FRAME_VOICE)) 00685 printf("Hangup received on %s\n", in->name); 00686 #endif 00687 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) { 00688 /* Got hung up */ 00689 *to=-1; 00690 strcpy(status, "CANCEL"); 00691 if (f) 00692 ast_frfree(f); 00693 return NULL; 00694 } 00695 00696 if (f && (f->frametype == AST_FRAME_DTMF)) { 00697 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) { 00698 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 00699 if (onedigit_goto(in, context, (char) f->subclass, 1)) { 00700 if (option_verbose > 3) 00701 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 00702 *to=0; 00703 *result = f->subclass; 00704 strcpy(status, "CANCEL"); 00705 ast_frfree(f); 00706 return NULL; 00707 } 00708 } 00709 00710 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 00711 (f->subclass == '*')) { /* hmm it it not guarenteed to be '*' anymore. */ 00712 if (option_verbose > 3) 00713 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 00714 *to=0; 00715 strcpy(status, "CANCEL"); 00716 ast_frfree(f); 00717 return NULL; 00718 } 00719 } 00720 00721 /* Forward HTML stuff */ 00722 if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 00723 ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen); 00724 00725 00726 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) { 00727 if (ast_write(outgoing->chan, f)) 00728 ast_log(LOG_WARNING, "Unable to forward voice\n"); 00729 } 00730 if (single && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_VIDUPDATE)) { 00731 if (option_verbose > 2) 00732 ast_verbose ( VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", in->name,outgoing->chan->name); 00733 ast_indicate(outgoing->chan, AST_CONTROL_VIDUPDATE); 00734 } 00735 ast_frfree(f); 00736 } 00737 if (!*to && (option_verbose > 2)) 00738 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); 00739 } 00740 00741 return peer; 00742 00743 }
char* app = "Dial" [static] |
Definition at line 62 of file app_dial.c.
char* descrip [static] |
Definition at line 66 of file app_dial.c.
enum { ... } dial_exec_option_args |
enum { ... } dial_exec_option_flags |
Definition at line 274 of file app_dial.c.
char* rapp = "RetryDial" [static] |
Definition at line 178 of file app_dial.c.
char* rdescrip [static] |
Definition at line 180 of file app_dial.c.
char* rsynopsis = "Place a call, retrying on failure allowing optional exit extension." [static] |
Definition at line 179 of file app_dial.c.
Definition at line 64 of file app_dial.c.
char* tdesc = "Dialing Application" [static] |
Definition at line 60 of file app_dial.c.