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