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