#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"
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 ((uint64_t)1 << 33) |
#define | DIAL_NOFORWARDHTML ((uint64_t)1 << 32) |
#define | DIAL_STILLGOING (1 << 31) |
#define | OPT_CALLEE_GO_ON ((uint64_t)1 << 36) |
#define | OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 34) |
#define | OPT_CANCEL_TIMEOUT ((uint64_t)1 << 37) |
#define | OPT_FORCE_CID_PRES ((uint64_t)1 << 39) |
#define | OPT_FORCE_CID_TAG ((uint64_t)1 << 38) |
#define | OPT_PEER_H ((uint64_t)1 << 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_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), OPT_CALLER_ANSWER = (1 << 31) } |
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 *to) |
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) |
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 = OPT_CALLER_ANSWER }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'c' ] = { .flag = ((uint64_t)1 << 34) }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'e' ] = { .flag = ((uint64_t)1 << 35) }, [ 'f' ] = { .flag = OPT_FORCECLID , .arg_index = OPT_ARG_FORCECLID + 1 }, [ 'F' ] = { .flag = ((uint64_t)1 << 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 }, [ '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 = ((uint64_t)1 << 38) , .arg_index = OPT_ARG_FORCE_CID_TAG + 1 }, [ 'u' ] = { .flag = ((uint64_t)1 << 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 = ((uint64_t)1 << 37) }, } |
static const char | rapp [] = "RetryDial" |
Definition in file app_dial.c.
#define AST_MAX_WATCHERS 256 |
#define CAN_EARLY_BRIDGE | ( | flags, | |||
chan, | |||||
peer | ) |
Value:
(!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \ OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \ OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | \ OPT_CALLER_PARK | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB) && \ !chan->audiohooks && !peer->audiohooks)
Definition at line 625 of file app_dial.c.
Referenced by dial_exec_full(), and do_forward().
#define DIAL_CALLERID_ABSENT ((uint64_t)1 << 33) |
#define DIAL_NOFORWARDHTML ((uint64_t)1 << 32) |
#define DIAL_STILLGOING (1 << 31) |
Definition at line 553 of file app_dial.c.
Referenced by dial_exec_full(), do_forward(), and wait_for_answer().
#define OPT_CALLEE_GO_ON ((uint64_t)1 << 36) |
#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 34) |
#define OPT_CANCEL_TIMEOUT ((uint64_t)1 << 37) |
#define OPT_FORCE_CID_PRES ((uint64_t)1 << 39) |
#define OPT_FORCE_CID_TAG ((uint64_t)1 << 38) |
#define OPT_PEER_H ((uint64_t)1 << 35) |
anonymous enum |
Definition at line 563 of file app_dial.c.
00563 { 00564 OPT_ARG_ANNOUNCE = 0, 00565 OPT_ARG_SENDDTMF, 00566 OPT_ARG_GOTO, 00567 OPT_ARG_DURATION_LIMIT, 00568 OPT_ARG_MUSICBACK, 00569 OPT_ARG_CALLEE_MACRO, 00570 OPT_ARG_RINGBACK, 00571 OPT_ARG_CALLEE_GOSUB, 00572 OPT_ARG_CALLEE_GO_ON, 00573 OPT_ARG_PRIVACY, 00574 OPT_ARG_DURATION_STOP, 00575 OPT_ARG_OPERMODE, 00576 OPT_ARG_SCREEN_NOINTRO, 00577 OPT_ARG_FORCECLID, 00578 OPT_ARG_FORCE_CID_TAG, 00579 OPT_ARG_FORCE_CID_PRES, 00580 /* note: this entry _MUST_ be the last one in the enum */ 00581 OPT_ARG_ARRAY_SIZE, 00582 };
anonymous enum |
Definition at line 518 of file app_dial.c.
00518 { 00519 OPT_ANNOUNCE = (1 << 0), 00520 OPT_RESETCDR = (1 << 1), 00521 OPT_DTMF_EXIT = (1 << 2), 00522 OPT_SENDDTMF = (1 << 3), 00523 OPT_FORCECLID = (1 << 4), 00524 OPT_GO_ON = (1 << 5), 00525 OPT_CALLEE_HANGUP = (1 << 6), 00526 OPT_CALLER_HANGUP = (1 << 7), 00527 OPT_ORIGINAL_CLID = (1 << 8), 00528 OPT_DURATION_LIMIT = (1 << 9), 00529 OPT_MUSICBACK = (1 << 10), 00530 OPT_CALLEE_MACRO = (1 << 11), 00531 OPT_SCREEN_NOINTRO = (1 << 12), 00532 OPT_SCREEN_NOCALLERID = (1 << 13), 00533 OPT_IGNORE_CONNECTEDLINE = (1 << 14), 00534 OPT_SCREENING = (1 << 15), 00535 OPT_PRIVACY = (1 << 16), 00536 OPT_RINGBACK = (1 << 17), 00537 OPT_DURATION_STOP = (1 << 18), 00538 OPT_CALLEE_TRANSFER = (1 << 19), 00539 OPT_CALLER_TRANSFER = (1 << 20), 00540 OPT_CALLEE_MONITOR = (1 << 21), 00541 OPT_CALLER_MONITOR = (1 << 22), 00542 OPT_GOTO = (1 << 23), 00543 OPT_OPERMODE = (1 << 24), 00544 OPT_CALLEE_PARK = (1 << 25), 00545 OPT_CALLER_PARK = (1 << 26), 00546 OPT_IGNORE_FORWARDING = (1 << 27), 00547 OPT_CALLEE_GOSUB = (1 << 28), 00548 OPT_CALLEE_MIXMONITOR = (1 << 29), 00549 OPT_CALLER_MIXMONITOR = (1 << 30), 00550 OPT_CALLER_ANSWER = (1 << 31), 00551 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 2885 of file app_dial.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2885 of file app_dial.c.
static void chanlist_free | ( | struct chanlist * | outgoing | ) | [static] |
Definition at line 647 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().
00648 { 00649 ast_party_connected_line_free(&outgoing->connected); 00650 ast_aoc_destroy_decoded(outgoing->aoc_s_rate_list); 00651 ast_free(outgoing); 00652 }
static int detect_disconnect | ( | struct ast_channel * | chan, | |
char | code, | |||
struct ast_str * | featurecode | |||
) | [static] |
Definition at line 1450 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.
01451 { 01452 struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */ 01453 struct ast_call_feature feature = { 0, }; 01454 int res; 01455 01456 ast_str_append(&featurecode, 1, "%c", code); 01457 01458 res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature); 01459 01460 if (res != AST_FEATURE_RETURN_STOREDIGITS) { 01461 ast_str_reset(featurecode); 01462 } 01463 if (feature.feature_mask & AST_FEATURE_DISCONNECT) { 01464 return 1; 01465 } 01466 01467 return 0; 01468 }
static int dial_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 2735 of file app_dial.c.
References dial_exec_full().
Referenced by load_module().
02736 { 02737 struct ast_flags64 peerflags; 02738 02739 memset(&peerflags, 0, sizeof(peerflags)); 02740 02741 return dial_exec_full(chan, data, &peerflags, NULL); 02742 }
static int dial_exec_full | ( | struct ast_channel * | chan, | |
const char * | data, | |||
struct ast_flags64 * | peerflags, | |||
int * | continue_exec | |||
) | [static] |
Definition at line 1785 of file app_dial.c.
References __ast_answer(), ast_channel::_state, ast_channel::accountcode, ast_channel::adsicpe, ast_party_connected_line::ani, ast_party_caller::ani, 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_CAUSE_INVALID_NUMBER_FORMAT, 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_redirecting_copy(), AST_PBX_GOTO_FAILED, 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_callerid(), 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, cid_name, cid_num, 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_channel::nativeformats, ast_party_dialed::number, 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_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_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_number::str, ast_party_dialed::str, ast_channel::stream, strsep(), ast_frame::subclass, ast_channel::tech, ast_channel::timingfunc, ast_channel::transfercapability, ast_party_dialed::transit_network_select, url, ast_party_number::valid, wait_for_answer(), and ast_channel::whentohangup.
Referenced by dial_exec(), and retrydial_exec().
01786 { 01787 int res = -1; /* default: error */ 01788 char *rest, *cur; /* scan the list of destinations */ 01789 struct chanlist *outgoing = NULL; /* list of destinations */ 01790 struct ast_channel *peer; 01791 int to; /* timeout */ 01792 struct cause_args num = { chan, 0, 0, 0 }; 01793 int cause; 01794 char numsubst[256]; 01795 char *cid_num = NULL, *cid_name = NULL, *cid_tag = NULL, *cid_pres = NULL; 01796 01797 struct ast_bridge_config config = { { 0, } }; 01798 struct timeval calldurationlimit = { 0, }; 01799 char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL; 01800 struct privacy_args pa = { 01801 .sentringing = 0, 01802 .privdb_val = 0, 01803 .status = "INVALIDARGS", 01804 }; 01805 int sentringing = 0, moh = 0; 01806 const char *outbound_group = NULL; 01807 int result = 0; 01808 char *parse; 01809 int opermode = 0; 01810 int delprivintro = 0; 01811 AST_DECLARE_APP_ARGS(args, 01812 AST_APP_ARG(peers); 01813 AST_APP_ARG(timeout); 01814 AST_APP_ARG(options); 01815 AST_APP_ARG(url); 01816 ); 01817 struct ast_flags64 opts = { 0, }; 01818 char *opt_args[OPT_ARG_ARRAY_SIZE]; 01819 struct ast_datastore *datastore = NULL; 01820 int fulldial = 0, num_dialed = 0; 01821 int ignore_cc = 0; 01822 char device_name[AST_CHANNEL_NAME]; 01823 01824 /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */ 01825 pbx_builtin_setvar_helper(chan, "DIALSTATUS", ""); 01826 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); 01827 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ""); 01828 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); 01829 pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); 01830 01831 if (ast_strlen_zero(data)) { 01832 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01833 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01834 return -1; 01835 } 01836 01837 parse = ast_strdupa(data); 01838 01839 AST_STANDARD_APP_ARGS(args, parse); 01840 01841 if (!ast_strlen_zero(args.options) && 01842 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) { 01843 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01844 goto done; 01845 } 01846 01847 if (ast_strlen_zero(args.peers)) { 01848 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01849 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01850 goto done; 01851 } 01852 01853 if (ast_cc_call_init(chan, &ignore_cc)) { 01854 goto done; 01855 } 01856 01857 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) { 01858 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]); 01859 01860 if (delprivintro < 0 || delprivintro > 1) { 01861 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro); 01862 delprivintro = 0; 01863 } 01864 } 01865 01866 if (!ast_test_flag64(&opts, OPT_RINGBACK)) { 01867 opt_args[OPT_ARG_RINGBACK] = NULL; 01868 } 01869 01870 if (ast_test_flag64(&opts, OPT_OPERMODE)) { 01871 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]); 01872 ast_verb(3, "Setting operator services mode to %d.\n", opermode); 01873 } 01874 01875 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) { 01876 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]); 01877 if (!calldurationlimit.tv_sec) { 01878 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]); 01879 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01880 goto done; 01881 } 01882 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0); 01883 } 01884 01885 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { 01886 dtmf_progress = opt_args[OPT_ARG_SENDDTMF]; 01887 dtmfcalled = strsep(&dtmf_progress, ":"); 01888 dtmfcalling = strsep(&dtmf_progress, ":"); 01889 } 01890 01891 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { 01892 if (ast_bridge_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) 01893 goto done; 01894 } 01895 01896 if (ast_test_flag64(&opts, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) 01897 ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &cid_name, &cid_num); 01898 if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) 01899 cid_tag = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_TAG]); 01900 if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) 01901 cid_pres = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_PRES]); 01902 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr) 01903 ast_cdr_reset(chan->cdr, NULL); 01904 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) 01905 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten); 01906 01907 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) { 01908 res = setup_privacy_args(&pa, &opts, opt_args, chan); 01909 if (res <= 0) 01910 goto out; 01911 res = -1; /* reset default */ 01912 } 01913 01914 if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) { 01915 __ast_answer(chan, 0, 0); 01916 } 01917 01918 if (continue_exec) 01919 *continue_exec = 0; 01920 01921 /* If a channel group has been specified, get it for use when we create peer channels */ 01922 01923 ast_channel_lock(chan); 01924 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) { 01925 outbound_group = ast_strdupa(outbound_group); 01926 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL); 01927 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) { 01928 outbound_group = ast_strdupa(outbound_group); 01929 } 01930 ast_channel_unlock(chan); 01931 ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE | 01932 OPT_CANCEL_TIMEOUT | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID); 01933 01934 /* loop through the list of dial destinations */ 01935 rest = args.peers; 01936 while ((cur = strsep(&rest, "&")) ) { 01937 struct chanlist *tmp; 01938 struct ast_channel *tc; /* channel for this destination */ 01939 /* Get a technology/[device:]number pair */ 01940 char *number = cur; 01941 char *interface = ast_strdupa(number); 01942 char *tech = strsep(&number, "/"); 01943 /* find if we already dialed this interface */ 01944 struct ast_dialed_interface *di; 01945 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; 01946 num_dialed++; 01947 if (!number) { 01948 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); 01949 goto out; 01950 } 01951 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 01952 goto out; 01953 if (opts.flags) { 01954 ast_copy_flags64(tmp, &opts, 01955 OPT_CANCEL_ELSEWHERE | 01956 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01957 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01958 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01959 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01960 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01961 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID); 01962 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML); 01963 } 01964 ast_copy_string(numsubst, number, sizeof(numsubst)); 01965 /* Request the peer */ 01966 01967 ast_channel_lock(chan); 01968 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); 01969 /* 01970 * Seed the chanlist's connected line information with previously 01971 * acquired connected line info from the incoming channel. The 01972 * previously acquired connected line info could have been set 01973 * through the CONNECTED_LINE dialplan function. 01974 */ 01975 ast_party_connected_line_copy(&tmp->connected, &chan->connected); 01976 ast_channel_unlock(chan); 01977 01978 if (datastore) 01979 dialed_interfaces = datastore->data; 01980 else { 01981 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { 01982 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 01983 chanlist_free(tmp); 01984 goto out; 01985 } 01986 01987 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01988 01989 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { 01990 ast_datastore_free(datastore); 01991 chanlist_free(tmp); 01992 goto out; 01993 } 01994 01995 datastore->data = dialed_interfaces; 01996 AST_LIST_HEAD_INIT(dialed_interfaces); 01997 01998 ast_channel_lock(chan); 01999 ast_channel_datastore_add(chan, datastore); 02000 ast_channel_unlock(chan); 02001 } 02002 02003 AST_LIST_LOCK(dialed_interfaces); 02004 AST_LIST_TRAVERSE(dialed_interfaces, di, list) { 02005 if (!strcasecmp(di->interface, interface)) { 02006 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", 02007 di->interface); 02008 break; 02009 } 02010 } 02011 AST_LIST_UNLOCK(dialed_interfaces); 02012 02013 if (di) { 02014 fulldial++; 02015 chanlist_free(tmp); 02016 continue; 02017 } 02018 02019 /* It is always ok to dial a Local interface. We only keep track of 02020 * which "real" interfaces have been dialed. The Local channel will 02021 * inherit this list so that if it ends up dialing a real interface, 02022 * it won't call one that has already been called. */ 02023 if (strcasecmp(tech, "Local")) { 02024 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) { 02025 AST_LIST_UNLOCK(dialed_interfaces); 02026 chanlist_free(tmp); 02027 goto out; 02028 } 02029 strcpy(di->interface, interface); 02030 02031 AST_LIST_LOCK(dialed_interfaces); 02032 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); 02033 AST_LIST_UNLOCK(dialed_interfaces); 02034 } 02035 02036 tc = ast_request(tech, chan->nativeformats, chan, numsubst, &cause); 02037 if (!tc) { 02038 /* If we can't, just go on to the next call */ 02039 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", 02040 tech, cause, ast_cause2str(cause)); 02041 handle_cause(cause, &num); 02042 if (!rest) /* we are on the last destination */ 02043 chan->hangupcause = cause; 02044 chanlist_free(tmp); 02045 if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) { 02046 if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) { 02047 ast_cc_extension_monitor_add_dialstring(chan, interface, ""); 02048 } 02049 } 02050 continue; 02051 } 02052 ast_channel_get_device_name(tc, device_name, sizeof(device_name)); 02053 if (!ignore_cc) { 02054 ast_cc_extension_monitor_add_dialstring(chan, interface, device_name); 02055 } 02056 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst); 02057 02058 ast_channel_lock(tc); 02059 while (ast_channel_trylock(chan)) { 02060 CHANNEL_DEADLOCK_AVOIDANCE(tc); 02061 } 02062 /* Setup outgoing SDP to match incoming one */ 02063 if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) { 02064 ast_rtp_instance_early_bridge_make_compatible(tc, chan); 02065 } 02066 02067 /* Inherit specially named variables from parent channel */ 02068 ast_channel_inherit_variables(chan, tc); 02069 ast_channel_datastore_inherit(chan, tc); 02070 02071 tc->appl = "AppDial"; 02072 tc->data = "(Outgoing Line)"; 02073 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup)); 02074 02075 /* If the new channel has no callerid, try to guess what it should be */ 02076 if (!tc->caller.id.number.valid) { 02077 if (chan->connected.id.number.valid) { 02078 struct ast_party_caller caller; 02079 02080 ast_party_caller_set_init(&caller, &tc->caller); 02081 caller.id = chan->connected.id; 02082 caller.ani = chan->connected.ani; 02083 ast_channel_set_caller_event(tc, &caller, NULL); 02084 } else if (!ast_strlen_zero(chan->dialed.number.str)) { 02085 ast_set_callerid(tc, chan->dialed.number.str, NULL, NULL); 02086 } else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) { 02087 ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL); 02088 } 02089 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02090 } 02091 02092 if (ast_test_flag64(peerflags, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) { 02093 struct ast_party_connected_line connected; 02094 int pres; 02095 02096 ast_party_connected_line_set_init(&connected, &tmp->chan->connected); 02097 if (cid_pres) { 02098 pres = ast_parse_caller_presentation(cid_pres); 02099 if (pres < 0) { 02100 pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02101 } 02102 } else { 02103 pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02104 } 02105 if (cid_num) { 02106 connected.id.number.valid = 1; 02107 connected.id.number.str = cid_num; 02108 connected.id.number.presentation = pres; 02109 } 02110 if (cid_name) { 02111 connected.id.name.valid = 1; 02112 connected.id.name.str = cid_name; 02113 connected.id.name.presentation = pres; 02114 } 02115 connected.id.tag = cid_tag; 02116 ast_channel_set_connected_line(tmp->chan, &connected, NULL); 02117 } else { 02118 ast_connected_line_copy_from_caller(&tc->connected, &chan->caller); 02119 } 02120 02121 ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting); 02122 02123 tc->dialed.transit_network_select = chan->dialed.transit_network_select; 02124 02125 if (!ast_strlen_zero(chan->accountcode)) { 02126 ast_string_field_set(tc, peeraccount, chan->accountcode); 02127 } 02128 if (ast_strlen_zero(tc->musicclass)) 02129 ast_string_field_set(tc, musicclass, chan->musicclass); 02130 02131 /* Pass ADSI CPE and transfer capability */ 02132 tc->adsicpe = chan->adsicpe; 02133 tc->transfercapability = chan->transfercapability; 02134 02135 /* If we have an outbound group, set this peer channel to it */ 02136 if (outbound_group) 02137 ast_app_group_set_channel(tc, outbound_group); 02138 /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */ 02139 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE)) 02140 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02141 02142 /* Check if we're forced by configuration */ 02143 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)) 02144 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02145 02146 02147 /* Inherit context and extension */ 02148 ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext); 02149 if (!ast_strlen_zero(chan->macroexten)) 02150 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten)); 02151 else 02152 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten)); 02153 02154 ast_channel_unlock(tc); 02155 res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */ 02156 02157 /* Save the info in cdr's that we called them */ 02158 if (chan->cdr) 02159 ast_cdr_setdestchan(chan->cdr, tc->name); 02160 02161 /* check the results of ast_call */ 02162 if (res) { 02163 /* Again, keep going even if there's an error */ 02164 ast_debug(1, "ast call on peer returned %d\n", res); 02165 ast_verb(3, "Couldn't call %s\n", numsubst); 02166 if (tc->hangupcause) { 02167 chan->hangupcause = tc->hangupcause; 02168 } 02169 ast_channel_unlock(chan); 02170 ast_cc_call_failed(chan, tc, interface); 02171 ast_hangup(tc); 02172 tc = NULL; 02173 chanlist_free(tmp); 02174 continue; 02175 } else { 02176 const char *tmpexten = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02177 senddialevent(chan, tc, numsubst); 02178 ast_verb(3, "Called %s\n", numsubst); 02179 ast_channel_unlock(chan); 02180 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 02181 char cidname[AST_MAX_EXTENSION]; 02182 ast_set_callerid(tc, tmpexten, get_cid_name(cidname, sizeof(cidname), chan), NULL); 02183 } 02184 } 02185 /* Put them in the list of outgoing thingies... We're ready now. 02186 XXX If we're forcibly removed, these outgoing calls won't get 02187 hung up XXX */ 02188 ast_set_flag64(tmp, DIAL_STILLGOING); 02189 tmp->chan = tc; 02190 tmp->next = outgoing; 02191 outgoing = tmp; 02192 /* If this line is up, don't try anybody else */ 02193 if (outgoing->chan->_state == AST_STATE_UP) 02194 break; 02195 } 02196 02197 if (ast_strlen_zero(args.timeout)) { 02198 to = -1; 02199 } else { 02200 to = atoi(args.timeout); 02201 if (to > 0) 02202 to *= 1000; 02203 else { 02204 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout); 02205 to = -1; 02206 } 02207 } 02208 02209 if (!outgoing) { 02210 strcpy(pa.status, "CHANUNAVAIL"); 02211 if (fulldial == num_dialed) { 02212 res = -1; 02213 goto out; 02214 } 02215 } else { 02216 /* Our status will at least be NOANSWER */ 02217 strcpy(pa.status, "NOANSWER"); 02218 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) { 02219 moh = 1; 02220 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) { 02221 char *original_moh = ast_strdupa(chan->musicclass); 02222 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]); 02223 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL); 02224 ast_string_field_set(chan, musicclass, original_moh); 02225 } else { 02226 ast_moh_start(chan, NULL, NULL); 02227 } 02228 ast_indicate(chan, AST_CONTROL_PROGRESS); 02229 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) { 02230 if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 02231 if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){ 02232 ast_indicate(chan, AST_CONTROL_RINGING); 02233 sentringing++; 02234 } else { 02235 ast_indicate(chan, AST_CONTROL_PROGRESS); 02236 } 02237 } else { 02238 ast_indicate(chan, AST_CONTROL_RINGING); 02239 sentringing++; 02240 } 02241 } 02242 } 02243 02244 peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress, ignore_cc); 02245 02246 /* The ast_channel_datastore_remove() function could fail here if the 02247 * datastore was moved to another channel during a masquerade. If this is 02248 * the case, don't free the datastore here because later, when the channel 02249 * to which the datastore was moved hangs up, it will attempt to free this 02250 * datastore again, causing a crash 02251 */ 02252 if (!ast_channel_datastore_remove(chan, datastore)) 02253 ast_datastore_free(datastore); 02254 if (!peer) { 02255 if (result) { 02256 res = result; 02257 } else if (to) { /* Musta gotten hung up */ 02258 res = -1; 02259 } else { /* Nobody answered, next please? */ 02260 res = 0; 02261 } 02262 02263 /* SIP, in particular, sends back this error code to indicate an 02264 * overlap dialled number needs more digits. */ 02265 if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) { 02266 res = AST_PBX_INCOMPLETE; 02267 } 02268 02269 /* almost done, although the 'else' block is 400 lines */ 02270 } else { 02271 const char *number; 02272 02273 if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) 02274 ast_answer(chan); 02275 02276 strcpy(pa.status, "ANSWER"); 02277 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02278 /* Ah ha! Someone answered within the desired timeframe. Of course after this 02279 we will always return with -1 so that it is hung up properly after the 02280 conversation. */ 02281 hanguptree(outgoing, peer, 1); 02282 outgoing = NULL; 02283 /* If appropriate, log that we have a destination channel and set the answer time */ 02284 if (chan->cdr) { 02285 ast_cdr_setdestchan(chan->cdr, peer->name); 02286 ast_cdr_setanswer(chan->cdr, peer->cdr->answer); 02287 } 02288 if (peer->name) 02289 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name); 02290 02291 ast_channel_lock(peer); 02292 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 02293 if (!number) 02294 number = numsubst; 02295 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); 02296 ast_channel_unlock(peer); 02297 02298 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { 02299 ast_debug(1, "app_dial: sendurl=%s.\n", args.url); 02300 ast_channel_sendurl( peer, args.url ); 02301 } 02302 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) { 02303 if (do_privacy(chan, peer, &opts, opt_args, &pa)) { 02304 res = 0; 02305 goto out; 02306 } 02307 } 02308 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) { 02309 res = 0; 02310 } else { 02311 int digit = 0; 02312 struct ast_channel *chans[2]; 02313 struct ast_channel *active_chan; 02314 02315 chans[0] = chan; 02316 chans[1] = peer; 02317 02318 /* we need to stream the announcment while monitoring the caller for a hangup */ 02319 02320 /* stream the file */ 02321 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language); 02322 if (res) { 02323 res = 0; 02324 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]); 02325 } 02326 02327 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY); 02328 while (peer->stream) { 02329 int ms; 02330 02331 ms = ast_sched_wait(peer->sched); 02332 02333 if (ms < 0 && !peer->timingfunc) { 02334 ast_stopstream(peer); 02335 break; 02336 } 02337 if (ms < 0) 02338 ms = 1000; 02339 02340 active_chan = ast_waitfor_n(chans, 2, &ms); 02341 if (active_chan) { 02342 struct ast_frame *fr = ast_read(active_chan); 02343 if (!fr) { 02344 ast_hangup(peer); 02345 res = -1; 02346 goto done; 02347 } 02348 switch(fr->frametype) { 02349 case AST_FRAME_DTMF_END: 02350 digit = fr->subclass.integer; 02351 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) { 02352 ast_stopstream(peer); 02353 res = ast_senddigit(chan, digit, 0); 02354 } 02355 break; 02356 case AST_FRAME_CONTROL: 02357 switch (fr->subclass.integer) { 02358 case AST_CONTROL_HANGUP: 02359 ast_frfree(fr); 02360 ast_hangup(peer); 02361 res = -1; 02362 goto done; 02363 default: 02364 break; 02365 } 02366 break; 02367 default: 02368 /* Ignore all others */ 02369 break; 02370 } 02371 ast_frfree(fr); 02372 } 02373 ast_sched_runq(peer->sched); 02374 } 02375 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY); 02376 } 02377 02378 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { 02379 /* chan and peer are going into the PBX, they both 02380 * should probably get CDR records. */ 02381 ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED); 02382 ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED); 02383 02384 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]); 02385 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); 02386 /* peer goes to the same context and extension as chan, so just copy info from chan*/ 02387 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02388 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02389 peer->priority = chan->priority + 2; 02390 ast_pbx_start(peer); 02391 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0); 02392 if (continue_exec) 02393 *continue_exec = 1; 02394 res = 0; 02395 goto done; 02396 } 02397 02398 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) { 02399 struct ast_app *theapp; 02400 const char *macro_result; 02401 02402 res = ast_autoservice_start(chan); 02403 if (res) { 02404 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02405 res = -1; 02406 } 02407 02408 theapp = pbx_findapp("Macro"); 02409 02410 if (theapp && !res) { /* XXX why check res here ? */ 02411 /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */ 02412 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02413 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02414 02415 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]); 02416 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]); 02417 ast_debug(1, "Macro exited with status %d\n", res); 02418 res = 0; 02419 } else { 02420 ast_log(LOG_ERROR, "Could not find application Macro\n"); 02421 res = -1; 02422 } 02423 02424 if (ast_autoservice_stop(chan) < 0) { 02425 res = -1; 02426 } 02427 02428 ast_channel_lock(peer); 02429 02430 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) { 02431 char *macro_transfer_dest; 02432 02433 if (!strcasecmp(macro_result, "BUSY")) { 02434 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02435 ast_set_flag64(peerflags, OPT_GO_ON); 02436 res = -1; 02437 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { 02438 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02439 ast_set_flag64(peerflags, OPT_GO_ON); 02440 res = -1; 02441 } else if (!strcasecmp(macro_result, "CONTINUE")) { 02442 /* hangup peer and keep chan alive assuming the macro has changed 02443 the context / exten / priority or perhaps 02444 the next priority in the current exten is desired. 02445 */ 02446 ast_set_flag64(peerflags, OPT_GO_ON); 02447 res = -1; 02448 } else if (!strcasecmp(macro_result, "ABORT")) { 02449 /* Hangup both ends unless the caller has the g flag */ 02450 res = -1; 02451 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { 02452 res = -1; 02453 /* perform a transfer to a new extension */ 02454 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/ 02455 replace_macro_delimiter(macro_transfer_dest); 02456 if (!ast_parseable_goto(chan, macro_transfer_dest)) 02457 ast_set_flag64(peerflags, OPT_GO_ON); 02458 } 02459 } 02460 } 02461 02462 ast_channel_unlock(peer); 02463 } 02464 02465 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) { 02466 struct ast_app *theapp; 02467 const char *gosub_result; 02468 char *gosub_args, *gosub_argstart; 02469 int res9 = -1; 02470 02471 res9 = ast_autoservice_start(chan); 02472 if (res9) { 02473 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02474 res9 = -1; 02475 } 02476 02477 theapp = pbx_findapp("Gosub"); 02478 02479 if (theapp && !res9) { 02480 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]); 02481 02482 /* Set where we came from */ 02483 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context)); 02484 ast_copy_string(peer->exten, "s", sizeof(peer->exten)); 02485 peer->priority = 0; 02486 02487 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ','); 02488 if (gosub_argstart) { 02489 *gosub_argstart = 0; 02490 if (asprintf(&gosub_args, "%s,s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], gosub_argstart + 1) < 0) { 02491 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02492 gosub_args = NULL; 02493 } 02494 *gosub_argstart = ','; 02495 } else { 02496 if (asprintf(&gosub_args, "%s,s,1", opt_args[OPT_ARG_CALLEE_GOSUB]) < 0) { 02497 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02498 gosub_args = NULL; 02499 } 02500 } 02501 02502 if (gosub_args) { 02503 res9 = pbx_exec(peer, theapp, gosub_args); 02504 if (!res9) { 02505 struct ast_pbx_args args; 02506 /* A struct initializer fails to compile for this case ... */ 02507 memset(&args, 0, sizeof(args)); 02508 args.no_hangup_chan = 1; 02509 ast_pbx_run_args(peer, &args); 02510 } 02511 ast_free(gosub_args); 02512 ast_debug(1, "Gosub exited with status %d\n", res9); 02513 } else { 02514 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n"); 02515 } 02516 02517 } else if (!res9) { 02518 ast_log(LOG_ERROR, "Could not find application Gosub\n"); 02519 res9 = -1; 02520 } 02521 02522 if (ast_autoservice_stop(chan) < 0) { 02523 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n"); 02524 res9 = -1; 02525 } 02526 02527 ast_channel_lock(peer); 02528 02529 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) { 02530 char *gosub_transfer_dest; 02531 const char *gosub_retval = pbx_builtin_getvar_helper(peer, "GOSUB_RETVAL"); 02532 02533 /* Inherit return value from the peer, so it can be used in the master */ 02534 if (gosub_retval) { 02535 pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", gosub_retval); 02536 } 02537 02538 if (!strcasecmp(gosub_result, "BUSY")) { 02539 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02540 ast_set_flag64(peerflags, OPT_GO_ON); 02541 res = -1; 02542 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) { 02543 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02544 ast_set_flag64(peerflags, OPT_GO_ON); 02545 res = -1; 02546 } else if (!strcasecmp(gosub_result, "CONTINUE")) { 02547 /* hangup peer and keep chan alive assuming the macro has changed 02548 the context / exten / priority or perhaps 02549 the next priority in the current exten is desired. 02550 */ 02551 ast_set_flag64(peerflags, OPT_GO_ON); 02552 res = -1; 02553 } else if (!strcasecmp(gosub_result, "ABORT")) { 02554 /* Hangup both ends unless the caller has the g flag */ 02555 res = -1; 02556 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) { 02557 res = -1; 02558 /* perform a transfer to a new extension */ 02559 if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/ 02560 replace_macro_delimiter(gosub_transfer_dest); 02561 if (!ast_parseable_goto(chan, gosub_transfer_dest)) 02562 ast_set_flag64(peerflags, OPT_GO_ON); 02563 } 02564 } 02565 } 02566 02567 ast_channel_unlock(peer); 02568 } 02569 02570 if (!res) { 02571 if (!ast_tvzero(calldurationlimit)) { 02572 struct timeval whentohangup = calldurationlimit; 02573 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup); 02574 } 02575 if (!ast_strlen_zero(dtmfcalled)) { 02576 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled); 02577 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0); 02578 } 02579 if (!ast_strlen_zero(dtmfcalling)) { 02580 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling); 02581 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0); 02582 } 02583 } 02584 02585 if (res) { /* some error */ 02586 res = -1; 02587 } else { 02588 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER)) 02589 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02590 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER)) 02591 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02592 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP)) 02593 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT); 02594 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP)) 02595 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT); 02596 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR)) 02597 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 02598 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR)) 02599 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 02600 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK)) 02601 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL); 02602 if (ast_test_flag64(peerflags, OPT_CALLER_PARK)) 02603 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL); 02604 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR)) 02605 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON); 02606 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR)) 02607 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON); 02608 if (ast_test_flag64(peerflags, OPT_GO_ON)) 02609 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN); 02610 02611 config.end_bridge_callback = end_bridge_callback; 02612 config.end_bridge_callback_data = chan; 02613 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; 02614 02615 if (moh) { 02616 moh = 0; 02617 ast_moh_stop(chan); 02618 } else if (sentringing) { 02619 sentringing = 0; 02620 ast_indicate(chan, -1); 02621 } 02622 /* Be sure no generators are left on it and reset the visible indication */ 02623 ast_deactivate_generator(chan); 02624 chan->visible_indication = 0; 02625 /* Make sure channels are compatible */ 02626 res = ast_channel_make_compatible(chan, peer); 02627 if (res < 0) { 02628 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name); 02629 ast_hangup(peer); 02630 res = -1; 02631 goto done; 02632 } 02633 if (opermode) { 02634 struct oprmode oprmode; 02635 02636 oprmode.peer = peer; 02637 oprmode.mode = opermode; 02638 02639 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0); 02640 } 02641 res = ast_bridge_call(chan, peer, &config); 02642 } 02643 02644 strcpy(peer->context, chan->context); 02645 02646 if (ast_test_flag64(&opts, OPT_PEER_H) 02647 && ast_exists_extension(peer, peer->context, "h", 1, 02648 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02649 int autoloopflag; 02650 int found; 02651 int res9; 02652 02653 strcpy(peer->exten, "h"); 02654 peer->priority = 1; 02655 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02656 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP); 02657 02658 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, 02659 peer->priority, 02660 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL), 02661 &found, 1)) == 0) { 02662 peer->priority++; 02663 } 02664 02665 if (found && res9) { 02666 /* Something bad happened, or a hangup has been requested. */ 02667 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02668 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02669 } 02670 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */ 02671 } 02672 if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) { 02673 if(!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) { 02674 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]); 02675 ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]); 02676 } else { /* F() */ 02677 int res; 02678 res = ast_goto_if_exists(peer, chan->context, chan->exten, (chan->priority) + 1); 02679 if (res == AST_PBX_GOTO_FAILED) { 02680 ast_hangup(peer); 02681 goto out; 02682 } 02683 } 02684 ast_pbx_start(peer); 02685 } else { 02686 if (!ast_check_hangup(chan)) 02687 chan->hangupcause = peer->hangupcause; 02688 ast_hangup(peer); 02689 } 02690 } 02691 out: 02692 if (moh) { 02693 moh = 0; 02694 ast_moh_stop(chan); 02695 } else if (sentringing) { 02696 sentringing = 0; 02697 ast_indicate(chan, -1); 02698 } 02699 02700 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02701 ast_filedelete(pa.privintro, NULL); 02702 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02703 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro); 02704 } else { 02705 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro); 02706 } 02707 } 02708 02709 ast_channel_early_bridge(chan, NULL); 02710 hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */ 02711 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02712 senddialendevent(chan, pa.status); 02713 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status); 02714 02715 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) { 02716 if (!ast_tvzero(calldurationlimit)) 02717 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup)); 02718 res = 0; 02719 } 02720 02721 done: 02722 if (config.warning_sound) { 02723 ast_free((char *)config.warning_sound); 02724 } 02725 if (config.end_sound) { 02726 ast_free((char *)config.end_sound); 02727 } 02728 if (config.start_sound) { 02729 ast_free((char *)config.start_sound); 02730 } 02731 ast_ignore_cc(chan); 02732 return res; 02733 }
static int dial_handle_playtones | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 1755 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().
01756 { 01757 struct ast_tone_zone_sound *ts = NULL; 01758 int res; 01759 const char *str = data; 01760 01761 if (ast_strlen_zero(str)) { 01762 ast_debug(1,"Nothing to play\n"); 01763 return -1; 01764 } 01765 01766 ts = ast_get_indication_tone(chan->zone, str); 01767 01768 if (ts && ts->data[0]) { 01769 res = ast_playtones_start(chan, 0, ts->data, 0); 01770 } else { 01771 res = -1; 01772 } 01773 01774 if (ts) { 01775 ts = ast_tone_zone_sound_unref(ts); 01776 } 01777 01778 if (res) { 01779 ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str); 01780 } 01781 01782 return res; 01783 }
static void do_forward | ( | struct chanlist * | o, | |
struct cause_args * | num, | |||
struct ast_flags64 * | peerflags, | |||
int | single, | |||
int * | to | |||
) | [static] |
helper function for wait_for_answer()
XXX this code is highly suspicious, as it essentially overwrites the outgoing channel without properly deleting it.
Definition at line 794 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_make_compatible(), ast_channel_redirecting_macro(), ast_channel_set_redirecting(), ast_channel_trylock, ast_channel_unlock, ast_channel_update_redirecting(), ast_clear_flag64, ast_copy_string(), ast_hangup(), ast_ignore_cc(), ast_indicate(), ast_log(), AST_MAX_EXTENSION, ast_party_caller_copy(), ast_party_connected_line_copy(), ast_party_id_free(), ast_party_id_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_callerid(), ast_strdup, ast_strdupa, 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, CHANNEL_DEADLOCK_AVOIDANCE, ast_channel::connected, ast_channel::context, ast_channel::data, DIAL_STILLGOING, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, get_cid_name(), 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_OR, senddialevent(), ast_party_number::str, ast_channel::tech, ast_party_dialed::transit_network_select, and ast_party_number::valid.
00796 { 00797 char tmpchan[256]; 00798 struct ast_channel *original = o->chan; 00799 struct ast_channel *c = o->chan; /* the winner */ 00800 struct ast_channel *in = num->chan; /* the input channel */ 00801 char *stuff; 00802 char *tech; 00803 int cause; 00804 00805 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan)); 00806 if ((stuff = strchr(tmpchan, '/'))) { 00807 *stuff++ = '\0'; 00808 tech = tmpchan; 00809 } else { 00810 const char *forward_context; 00811 ast_channel_lock(c); 00812 forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT"); 00813 if (ast_strlen_zero(forward_context)) { 00814 forward_context = NULL; 00815 } 00816 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context); 00817 ast_channel_unlock(c); 00818 stuff = tmpchan; 00819 tech = "Local"; 00820 } 00821 00822 ast_cel_report_event(in, AST_CEL_FORWARD, NULL, c->call_forward, NULL); 00823 00824 /* Before processing channel, go ahead and check for forwarding */ 00825 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); 00826 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ 00827 if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) { 00828 ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); 00829 c = o->chan = NULL; 00830 cause = AST_CAUSE_BUSY; 00831 } else { 00832 /* Setup parameters */ 00833 c = o->chan = ast_request(tech, in->nativeformats, in, stuff, &cause); 00834 if (c) { 00835 if (single) 00836 ast_channel_make_compatible(o->chan, in); 00837 ast_channel_inherit_variables(in, o->chan); 00838 ast_channel_datastore_inherit(in, o->chan); 00839 /* When a call is forwarded, we don't want to track new interfaces 00840 * dialed for CC purposes. Setting the done flag will ensure that 00841 * any Dial operations that happen later won't record CC interfaces. 00842 */ 00843 ast_ignore_cc(o->chan); 00844 ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", o->chan->name); 00845 } else 00846 ast_log(LOG_NOTICE, 00847 "Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n", 00848 tech, stuff, cause); 00849 } 00850 if (!c) { 00851 ast_clear_flag64(o, DIAL_STILLGOING); 00852 handle_cause(cause, num); 00853 ast_hangup(original); 00854 } else { 00855 struct ast_party_redirecting redirecting; 00856 00857 if (single && CAN_EARLY_BRIDGE(peerflags, c, in)) { 00858 ast_rtp_instance_early_bridge_make_compatible(c, in); 00859 } 00860 00861 ast_channel_set_redirecting(c, &original->redirecting, NULL); 00862 ast_channel_lock(c); 00863 while (ast_channel_trylock(in)) { 00864 CHANNEL_DEADLOCK_AVOIDANCE(c); 00865 } 00866 if (!c->redirecting.from.number.valid 00867 || ast_strlen_zero(c->redirecting.from.number.str)) { 00868 /* 00869 * The call was not previously redirected so it is 00870 * now redirected from this number. 00871 */ 00872 ast_party_number_free(&c->redirecting.from.number); 00873 ast_party_number_init(&c->redirecting.from.number); 00874 c->redirecting.from.number.valid = 1; 00875 c->redirecting.from.number.str = 00876 ast_strdup(S_OR(in->macroexten, in->exten)); 00877 } 00878 00879 c->dialed.transit_network_select = in->dialed.transit_network_select; 00880 00881 if (ast_test_flag64(o, OPT_FORCECLID)) { 00882 ast_party_id_free(&c->caller.id); 00883 ast_party_id_init(&c->caller.id); 00884 c->caller.id.number.valid = 1; 00885 c->caller.id.number.str = ast_strdup(S_OR(in->macroexten, in->exten)); 00886 ast_string_field_set(c, accountcode, c->accountcode); 00887 } else { 00888 ast_party_caller_copy(&c->caller, &in->caller); 00889 ast_string_field_set(c, accountcode, in->accountcode); 00890 } 00891 ast_party_connected_line_copy(&c->connected, &original->connected); 00892 c->appl = "AppDial"; 00893 c->data = "(Outgoing Line)"; 00894 /* 00895 * We must unlock c before calling ast_channel_redirecting_macro, because 00896 * we put c into autoservice there. That is pretty much a guaranteed 00897 * deadlock. This is why the handling of c's lock may seem a bit unusual 00898 * here. 00899 */ 00900 ast_party_redirecting_init(&redirecting); 00901 ast_party_redirecting_copy(&redirecting, &c->redirecting); 00902 ast_channel_unlock(c); 00903 if (ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) { 00904 ast_channel_update_redirecting(in, &redirecting, NULL); 00905 } 00906 ast_party_redirecting_free(&redirecting); 00907 ast_channel_unlock(in); 00908 00909 ast_clear_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE); 00910 if (ast_test_flag64(peerflags, OPT_CANCEL_TIMEOUT)) { 00911 *to = -1; 00912 } 00913 00914 if (ast_call(c, stuff, 0)) { 00915 ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n", 00916 tech, stuff); 00917 ast_clear_flag64(o, DIAL_STILLGOING); 00918 ast_hangup(original); 00919 ast_hangup(c); 00920 c = o->chan = NULL; 00921 num->nochan++; 00922 } else { 00923 ast_channel_lock(c); 00924 while (ast_channel_trylock(in)) { 00925 CHANNEL_DEADLOCK_AVOIDANCE(c); 00926 } 00927 senddialevent(in, c, stuff); 00928 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 00929 char cidname[AST_MAX_EXTENSION] = ""; 00930 const char *tmpexten; 00931 tmpexten = ast_strdupa(S_OR(in->macroexten, in->exten)); 00932 ast_channel_unlock(in); 00933 ast_channel_unlock(c); 00934 ast_set_callerid(c, tmpexten, get_cid_name(cidname, sizeof(cidname), in), NULL); 00935 } else { 00936 ast_channel_unlock(in); 00937 ast_channel_unlock(c); 00938 } 00939 /* Hangup the original channel now, in case we needed it */ 00940 ast_hangup(original); 00941 } 00942 if (single) { 00943 ast_indicate(in, -1); 00944 } 00945 } 00946 }
static void end_bridge_callback | ( | void * | data | ) | [static] |
Definition at line 1726 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().
01727 { 01728 char buf[80]; 01729 time_t end; 01730 struct ast_channel *chan = data; 01731 01732 if (!chan->cdr) { 01733 return; 01734 } 01735 01736 time(&end); 01737 01738 ast_channel_lock(chan); 01739 if (chan->cdr->answer.tv_sec) { 01740 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec); 01741 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 01742 } 01743 01744 if (chan->cdr->start.tv_sec) { 01745 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec); 01746 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 01747 } 01748 ast_channel_unlock(chan); 01749 }
static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
struct ast_channel * | originator, | |||
struct ast_channel * | terminator | |||
) | [static] |
Definition at line 1751 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec(), and dial_exec_full().
01751 { 01752 bconfig->end_bridge_callback_data = originator; 01753 }
static const char* get_cid_name | ( | char * | name, | |
int | namelen, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 744 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(), and do_forward().
00745 { 00746 const char *context; 00747 const char *exten; 00748 00749 ast_channel_lock(chan); 00750 context = ast_strdupa(S_OR(chan->macrocontext, chan->context)); 00751 exten = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 00752 ast_channel_unlock(chan); 00753 00754 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : ""; 00755 }
static void handle_cause | ( | int | cause, | |
struct cause_args * | num | |||
) | [static] |
Definition at line 687 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().
00688 { 00689 struct ast_cdr *cdr = num->chan->cdr; 00690 00691 switch(cause) { 00692 case AST_CAUSE_BUSY: 00693 if (cdr) 00694 ast_cdr_busy(cdr); 00695 num->busy++; 00696 break; 00697 00698 case AST_CAUSE_CONGESTION: 00699 if (cdr) 00700 ast_cdr_failed(cdr); 00701 num->congestion++; 00702 break; 00703 00704 case AST_CAUSE_NO_ROUTE_DESTINATION: 00705 case AST_CAUSE_UNREGISTERED: 00706 if (cdr) 00707 ast_cdr_failed(cdr); 00708 num->nochan++; 00709 break; 00710 00711 case AST_CAUSE_NO_ANSWER: 00712 if (cdr) { 00713 ast_cdr_noanswer(cdr); 00714 } 00715 break; 00716 case AST_CAUSE_NORMAL_CLEARING: 00717 break; 00718 00719 default: 00720 num->nochan++; 00721 break; 00722 } 00723 }
static void hanguptree | ( | struct chanlist * | outgoing, | |
struct ast_channel * | exception, | |||
int | answered_elsewhere | |||
) | [static] |
Definition at line 654 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().
00655 { 00656 /* Hang up a tree of stuff */ 00657 struct chanlist *oo; 00658 while (outgoing) { 00659 /* Hangup any existing lines we have open */ 00660 if (outgoing->chan && (outgoing->chan != exception)) { 00661 if (answered_elsewhere) { 00662 /* The flag is used for local channel inheritance and stuff */ 00663 ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE); 00664 /* This is for the channel drivers */ 00665 outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE; 00666 } 00667 ast_hangup(outgoing->chan); 00668 } 00669 oo = outgoing; 00670 outgoing = outgoing->next; 00671 chanlist_free(oo); 00672 } 00673 }
static int load_module | ( | void | ) | [static] |
Definition at line 2868 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().
02869 { 02870 int res; 02871 struct ast_context *con; 02872 02873 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial"); 02874 if (!con) 02875 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n"); 02876 else 02877 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial"); 02878 02879 res = ast_register_application_xml(app, dial_exec); 02880 res |= ast_register_application_xml(rapp, retrydial_exec); 02881 02882 return res; 02883 }
static int onedigit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
char | exten, | |||
int | pri | |||
) | [static] |
Definition at line 725 of file app_dial.c.
References ast_goto_if_exists(), ast_strlen_zero(), ast_channel::context, and ast_channel::macrocontext.
Referenced by retrydial_exec().
00726 { 00727 char rexten[2] = { exten, '\0' }; 00728 00729 if (context) { 00730 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00731 return 1; 00732 } else { 00733 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00734 return 1; 00735 else if (!ast_strlen_zero(chan->macrocontext)) { 00736 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00737 return 1; 00738 } 00739 } 00740 return 0; 00741 }
static void replace_macro_delimiter | ( | char * | s | ) | [static] |
static int retrydial_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 2744 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().
02745 { 02746 char *parse; 02747 const char *context = NULL; 02748 int sleepms = 0, loops = 0, res = -1; 02749 struct ast_flags64 peerflags = { 0, }; 02750 AST_DECLARE_APP_ARGS(args, 02751 AST_APP_ARG(announce); 02752 AST_APP_ARG(sleep); 02753 AST_APP_ARG(retries); 02754 AST_APP_ARG(dialdata); 02755 ); 02756 02757 if (ast_strlen_zero(data)) { 02758 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 02759 return -1; 02760 } 02761 02762 parse = ast_strdupa(data); 02763 AST_STANDARD_APP_ARGS(args, parse); 02764 02765 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep))) 02766 sleepms *= 1000; 02767 02768 if (!ast_strlen_zero(args.retries)) { 02769 loops = atoi(args.retries); 02770 } 02771 02772 if (!args.dialdata) { 02773 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp); 02774 goto done; 02775 } 02776 02777 if (sleepms < 1000) 02778 sleepms = 10000; 02779 02780 if (!loops) 02781 loops = -1; /* run forever */ 02782 02783 ast_channel_lock(chan); 02784 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 02785 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL; 02786 ast_channel_unlock(chan); 02787 02788 res = 0; 02789 while (loops) { 02790 int continue_exec; 02791 02792 chan->data = "Retrying"; 02793 if (ast_test_flag(chan, AST_FLAG_MOH)) 02794 ast_moh_stop(chan); 02795 02796 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec); 02797 if (continue_exec) 02798 break; 02799 02800 if (res == 0) { 02801 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) { 02802 if (!ast_strlen_zero(args.announce)) { 02803 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 02804 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 02805 ast_waitstream(chan, AST_DIGIT_ANY); 02806 } else 02807 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 02808 } 02809 if (!res && sleepms) { 02810 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02811 ast_moh_start(chan, NULL, NULL); 02812 res = ast_waitfordigit(chan, sleepms); 02813 } 02814 } else { 02815 if (!ast_strlen_zero(args.announce)) { 02816 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 02817 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 02818 res = ast_waitstream(chan, ""); 02819 } else 02820 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 02821 } 02822 if (sleepms) { 02823 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02824 ast_moh_start(chan, NULL, NULL); 02825 if (!res) 02826 res = ast_waitfordigit(chan, sleepms); 02827 } 02828 } 02829 } 02830 02831 if (res < 0 || res == AST_PBX_INCOMPLETE) { 02832 break; 02833 } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 02834 if (onedigit_goto(chan, context, (char) res, 1)) { 02835 res = 0; 02836 break; 02837 } 02838 } 02839 loops--; 02840 } 02841 if (loops == 0) 02842 res = 0; 02843 else if (res == 1) 02844 res = 0; 02845 02846 if (ast_test_flag(chan, AST_FLAG_MOH)) 02847 ast_moh_stop(chan); 02848 done: 02849 return res; 02850 }
static void senddialendevent | ( | struct ast_channel * | src, | |
const char * | dialstatus | |||
) | [static] |
Definition at line 776 of file app_dial.c.
References ast_manager_event, EVENT_FLAG_CALL, ast_channel::name, and ast_channel::uniqueid.
Referenced by dial_exec_full().
00777 { 00778 ast_manager_event(src, EVENT_FLAG_CALL, "Dial", 00779 "SubEvent: End\r\n" 00780 "Channel: %s\r\n" 00781 "UniqueID: %s\r\n" 00782 "DialStatus: %s\r\n", 00783 src->name, src->uniqueid, dialstatus); 00784 }
static void senddialevent | ( | struct ast_channel * | src, | |
struct ast_channel * | dst, | |||
const char * | dialstring | |||
) | [static] |
Definition at line 757 of file app_dial.c.
References ast_manager_event_multichan, ast_channel::caller, EVENT_FLAG_CALL, 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().
00758 { 00759 struct ast_channel *chans[] = { src, dst }; 00760 ast_manager_event_multichan(EVENT_FLAG_CALL, "Dial", 2, chans, 00761 "SubEvent: Begin\r\n" 00762 "Channel: %s\r\n" 00763 "Destination: %s\r\n" 00764 "CallerIDNum: %s\r\n" 00765 "CallerIDName: %s\r\n" 00766 "UniqueID: %s\r\n" 00767 "DestUniqueID: %s\r\n" 00768 "Dialstring: %s\r\n", 00769 src->name, dst->name, 00770 S_COR(src->caller.id.number.valid, src->caller.id.number.str, "<unknown>"), 00771 S_COR(src->caller.id.name.valid, src->caller.id.name.str, "<unknown>"), 00772 src->uniqueid, dst->uniqueid, 00773 dialstring ? dialstring : ""); 00774 }
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 1624 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().
01626 { 01627 char callerid[60]; 01628 int res; 01629 char *l; 01630 int silencethreshold; 01631 01632 if (chan->caller.id.number.valid 01633 && !ast_strlen_zero(chan->caller.id.number.str)) { 01634 l = ast_strdupa(chan->caller.id.number.str); 01635 ast_shrink_phone_number(l); 01636 if (ast_test_flag64(opts, OPT_PRIVACY) ) { 01637 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l); 01638 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l); 01639 } else { 01640 ast_verb(3, "Privacy Screening, clid is '%s'\n", l); 01641 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01642 } 01643 } else { 01644 char *tnam, *tn2; 01645 01646 tnam = ast_strdupa(chan->name); 01647 /* clean the channel name so slashes don't try to end up in disk file name */ 01648 for (tn2 = tnam; *tn2; tn2++) { 01649 if (*tn2 == '/') /* any other chars to be afraid of? */ 01650 *tn2 = '='; 01651 } 01652 ast_verb(3, "Privacy-- callerid is empty\n"); 01653 01654 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); 01655 l = callerid; 01656 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01657 } 01658 01659 ast_copy_string(pa->privcid, l, sizeof(pa->privcid)); 01660 01661 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) { 01662 /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */ 01663 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid); 01664 pa->privdb_val = AST_PRIVACY_ALLOW; 01665 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) { 01666 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val); 01667 } 01668 01669 if (pa->privdb_val == AST_PRIVACY_DENY) { 01670 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); 01671 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status)); 01672 return 0; 01673 } else if (pa->privdb_val == AST_PRIVACY_KILL) { 01674 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status)); 01675 return 0; /* Is this right? */ 01676 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) { 01677 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status)); 01678 return 0; /* is this right??? */ 01679 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) { 01680 /* Get the user's intro, store it in priv-callerintros/$CID, 01681 unless it is already there-- this should be done before the 01682 call is actually dialed */ 01683 01684 /* make sure the priv-callerintros dir actually exists */ 01685 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR); 01686 if ((res = ast_mkdir(pa->privintro, 0755))) { 01687 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res)); 01688 return -1; 01689 } 01690 01691 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); 01692 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) { 01693 /* the DELUX version of this code would allow this caller the 01694 option to hear and retape their previously recorded intro. 01695 */ 01696 } else { 01697 int duration; /* for feedback from play_and_wait */ 01698 /* the file doesn't exist yet. Let the caller submit his 01699 vocal intro for posterity */ 01700 /* priv-recordintro script: 01701 01702 "At the tone, please say your name:" 01703 01704 */ 01705 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE); 01706 ast_answer(chan); 01707 res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "sln", &duration, silencethreshold, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */ 01708 /* don't think we'll need a lock removed, we took care of 01709 conflicts by naming the pa.privintro file */ 01710 if (res == -1) { 01711 /* Delete the file regardless since they hung up during recording */ 01712 ast_filedelete(pa->privintro, NULL); 01713 if (ast_fileexists(pa->privintro, NULL, NULL) > 0) 01714 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro); 01715 else 01716 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro); 01717 return -1; 01718 } 01719 if (!ast_streamfile(chan, "vm-dialout", chan->language) ) 01720 ast_waitstream(chan, ""); 01721 } 01722 } 01723 return 1; /* success */ 01724 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2852 of file app_dial.c.
References ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), and ast_unregister_application().
02853 { 02854 int res; 02855 struct ast_context *con; 02856 02857 res = ast_unregister_application(app); 02858 res |= ast_unregister_application(rapp); 02859 02860 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) { 02861 ast_context_remove_extension2(con, "s", 1, NULL, 0); 02862 ast_context_destroy(con, "app_dial"); /* leave nothing behind */ 02863 } 02864 02865 return res; 02866 }
static int valid_priv_reply | ( | struct ast_flags64 * | opts, | |
int | res | |||
) | [static] |
Definition at line 1478 of file app_dial.c.
References ast_test_flag64, OPT_PRIVACY, and OPT_SCREENING.
01479 { 01480 if (res < '1') 01481 return 0; 01482 if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5') 01483 return 1; 01484 if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4') 01485 return 1; 01486 return 0; 01487 }
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 | |||
) | [static] |
Definition at line 957 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().
00963 { 00964 struct cause_args num = *num_in; 00965 int prestart = num.busy + num.congestion + num.nochan; 00966 int orig = *to; 00967 struct ast_channel *peer = NULL; 00968 /* single is set if only one destination is enabled */ 00969 int single = outgoing && !outgoing->next; 00970 #ifdef HAVE_EPOLL 00971 struct chanlist *epollo; 00972 #endif 00973 struct ast_party_connected_line connected_caller; 00974 struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1); 00975 int cc_recall_core_id; 00976 int is_cc_recall; 00977 int cc_frame_received = 0; 00978 int num_ringing = 0; 00979 00980 ast_party_connected_line_init(&connected_caller); 00981 if (single) { 00982 /* Turn off hold music, etc */ 00983 if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK)) { 00984 ast_deactivate_generator(in); 00985 /* If we are calling a single channel, and not providing ringback or music, */ 00986 /* then, make them compatible for in-band tone purpose */ 00987 if (ast_channel_make_compatible(outgoing->chan, in) < 0) { 00988 /* If these channels can not be made compatible, 00989 * there is no point in continuing. The bridge 00990 * will just fail if it gets that far. 00991 */ 00992 *to = -1; 00993 strcpy(pa->status, "CONGESTION"); 00994 ast_cdr_failed(in->cdr); 00995 return NULL; 00996 } 00997 } 00998 00999 if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_CALLERID_ABSENT)) { 01000 ast_channel_lock(outgoing->chan); 01001 ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->caller); 01002 ast_channel_unlock(outgoing->chan); 01003 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01004 ast_channel_update_connected_line(in, &connected_caller, NULL); 01005 ast_party_connected_line_free(&connected_caller); 01006 } 01007 } 01008 01009 is_cc_recall = ast_cc_is_recall(in, &cc_recall_core_id, NULL); 01010 01011 #ifdef HAVE_EPOLL 01012 for (epollo = outgoing; epollo; epollo = epollo->next) 01013 ast_poll_channel_add(in, epollo->chan); 01014 #endif 01015 01016 while (*to && !peer) { 01017 struct chanlist *o; 01018 int pos = 0; /* how many channels do we handle */ 01019 int numlines = prestart; 01020 struct ast_channel *winner; 01021 struct ast_channel *watchers[AST_MAX_WATCHERS]; 01022 01023 watchers[pos++] = in; 01024 for (o = outgoing; o; o = o->next) { 01025 /* Keep track of important channels */ 01026 if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan) 01027 watchers[pos++] = o->chan; 01028 numlines++; 01029 } 01030 if (pos == 1) { /* only the input channel is available */ 01031 if (numlines == (num.busy + num.congestion + num.nochan)) { 01032 ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan); 01033 if (num.busy) 01034 strcpy(pa->status, "BUSY"); 01035 else if (num.congestion) 01036 strcpy(pa->status, "CONGESTION"); 01037 else if (num.nochan) 01038 strcpy(pa->status, "CHANUNAVAIL"); 01039 } else { 01040 ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan); 01041 } 01042 *to = 0; 01043 if (is_cc_recall) { 01044 ast_cc_failed(cc_recall_core_id, "Everyone is busy/congested for the recall. How sad"); 01045 } 01046 return NULL; 01047 } 01048 winner = ast_waitfor_n(watchers, pos, to); 01049 for (o = outgoing; o; o = o->next) { 01050 struct ast_frame *f; 01051 struct ast_channel *c = o->chan; 01052 01053 if (c == NULL) 01054 continue; 01055 if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) { 01056 if (!peer) { 01057 ast_verb(3, "%s answered %s\n", c->name, in->name); 01058 if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { 01059 if (o->pending_connected_update) { 01060 if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { 01061 ast_channel_update_connected_line(in, &o->connected, NULL); 01062 } 01063 } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { 01064 ast_channel_lock(c); 01065 ast_connected_line_copy_from_caller(&connected_caller, &c->caller); 01066 ast_channel_unlock(c); 01067 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01068 ast_channel_update_connected_line(in, &connected_caller, NULL); 01069 ast_party_connected_line_free(&connected_caller); 01070 } 01071 } 01072 if (o->aoc_s_rate_list) { 01073 size_t encoded_size; 01074 struct ast_aoc_encoded *encoded; 01075 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) { 01076 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size); 01077 ast_aoc_destroy_encoded(encoded); 01078 } 01079 } 01080 peer = c; 01081 ast_copy_flags64(peerflags, o, 01082 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01083 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01084 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01085 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01086 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01087 DIAL_NOFORWARDHTML); 01088 ast_string_field_set(c, dialcontext, ""); 01089 ast_copy_string(c->exten, "", sizeof(c->exten)); 01090 } 01091 continue; 01092 } 01093 if (c != winner) 01094 continue; 01095 /* here, o->chan == c == winner */ 01096 if (!ast_strlen_zero(c->call_forward)) { 01097 pa->sentringing = 0; 01098 if (!ignore_cc && (f = ast_read(c))) { 01099 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_CC) { 01100 /* This channel is forwarding the call, and is capable of CC, so 01101 * be sure to add the new device interface to the list 01102 */ 01103 ast_handle_cc_control_frame(in, c, f->data.ptr); 01104 } 01105 ast_frfree(f); 01106 } 01107 do_forward(o, &num, peerflags, single, to); 01108 continue; 01109 } 01110 f = ast_read(winner); 01111 if (!f) { 01112 in->hangupcause = c->hangupcause; 01113 #ifdef HAVE_EPOLL 01114 ast_poll_channel_del(in, c); 01115 #endif 01116 ast_hangup(c); 01117 c = o->chan = NULL; 01118 ast_clear_flag64(o, DIAL_STILLGOING); 01119 handle_cause(in->hangupcause, &num); 01120 continue; 01121 } 01122 if (f->frametype == AST_FRAME_CONTROL) { 01123 switch (f->subclass.integer) { 01124 case AST_CONTROL_ANSWER: 01125 /* This is our guy if someone answered. */ 01126 if (!peer) { 01127 ast_verb(3, "%s answered %s\n", c->name, in->name); 01128 if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { 01129 if (o->pending_connected_update) { 01130 if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { 01131 ast_channel_update_connected_line(in, &o->connected, NULL); 01132 } 01133 } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { 01134 ast_channel_lock(c); 01135 ast_connected_line_copy_from_caller(&connected_caller, &c->caller); 01136 ast_channel_unlock(c); 01137 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 01138 ast_channel_update_connected_line(in, &connected_caller, NULL); 01139 ast_party_connected_line_free(&connected_caller); 01140 } 01141 } 01142 if (o->aoc_s_rate_list) { 01143 size_t encoded_size; 01144 struct ast_aoc_encoded *encoded; 01145 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) { 01146 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size); 01147 ast_aoc_destroy_encoded(encoded); 01148 } 01149 } 01150 peer = c; 01151 if (peer->cdr) { 01152 peer->cdr->answer = ast_tvnow(); 01153 peer->cdr->disposition = AST_CDR_ANSWERED; 01154 } 01155 ast_copy_flags64(peerflags, o, 01156 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01157 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01158 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01159 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01160 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01161 DIAL_NOFORWARDHTML); 01162 ast_string_field_set(c, dialcontext, ""); 01163 ast_copy_string(c->exten, "", sizeof(c->exten)); 01164 if (CAN_EARLY_BRIDGE(peerflags, in, peer)) 01165 /* Setup early bridge if appropriate */ 01166 ast_channel_early_bridge(in, peer); 01167 } 01168 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 01169 in->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01170 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 01171 break; 01172 case AST_CONTROL_BUSY: 01173 ast_verb(3, "%s is busy\n", c->name); 01174 in->hangupcause = c->hangupcause; 01175 ast_hangup(c); 01176 c = o->chan = NULL; 01177 ast_clear_flag64(o, DIAL_STILLGOING); 01178 handle_cause(AST_CAUSE_BUSY, &num); 01179 break; 01180 case AST_CONTROL_CONGESTION: 01181 ast_verb(3, "%s is circuit-busy\n", c->name); 01182 in->hangupcause = c->hangupcause; 01183 ast_hangup(c); 01184 c = o->chan = NULL; 01185 ast_clear_flag64(o, DIAL_STILLGOING); 01186 handle_cause(AST_CAUSE_CONGESTION, &num); 01187 break; 01188 case AST_CONTROL_RINGING: 01189 /* This is a tricky area to get right when using a native 01190 * CC agent. The reason is that we do the best we can to send only a 01191 * single ringing notification to the caller. 01192 * 01193 * Call completion complicates the logic used here. CCNR is typically 01194 * offered during a ringing message. Let's say that party A calls 01195 * parties B, C, and D. B and C do not support CC requests, but D 01196 * does. If we were to receive a ringing notification from B before 01197 * the others, then we would end up sending a ringing message to 01198 * A with no CCNR offer present. 01199 * 01200 * The approach that we have taken is that if we receive a ringing 01201 * response from a party and no CCNR offer is present, we need to 01202 * wait. Specifically, we need to wait until either a) a called party 01203 * offers CCNR in its ringing response or b) all called parties have 01204 * responded in some way to our call and none offers CCNR. 01205 * 01206 * The drawback to this is that if one of the parties has a delayed 01207 * response or, god forbid, one just plain doesn't respond to our 01208 * outgoing call, then this will result in a significant delay between 01209 * when the caller places the call and hears ringback. 01210 * 01211 * Note also that if CC is disabled for this call, then it is perfectly 01212 * fine for ringing frames to get sent through. 01213 */ 01214 ++num_ringing; 01215 if (ignore_cc || cc_frame_received || num_ringing == numlines) { 01216 ast_verb(3, "%s is ringing\n", c->name); 01217 /* Setup early media if appropriate */ 01218 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 01219 ast_channel_early_bridge(in, c); 01220 if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 01221 ast_indicate(in, AST_CONTROL_RINGING); 01222 pa->sentringing++; 01223 } 01224 } 01225 break; 01226 case AST_CONTROL_PROGRESS: 01227 ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name); 01228 /* Setup early media if appropriate */ 01229 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 01230 ast_channel_early_bridge(in, c); 01231 if (!ast_test_flag64(outgoing, OPT_RINGBACK)) 01232 if (single || (!single && !pa->sentringing)) { 01233 ast_indicate(in, AST_CONTROL_PROGRESS); 01234 } 01235 if(!ast_strlen_zero(dtmf_progress)) { 01236 ast_verb(3, "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", dtmf_progress); 01237 ast_dtmf_stream(c, in, dtmf_progress, 250, 0); 01238 } 01239 break; 01240 case AST_CONTROL_VIDUPDATE: 01241 ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name); 01242 ast_indicate(in, AST_CONTROL_VIDUPDATE); 01243 break; 01244 case AST_CONTROL_SRCUPDATE: 01245 ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name); 01246 ast_indicate(in, AST_CONTROL_SRCUPDATE); 01247 break; 01248 case AST_CONTROL_CONNECTED_LINE: 01249 if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { 01250 ast_verb(3, "Connected line update to %s prevented.\n", in->name); 01251 } else if (!single) { 01252 struct ast_party_connected_line connected; 01253 ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", c->name, in->name); 01254 ast_party_connected_line_set_init(&connected, &o->connected); 01255 ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected); 01256 ast_party_connected_line_set(&o->connected, &connected, NULL); 01257 ast_party_connected_line_free(&connected); 01258 o->pending_connected_update = 1; 01259 } else { 01260 if (ast_channel_connected_line_macro(c, in, f, 1, 1)) { 01261 ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen); 01262 } 01263 } 01264 break; 01265 case AST_CONTROL_AOC: 01266 { 01267 struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan); 01268 if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) { 01269 ast_aoc_destroy_decoded(o->aoc_s_rate_list); 01270 o->aoc_s_rate_list = decoded; 01271 } else { 01272 ast_aoc_destroy_decoded(decoded); 01273 } 01274 } 01275 break; 01276 case AST_CONTROL_REDIRECTING: 01277 if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { 01278 ast_verb(3, "Redirecting update to %s prevented.\n", in->name); 01279 } else { 01280 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", c->name, in->name); 01281 if (ast_channel_redirecting_macro(c, in, f, 1, 1)) { 01282 ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); 01283 } 01284 pa->sentringing = 0; 01285 } 01286 break; 01287 case AST_CONTROL_PROCEEDING: 01288 ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name); 01289 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 01290 ast_channel_early_bridge(in, c); 01291 if (!ast_test_flag64(outgoing, OPT_RINGBACK)) 01292 ast_indicate(in, AST_CONTROL_PROCEEDING); 01293 break; 01294 case AST_CONTROL_HOLD: 01295 ast_verb(3, "Call on %s placed on hold\n", c->name); 01296 ast_indicate(in, AST_CONTROL_HOLD); 01297 break; 01298 case AST_CONTROL_UNHOLD: 01299 ast_verb(3, "Call on %s left from hold\n", c->name); 01300 ast_indicate(in, AST_CONTROL_UNHOLD); 01301 break; 01302 case AST_CONTROL_OFFHOOK: 01303 case AST_CONTROL_FLASH: 01304 /* Ignore going off hook and flash */ 01305 break; 01306 case AST_CONTROL_CC: 01307 if (!ignore_cc) { 01308 ast_handle_cc_control_frame(in, c, f->data.ptr); 01309 cc_frame_received = 1; 01310 } 01311 break; 01312 case -1: 01313 if (!ast_test_flag64(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) { 01314 ast_verb(3, "%s stopped sounds\n", c->name); 01315 ast_indicate(in, -1); 01316 pa->sentringing = 0; 01317 } 01318 break; 01319 default: 01320 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer); 01321 } 01322 } else if (single) { 01323 switch (f->frametype) { 01324 case AST_FRAME_VOICE: 01325 case AST_FRAME_IMAGE: 01326 case AST_FRAME_TEXT: 01327 if (ast_write(in, f)) { 01328 ast_log(LOG_WARNING, "Unable to write frame\n"); 01329 } 01330 break; 01331 case AST_FRAME_HTML: 01332 if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass.integer, f->data.ptr, f->datalen) == -1) { 01333 ast_log(LOG_WARNING, "Unable to send URL\n"); 01334 } 01335 break; 01336 default: 01337 break; 01338 } 01339 } 01340 ast_frfree(f); 01341 } /* end for */ 01342 if (winner == in) { 01343 struct ast_frame *f = ast_read(in); 01344 #if 0 01345 if (f && (f->frametype != AST_FRAME_VOICE)) 01346 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 01347 else if (!f || (f->frametype != AST_FRAME_VOICE)) 01348 printf("Hangup received on %s\n", in->name); 01349 #endif 01350 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) { 01351 /* Got hung up */ 01352 *to = -1; 01353 strcpy(pa->status, "CANCEL"); 01354 ast_cdr_noanswer(in->cdr); 01355 if (f) { 01356 if (f->data.uint32) { 01357 in->hangupcause = f->data.uint32; 01358 } 01359 ast_frfree(f); 01360 } 01361 if (is_cc_recall) { 01362 ast_cc_completed(in, "CC completed, although the caller hung up (cancelled)"); 01363 } 01364 return NULL; 01365 } 01366 01367 /* now f is guaranteed non-NULL */ 01368 if (f->frametype == AST_FRAME_DTMF) { 01369 if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) { 01370 const char *context; 01371 ast_channel_lock(in); 01372 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 01373 if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) { 01374 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer); 01375 *to = 0; 01376 ast_cdr_noanswer(in->cdr); 01377 *result = f->subclass.integer; 01378 strcpy(pa->status, "CANCEL"); 01379 ast_frfree(f); 01380 ast_channel_unlock(in); 01381 if (is_cc_recall) { 01382 ast_cc_completed(in, "CC completed, but the caller used DTMF to exit"); 01383 } 01384 return NULL; 01385 } 01386 ast_channel_unlock(in); 01387 } 01388 01389 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && 01390 detect_disconnect(in, f->subclass.integer, featurecode)) { 01391 ast_verb(3, "User requested call disconnect.\n"); 01392 *to = 0; 01393 strcpy(pa->status, "CANCEL"); 01394 ast_cdr_noanswer(in->cdr); 01395 ast_frfree(f); 01396 if (is_cc_recall) { 01397 ast_cc_completed(in, "CC completed, but the caller hung up with DTMF"); 01398 } 01399 return NULL; 01400 } 01401 } 01402 01403 /* Forward HTML stuff */ 01404 if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML)) 01405 if (ast_channel_sendhtml(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen) == -1) 01406 ast_log(LOG_WARNING, "Unable to send URL\n"); 01407 01408 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) { 01409 if (ast_write(outgoing->chan, f)) 01410 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n"); 01411 } 01412 if (single && (f->frametype == AST_FRAME_CONTROL)) { 01413 if ((f->subclass.integer == AST_CONTROL_HOLD) || 01414 (f->subclass.integer == AST_CONTROL_UNHOLD) || 01415 (f->subclass.integer == AST_CONTROL_VIDUPDATE) || 01416 (f->subclass.integer == AST_CONTROL_SRCUPDATE)) { 01417 ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass.integer, outgoing->chan->name); 01418 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01419 } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) { 01420 if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) { 01421 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01422 } 01423 } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) { 01424 if (ast_channel_redirecting_macro(in, outgoing->chan, f, 0, 1)) { 01425 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01426 } 01427 } 01428 } 01429 ast_frfree(f); 01430 } 01431 if (!*to) 01432 ast_verb(3, "Nobody picked up in %d ms\n", orig); 01433 if (!*to || ast_check_hangup(in)) 01434 ast_cdr_noanswer(in->cdr); 01435 } 01436 01437 #ifdef HAVE_EPOLL 01438 for (epollo = outgoing; epollo; epollo = epollo->next) { 01439 if (epollo->chan) 01440 ast_poll_channel_del(in, epollo->chan); 01441 } 01442 #endif 01443 01444 if (is_cc_recall) { 01445 ast_cc_completed(in, "Recall completed!"); 01446 } 01447 return peer; 01448 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 2885 of file app_dial.c.
const char app[] = "Dial" [static] |
Definition at line 515 of file app_dial.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2885 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 = OPT_CALLER_ANSWER }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'c' ] = { .flag = ((uint64_t)1 << 34) }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'e' ] = { .flag = ((uint64_t)1 << 35) }, [ 'f' ] = { .flag = OPT_FORCECLID , .arg_index = OPT_ARG_FORCECLID + 1 }, [ 'F' ] = { .flag = ((uint64_t)1 << 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 }, [ '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 = ((uint64_t)1 << 38) , .arg_index = OPT_ARG_FORCE_CID_TAG + 1 }, [ 'u' ] = { .flag = ((uint64_t)1 << 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 = ((uint64_t)1 << 37) }, } [static] |
const char rapp[] = "RetryDial" [static] |
Definition at line 516 of file app_dial.c.