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