#include "asterisk.h"
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.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/rtp_engine.h"
#include "asterisk/cdr.h"
#include "asterisk/manager.h"
#include "asterisk/privacy.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/dsp.h"
#include "asterisk/cel.h"
#include "asterisk/aoc.h"
#include "asterisk/ccss.h"
#include "asterisk/indications.h"
#include "asterisk/framehook.h"
Go to the source code of this file.
Data Structures | |
struct | cause_args |
struct | chanlist |
List of channel drivers. More... | |
struct | privacy_args |
Defines | |
#define | AST_MAX_WATCHERS 256 |
#define | CAN_EARLY_BRIDGE(flags, chan, peer) |
#define | DIAL_CALLERID_ABSENT (1LLU << 33) |
#define | DIAL_NOFORWARDHTML (1LLU << 32) |
#define | DIAL_STILLGOING (1LLU << 31) |
#define | OPT_CALLEE_GO_ON (1LLU << 36) |
#define | OPT_CALLER_ANSWER (1LLU << 40) |
#define | OPT_CANCEL_ELSEWHERE (1LLU << 34) |
#define | OPT_CANCEL_TIMEOUT (1LLU << 37) |
#define | OPT_FORCE_CID_PRES (1LLU << 39) |
#define | OPT_FORCE_CID_TAG (1LLU << 38) |
#define | OPT_PEER_H (1LLU << 35) |
Enumerations | |
enum | { OPT_ARG_ANNOUNCE = 0, OPT_ARG_SENDDTMF, OPT_ARG_GOTO, OPT_ARG_DURATION_LIMIT, OPT_ARG_MUSICBACK, OPT_ARG_CALLEE_MACRO, OPT_ARG_RINGBACK, OPT_ARG_CALLEE_GOSUB, OPT_ARG_CALLEE_GO_ON, OPT_ARG_PRIVACY, OPT_ARG_DURATION_STOP, OPT_ARG_OPERMODE, OPT_ARG_SCREEN_NOINTRO, OPT_ARG_ORIGINAL_CLID, OPT_ARG_FORCECLID, OPT_ARG_FORCE_CID_TAG, OPT_ARG_FORCE_CID_PRES, OPT_ARG_ARRAY_SIZE } |
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_ORIGINAL_CLID = (1 << 8), OPT_DURATION_LIMIT = (1 << 9), OPT_MUSICBACK = (1 << 10), OPT_CALLEE_MACRO = (1 << 11), OPT_SCREEN_NOINTRO = (1 << 12), OPT_SCREEN_NOCALLERID = (1 << 13), OPT_IGNORE_CONNECTEDLINE = (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), OPT_OPERMODE = (1 << 24), OPT_CALLEE_PARK = (1 << 25), OPT_CALLER_PARK = (1 << 26), OPT_IGNORE_FORWARDING = (1 << 27), OPT_CALLEE_GOSUB = (1 << 28), OPT_CALLEE_MIXMONITOR = (1 << 29), OPT_CALLER_MIXMONITOR = (1 << 30) } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static void | chanlist_free (struct chanlist *outgoing) |
static int | detect_disconnect (struct ast_channel *chan, char code, struct ast_str *featurecode) |
static int | dial_exec (struct ast_channel *chan, const char *data) |
static int | dial_exec_full (struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec) |
static int | dial_handle_playtones (struct ast_channel *chan, const char *data) |
static void | do_forward (struct chanlist *o, struct cause_args *num, struct ast_flags64 *peerflags, int single, int caller_entertained, int *to, struct ast_party_id *forced_clid, struct ast_party_id *stored_clid) |
static void | end_bridge_callback (void *data) |
static void | end_bridge_callback_data_fixup (struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) |
static const char * | get_cid_name (char *name, int namelen, struct ast_channel *chan) |
static void | handle_cause (int cause, struct cause_args *num) |
static void | hanguptree (struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere) |
static int | load_module (void) |
static int | onedigit_goto (struct ast_channel *chan, const char *context, char exten, int pri) |
static void | replace_macro_delimiter (char *s) |
static int | retrydial_exec (struct ast_channel *chan, const char *data) |
static void | senddialendevent (struct ast_channel *src, const char *dialstatus) |
static void | senddialevent (struct ast_channel *src, struct ast_channel *dst, const char *dialstring) |
static int | setup_privacy_args (struct privacy_args *pa, struct ast_flags64 *opts, char *opt_args[], struct ast_channel *chan) |
returns 1 if successful, 0 or <0 if the caller should 'goto out' | |
static int | unload_module (void) |
static int | valid_priv_reply (struct ast_flags64 *opts, int res) |
static struct ast_channel * | wait_for_answer (struct ast_channel *in, struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags, char *opt_args[], struct privacy_args *pa, const struct cause_args *num_in, int *result, char *dtmf_progress, const int ignore_cc, struct ast_party_id *forced_clid, struct ast_party_id *stored_clid) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialing Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
static const char | app [] = "Dial" |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_app_option | dial_exec_options [128] = { [ 'A' ] = { .flag = OPT_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'a' ] = { .flag = (1LLU << 40) }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'c' ] = { .flag = (1LLU << 34) }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'e' ] = { .flag = (1LLU << 35) }, [ 'f' ] = { .flag = OPT_FORCECLID , .arg_index = OPT_ARG_FORCECLID + 1 }, [ 'F' ] = { .flag = (1LLU << 36) , .arg_index = OPT_ARG_CALLEE_GO_ON + 1 }, [ 'g' ] = { .flag = OPT_GO_ON }, [ 'G' ] = { .flag = OPT_GOTO , .arg_index = OPT_ARG_GOTO + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'i' ] = { .flag = OPT_IGNORE_FORWARDING }, [ 'I' ] = { .flag = OPT_IGNORE_CONNECTEDLINE }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'm' ] = { .flag = OPT_MUSICBACK , .arg_index = OPT_ARG_MUSICBACK + 1 }, [ 'M' ] = { .flag = OPT_CALLEE_MACRO , .arg_index = OPT_ARG_CALLEE_MACRO + 1 }, [ 'n' ] = { .flag = OPT_SCREEN_NOINTRO , .arg_index = OPT_ARG_SCREEN_NOINTRO + 1 }, [ 'N' ] = { .flag = OPT_SCREEN_NOCALLERID }, [ 'o' ] = { .flag = OPT_ORIGINAL_CLID , .arg_index = OPT_ARG_ORIGINAL_CLID + 1 }, [ 'O' ] = { .flag = OPT_OPERMODE , .arg_index = OPT_ARG_OPERMODE + 1 }, [ 'p' ] = { .flag = OPT_SCREENING }, [ 'P' ] = { .flag = OPT_PRIVACY , .arg_index = OPT_ARG_PRIVACY + 1 }, [ 'r' ] = { .flag = OPT_RINGBACK , .arg_index = OPT_ARG_RINGBACK + 1 }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 's' ] = { .flag = (1LLU << 38) , .arg_index = OPT_ARG_FORCE_CID_TAG + 1 }, [ 'u' ] = { .flag = (1LLU << 39) , .arg_index = OPT_ARG_FORCE_CID_PRES + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'U' ] = { .flag = OPT_CALLEE_GOSUB , .arg_index = OPT_ARG_CALLEE_GOSUB + 1 }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR }, [ 'x' ] = { .flag = OPT_CALLEE_MIXMONITOR }, [ 'X' ] = { .flag = OPT_CALLER_MIXMONITOR }, [ 'z' ] = { .flag = (1LLU << 37) }, } |
static const char | rapp [] = "RetryDial" |
Definition in file app_dial.c.
#define AST_MAX_WATCHERS 256 |
#define CAN_EARLY_BRIDGE | ( | flags, | |||
chan, | |||||
peer | ) |
#define DIAL_CALLERID_ABSENT (1LLU << 33) |
Definition at line 582 of file app_dial.c.
Referenced by dial_exec_full(), do_forward(), and wait_for_answer().
#define DIAL_NOFORWARDHTML (1LLU << 32) |
#define DIAL_STILLGOING (1LLU << 31) |
Definition at line 580 of file app_dial.c.
Referenced by dial_exec_full(), do_forward(), and wait_for_answer().
#define OPT_CALLEE_GO_ON (1LLU << 36) |
#define OPT_CALLER_ANSWER (1LLU << 40) |
#define OPT_CANCEL_ELSEWHERE (1LLU << 34) |
#define OPT_CANCEL_TIMEOUT (1LLU << 37) |
#define OPT_FORCE_CID_PRES (1LLU << 39) |
#define OPT_FORCE_CID_TAG (1LLU << 38) |
#define OPT_PEER_H (1LLU << 35) |
anonymous enum |
Definition at line 591 of file app_dial.c.
00591 { 00592 OPT_ARG_ANNOUNCE = 0, 00593 OPT_ARG_SENDDTMF, 00594 OPT_ARG_GOTO, 00595 OPT_ARG_DURATION_LIMIT, 00596 OPT_ARG_MUSICBACK, 00597 OPT_ARG_CALLEE_MACRO, 00598 OPT_ARG_RINGBACK, 00599 OPT_ARG_CALLEE_GOSUB, 00600 OPT_ARG_CALLEE_GO_ON, 00601 OPT_ARG_PRIVACY, 00602 OPT_ARG_DURATION_STOP, 00603 OPT_ARG_OPERMODE, 00604 OPT_ARG_SCREEN_NOINTRO, 00605 OPT_ARG_ORIGINAL_CLID, 00606 OPT_ARG_FORCECLID, 00607 OPT_ARG_FORCE_CID_TAG, 00608 OPT_ARG_FORCE_CID_PRES, 00609 /* note: this entry _MUST_ be the last one in the enum */ 00610 OPT_ARG_ARRAY_SIZE, 00611 };
anonymous enum |
Definition at line 545 of file app_dial.c.
00545 { 00546 OPT_ANNOUNCE = (1 << 0), 00547 OPT_RESETCDR = (1 << 1), 00548 OPT_DTMF_EXIT = (1 << 2), 00549 OPT_SENDDTMF = (1 << 3), 00550 OPT_FORCECLID = (1 << 4), 00551 OPT_GO_ON = (1 << 5), 00552 OPT_CALLEE_HANGUP = (1 << 6), 00553 OPT_CALLER_HANGUP = (1 << 7), 00554 OPT_ORIGINAL_CLID = (1 << 8), 00555 OPT_DURATION_LIMIT = (1 << 9), 00556 OPT_MUSICBACK = (1 << 10), 00557 OPT_CALLEE_MACRO = (1 << 11), 00558 OPT_SCREEN_NOINTRO = (1 << 12), 00559 OPT_SCREEN_NOCALLERID = (1 << 13), 00560 OPT_IGNORE_CONNECTEDLINE = (1 << 14), 00561 OPT_SCREENING = (1 << 15), 00562 OPT_PRIVACY = (1 << 16), 00563 OPT_RINGBACK = (1 << 17), 00564 OPT_DURATION_STOP = (1 << 18), 00565 OPT_CALLEE_TRANSFER = (1 << 19), 00566 OPT_CALLER_TRANSFER = (1 << 20), 00567 OPT_CALLEE_MONITOR = (1 << 21), 00568 OPT_CALLER_MONITOR = (1 << 22), 00569 OPT_GOTO = (1 << 23), 00570 OPT_OPERMODE = (1 << 24), 00571 OPT_CALLEE_PARK = (1 << 25), 00572 OPT_CALLER_PARK = (1 << 26), 00573 OPT_IGNORE_FORWARDING = (1 << 27), 00574 OPT_CALLEE_GOSUB = (1 << 28), 00575 OPT_CALLEE_MIXMONITOR = (1 << 29), 00576 OPT_CALLER_MIXMONITOR = (1 << 30), 00577 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 3199 of file app_dial.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 3199 of file app_dial.c.
static void chanlist_free | ( | struct chanlist * | outgoing | ) | [static] |
Definition at line 677 of file app_dial.c.
References chanlist::aoc_s_rate_list, ast_aoc_destroy_decoded(), ast_free, ast_party_connected_line_free(), and chanlist::connected.
Referenced by dial_exec_full(), and hanguptree().
00678 { 00679 ast_party_connected_line_free(&outgoing->connected); 00680 ast_aoc_destroy_decoded(outgoing->aoc_s_rate_list); 00681 ast_free(outgoing); 00682 }
static int detect_disconnect | ( | struct ast_channel * | chan, | |
char | code, | |||
struct ast_str * | featurecode | |||
) | [static] |
Definition at line 1648 of file app_dial.c.
References ast_feature_detect(), AST_FEATURE_DISCONNECT, AST_FEATURE_RETURN_STOREDIGITS, ast_str_append(), ast_str_buffer(), ast_str_reset(), and ast_call_feature::feature_mask.
01649 { 01650 struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */ 01651 struct ast_call_feature feature = { 0, }; 01652 int res; 01653 01654 ast_str_append(&featurecode, 1, "%c", code); 01655 01656 res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature); 01657 01658 if (res != AST_FEATURE_RETURN_STOREDIGITS) { 01659 ast_str_reset(featurecode); 01660 } 01661 if (feature.feature_mask & AST_FEATURE_DISCONNECT) { 01662 return 1; 01663 } 01664 01665 return 0; 01666 }
static int dial_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3049 of file app_dial.c.
References dial_exec_full().
Referenced by load_module().
03050 { 03051 struct ast_flags64 peerflags; 03052 03053 memset(&peerflags, 0, sizeof(peerflags)); 03054 03055 return dial_exec_full(chan, data, &peerflags, NULL); 03056 }
static int dial_exec_full | ( | struct ast_channel * | chan, | |
const char * | data, | |||
struct ast_flags64 * | peerflags, | |||
int * | continue_exec | |||
) | [static] |
Definition at line 1983 of file app_dial.c.
References ast_channel::_state, accountcode, ast_channel::accountcode, ast_channel::adsicpe, ast_cdr::answer, ast_channel::appl, args, asprintf, ast_answer(), AST_APP_ARG, ast_app_group_set_channel(), ast_app_parse_options64(), ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_call(), ast_bridge_timelimit(), ast_call(), ast_callerid_parse(), ast_calloc, ast_cause2str(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_cc_busy_interface(), ast_cc_call_failed(), ast_cc_call_init(), ast_cc_callback(), ast_cc_extension_monitor_add_dialstring(), AST_CDR_FLAG_DIALED, ast_cdr_reset(), ast_cdr_setanswer(), ast_cdr_setdestchan(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_inherit(), ast_channel_datastore_remove(), ast_channel_early_bridge(), ast_channel_get_device_name(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_make_compatible(), AST_CHANNEL_NAME, ast_channel_sendurl(), ast_channel_set_caller_event(), ast_channel_set_connected_line(), ast_channel_setoption(), ast_channel_supports_html(), ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_connected_line_copy_from_caller(), AST_CONTROL_HANGUP, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_copy_flags64, ast_copy_string(), ast_datastore_alloc, ast_datastore_free(), ast_deactivate_generator(), ast_debug, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_dtmf_stream(), ast_exists_extension(), AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, ast_filedelete(), ast_fileexists(), AST_FLAG_ANSWERED_ELSEWHERE, AST_FLAG_END_DTMF_ONLY, AST_FLAG_IN_AUTOLOOP, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, ast_free, ast_frfree, ast_goto_if_exists(), ast_hangup(), ast_ignore_cc(), ast_indicate(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), AST_OPTION_OPRMODE, ast_parse_caller_presentation(), ast_parseable_goto(), ast_party_caller_set_init(), ast_party_connected_line_copy(), ast_party_connected_line_set_init(), ast_party_id_init(), ast_party_id_set_init(), ast_party_redirecting_copy(), AST_PBX_INCOMPLETE, ast_pbx_run_args(), ast_pbx_start(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRIVACY_UNKNOWN, ast_read(), ast_request(), ast_rtp_instance_early_bridge_make_compatible(), ast_sched_runq(), ast_sched_wait(), ast_senddigit(), ast_set2_flag, ast_set2_flag64, ast_set_flag, ast_set_flag64, ast_spawn_extension(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_test_flag64, ast_tvadd(), ast_tvnow(), ast_tvzero(), ast_verb, ast_waitfor_n(), ast_channel::caller, CAN_EARLY_BRIDGE, cause, ast_channel::cdr, chanlist::chan, cause_args::chan, chanlist_free(), CHANNEL_DEADLOCK_AVOIDANCE, config, connected, ast_channel::connected, ast_channel::context, ast_channel::data, ast_datastore::data, DATASTORE_INHERIT_FOREVER, di, DIAL_CALLERID_ABSENT, dial_exec_options, dial_handle_playtones(), DIAL_NOFORWARDHTML, DIAL_STILLGOING, dialcontext, ast_channel::dialed, dialed_interface_info, end_bridge_callback(), end_bridge_callback_data_fixup(), errno, ast_channel::exten, ast_flags64::flags, ast_frame::frametype, get_cid_name(), handle_cause(), ast_channel::hangupcause, hanguptree(), ast_party_connected_line::id, ast_party_caller::id, ast_datastore::inheritance, ast_frame_subclass::integer, ast_channel::language, ast_dialed_interface::list, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, oprmode::mode, moh, musicclass, ast_channel::musicclass, ast_channel::name, ast_party_id::name, ast_channel::nativeformats, ast_party_id::number, OPT_ANNOUNCE, OPT_ARG_ANNOUNCE, OPT_ARG_ARRAY_SIZE, OPT_ARG_CALLEE_GO_ON, OPT_ARG_CALLEE_GOSUB, OPT_ARG_CALLEE_MACRO, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_FORCE_CID_PRES, OPT_ARG_FORCE_CID_TAG, OPT_ARG_FORCECLID, OPT_ARG_GOTO, OPT_ARG_OPERMODE, OPT_ARG_ORIGINAL_CLID, OPT_ARG_PRIVACY, OPT_ARG_RINGBACK, OPT_ARG_SCREEN_NOINTRO, OPT_ARG_SENDDTMF, OPT_CALLEE_GO_ON, OPT_CALLEE_GOSUB, OPT_CALLEE_HANGUP, OPT_CALLEE_MACRO, OPT_CALLEE_MIXMONITOR, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_ANSWER, OPT_CALLER_HANGUP, OPT_CALLER_MIXMONITOR, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_CANCEL_ELSEWHERE, OPT_CANCEL_TIMEOUT, OPT_DTMF_EXIT, OPT_DURATION_LIMIT, OPT_DURATION_STOP, OPT_FORCE_CID_PRES, OPT_FORCE_CID_TAG, OPT_FORCECLID, OPT_GO_ON, OPT_GOTO, OPT_IGNORE_CONNECTEDLINE, OPT_IGNORE_FORWARDING, OPT_MUSICBACK, OPT_OPERMODE, OPT_ORIGINAL_CLID, OPT_PEER_H, OPT_PRIVACY, OPT_RESETCDR, OPT_RINGBACK, OPT_SCREEN_NOINTRO, OPT_SCREENING, OPT_SENDDTMF, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), oprmode::peer, ast_party_number::presentation, ast_channel::priority, privacy_args::privdb_val, privacy_args::privintro, ast_channel::redirecting, replace_macro_delimiter(), S_COR, S_OR, ast_channel::sched, senddialendevent(), senddialevent(), privacy_args::sentringing, setup_privacy_args(), privacy_args::status, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_channel::stream, strsep(), ast_party_id::subaddress, ast_frame::subclass, ast_party_id::tag, ast_channel::tech, ast_channel::timingfunc, ast_channel::transfercapability, ast_party_dialed::transit_network_select, url, ast_party_number::valid, ast_party_name::valid, wait_for_answer(), and ast_channel::whentohangup.
Referenced by dial_exec(), and retrydial_exec().
01984 { 01985 int res = -1; /* default: error */ 01986 char *rest, *cur; /* scan the list of destinations */ 01987 struct chanlist *outgoing = NULL; /* list of destinations */ 01988 struct ast_channel *peer; 01989 int to; /* timeout */ 01990 struct cause_args num = { chan, 0, 0, 0 }; 01991 int cause; 01992 char numsubst[256]; 01993 01994 struct ast_bridge_config config = { { 0, } }; 01995 struct timeval calldurationlimit = { 0, }; 01996 char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL; 01997 struct privacy_args pa = { 01998 .sentringing = 0, 01999 .privdb_val = 0, 02000 .status = "INVALIDARGS", 02001 }; 02002 int sentringing = 0, moh = 0; 02003 const char *outbound_group = NULL; 02004 int result = 0; 02005 char *parse; 02006 int opermode = 0; 02007 int delprivintro = 0; 02008 AST_DECLARE_APP_ARGS(args, 02009 AST_APP_ARG(peers); 02010 AST_APP_ARG(timeout); 02011 AST_APP_ARG(options); 02012 AST_APP_ARG(url); 02013 ); 02014 struct ast_flags64 opts = { 0, }; 02015 char *opt_args[OPT_ARG_ARRAY_SIZE]; 02016 struct ast_datastore *datastore = NULL; 02017 int fulldial = 0, num_dialed = 0; 02018 int ignore_cc = 0; 02019 char device_name[AST_CHANNEL_NAME]; 02020 char forced_clid_name[AST_MAX_EXTENSION]; 02021 char stored_clid_name[AST_MAX_EXTENSION]; 02022 int force_forwards_only; /*!< TRUE if force CallerID on call forward only. Legacy behaviour.*/ 02023 /*! 02024 * \brief Forced CallerID party information to send. 02025 * \note This will not have any malloced strings so do not free it. 02026 */ 02027 struct ast_party_id forced_clid; 02028 /*! 02029 * \brief Stored CallerID information if needed. 02030 * 02031 * \note If OPT_ORIGINAL_CLID set then this is the o option 02032 * CallerID. Otherwise it is the dialplan extension and hint 02033 * name. 02034 * 02035 * \note This will not have any malloced strings so do not free it. 02036 */ 02037 struct ast_party_id stored_clid; 02038 /*! 02039 * \brief CallerID party information to store. 02040 * \note This will not have any malloced strings so do not free it. 02041 */ 02042 struct ast_party_caller caller; 02043 02044 /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */ 02045 pbx_builtin_setvar_helper(chan, "DIALSTATUS", ""); 02046 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); 02047 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ""); 02048 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); 02049 pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); 02050 02051 if (ast_strlen_zero(data)) { 02052 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 02053 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02054 return -1; 02055 } 02056 02057 parse = ast_strdupa(data); 02058 02059 AST_STANDARD_APP_ARGS(args, parse); 02060 02061 if (!ast_strlen_zero(args.options) && 02062 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) { 02063 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02064 goto done; 02065 } 02066 02067 if (ast_strlen_zero(args.peers)) { 02068 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 02069 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02070 goto done; 02071 } 02072 02073 if (ast_cc_call_init(chan, &ignore_cc)) { 02074 goto done; 02075 } 02076 02077 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) { 02078 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]); 02079 02080 if (delprivintro < 0 || delprivintro > 1) { 02081 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro); 02082 delprivintro = 0; 02083 } 02084 } 02085 02086 if (!ast_test_flag64(&opts, OPT_RINGBACK)) { 02087 opt_args[OPT_ARG_RINGBACK] = NULL; 02088 } 02089 02090 if (ast_test_flag64(&opts, OPT_OPERMODE)) { 02091 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]); 02092 ast_verb(3, "Setting operator services mode to %d.\n", opermode); 02093 } 02094 02095 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) { 02096 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]); 02097 if (!calldurationlimit.tv_sec) { 02098 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]); 02099 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02100 goto done; 02101 } 02102 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0); 02103 } 02104 02105 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { 02106 dtmf_progress = opt_args[OPT_ARG_SENDDTMF]; 02107 dtmfcalled = strsep(&dtmf_progress, ":"); 02108 dtmfcalling = strsep(&dtmf_progress, ":"); 02109 } 02110 02111 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { 02112 if (ast_bridge_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) 02113 goto done; 02114 } 02115 02116 /* Setup the forced CallerID information to send if used. */ 02117 ast_party_id_init(&forced_clid); 02118 force_forwards_only = 0; 02119 if (ast_test_flag64(&opts, OPT_FORCECLID)) { 02120 if (ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) { 02121 ast_channel_lock(chan); 02122 forced_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02123 ast_channel_unlock(chan); 02124 forced_clid_name[0] = '\0'; 02125 forced_clid.name.str = (char *) get_cid_name(forced_clid_name, 02126 sizeof(forced_clid_name), chan); 02127 force_forwards_only = 1; 02128 } else { 02129 /* Note: The opt_args[OPT_ARG_FORCECLID] string value is altered here. */ 02130 ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &forced_clid.name.str, 02131 &forced_clid.number.str); 02132 } 02133 if (!ast_strlen_zero(forced_clid.name.str)) { 02134 forced_clid.name.valid = 1; 02135 } 02136 if (!ast_strlen_zero(forced_clid.number.str)) { 02137 forced_clid.number.valid = 1; 02138 } 02139 } 02140 if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) 02141 && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) { 02142 forced_clid.tag = opt_args[OPT_ARG_FORCE_CID_TAG]; 02143 } 02144 forced_clid.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02145 if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) 02146 && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) { 02147 int pres; 02148 02149 pres = ast_parse_caller_presentation(opt_args[OPT_ARG_FORCE_CID_PRES]); 02150 if (0 <= pres) { 02151 forced_clid.number.presentation = pres; 02152 } 02153 } 02154 02155 /* Setup the stored CallerID information if needed. */ 02156 ast_party_id_init(&stored_clid); 02157 if (ast_test_flag64(&opts, OPT_ORIGINAL_CLID)) { 02158 if (ast_strlen_zero(opt_args[OPT_ARG_ORIGINAL_CLID])) { 02159 ast_channel_lock(chan); 02160 ast_party_id_set_init(&stored_clid, &chan->caller.id); 02161 if (!ast_strlen_zero(chan->caller.id.name.str)) { 02162 stored_clid.name.str = ast_strdupa(chan->caller.id.name.str); 02163 } 02164 if (!ast_strlen_zero(chan->caller.id.number.str)) { 02165 stored_clid.number.str = ast_strdupa(chan->caller.id.number.str); 02166 } 02167 if (!ast_strlen_zero(chan->caller.id.subaddress.str)) { 02168 stored_clid.subaddress.str = ast_strdupa(chan->caller.id.subaddress.str); 02169 } 02170 if (!ast_strlen_zero(chan->caller.id.tag)) { 02171 stored_clid.tag = ast_strdupa(chan->caller.id.tag); 02172 } 02173 ast_channel_unlock(chan); 02174 } else { 02175 /* Note: The opt_args[OPT_ARG_ORIGINAL_CLID] string value is altered here. */ 02176 ast_callerid_parse(opt_args[OPT_ARG_ORIGINAL_CLID], &stored_clid.name.str, 02177 &stored_clid.number.str); 02178 if (!ast_strlen_zero(stored_clid.name.str)) { 02179 stored_clid.name.valid = 1; 02180 } 02181 if (!ast_strlen_zero(stored_clid.number.str)) { 02182 stored_clid.number.valid = 1; 02183 } 02184 } 02185 } else { 02186 /* 02187 * In case the new channel has no preset CallerID number by the 02188 * channel driver, setup the dialplan extension and hint name. 02189 */ 02190 stored_clid_name[0] = '\0'; 02191 stored_clid.name.str = (char *) get_cid_name(stored_clid_name, 02192 sizeof(stored_clid_name), chan); 02193 if (ast_strlen_zero(stored_clid.name.str)) { 02194 stored_clid.name.str = NULL; 02195 } else { 02196 stored_clid.name.valid = 1; 02197 } 02198 ast_channel_lock(chan); 02199 stored_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02200 stored_clid.number.valid = 1; 02201 ast_channel_unlock(chan); 02202 } 02203 02204 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr) 02205 ast_cdr_reset(chan->cdr, NULL); 02206 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) 02207 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten); 02208 02209 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) { 02210 res = setup_privacy_args(&pa, &opts, opt_args, chan); 02211 if (res <= 0) 02212 goto out; 02213 res = -1; /* reset default */ 02214 } 02215 02216 if (continue_exec) 02217 *continue_exec = 0; 02218 02219 /* If a channel group has been specified, get it for use when we create peer channels */ 02220 02221 ast_channel_lock(chan); 02222 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) { 02223 outbound_group = ast_strdupa(outbound_group); 02224 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL); 02225 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) { 02226 outbound_group = ast_strdupa(outbound_group); 02227 } 02228 ast_channel_unlock(chan); 02229 02230 /* Set per dial instance flags. These flags are also passed back to RetryDial. */ 02231 ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID 02232 | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_CANCEL_TIMEOUT 02233 | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID); 02234 02235 /* loop through the list of dial destinations */ 02236 rest = args.peers; 02237 while ((cur = strsep(&rest, "&")) ) { 02238 struct chanlist *tmp; 02239 struct ast_channel *tc; /* channel for this destination */ 02240 /* Get a technology/[device:]number pair */ 02241 char *number = cur; 02242 char *interface = ast_strdupa(number); 02243 char *tech = strsep(&number, "/"); 02244 /* find if we already dialed this interface */ 02245 struct ast_dialed_interface *di; 02246 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; 02247 num_dialed++; 02248 if (ast_strlen_zero(number)) { 02249 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); 02250 goto out; 02251 } 02252 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 02253 goto out; 02254 if (opts.flags) { 02255 /* Set per outgoing call leg options. */ 02256 ast_copy_flags64(tmp, &opts, 02257 OPT_CANCEL_ELSEWHERE | 02258 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 02259 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 02260 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 02261 OPT_CALLEE_PARK | OPT_CALLER_PARK | 02262 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 02263 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_IGNORE_CONNECTEDLINE); 02264 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML); 02265 } 02266 ast_copy_string(numsubst, number, sizeof(numsubst)); 02267 /* Request the peer */ 02268 02269 ast_channel_lock(chan); 02270 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); 02271 /* 02272 * Seed the chanlist's connected line information with previously 02273 * acquired connected line info from the incoming channel. The 02274 * previously acquired connected line info could have been set 02275 * through the CONNECTED_LINE dialplan function. 02276 */ 02277 ast_party_connected_line_copy(&tmp->connected, &chan->connected); 02278 ast_channel_unlock(chan); 02279 02280 if (datastore) 02281 dialed_interfaces = datastore->data; 02282 else { 02283 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { 02284 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 02285 chanlist_free(tmp); 02286 goto out; 02287 } 02288 02289 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 02290 02291 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { 02292 ast_datastore_free(datastore); 02293 chanlist_free(tmp); 02294 goto out; 02295 } 02296 02297 datastore->data = dialed_interfaces; 02298 AST_LIST_HEAD_INIT(dialed_interfaces); 02299 02300 ast_channel_lock(chan); 02301 ast_channel_datastore_add(chan, datastore); 02302 ast_channel_unlock(chan); 02303 } 02304 02305 AST_LIST_LOCK(dialed_interfaces); 02306 AST_LIST_TRAVERSE(dialed_interfaces, di, list) { 02307 if (!strcasecmp(di->interface, interface)) { 02308 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", 02309 di->interface); 02310 break; 02311 } 02312 } 02313 AST_LIST_UNLOCK(dialed_interfaces); 02314 02315 if (di) { 02316 fulldial++; 02317 chanlist_free(tmp); 02318 continue; 02319 } 02320 02321 /* It is always ok to dial a Local interface. We only keep track of 02322 * which "real" interfaces have been dialed. The Local channel will 02323 * inherit this list so that if it ends up dialing a real interface, 02324 * it won't call one that has already been called. */ 02325 if (strcasecmp(tech, "Local")) { 02326 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) { 02327 AST_LIST_UNLOCK(dialed_interfaces); 02328 chanlist_free(tmp); 02329 goto out; 02330 } 02331 strcpy(di->interface, interface); 02332 02333 AST_LIST_LOCK(dialed_interfaces); 02334 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); 02335 AST_LIST_UNLOCK(dialed_interfaces); 02336 } 02337 02338 tc = ast_request(tech, chan->nativeformats, chan, numsubst, &cause); 02339 if (!tc) { 02340 /* If we can't, just go on to the next call */ 02341 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", 02342 tech, cause, ast_cause2str(cause)); 02343 handle_cause(cause, &num); 02344 if (!rest) /* we are on the last destination */ 02345 chan->hangupcause = cause; 02346 chanlist_free(tmp); 02347 if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) { 02348 if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) { 02349 ast_cc_extension_monitor_add_dialstring(chan, interface, ""); 02350 } 02351 } 02352 continue; 02353 } 02354 ast_channel_get_device_name(tc, device_name, sizeof(device_name)); 02355 if (!ignore_cc) { 02356 ast_cc_extension_monitor_add_dialstring(chan, interface, device_name); 02357 } 02358 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst); 02359 02360 ast_channel_lock(tc); 02361 while (ast_channel_trylock(chan)) { 02362 CHANNEL_DEADLOCK_AVOIDANCE(tc); 02363 } 02364 /* Setup outgoing SDP to match incoming one */ 02365 if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) { 02366 ast_rtp_instance_early_bridge_make_compatible(tc, chan); 02367 } 02368 02369 /* Inherit specially named variables from parent channel */ 02370 ast_channel_inherit_variables(chan, tc); 02371 ast_channel_datastore_inherit(chan, tc); 02372 02373 tc->appl = "AppDial"; 02374 tc->data = "(Outgoing Line)"; 02375 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup)); 02376 02377 /* Determine CallerID to store in outgoing channel. */ 02378 ast_party_caller_set_init(&caller, &tc->caller); 02379 if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 02380 caller.id = stored_clid; 02381 ast_channel_set_caller_event(tc, &caller, NULL); 02382 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02383 } else if (ast_strlen_zero(S_COR(tc->caller.id.number.valid, 02384 tc->caller.id.number.str, NULL))) { 02385 /* 02386 * The new channel has no preset CallerID number by the channel 02387 * driver. Use the dialplan extension and hint name. 02388 */ 02389 caller.id = stored_clid; 02390 if (!caller.id.name.valid 02391 && !ast_strlen_zero(S_COR(chan->connected.id.name.valid, 02392 chan->connected.id.name.str, NULL))) { 02393 /* 02394 * No hint name available. We have a connected name supplied by 02395 * the dialplan we can use instead. 02396 */ 02397 caller.id.name.valid = 1; 02398 caller.id.name = chan->connected.id.name; 02399 } 02400 ast_channel_set_caller_event(tc, &caller, NULL); 02401 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02402 } else if (ast_strlen_zero(S_COR(tc->caller.id.name.valid, tc->caller.id.name.str, 02403 NULL))) { 02404 /* The new channel has no preset CallerID name by the channel driver. */ 02405 if (!ast_strlen_zero(S_COR(chan->connected.id.name.valid, 02406 chan->connected.id.name.str, NULL))) { 02407 /* 02408 * We have a connected name supplied by the dialplan we can 02409 * use instead. 02410 */ 02411 caller.id.name.valid = 1; 02412 caller.id.name = chan->connected.id.name; 02413 ast_channel_set_caller_event(tc, &caller, NULL); 02414 } 02415 } 02416 02417 /* Determine CallerID for outgoing channel to send. */ 02418 if (ast_test_flag64(peerflags, OPT_FORCECLID) && !force_forwards_only) { 02419 struct ast_party_connected_line connected; 02420 02421 ast_party_connected_line_set_init(&connected, &tc->connected); 02422 connected.id = forced_clid; 02423 ast_channel_set_connected_line(tc, &connected, NULL); 02424 } else { 02425 ast_connected_line_copy_from_caller(&tc->connected, &chan->caller); 02426 } 02427 02428 ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting); 02429 02430 tc->dialed.transit_network_select = chan->dialed.transit_network_select; 02431 02432 if (!ast_strlen_zero(chan->accountcode)) { 02433 ast_string_field_set(tc, accountcode, chan->accountcode); 02434 } 02435 if (ast_strlen_zero(tc->musicclass)) 02436 ast_string_field_set(tc, musicclass, chan->musicclass); 02437 02438 /* Pass ADSI CPE and transfer capability */ 02439 tc->adsicpe = chan->adsicpe; 02440 tc->transfercapability = chan->transfercapability; 02441 02442 /* If we have an outbound group, set this peer channel to it */ 02443 if (outbound_group) 02444 ast_app_group_set_channel(tc, outbound_group); 02445 /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */ 02446 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE)) 02447 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02448 02449 /* Check if we're forced by configuration */ 02450 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)) 02451 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02452 02453 02454 /* Inherit context and extension */ 02455 ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext); 02456 if (!ast_strlen_zero(chan->macroexten)) 02457 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten)); 02458 else 02459 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten)); 02460 02461 ast_channel_unlock(tc); 02462 ast_channel_unlock(chan); 02463 res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */ 02464 ast_channel_lock(chan); 02465 02466 /* Save the info in cdr's that we called them */ 02467 if (chan->cdr) 02468 ast_cdr_setdestchan(chan->cdr, tc->name); 02469 02470 /* check the results of ast_call */ 02471 if (res) { 02472 /* Again, keep going even if there's an error */ 02473 ast_debug(1, "ast call on peer returned %d\n", res); 02474 ast_verb(3, "Couldn't call %s/%s\n", tech, numsubst); 02475 if (tc->hangupcause) { 02476 chan->hangupcause = tc->hangupcause; 02477 } 02478 ast_channel_unlock(chan); 02479 ast_cc_call_failed(chan, tc, interface); 02480 ast_hangup(tc); 02481 tc = NULL; 02482 chanlist_free(tmp); 02483 continue; 02484 } else { 02485 senddialevent(chan, tc, numsubst); 02486 ast_verb(3, "Called %s/%s\n", tech, numsubst); 02487 ast_channel_unlock(chan); 02488 } 02489 /* Put them in the list of outgoing thingies... We're ready now. 02490 XXX If we're forcibly removed, these outgoing calls won't get 02491 hung up XXX */ 02492 ast_set_flag64(tmp, DIAL_STILLGOING); 02493 tmp->chan = tc; 02494 tmp->next = outgoing; 02495 outgoing = tmp; 02496 /* If this line is up, don't try anybody else */ 02497 if (outgoing->chan->_state == AST_STATE_UP) 02498 break; 02499 } 02500 02501 if (ast_strlen_zero(args.timeout)) { 02502 to = -1; 02503 } else { 02504 to = atoi(args.timeout); 02505 if (to > 0) 02506 to *= 1000; 02507 else { 02508 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout); 02509 to = -1; 02510 } 02511 } 02512 02513 if (!outgoing) { 02514 strcpy(pa.status, "CHANUNAVAIL"); 02515 if (fulldial == num_dialed) { 02516 res = -1; 02517 goto out; 02518 } 02519 } else { 02520 /* Our status will at least be NOANSWER */ 02521 strcpy(pa.status, "NOANSWER"); 02522 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) { 02523 moh = 1; 02524 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) { 02525 char *original_moh = ast_strdupa(chan->musicclass); 02526 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]); 02527 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL); 02528 ast_string_field_set(chan, musicclass, original_moh); 02529 } else { 02530 ast_moh_start(chan, NULL, NULL); 02531 } 02532 ast_indicate(chan, AST_CONTROL_PROGRESS); 02533 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) { 02534 if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 02535 if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){ 02536 ast_indicate(chan, AST_CONTROL_RINGING); 02537 sentringing++; 02538 } else { 02539 ast_indicate(chan, AST_CONTROL_PROGRESS); 02540 } 02541 } else { 02542 ast_indicate(chan, AST_CONTROL_RINGING); 02543 sentringing++; 02544 } 02545 } 02546 } 02547 02548 peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, 02549 dtmf_progress, ignore_cc, &forced_clid, &stored_clid); 02550 02551 /* The ast_channel_datastore_remove() function could fail here if the 02552 * datastore was moved to another channel during a masquerade. If this is 02553 * the case, don't free the datastore here because later, when the channel 02554 * to which the datastore was moved hangs up, it will attempt to free this 02555 * datastore again, causing a crash 02556 */ 02557 ast_channel_lock(chan); 02558 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); /* make sure we weren't cleaned up already */ 02559 if (datastore && !ast_channel_datastore_remove(chan, datastore)) { 02560 ast_datastore_free(datastore); 02561 } 02562 ast_channel_unlock(chan); 02563 if (!peer) { 02564 if (result) { 02565 res = result; 02566 } else if (to) { /* Musta gotten hung up */ 02567 res = -1; 02568 } else { /* Nobody answered, next please? */ 02569 res = 0; 02570 } 02571 } else { 02572 const char *number; 02573 02574 if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) 02575 ast_answer(chan); 02576 02577 strcpy(pa.status, "ANSWER"); 02578 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02579 /* Ah ha! Someone answered within the desired timeframe. Of course after this 02580 we will always return with -1 so that it is hung up properly after the 02581 conversation. */ 02582 hanguptree(outgoing, peer, 1); 02583 outgoing = NULL; 02584 /* If appropriate, log that we have a destination channel and set the answer time */ 02585 if (chan->cdr) { 02586 ast_cdr_setdestchan(chan->cdr, peer->name); 02587 ast_cdr_setanswer(chan->cdr, peer->cdr->answer); 02588 } 02589 if (peer->name) 02590 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name); 02591 02592 ast_channel_lock(peer); 02593 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 02594 if (!number) 02595 number = numsubst; 02596 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); 02597 ast_channel_unlock(peer); 02598 02599 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { 02600 ast_debug(1, "app_dial: sendurl=%s.\n", args.url); 02601 ast_channel_sendurl( peer, args.url ); 02602 } 02603 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) { 02604 if (do_privacy(chan, peer, &opts, opt_args, &pa)) { 02605 res = 0; 02606 goto out; 02607 } 02608 } 02609 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) { 02610 res = 0; 02611 } else { 02612 int digit = 0; 02613 struct ast_channel *chans[2]; 02614 struct ast_channel *active_chan; 02615 02616 chans[0] = chan; 02617 chans[1] = peer; 02618 02619 /* we need to stream the announcment while monitoring the caller for a hangup */ 02620 02621 /* stream the file */ 02622 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language); 02623 if (res) { 02624 res = 0; 02625 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]); 02626 } 02627 02628 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY); 02629 while (peer->stream) { 02630 int ms; 02631 02632 ms = ast_sched_wait(peer->sched); 02633 02634 if (ms < 0 && !peer->timingfunc) { 02635 ast_stopstream(peer); 02636 break; 02637 } 02638 if (ms < 0) 02639 ms = 1000; 02640 02641 active_chan = ast_waitfor_n(chans, 2, &ms); 02642 if (active_chan) { 02643 struct ast_frame *fr = ast_read(active_chan); 02644 if (!fr) { 02645 ast_hangup(peer); 02646 res = -1; 02647 goto done; 02648 } 02649 switch(fr->frametype) { 02650 case AST_FRAME_DTMF_END: 02651 digit = fr->subclass.integer; 02652 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) { 02653 ast_stopstream(peer); 02654 res = ast_senddigit(chan, digit, 0); 02655 } 02656 break; 02657 case AST_FRAME_CONTROL: 02658 switch (fr->subclass.integer) { 02659 case AST_CONTROL_HANGUP: 02660 ast_frfree(fr); 02661 ast_hangup(peer); 02662 res = -1; 02663 goto done; 02664 default: 02665 break; 02666 } 02667 break; 02668 default: 02669 /* Ignore all others */ 02670 break; 02671 } 02672 ast_frfree(fr); 02673 } 02674 ast_sched_runq(peer->sched); 02675 } 02676 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY); 02677 } 02678 02679 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { 02680 /* chan and peer are going into the PBX, they both 02681 * should probably get CDR records. */ 02682 ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED); 02683 ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED); 02684 02685 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]); 02686 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); 02687 /* peer goes to the same context and extension as chan, so just copy info from chan*/ 02688 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02689 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02690 peer->priority = chan->priority + 2; 02691 if (ast_pbx_start(peer)) { 02692 ast_hangup(peer); 02693 } 02694 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0); 02695 if (continue_exec) 02696 *continue_exec = 1; 02697 res = 0; 02698 goto done; 02699 } 02700 02701 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) { 02702 struct ast_app *theapp; 02703 const char *macro_result; 02704 02705 res = ast_autoservice_start(chan); 02706 if (res) { 02707 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02708 res = -1; 02709 } 02710 02711 theapp = pbx_findapp("Macro"); 02712 02713 if (theapp && !res) { /* XXX why check res here ? */ 02714 /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */ 02715 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02716 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02717 02718 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]); 02719 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]); 02720 ast_debug(1, "Macro exited with status %d\n", res); 02721 res = 0; 02722 } else { 02723 ast_log(LOG_ERROR, "Could not find application Macro\n"); 02724 res = -1; 02725 } 02726 02727 if (ast_autoservice_stop(chan) < 0) { 02728 res = -1; 02729 } 02730 02731 ast_channel_lock(peer); 02732 02733 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) { 02734 char *macro_transfer_dest; 02735 02736 if (!strcasecmp(macro_result, "BUSY")) { 02737 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02738 ast_set_flag64(peerflags, OPT_GO_ON); 02739 res = -1; 02740 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { 02741 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02742 ast_set_flag64(peerflags, OPT_GO_ON); 02743 res = -1; 02744 } else if (!strcasecmp(macro_result, "CONTINUE")) { 02745 /* hangup peer and keep chan alive assuming the macro has changed 02746 the context / exten / priority or perhaps 02747 the next priority in the current exten is desired. 02748 */ 02749 ast_set_flag64(peerflags, OPT_GO_ON); 02750 res = -1; 02751 } else if (!strcasecmp(macro_result, "ABORT")) { 02752 /* Hangup both ends unless the caller has the g flag */ 02753 res = -1; 02754 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { 02755 res = -1; 02756 /* perform a transfer to a new extension */ 02757 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/ 02758 replace_macro_delimiter(macro_transfer_dest); 02759 if (!ast_parseable_goto(chan, macro_transfer_dest)) 02760 ast_set_flag64(peerflags, OPT_GO_ON); 02761 } 02762 } 02763 } 02764 02765 ast_channel_unlock(peer); 02766 } 02767 02768 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) { 02769 struct ast_app *theapp; 02770 const char *gosub_result; 02771 char *gosub_args, *gosub_argstart; 02772 int res9 = -1; 02773 02774 res9 = ast_autoservice_start(chan); 02775 if (res9) { 02776 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02777 res9 = -1; 02778 } 02779 02780 theapp = pbx_findapp("Gosub"); 02781 02782 if (theapp && !res9) { 02783 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]); 02784 02785 /* Set where we came from */ 02786 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context)); 02787 ast_copy_string(peer->exten, "s", sizeof(peer->exten)); 02788 peer->priority = 0; 02789 02790 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ','); 02791 if (gosub_argstart) { 02792 const char *what_is_s = "s"; 02793 *gosub_argstart = 0; 02794 if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) && 02795 ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02796 what_is_s = "~~s~~"; 02797 } 02798 if (asprintf(&gosub_args, "%s,%s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s, gosub_argstart + 1) < 0) { 02799 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02800 gosub_args = NULL; 02801 } 02802 *gosub_argstart = ','; 02803 } else { 02804 const char *what_is_s = "s"; 02805 if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) && 02806 ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02807 what_is_s = "~~s~~"; 02808 } 02809 if (asprintf(&gosub_args, "%s,%s,1", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s) < 0) { 02810 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02811 gosub_args = NULL; 02812 } 02813 } 02814 02815 if (gosub_args) { 02816 res9 = pbx_exec(peer, theapp, gosub_args); 02817 if (!res9) { 02818 struct ast_pbx_args args; 02819 /* A struct initializer fails to compile for this case ... */ 02820 memset(&args, 0, sizeof(args)); 02821 args.no_hangup_chan = 1; 02822 ast_pbx_run_args(peer, &args); 02823 } 02824 ast_free(gosub_args); 02825 ast_debug(1, "Gosub exited with status %d\n", res9); 02826 } else { 02827 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n"); 02828 } 02829 02830 } else if (!res9) { 02831 ast_log(LOG_ERROR, "Could not find application Gosub\n"); 02832 res9 = -1; 02833 } 02834 02835 if (ast_autoservice_stop(chan) < 0) { 02836 res9 = -1; 02837 } 02838 02839 ast_channel_lock(peer); 02840 02841 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) { 02842 char *gosub_transfer_dest; 02843 const char *gosub_retval = pbx_builtin_getvar_helper(peer, "GOSUB_RETVAL"); 02844 02845 /* Inherit return value from the peer, so it can be used in the master */ 02846 if (gosub_retval) { 02847 pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", gosub_retval); 02848 } 02849 02850 if (!strcasecmp(gosub_result, "BUSY")) { 02851 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02852 ast_set_flag64(peerflags, OPT_GO_ON); 02853 res = -1; 02854 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) { 02855 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02856 ast_set_flag64(peerflags, OPT_GO_ON); 02857 res = -1; 02858 } else if (!strcasecmp(gosub_result, "CONTINUE")) { 02859 /* hangup peer and keep chan alive assuming the macro has changed 02860 the context / exten / priority or perhaps 02861 the next priority in the current exten is desired. 02862 */ 02863 ast_set_flag64(peerflags, OPT_GO_ON); 02864 res = -1; 02865 } else if (!strcasecmp(gosub_result, "ABORT")) { 02866 /* Hangup both ends unless the caller has the g flag */ 02867 res = -1; 02868 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) { 02869 res = -1; 02870 /* perform a transfer to a new extension */ 02871 if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/ 02872 replace_macro_delimiter(gosub_transfer_dest); 02873 if (!ast_parseable_goto(chan, gosub_transfer_dest)) 02874 ast_set_flag64(peerflags, OPT_GO_ON); 02875 } 02876 } 02877 } 02878 02879 ast_channel_unlock(peer); 02880 } 02881 02882 if (!res) { 02883 if (!ast_tvzero(calldurationlimit)) { 02884 struct timeval whentohangup = calldurationlimit; 02885 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup); 02886 } 02887 if (!ast_strlen_zero(dtmfcalled)) { 02888 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled); 02889 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0); 02890 } 02891 if (!ast_strlen_zero(dtmfcalling)) { 02892 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling); 02893 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0); 02894 } 02895 } 02896 02897 if (res) { /* some error */ 02898 res = -1; 02899 } else { 02900 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER)) 02901 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02902 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER)) 02903 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02904 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP)) 02905 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT); 02906 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP)) 02907 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT); 02908 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR)) 02909 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 02910 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR)) 02911 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 02912 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK)) 02913 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL); 02914 if (ast_test_flag64(peerflags, OPT_CALLER_PARK)) 02915 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL); 02916 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR)) 02917 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON); 02918 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR)) 02919 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON); 02920 if (ast_test_flag64(peerflags, OPT_GO_ON)) 02921 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN); 02922 02923 config.end_bridge_callback = end_bridge_callback; 02924 config.end_bridge_callback_data = chan; 02925 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; 02926 02927 if (moh) { 02928 moh = 0; 02929 ast_moh_stop(chan); 02930 } else if (sentringing) { 02931 sentringing = 0; 02932 ast_indicate(chan, -1); 02933 } 02934 /* Be sure no generators are left on it and reset the visible indication */ 02935 ast_deactivate_generator(chan); 02936 chan->visible_indication = 0; 02937 /* Make sure channels are compatible */ 02938 res = ast_channel_make_compatible(chan, peer); 02939 if (res < 0) { 02940 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name); 02941 ast_hangup(peer); 02942 res = -1; 02943 goto done; 02944 } 02945 if (opermode) { 02946 struct oprmode oprmode; 02947 02948 oprmode.peer = peer; 02949 oprmode.mode = opermode; 02950 02951 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0); 02952 } 02953 res = ast_bridge_call(chan, peer, &config); 02954 } 02955 02956 strcpy(peer->context, chan->context); 02957 02958 if (ast_test_flag64(&opts, OPT_PEER_H) 02959 && ast_exists_extension(peer, peer->context, "h", 1, 02960 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02961 int autoloopflag; 02962 int found; 02963 int res9; 02964 02965 strcpy(peer->exten, "h"); 02966 peer->priority = 1; 02967 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02968 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP); 02969 02970 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, 02971 peer->priority, 02972 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL), 02973 &found, 1)) == 0) { 02974 peer->priority++; 02975 } 02976 02977 if (found && res9) { 02978 /* Something bad happened, or a hangup has been requested. */ 02979 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02980 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02981 } 02982 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */ 02983 } 02984 if (!ast_check_hangup(peer)) { 02985 if (ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) { 02986 int goto_res; 02987 02988 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) { 02989 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]); 02990 goto_res = ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]); 02991 } else { /* F() */ 02992 goto_res = ast_goto_if_exists(peer, chan->context, 02993 chan->exten, chan->priority + 1); 02994 } 02995 if (!goto_res && !ast_pbx_start(peer)) { 02996 /* The peer is now running its own PBX. */ 02997 goto out; 02998 } 02999 } 03000 } else if (!ast_check_hangup(chan)) { 03001 chan->hangupcause = peer->hangupcause; 03002 } 03003 ast_hangup(peer); 03004 } 03005 out: 03006 if (moh) { 03007 moh = 0; 03008 ast_moh_stop(chan); 03009 } else if (sentringing) { 03010 sentringing = 0; 03011 ast_indicate(chan, -1); 03012 } 03013 03014 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) { 03015 ast_filedelete(pa.privintro, NULL); 03016 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) { 03017 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro); 03018 } else { 03019 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro); 03020 } 03021 } 03022 03023 ast_channel_early_bridge(chan, NULL); 03024 hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */ 03025 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 03026 senddialendevent(chan, pa.status); 03027 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status); 03028 03029 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) { 03030 if (!ast_tvzero(calldurationlimit)) 03031 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup)); 03032 res = 0; 03033 } 03034 03035 done: 03036 if (config.warning_sound) { 03037 ast_free((char *)config.warning_sound); 03038 } 03039 if (config.end_sound) { 03040 ast_free((char *)config.end_sound); 03041 } 03042 if (config.start_sound) { 03043 ast_free((char *)config.start_sound); 03044 } 03045 ast_ignore_cc(chan); 03046 return res; 03047 }
static int dial_handle_playtones | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 1953 of file app_dial.c.
References ast_debug, ast_get_indication_tone(), ast_log(), ast_playtones_start(), ast_strlen_zero(), ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, LOG_WARNING, str, and ast_channel::zone.
Referenced by dial_exec_full().
01954 { 01955 struct ast_tone_zone_sound *ts = NULL; 01956 int res; 01957 const char *str = data; 01958 01959 if (ast_strlen_zero(str)) { 01960 ast_debug(1,"Nothing to play\n"); 01961 return -1; 01962 } 01963 01964 ts = ast_get_indication_tone(chan->zone, str); 01965 01966 if (ts && ts->data[0]) { 01967 res = ast_playtones_start(chan, 0, ts->data, 0); 01968 } else { 01969 res = -1; 01970 } 01971 01972 if (ts) { 01973 ts = ast_tone_zone_sound_unref(ts); 01974 } 01975 01976 if (res) { 01977 ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str); 01978 } 01979 01980 return res; 01981 }
static void do_forward | ( | struct chanlist * | o, | |
struct cause_args * | num, | |||
struct ast_flags64 * | peerflags, | |||
int | single, | |||
int | caller_entertained, | |||
int * | to, | |||
struct ast_party_id * | forced_clid, | |||
struct ast_party_id * | stored_clid | |||
) | [static] |
helper function for wait_for_answer()
o | Outgoing call channel list. | |
num | Incoming call channel cause accumulation | |
peerflags | Dial option flags | |
single | TRUE if there is only one outgoing call. | |
caller_entertained | TRUE if the caller is being entertained by MOH or ringback. | |
to | Remaining call timeout time. | |
forced_clid | OPT_FORCECLID caller id to send | |
stored_clid | Caller id representing the called party if needed |
Definition at line 837 of file app_dial.c.
References ast_channel::accountcode, accountcode, ast_channel::appl, ast_call(), AST_CAUSE_BUSY, AST_CEL_FORWARD, ast_cel_report_event(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_lock_both, ast_channel_make_compatible(), ast_channel_redirecting_macro(), ast_channel_set_caller_event(), ast_channel_unlock, ast_channel_update_redirecting(), ast_clear_flag64, ast_connected_line_copy_from_caller(), ast_copy_string(), ast_hangup(), ast_ignore_cc(), ast_indicate(), ast_log(), ast_party_caller_set_init(), ast_party_connected_line_copy(), ast_party_connected_line_init(), ast_party_number_free(), ast_party_number_init(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_request(), ast_rtp_instance_early_bridge_make_compatible(), ast_set_flag64, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_test_flag64, ast_verb, ast_channel::call_forward, ast_channel::caller, CAN_EARLY_BRIDGE, cause, cause_args::chan, chanlist::chan, ast_channel::connected, connected, ast_channel::context, ast_channel::data, DIAL_CALLERID_ABSENT, DIAL_STILLGOING, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, handle_cause(), ast_party_caller::id, LOG_NOTICE, ast_channel::macroexten, ast_channel::name, ast_channel::nativeformats, cause_args::nochan, ast_party_id::number, OPT_CANCEL_TIMEOUT, OPT_FORCECLID, OPT_IGNORE_CONNECTEDLINE, OPT_IGNORE_FORWARDING, OPT_ORIGINAL_CLID, pbx_builtin_getvar_helper(), ast_channel::redirecting, S_COR, S_OR, senddialevent(), ast_party_number::str, ast_channel::tech, ast_party_dialed::transit_network_select, and ast_party_number::valid.
00840 { 00841 char tmpchan[256]; 00842 struct ast_channel *original = o->chan; 00843 struct ast_channel *c = o->chan; /* the winner */ 00844 struct ast_channel *in = num->chan; /* the input channel */ 00845 char *stuff; 00846 char *tech; 00847 int cause; 00848 struct ast_party_caller caller; 00849 00850 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan)); 00851 if ((stuff = strchr(tmpchan, '/'))) { 00852 *stuff++ = '\0'; 00853 tech = tmpchan; 00854 } else { 00855 const char *forward_context; 00856 ast_channel_lock(c); 00857 forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT"); 00858 if (ast_strlen_zero(forward_context)) { 00859 forward_context = NULL; 00860 } 00861 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context); 00862 ast_channel_unlock(c); 00863 stuff = tmpchan; 00864 tech = "Local"; 00865 } 00866 if (!strcasecmp(tech, "Local")) { 00867 /* 00868 * Drop the connected line update block for local channels since 00869 * this is going to run dialplan and the user can change his 00870 * mind about what connected line information he wants to send. 00871 */ 00872 ast_clear_flag64(o, OPT_IGNORE_CONNECTEDLINE); 00873 } 00874 00875 ast_cel_report_event(in, AST_CEL_FORWARD, NULL, c->call_forward, NULL); 00876 00877 /* Before processing channel, go ahead and check for forwarding */ 00878 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); 00879 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ 00880 if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) { 00881 ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); 00882 c = o->chan = NULL; 00883 cause = AST_CAUSE_BUSY; 00884 } else { 00885 /* Setup parameters */ 00886 c = o->chan = ast_request(tech, in->nativeformats, in, stuff, &cause); 00887 if (c) { 00888 if (single && !caller_entertained) { 00889 ast_channel_make_compatible(o->chan, in); 00890 } 00891 ast_channel_lock_both(in, o->chan); 00892 ast_channel_inherit_variables(in, o->chan); 00893 ast_channel_datastore_inherit(in, o->chan); 00894 ast_channel_unlock(in); 00895 ast_channel_unlock(o->chan); 00896 /* When a call is forwarded, we don't want to track new interfaces 00897 * dialed for CC purposes. Setting the done flag will ensure that 00898 * any Dial operations that happen later won't record CC interfaces. 00899 */ 00900 ast_ignore_cc(o->chan); 00901 ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", o->chan->name); 00902 } else 00903 ast_log(LOG_NOTICE, 00904 "Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n", 00905 tech, stuff, cause); 00906 } 00907 if (!c) { 00908 ast_clear_flag64(o, DIAL_STILLGOING); 00909 handle_cause(cause, num); 00910 ast_hangup(original); 00911 } else { 00912 ast_channel_lock_both(c, original); 00913 ast_party_redirecting_copy(&c->redirecting, &original->redirecting); 00914 ast_channel_unlock(c); 00915 ast_channel_unlock(original); 00916 00917 ast_channel_lock_both(c, in); 00918 00919 if (single && !caller_entertained && CAN_EARLY_BRIDGE(peerflags, c, in)) { 00920 ast_rtp_instance_early_bridge_make_compatible(c, in); 00921 } 00922 00923 if (!c->redirecting.from.number.valid 00924 || ast_strlen_zero(c->redirecting.from.number.str)) { 00925 /* 00926 * The call was not previously redirected so it is 00927 * now redirected from this number. 00928 */ 00929 ast_party_number_free(&c->redirecting.from.number); 00930 ast_party_number_init(&c->redirecting.from.number); 00931 c->redirecting.from.number.valid = 1; 00932 c->redirecting.from.number.str = 00933 ast_strdup(S_OR(in->macroexten, in->exten)); 00934 } 00935 00936 c->dialed.transit_network_select = in->dialed.transit_network_select; 00937 00938 /* Determine CallerID to store in outgoing channel. */ 00939 ast_party_caller_set_init(&caller, &c->caller); 00940 if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 00941 caller.id = *stored_clid; 00942 ast_channel_set_caller_event(c, &caller, NULL); 00943 ast_set_flag64(o, DIAL_CALLERID_ABSENT); 00944 } else if (ast_strlen_zero(S_COR(c->caller.id.number.valid, 00945 c->caller.id.number.str, NULL))) { 00946 /* 00947 * The new channel has no preset CallerID number by the channel 00948 * driver. Use the dialplan extension and hint name. 00949 */ 00950 caller.id = *stored_clid; 00951 ast_channel_set_caller_event(c, &caller, NULL); 00952 ast_set_flag64(o, DIAL_CALLERID_ABSENT); 00953 } else { 00954 ast_clear_flag64(o, DIAL_CALLERID_ABSENT); 00955 } 00956 00957 /* Determine CallerID for outgoing channel to send. */ 00958 if (ast_test_flag64(o, OPT_FORCECLID)) { 00959 struct ast_party_connected_line connected; 00960 00961 ast_party_connected_line_init(&connected); 00962 connected.id = *forced_clid; 00963 ast_party_connected_line_copy(&c->connected, &connected); 00964 } else { 00965 ast_connected_line_copy_from_caller(&c->connected, &in->caller); 00966 } 00967 00968 ast_string_field_set(c, accountcode, in->accountcode); 00969 00970 c->appl = "AppDial"; 00971 c->data = "(Outgoing Line)"; 00972 00973 ast_channel_unlock(in); 00974 if (single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { 00975 struct ast_party_redirecting redirecting; 00976 00977 /* 00978 * Redirecting updates to the caller make sense only on single 00979 * calls. 00980 * 00981 * We must unlock c before calling 00982 * ast_channel_redirecting_macro, because we put c into 00983 * autoservice there. That is pretty much a guaranteed 00984 * deadlock. This is why the handling of c's lock may seem a 00985 * bit unusual here. 00986 */ 00987 ast_party_redirecting_init(&redirecting); 00988 ast_party_redirecting_copy(&redirecting, &c->redirecting); 00989 ast_channel_unlock(c); 00990 if (ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) { 00991 ast_channel_update_redirecting(in, &redirecting, NULL); 00992 } 00993 ast_party_redirecting_free(&redirecting); 00994 } else { 00995 ast_channel_unlock(c); 00996 } 00997 00998 if (ast_test_flag64(peerflags, OPT_CANCEL_TIMEOUT)) { 00999 *to = -1; 01000 } 01001 01002 if (ast_call(c, stuff, 0)) { 01003 ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n", 01004 tech, stuff); 01005 ast_clear_flag64(o, DIAL_STILLGOING); 01006 ast_hangup(original); 01007 ast_hangup(c); 01008 c = o->chan = NULL; 01009 num->nochan++; 01010 } else { 01011 ast_channel_lock_both(c, in); 01012 senddialevent(in, c, stuff); 01013 ast_channel_unlock(in); 01014 ast_channel_unlock(c); 01015 /* Hangup the original channel now, in case we needed it */ 01016 ast_hangup(original); 01017 } 01018 if (single && !caller_entertained) { 01019 ast_indicate(in, -1); 01020 } 01021 } 01022 }
static void end_bridge_callback | ( | void * | data | ) | [static] |
Definition at line 1924 of file app_dial.c.
References ast_cdr::answer, ast_channel_lock, ast_channel_unlock, ast_channel::cdr, pbx_builtin_setvar_helper(), and ast_cdr::start.
Referenced by app_exec(), and dial_exec_full().
01925 { 01926 char buf[80]; 01927 time_t end; 01928 struct ast_channel *chan = data; 01929 01930 if (!chan->cdr) { 01931 return; 01932 } 01933 01934 time(&end); 01935 01936 ast_channel_lock(chan); 01937 if (chan->cdr->answer.tv_sec) { 01938 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec); 01939 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 01940 } 01941 01942 if (chan->cdr->start.tv_sec) { 01943 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec); 01944 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 01945 } 01946 ast_channel_unlock(chan); 01947 }
static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
struct ast_channel * | originator, | |||
struct ast_channel * | terminator | |||
) | [static] |
Definition at line 1949 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec(), and dial_exec_full().
01949 { 01950 bconfig->end_bridge_callback_data = originator; 01951 }
static const char* get_cid_name | ( | char * | name, | |
int | namelen, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 774 of file app_dial.c.
References ast_channel_lock, ast_channel_unlock, ast_get_hint(), ast_strdupa, ast_channel::context, context, ast_channel::exten, exten, ast_channel::macrocontext, ast_channel::macroexten, and S_OR.
Referenced by dial_exec_full().
00775 { 00776 const char *context; 00777 const char *exten; 00778 00779 ast_channel_lock(chan); 00780 context = ast_strdupa(S_OR(chan->macrocontext, chan->context)); 00781 exten = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 00782 ast_channel_unlock(chan); 00783 00784 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : ""; 00785 }
static void handle_cause | ( | int | cause, | |
struct cause_args * | num | |||
) | [static] |
Definition at line 717 of file app_dial.c.
References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNREGISTERED, ast_cdr_busy(), ast_cdr_failed(), ast_cdr_noanswer(), cause_args::busy, ast_channel::cdr, cause_args::chan, cause_args::congestion, and cause_args::nochan.
Referenced by __ast_request_and_dial(), ast_call_forward(), dial_exec_full(), and do_forward().
00718 { 00719 struct ast_cdr *cdr = num->chan->cdr; 00720 00721 switch(cause) { 00722 case AST_CAUSE_BUSY: 00723 if (cdr) 00724 ast_cdr_busy(cdr); 00725 num->busy++; 00726 break; 00727 00728 case AST_CAUSE_CONGESTION: 00729 if (cdr) 00730 ast_cdr_failed(cdr); 00731 num->congestion++; 00732 break; 00733 00734 case AST_CAUSE_NO_ROUTE_DESTINATION: 00735 case AST_CAUSE_UNREGISTERED: 00736 if (cdr) 00737 ast_cdr_failed(cdr); 00738 num->nochan++; 00739 break; 00740 00741 case AST_CAUSE_NO_ANSWER: 00742 if (cdr) { 00743 ast_cdr_noanswer(cdr); 00744 } 00745 break; 00746 case AST_CAUSE_NORMAL_CLEARING: 00747 break; 00748 00749 default: 00750 num->nochan++; 00751 break; 00752 } 00753 }
static void hanguptree | ( | struct chanlist * | outgoing, | |
struct ast_channel * | exception, | |||
int | answered_elsewhere | |||
) | [static] |
Definition at line 684 of file app_dial.c.
References AST_CAUSE_ANSWERED_ELSEWHERE, AST_FLAG_ANSWERED_ELSEWHERE, ast_hangup(), ast_set_flag, chanlist::chan, chanlist_free(), ast_channel::hangupcause, and chanlist::next.
Referenced by dial_exec_full().
00685 { 00686 /* Hang up a tree of stuff */ 00687 struct chanlist *oo; 00688 while (outgoing) { 00689 /* Hangup any existing lines we have open */ 00690 if (outgoing->chan && (outgoing->chan != exception)) { 00691 if (answered_elsewhere) { 00692 /* The flag is used for local channel inheritance and stuff */ 00693 ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE); 00694 /* This is for the channel drivers */ 00695 outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE; 00696 } 00697 ast_hangup(outgoing->chan); 00698 } 00699 oo = outgoing; 00700 outgoing = outgoing->next; 00701 chanlist_free(oo); 00702 } 00703 }
static int load_module | ( | void | ) | [static] |
Definition at line 3182 of file app_dial.c.
References ast_add_extension2(), ast_context_find_or_create(), ast_free_ptr, ast_log(), ast_register_application_xml, ast_strdup, dial_exec(), LOG_ERROR, and retrydial_exec().
03183 { 03184 int res; 03185 struct ast_context *con; 03186 03187 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial"); 03188 if (!con) 03189 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n"); 03190 else 03191 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial"); 03192 03193 res = ast_register_application_xml(app, dial_exec); 03194 res |= ast_register_application_xml(rapp, retrydial_exec); 03195 03196 return res; 03197 }
static int onedigit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
char | exten, | |||
int | pri | |||
) | [static] |
Definition at line 755 of file app_dial.c.
References ast_goto_if_exists(), ast_strlen_zero(), ast_channel::context, and ast_channel::macrocontext.
Referenced by retrydial_exec().
00756 { 00757 char rexten[2] = { exten, '\0' }; 00758 00759 if (context) { 00760 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00761 return 1; 00762 } else { 00763 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00764 return 1; 00765 else if (!ast_strlen_zero(chan->macrocontext)) { 00766 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00767 return 1; 00768 } 00769 } 00770 return 0; 00771 }
static void replace_macro_delimiter | ( | char * | s | ) | [static] |
static int retrydial_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3058 of file app_dial.c.
References args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_fileexists(), AST_FLAG_MOH, ast_log(), ast_moh_start(), ast_moh_stop(), AST_PBX_INCOMPLETE, AST_STANDARD_APP_ARGS, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_flag64, ast_waitfordigit(), ast_waitstream(), ast_channel::data, dial_exec_full(), LOG_ERROR, LOG_WARNING, onedigit_goto(), OPT_DTMF_EXIT, parse(), and pbx_builtin_getvar_helper().
Referenced by load_module().
03059 { 03060 char *parse; 03061 const char *context = NULL; 03062 int sleepms = 0, loops = 0, res = -1; 03063 struct ast_flags64 peerflags = { 0, }; 03064 AST_DECLARE_APP_ARGS(args, 03065 AST_APP_ARG(announce); 03066 AST_APP_ARG(sleep); 03067 AST_APP_ARG(retries); 03068 AST_APP_ARG(dialdata); 03069 ); 03070 03071 if (ast_strlen_zero(data)) { 03072 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 03073 return -1; 03074 } 03075 03076 parse = ast_strdupa(data); 03077 AST_STANDARD_APP_ARGS(args, parse); 03078 03079 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep))) 03080 sleepms *= 1000; 03081 03082 if (!ast_strlen_zero(args.retries)) { 03083 loops = atoi(args.retries); 03084 } 03085 03086 if (!args.dialdata) { 03087 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp); 03088 goto done; 03089 } 03090 03091 if (sleepms < 1000) 03092 sleepms = 10000; 03093 03094 if (!loops) 03095 loops = -1; /* run forever */ 03096 03097 ast_channel_lock(chan); 03098 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 03099 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL; 03100 ast_channel_unlock(chan); 03101 03102 res = 0; 03103 while (loops) { 03104 int continue_exec; 03105 03106 chan->data = "Retrying"; 03107 if (ast_test_flag(chan, AST_FLAG_MOH)) 03108 ast_moh_stop(chan); 03109 03110 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec); 03111 if (continue_exec) 03112 break; 03113 03114 if (res == 0) { 03115 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) { 03116 if (!ast_strlen_zero(args.announce)) { 03117 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 03118 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 03119 ast_waitstream(chan, AST_DIGIT_ANY); 03120 } else 03121 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 03122 } 03123 if (!res && sleepms) { 03124 if (!ast_test_flag(chan, AST_FLAG_MOH)) 03125 ast_moh_start(chan, NULL, NULL); 03126 res = ast_waitfordigit(chan, sleepms); 03127 } 03128 } else { 03129 if (!ast_strlen_zero(args.announce)) { 03130 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 03131 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 03132 res = ast_waitstream(chan, ""); 03133 } else 03134 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 03135 } 03136 if (sleepms) { 03137 if (!ast_test_flag(chan, AST_FLAG_MOH)) 03138 ast_moh_start(chan, NULL, NULL); 03139 if (!res) 03140 res = ast_waitfordigit(chan, sleepms); 03141 } 03142 } 03143 } 03144 03145 if (res < 0 || res == AST_PBX_INCOMPLETE) { 03146 break; 03147 } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 03148 if (onedigit_goto(chan, context, (char) res, 1)) { 03149 res = 0; 03150 break; 03151 } 03152 } 03153 loops--; 03154 } 03155 if (loops == 0) 03156 res = 0; 03157 else if (res == 1) 03158 res = 0; 03159 03160 if (ast_test_flag(chan, AST_FLAG_MOH)) 03161 ast_moh_stop(chan); 03162 done: 03163 return res; 03164 }
static void senddialendevent | ( | struct ast_channel * | src, | |
const char * | dialstatus | |||
) | [static] |
Definition at line 810 of file app_dial.c.
References ast_manager_event, EVENT_FLAG_CALL, ast_channel::name, and ast_channel::uniqueid.
Referenced by dial_exec_full().
00811 { 00812 ast_manager_event(src, EVENT_FLAG_CALL, "Dial", 00813 "SubEvent: End\r\n" 00814 "Channel: %s\r\n" 00815 "UniqueID: %s\r\n" 00816 "DialStatus: %s\r\n", 00817 src->name, src->uniqueid, dialstatus); 00818 }
static void senddialevent | ( | struct ast_channel * | src, | |
struct ast_channel * | dst, | |||
const char * | dialstring | |||
) | [static] |
Definition at line 787 of file app_dial.c.
References ast_manager_event_multichan, ast_channel::caller, ast_channel::connected, EVENT_FLAG_CALL, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_channel::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.
Referenced by dial_exec_full(), and do_forward().
00788 { 00789 struct ast_channel *chans[] = { src, dst }; 00790 ast_manager_event_multichan(EVENT_FLAG_CALL, "Dial", 2, chans, 00791 "SubEvent: Begin\r\n" 00792 "Channel: %s\r\n" 00793 "Destination: %s\r\n" 00794 "CallerIDNum: %s\r\n" 00795 "CallerIDName: %s\r\n" 00796 "ConnectedLineNum: %s\r\n" 00797 "ConnectedLineName: %s\r\n" 00798 "UniqueID: %s\r\n" 00799 "DestUniqueID: %s\r\n" 00800 "Dialstring: %s\r\n", 00801 src->name, dst->name, 00802 S_COR(src->caller.id.number.valid, src->caller.id.number.str, "<unknown>"), 00803 S_COR(src->caller.id.name.valid, src->caller.id.name.str, "<unknown>"), 00804 S_COR(src->connected.id.number.valid, src->connected.id.number.str, "<unknown>"), 00805 S_COR(src->connected.id.name.valid, src->connected.id.name.str, "<unknown>"), 00806 src->uniqueid, dst->uniqueid, 00807 dialstring ? dialstring : ""); 00808 }
static int setup_privacy_args | ( | struct privacy_args * | pa, | |
struct ast_flags64 * | opts, | |||
char * | opt_args[], | |||
struct ast_channel * | chan | |||
) | [static] |
returns 1 if successful, 0 or <0 if the caller should 'goto out'
Definition at line 1822 of file app_dial.c.
References ast_answer(), ast_config_AST_DATA_DIR, ast_copy_string(), ast_dsp_get_threshold_from_settings(), ast_filedelete(), ast_fileexists(), ast_log(), ast_mkdir(), 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_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag64, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::exten, ast_party_caller::id, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_party_id::number, OPT_ARG_PRIVACY, OPT_PRIVACY, OPT_SCREEN_NOCALLERID, privacy_args::privcid, privacy_args::privdb_val, privacy_args::privintro, silencethreshold, privacy_args::status, ast_party_number::str, THRESHOLD_SILENCE, and ast_party_number::valid.
Referenced by dial_exec_full().
01824 { 01825 char callerid[60]; 01826 int res; 01827 char *l; 01828 int silencethreshold; 01829 01830 if (chan->caller.id.number.valid 01831 && !ast_strlen_zero(chan->caller.id.number.str)) { 01832 l = ast_strdupa(chan->caller.id.number.str); 01833 ast_shrink_phone_number(l); 01834 if (ast_test_flag64(opts, OPT_PRIVACY) ) { 01835 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l); 01836 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l); 01837 } else { 01838 ast_verb(3, "Privacy Screening, clid is '%s'\n", l); 01839 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01840 } 01841 } else { 01842 char *tnam, *tn2; 01843 01844 tnam = ast_strdupa(chan->name); 01845 /* clean the channel name so slashes don't try to end up in disk file name */ 01846 for (tn2 = tnam; *tn2; tn2++) { 01847 if (*tn2 == '/') /* any other chars to be afraid of? */ 01848 *tn2 = '='; 01849 } 01850 ast_verb(3, "Privacy-- callerid is empty\n"); 01851 01852 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); 01853 l = callerid; 01854 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01855 } 01856 01857 ast_copy_string(pa->privcid, l, sizeof(pa->privcid)); 01858 01859 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) { 01860 /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */ 01861 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid); 01862 pa->privdb_val = AST_PRIVACY_ALLOW; 01863 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) { 01864 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val); 01865 } 01866 01867 if (pa->privdb_val == AST_PRIVACY_DENY) { 01868 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); 01869 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status)); 01870 return 0; 01871 } else if (pa->privdb_val == AST_PRIVACY_KILL) { 01872 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status)); 01873 return 0; /* Is this right? */ 01874 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) { 01875 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status)); 01876 return 0; /* is this right??? */ 01877 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) { 01878 /* Get the user's intro, store it in priv-callerintros/$CID, 01879 unless it is already there-- this should be done before the 01880 call is actually dialed */ 01881 01882 /* make sure the priv-callerintros dir actually exists */ 01883 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR); 01884 if ((res = ast_mkdir(pa->privintro, 0755))) { 01885 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res)); 01886 return -1; 01887 } 01888 01889 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); 01890 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) { 01891 /* the DELUX version of this code would allow this caller the 01892 option to hear and retape their previously recorded intro. 01893 */ 01894 } else { 01895 int duration; /* for feedback from play_and_wait */ 01896 /* the file doesn't exist yet. Let the caller submit his 01897 vocal intro for posterity */ 01898 /* priv-recordintro script: 01899 01900 "At the tone, please say your name:" 01901 01902 */ 01903 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE); 01904 ast_answer(chan); 01905 res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "sln", &duration, NULL, silencethreshold, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */ 01906 /* don't think we'll need a lock removed, we took care of 01907 conflicts by naming the pa.privintro file */ 01908 if (res == -1) { 01909 /* Delete the file regardless since they hung up during recording */ 01910 ast_filedelete(pa->privintro, NULL); 01911 if (ast_fileexists(pa->privintro, NULL, NULL) > 0) 01912 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro); 01913 else 01914 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro); 01915 return -1; 01916 } 01917 if (!ast_streamfile(chan, "vm-dialout", chan->language) ) 01918 ast_waitstream(chan, ""); 01919 } 01920 } 01921 return 1; /* success */ 01922 }
static int unload_module | ( | void | ) | [static] |
Definition at line 3166 of file app_dial.c.
References ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), and ast_unregister_application().
03167 { 03168 int res; 03169 struct ast_context *con; 03170 03171 res = ast_unregister_application(app); 03172 res |= ast_unregister_application(rapp); 03173 03174 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) { 03175 ast_context_remove_extension2(con, "s", 1, NULL, 0); 03176 ast_context_destroy(con, "app_dial"); /* leave nothing behind */ 03177 } 03178 03179 return res; 03180 }
static int valid_priv_reply | ( | struct ast_flags64 * | opts, | |
int | res | |||
) | [static] |
Definition at line 1676 of file app_dial.c.
References ast_test_flag64, OPT_PRIVACY, and OPT_SCREENING.
01677 { 01678 if (res < '1') 01679 return 0; 01680 if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5') 01681 return 1; 01682 if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4') 01683 return 1; 01684 return 0; 01685 }
static struct ast_channel* wait_for_answer | ( | struct ast_channel * | in, | |
struct chanlist * | outgoing, | |||
int * | to, | |||
struct ast_flags64 * | peerflags, | |||
char * | opt_args[], | |||
struct privacy_args * | pa, | |||
const struct cause_args * | num_in, | |||
int * | result, | |||
char * | dtmf_progress, | |||
const int | ignore_cc, | |||
struct ast_party_id * | forced_clid, | |||
struct ast_party_id * | stored_clid | |||
) | [static] |
Definition at line 1033 of file app_dial.c.
References ast_channel::_state, ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_cc_failed(), ast_cc_is_recall(), ast_cdr_failed(), ast_channel_connected_line_macro(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_AOC, ast_copy_flags64, ast_copy_string(), ast_deactivate_generator(), ast_indicate_data(), AST_MAX_WATCHERS, ast_party_connected_line_free(), ast_party_connected_line_init(), ast_poll_channel_add(), AST_STATE_UP, ast_str_alloca, ast_string_field_set, ast_test_flag64, ast_verb, ast_waitfor_n(), cause_args::busy, ast_channel::caller, chanlist::chan, cause_args::congestion, ast_channel::connected, DIAL_CALLERID_ABSENT, DIAL_NOFORWARDHTML, DIAL_STILLGOING, dialcontext, f, FEATURE_MAX_LEN, ast_channel::name, chanlist::next, cause_args::nochan, OPT_CALLEE_HANGUP, OPT_CALLEE_MIXMONITOR, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MIXMONITOR, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_IGNORE_CONNECTEDLINE, OPT_MUSICBACK, OPT_RINGBACK, ast_party_connected_line::source, and privacy_args::status.
Referenced by dial_exec_full().
01040 { 01041 struct cause_args num = *num_in; 01042 int prestart = num.busy + num.congestion + num.nochan; 01043 int orig = *to; 01044 struct ast_channel *peer = NULL; 01045 /* single is set if only one destination is enabled */ 01046 int single = outgoing && !outgoing->next; 01047 int caller_entertained = outgoing 01048 && ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK); 01049 #ifdef HAVE_EPOLL 01050 struct chanlist *epollo; 01051 #endif 01052 struct ast_party_connected_line connected_caller; 01053 struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1); 01054 int cc_recall_core_id; 01055 int is_cc_recall; 01056 int cc_frame_received = 0; 01057 int num_ringing = 0; 01058 01059 ast_party_connected_line_init(&connected_caller); 01060 if (single) { 01061 /* Turn off hold music, etc */ 01062 if (!caller_entertained) { 01063 ast_deactivate_generator(in); 01064 /* If we are calling a single channel, and not providing ringback or music, */ 01065 /* then, make them compatible for in-band tone purpose */ 01066 if (ast_channel_make_compatible(outgoing->chan, in) < 0) { 01067 /* If these channels can not be made compatible, 01068 * there is no point in continuing. The bridge 01069 * will just fail if it gets that far. 01070 */ 01071 *to = -1; 01072 strcpy(pa->status, "CONGESTION"); 01073 ast_cdr_failed(in->cdr); 01074 return NULL; 01075 } 01076 } 01077 01078 if (!ast_test_flag64(outgoing, OPT_IGNORE_CONNECTEDLINE) 01079 && !ast_test_flag64(outgoing, DIAL_CALLERID_ABSENT)) { 01080 ast_channel_lock(outgoing->chan); 01081 ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->caller); 01082 ast_channel_unlock(outgoing->chan); 01083 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01084 if (ast_channel_connected_line_macro(outgoing->chan, in, &connected_caller, 1, 0)) { 01085 ast_channel_update_connected_line(in, &connected_caller, NULL); 01086 } 01087 ast_party_connected_line_free(&connected_caller); 01088 } 01089 } 01090 01091 is_cc_recall = ast_cc_is_recall(in, &cc_recall_core_id, NULL); 01092 01093 #ifdef HAVE_EPOLL 01094 for (epollo = outgoing; epollo; epollo = epollo->next) 01095 ast_poll_channel_add(in, epollo->chan); 01096 #endif 01097 01098 while (*to && !peer) { 01099 struct chanlist *o; 01100 int pos = 0; /* how many channels do we handle */ 01101 int numlines = prestart; 01102 struct ast_channel *winner; 01103 struct ast_channel *watchers[AST_MAX_WATCHERS]; 01104 01105 watchers[pos++] = in; 01106 for (o = outgoing; o; o = o->next) { 01107 /* Keep track of important channels */ 01108 if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan) 01109 watchers[pos++] = o->chan; 01110 numlines++; 01111 } 01112 if (pos == 1) { /* only the input channel is available */ 01113 if (numlines == (num.busy + num.congestion + num.nochan)) { 01114 ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan); 01115 if (num.busy) 01116 strcpy(pa->status, "BUSY"); 01117 else if (num.congestion) 01118 strcpy(pa->status, "CONGESTION"); 01119 else if (num.nochan) 01120 strcpy(pa->status, "CHANUNAVAIL"); 01121 } else { 01122 ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan); 01123 } 01124 *to = 0; 01125 if (is_cc_recall) { 01126 ast_cc_failed(cc_recall_core_id, "Everyone is busy/congested for the recall. How sad"); 01127 } 01128 return NULL; 01129 } 01130 winner = ast_waitfor_n(watchers, pos, to); 01131 for (o = outgoing; o; o = o->next) { 01132 struct ast_frame *f; 01133 struct ast_channel *c = o->chan; 01134 01135 if (c == NULL) 01136 continue; 01137 if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) { 01138 if (!peer) { 01139 ast_verb(3, "%s answered %s\n", c->name, in->name); 01140 if (!single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { 01141 if (o->pending_connected_update) { 01142 if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { 01143 ast_channel_update_connected_line(in, &o->connected, NULL); 01144 } 01145 } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { 01146 ast_channel_lock(c); 01147 ast_connected_line_copy_from_caller(&connected_caller, &c->caller); 01148 ast_channel_unlock(c); 01149 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01150 if (ast_channel_connected_line_macro(c, in, &connected_caller, 1, 0)) { 01151 ast_channel_update_connected_line(in, &connected_caller, NULL); 01152 } 01153 ast_party_connected_line_free(&connected_caller); 01154 } 01155 } 01156 if (o->aoc_s_rate_list) { 01157 size_t encoded_size; 01158 struct ast_aoc_encoded *encoded; 01159 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) { 01160 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size); 01161 ast_aoc_destroy_encoded(encoded); 01162 } 01163 } 01164 peer = c; 01165 ast_copy_flags64(peerflags, o, 01166 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01167 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01168 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01169 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01170 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01171 DIAL_NOFORWARDHTML); 01172 ast_string_field_set(c, dialcontext, ""); 01173 ast_copy_string(c->exten, "", sizeof(c->exten)); 01174 } 01175 continue; 01176 } 01177 if (c != winner) 01178 continue; 01179 /* here, o->chan == c == winner */ 01180 if (!ast_strlen_zero(c->call_forward)) { 01181 pa->sentringing = 0; 01182 if (!ignore_cc && (f = ast_read(c))) { 01183 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_CC) { 01184 /* This channel is forwarding the call, and is capable of CC, so 01185 * be sure to add the new device interface to the list 01186 */ 01187 ast_handle_cc_control_frame(in, c, f->data.ptr); 01188 } 01189 ast_frfree(f); 01190 } 01191 01192 if (o->pending_connected_update) { 01193 /* 01194 * Re-seed the chanlist's connected line information with 01195 * previously acquired connected line info from the incoming 01196 * channel. The previously acquired connected line info could 01197 * have been set through the CONNECTED_LINE dialplan function. 01198 */ 01199 o->pending_connected_update = 0; 01200 ast_channel_lock(in); 01201 ast_party_connected_line_copy(&o->connected, &in->connected); 01202 ast_channel_unlock(in); 01203 } 01204 01205 do_forward(o, &num, peerflags, single, caller_entertained, to, 01206 forced_clid, stored_clid); 01207 01208 if (single && o->chan 01209 && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE) 01210 && !ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { 01211 ast_channel_lock(o->chan); 01212 ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller); 01213 ast_channel_unlock(o->chan); 01214 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01215 if (ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) { 01216 ast_channel_update_connected_line(in, &connected_caller, NULL); 01217 } 01218 ast_party_connected_line_free(&connected_caller); 01219 } 01220 continue; 01221 } 01222 f = ast_read(winner); 01223 if (!f) { 01224 in->hangupcause = c->hangupcause; 01225 #ifdef HAVE_EPOLL 01226 ast_poll_channel_del(in, c); 01227 #endif 01228 ast_hangup(c); 01229 c = o->chan = NULL; 01230 ast_clear_flag64(o, DIAL_STILLGOING); 01231 handle_cause(in->hangupcause, &num); 01232 continue; 01233 } 01234 switch (f->frametype) { 01235 case AST_FRAME_CONTROL: 01236 switch (f->subclass.integer) { 01237 case AST_CONTROL_ANSWER: 01238 /* This is our guy if someone answered. */ 01239 if (!peer) { 01240 ast_verb(3, "%s answered %s\n", c->name, in->name); 01241 if (!single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { 01242 if (o->pending_connected_update) { 01243 if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { 01244 ast_channel_update_connected_line(in, &o->connected, NULL); 01245 } 01246 } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { 01247 ast_channel_lock(c); 01248 ast_connected_line_copy_from_caller(&connected_caller, &c->caller); 01249 ast_channel_unlock(c); 01250 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01251 if (ast_channel_connected_line_macro(c, in, &connected_caller, 1, 0)) { 01252 ast_channel_update_connected_line(in, &connected_caller, NULL); 01253 } 01254 ast_party_connected_line_free(&connected_caller); 01255 } 01256 } 01257 if (o->aoc_s_rate_list) { 01258 size_t encoded_size; 01259 struct ast_aoc_encoded *encoded; 01260 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) { 01261 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size); 01262 ast_aoc_destroy_encoded(encoded); 01263 } 01264 } 01265 peer = c; 01266 if (peer->cdr) { 01267 peer->cdr->answer = ast_tvnow(); 01268 peer->cdr->disposition = AST_CDR_ANSWERED; 01269 } 01270 ast_copy_flags64(peerflags, o, 01271 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01272 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01273 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01274 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01275 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01276 DIAL_NOFORWARDHTML); 01277 ast_string_field_set(c, dialcontext, ""); 01278 ast_copy_string(c->exten, "", sizeof(c->exten)); 01279 if (CAN_EARLY_BRIDGE(peerflags, in, peer)) 01280 /* Setup early bridge if appropriate */ 01281 ast_channel_early_bridge(in, peer); 01282 } 01283 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 01284 in->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01285 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01286 break; 01287 case AST_CONTROL_BUSY: 01288 ast_verb(3, "%s is busy\n", c->name); 01289 in->hangupcause = c->hangupcause; 01290 ast_hangup(c); 01291 c = o->chan = NULL; 01292 ast_clear_flag64(o, DIAL_STILLGOING); 01293 handle_cause(AST_CAUSE_BUSY, &num); 01294 break; 01295 case AST_CONTROL_CONGESTION: 01296 ast_verb(3, "%s is circuit-busy\n", c->name); 01297 in->hangupcause = c->hangupcause; 01298 ast_hangup(c); 01299 c = o->chan = NULL; 01300 ast_clear_flag64(o, DIAL_STILLGOING); 01301 handle_cause(AST_CAUSE_CONGESTION, &num); 01302 break; 01303 case AST_CONTROL_RINGING: 01304 /* This is a tricky area to get right when using a native 01305 * CC agent. The reason is that we do the best we can to send only a 01306 * single ringing notification to the caller. 01307 * 01308 * Call completion complicates the logic used here. CCNR is typically 01309 * offered during a ringing message. Let's say that party A calls 01310 * parties B, C, and D. B and C do not support CC requests, but D 01311 * does. If we were to receive a ringing notification from B before 01312 * the others, then we would end up sending a ringing message to 01313 * A with no CCNR offer present. 01314 * 01315 * The approach that we have taken is that if we receive a ringing 01316 * response from a party and no CCNR offer is present, we need to 01317 * wait. Specifically, we need to wait until either a) a called party 01318 * offers CCNR in its ringing response or b) all called parties have 01319 * responded in some way to our call and none offers CCNR. 01320 * 01321 * The drawback to this is that if one of the parties has a delayed 01322 * response or, god forbid, one just plain doesn't respond to our 01323 * outgoing call, then this will result in a significant delay between 01324 * when the caller places the call and hears ringback. 01325 * 01326 * Note also that if CC is disabled for this call, then it is perfectly 01327 * fine for ringing frames to get sent through. 01328 */ 01329 ++num_ringing; 01330 if (ignore_cc || cc_frame_received || num_ringing == numlines) { 01331 ast_verb(3, "%s is ringing\n", c->name); 01332 /* Setup early media if appropriate */ 01333 if (single && !caller_entertained 01334 && CAN_EARLY_BRIDGE(peerflags, in, c)) { 01335 ast_channel_early_bridge(in, c); 01336 } 01337 if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 01338 ast_indicate(in, AST_CONTROL_RINGING); 01339 pa->sentringing++; 01340 } 01341 } 01342 break; 01343 case AST_CONTROL_PROGRESS: 01344 ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name); 01345 /* Setup early media if appropriate */ 01346 if (single && !caller_entertained 01347 && CAN_EARLY_BRIDGE(peerflags, in, c)) { 01348 ast_channel_early_bridge(in, c); 01349 } 01350 if (!ast_test_flag64(outgoing, OPT_RINGBACK)) { 01351 if (single || (!single && !pa->sentringing)) { 01352 ast_indicate(in, AST_CONTROL_PROGRESS); 01353 } 01354 } 01355 if (!ast_strlen_zero(dtmf_progress)) { 01356 ast_verb(3, 01357 "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", 01358 dtmf_progress); 01359 ast_dtmf_stream(c, in, dtmf_progress, 250, 0); 01360 } 01361 break; 01362 case AST_CONTROL_VIDUPDATE: 01363 case AST_CONTROL_SRCUPDATE: 01364 case AST_CONTROL_SRCCHANGE: 01365 if (!single || caller_entertained) { 01366 break; 01367 } 01368 ast_verb(3, "%s requested media update control %d, passing it to %s\n", 01369 c->name, f->subclass.integer, in->name); 01370 ast_indicate(in, f->subclass.integer); 01371 break; 01372 case AST_CONTROL_CONNECTED_LINE: 01373 if (ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { 01374 ast_verb(3, "Connected line update to %s prevented.\n", in->name); 01375 break; 01376 } 01377 if (!single) { 01378 struct ast_party_connected_line connected; 01379 01380 ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", 01381 c->name, in->name); 01382 ast_party_connected_line_set_init(&connected, &o->connected); 01383 ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected); 01384 ast_party_connected_line_set(&o->connected, &connected, NULL); 01385 ast_party_connected_line_free(&connected); 01386 o->pending_connected_update = 1; 01387 break; 01388 } 01389 if (ast_channel_connected_line_macro(c, in, f, 1, 1)) { 01390 ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen); 01391 } 01392 break; 01393 case AST_CONTROL_AOC: 01394 { 01395 struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan); 01396 if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) { 01397 ast_aoc_destroy_decoded(o->aoc_s_rate_list); 01398 o->aoc_s_rate_list = decoded; 01399 } else { 01400 ast_aoc_destroy_decoded(decoded); 01401 } 01402 } 01403 break; 01404 case AST_CONTROL_REDIRECTING: 01405 if (!single) { 01406 /* 01407 * Redirecting updates to the caller make sense only on single 01408 * calls. 01409 */ 01410 break; 01411 } 01412 if (ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { 01413 ast_verb(3, "Redirecting update to %s prevented.\n", in->name); 01414 break; 01415 } 01416 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", 01417 c->name, in->name); 01418 if (ast_channel_redirecting_macro(c, in, f, 1, 1)) { 01419 ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); 01420 } 01421 pa->sentringing = 0; 01422 break; 01423 case AST_CONTROL_PROCEEDING: 01424 ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name); 01425 if (single && !caller_entertained 01426 && CAN_EARLY_BRIDGE(peerflags, in, c)) { 01427 ast_channel_early_bridge(in, c); 01428 } 01429 if (!ast_test_flag64(outgoing, OPT_RINGBACK)) 01430 ast_indicate(in, AST_CONTROL_PROCEEDING); 01431 break; 01432 case AST_CONTROL_HOLD: 01433 /* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */ 01434 ast_verb(3, "Call on %s placed on hold\n", c->name); 01435 ast_indicate_data(in, AST_CONTROL_HOLD, f->data.ptr, f->datalen); 01436 break; 01437 case AST_CONTROL_UNHOLD: 01438 /* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */ 01439 ast_verb(3, "Call on %s left from hold\n", c->name); 01440 ast_indicate(in, AST_CONTROL_UNHOLD); 01441 break; 01442 case AST_CONTROL_OFFHOOK: 01443 case AST_CONTROL_FLASH: 01444 /* Ignore going off hook and flash */ 01445 break; 01446 case AST_CONTROL_CC: 01447 if (!ignore_cc) { 01448 ast_handle_cc_control_frame(in, c, f->data.ptr); 01449 cc_frame_received = 1; 01450 } 01451 break; 01452 case -1: 01453 if (single && !caller_entertained) { 01454 ast_verb(3, "%s stopped sounds\n", c->name); 01455 ast_indicate(in, -1); 01456 pa->sentringing = 0; 01457 } 01458 break; 01459 default: 01460 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer); 01461 break; 01462 } 01463 break; 01464 case AST_FRAME_VOICE: 01465 case AST_FRAME_IMAGE: 01466 if (caller_entertained) { 01467 break; 01468 } 01469 /* Fall through */ 01470 case AST_FRAME_TEXT: 01471 if (single && ast_write(in, f)) { 01472 ast_log(LOG_WARNING, "Unable to write frametype: %d\n", 01473 f->frametype); 01474 } 01475 break; 01476 case AST_FRAME_HTML: 01477 if (single && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) 01478 && ast_channel_sendhtml(in, f->subclass.integer, f->data.ptr, f->datalen) == -1) { 01479 ast_log(LOG_WARNING, "Unable to send URL\n"); 01480 } 01481 break; 01482 default: 01483 break; 01484 } 01485 ast_frfree(f); 01486 } /* end for */ 01487 if (winner == in) { 01488 struct ast_frame *f = ast_read(in); 01489 #if 0 01490 if (f && (f->frametype != AST_FRAME_VOICE)) 01491 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 01492 else if (!f || (f->frametype != AST_FRAME_VOICE)) 01493 printf("Hangup received on %s\n", in->name); 01494 #endif 01495 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) { 01496 /* Got hung up */ 01497 *to = -1; 01498 strcpy(pa->status, "CANCEL"); 01499 ast_cdr_noanswer(in->cdr); 01500 if (f) { 01501 if (f->data.uint32) { 01502 in->hangupcause = f->data.uint32; 01503 } 01504 ast_frfree(f); 01505 } 01506 if (is_cc_recall) { 01507 ast_cc_completed(in, "CC completed, although the caller hung up (cancelled)"); 01508 } 01509 return NULL; 01510 } 01511 01512 /* now f is guaranteed non-NULL */ 01513 if (f->frametype == AST_FRAME_DTMF) { 01514 if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) { 01515 const char *context; 01516 ast_channel_lock(in); 01517 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 01518 if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) { 01519 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer); 01520 *to = 0; 01521 ast_cdr_noanswer(in->cdr); 01522 *result = f->subclass.integer; 01523 strcpy(pa->status, "CANCEL"); 01524 ast_frfree(f); 01525 ast_channel_unlock(in); 01526 if (is_cc_recall) { 01527 ast_cc_completed(in, "CC completed, but the caller used DTMF to exit"); 01528 } 01529 return NULL; 01530 } 01531 ast_channel_unlock(in); 01532 } 01533 01534 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && 01535 detect_disconnect(in, f->subclass.integer, featurecode)) { 01536 ast_verb(3, "User requested call disconnect.\n"); 01537 *to = 0; 01538 strcpy(pa->status, "CANCEL"); 01539 ast_cdr_noanswer(in->cdr); 01540 ast_frfree(f); 01541 if (is_cc_recall) { 01542 ast_cc_completed(in, "CC completed, but the caller hung up with DTMF"); 01543 } 01544 return NULL; 01545 } 01546 } 01547 01548 /* Send the frame from the in channel to all outgoing channels. */ 01549 for (o = outgoing; o; o = o->next) { 01550 if (!o->chan || !ast_test_flag64(o, DIAL_STILLGOING)) { 01551 /* This outgoing channel has died so don't send the frame to it. */ 01552 continue; 01553 } 01554 switch (f->frametype) { 01555 case AST_FRAME_HTML: 01556 /* Forward HTML stuff */ 01557 if (!ast_test_flag64(o, DIAL_NOFORWARDHTML) 01558 && ast_channel_sendhtml(o->chan, f->subclass.integer, f->data.ptr, f->datalen) == -1) { 01559 ast_log(LOG_WARNING, "Unable to send URL\n"); 01560 } 01561 break; 01562 case AST_FRAME_VOICE: 01563 case AST_FRAME_IMAGE: 01564 if (!single || caller_entertained) { 01565 /* 01566 * We are calling multiple parties or caller is being 01567 * entertained and has thus not been made compatible. 01568 * No need to check any other called parties. 01569 */ 01570 goto skip_frame; 01571 } 01572 /* Fall through */ 01573 case AST_FRAME_TEXT: 01574 case AST_FRAME_DTMF_BEGIN: 01575 case AST_FRAME_DTMF_END: 01576 if (ast_write(o->chan, f)) { 01577 ast_log(LOG_WARNING, "Unable to forward frametype: %d\n", 01578 f->frametype); 01579 } 01580 break; 01581 case AST_FRAME_CONTROL: 01582 switch (f->subclass.integer) { 01583 case AST_CONTROL_HOLD: 01584 ast_verb(3, "Call on %s placed on hold\n", o->chan->name); 01585 ast_indicate_data(o->chan, AST_CONTROL_HOLD, f->data.ptr, f->datalen); 01586 break; 01587 case AST_CONTROL_UNHOLD: 01588 ast_verb(3, "Call on %s left from hold\n", o->chan->name); 01589 ast_indicate(o->chan, AST_CONTROL_UNHOLD); 01590 break; 01591 case AST_CONTROL_VIDUPDATE: 01592 case AST_CONTROL_SRCUPDATE: 01593 case AST_CONTROL_SRCCHANGE: 01594 if (!single || caller_entertained) { 01595 /* 01596 * We are calling multiple parties or caller is being 01597 * entertained and has thus not been made compatible. 01598 * No need to check any other called parties. 01599 */ 01600 goto skip_frame; 01601 } 01602 ast_verb(3, "%s requested media update control %d, passing it to %s\n", 01603 in->name, f->subclass.integer, o->chan->name); 01604 ast_indicate(o->chan, f->subclass.integer); 01605 break; 01606 case AST_CONTROL_CONNECTED_LINE: 01607 if (ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) { 01608 ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen); 01609 } 01610 break; 01611 case AST_CONTROL_REDIRECTING: 01612 if (ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) { 01613 ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen); 01614 } 01615 break; 01616 default: 01617 /* We are not going to do anything with this frame. */ 01618 goto skip_frame; 01619 } 01620 break; 01621 default: 01622 /* We are not going to do anything with this frame. */ 01623 goto skip_frame; 01624 } 01625 } 01626 skip_frame:; 01627 ast_frfree(f); 01628 } 01629 if (!*to) 01630 ast_verb(3, "Nobody picked up in %d ms\n", orig); 01631 if (!*to || ast_check_hangup(in)) 01632 ast_cdr_noanswer(in->cdr); 01633 } 01634 01635 #ifdef HAVE_EPOLL 01636 for (epollo = outgoing; epollo; epollo = epollo->next) { 01637 if (epollo->chan) 01638 ast_poll_channel_del(in, epollo->chan); 01639 } 01640 #endif 01641 01642 if (is_cc_recall) { 01643 ast_cc_completed(in, "Recall completed!"); 01644 } 01645 return peer; 01646 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialing Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 3199 of file app_dial.c.
const char app[] = "Dial" [static] |
Definition at line 542 of file app_dial.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3199 of file app_dial.c.
struct ast_app_option dial_exec_options[128] = { [ 'A' ] = { .flag = OPT_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'a' ] = { .flag = (1LLU << 40) }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'c' ] = { .flag = (1LLU << 34) }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'e' ] = { .flag = (1LLU << 35) }, [ 'f' ] = { .flag = OPT_FORCECLID , .arg_index = OPT_ARG_FORCECLID + 1 }, [ 'F' ] = { .flag = (1LLU << 36) , .arg_index = OPT_ARG_CALLEE_GO_ON + 1 }, [ 'g' ] = { .flag = OPT_GO_ON }, [ 'G' ] = { .flag = OPT_GOTO , .arg_index = OPT_ARG_GOTO + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'i' ] = { .flag = OPT_IGNORE_FORWARDING }, [ 'I' ] = { .flag = OPT_IGNORE_CONNECTEDLINE }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'm' ] = { .flag = OPT_MUSICBACK , .arg_index = OPT_ARG_MUSICBACK + 1 }, [ 'M' ] = { .flag = OPT_CALLEE_MACRO , .arg_index = OPT_ARG_CALLEE_MACRO + 1 }, [ 'n' ] = { .flag = OPT_SCREEN_NOINTRO , .arg_index = OPT_ARG_SCREEN_NOINTRO + 1 }, [ 'N' ] = { .flag = OPT_SCREEN_NOCALLERID }, [ 'o' ] = { .flag = OPT_ORIGINAL_CLID , .arg_index = OPT_ARG_ORIGINAL_CLID + 1 }, [ 'O' ] = { .flag = OPT_OPERMODE , .arg_index = OPT_ARG_OPERMODE + 1 }, [ 'p' ] = { .flag = OPT_SCREENING }, [ 'P' ] = { .flag = OPT_PRIVACY , .arg_index = OPT_ARG_PRIVACY + 1 }, [ 'r' ] = { .flag = OPT_RINGBACK , .arg_index = OPT_ARG_RINGBACK + 1 }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 's' ] = { .flag = (1LLU << 38) , .arg_index = OPT_ARG_FORCE_CID_TAG + 1 }, [ 'u' ] = { .flag = (1LLU << 39) , .arg_index = OPT_ARG_FORCE_CID_PRES + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'U' ] = { .flag = OPT_CALLEE_GOSUB , .arg_index = OPT_ARG_CALLEE_GOSUB + 1 }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR }, [ 'x' ] = { .flag = OPT_CALLEE_MIXMONITOR }, [ 'X' ] = { .flag = OPT_CALLER_MIXMONITOR }, [ 'z' ] = { .flag = (1LLU << 37) }, } [static] |
const char rapp[] = "RetryDial" [static] |
Definition at line 543 of file app_dial.c.