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