#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 2897 of file app_dial.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2897 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 1452 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.
01453 { 01454 struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */ 01455 struct ast_call_feature feature = { 0, }; 01456 int res; 01457 01458 ast_str_append(&featurecode, 1, "%c", code); 01459 01460 res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature); 01461 01462 if (res != AST_FEATURE_RETURN_STOREDIGITS) { 01463 ast_str_reset(featurecode); 01464 } 01465 if (feature.feature_mask & AST_FEATURE_DISCONNECT) { 01466 return 1; 01467 } 01468 01469 return 0; 01470 }
static int dial_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 2747 of file app_dial.c.
References dial_exec_full().
Referenced by load_module().
02748 { 02749 struct ast_flags64 peerflags; 02750 02751 memset(&peerflags, 0, sizeof(peerflags)); 02752 02753 return dial_exec_full(chan, data, &peerflags, NULL); 02754 }
static int dial_exec_full | ( | struct ast_channel * | chan, | |
const char * | data, | |||
struct ast_flags64 * | peerflags, | |||
int * | continue_exec | |||
) | [static] |
Definition at line 1787 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().
01788 { 01789 int res = -1; /* default: error */ 01790 char *rest, *cur; /* scan the list of destinations */ 01791 struct chanlist *outgoing = NULL; /* list of destinations */ 01792 struct ast_channel *peer; 01793 int to; /* timeout */ 01794 struct cause_args num = { chan, 0, 0, 0 }; 01795 int cause; 01796 char numsubst[256]; 01797 char *cid_num = NULL, *cid_name = NULL, *cid_tag = NULL, *cid_pres = NULL; 01798 01799 struct ast_bridge_config config = { { 0, } }; 01800 struct timeval calldurationlimit = { 0, }; 01801 char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL; 01802 struct privacy_args pa = { 01803 .sentringing = 0, 01804 .privdb_val = 0, 01805 .status = "INVALIDARGS", 01806 }; 01807 int sentringing = 0, moh = 0; 01808 const char *outbound_group = NULL; 01809 int result = 0; 01810 char *parse; 01811 int opermode = 0; 01812 int delprivintro = 0; 01813 AST_DECLARE_APP_ARGS(args, 01814 AST_APP_ARG(peers); 01815 AST_APP_ARG(timeout); 01816 AST_APP_ARG(options); 01817 AST_APP_ARG(url); 01818 ); 01819 struct ast_flags64 opts = { 0, }; 01820 char *opt_args[OPT_ARG_ARRAY_SIZE]; 01821 struct ast_datastore *datastore = NULL; 01822 int fulldial = 0, num_dialed = 0; 01823 int ignore_cc = 0; 01824 char device_name[AST_CHANNEL_NAME]; 01825 01826 /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */ 01827 pbx_builtin_setvar_helper(chan, "DIALSTATUS", ""); 01828 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); 01829 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ""); 01830 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); 01831 pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); 01832 01833 if (ast_strlen_zero(data)) { 01834 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01835 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01836 return -1; 01837 } 01838 01839 parse = ast_strdupa(data); 01840 01841 AST_STANDARD_APP_ARGS(args, parse); 01842 01843 if (!ast_strlen_zero(args.options) && 01844 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) { 01845 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01846 goto done; 01847 } 01848 01849 if (ast_strlen_zero(args.peers)) { 01850 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01851 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01852 goto done; 01853 } 01854 01855 if (ast_cc_call_init(chan, &ignore_cc)) { 01856 goto done; 01857 } 01858 01859 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) { 01860 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]); 01861 01862 if (delprivintro < 0 || delprivintro > 1) { 01863 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro); 01864 delprivintro = 0; 01865 } 01866 } 01867 01868 if (!ast_test_flag64(&opts, OPT_RINGBACK)) { 01869 opt_args[OPT_ARG_RINGBACK] = NULL; 01870 } 01871 01872 if (ast_test_flag64(&opts, OPT_OPERMODE)) { 01873 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]); 01874 ast_verb(3, "Setting operator services mode to %d.\n", opermode); 01875 } 01876 01877 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) { 01878 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]); 01879 if (!calldurationlimit.tv_sec) { 01880 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]); 01881 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01882 goto done; 01883 } 01884 ast_verb(3, "Setting call duration limit to %.3lf milliseconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0); 01885 } 01886 01887 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { 01888 dtmf_progress = opt_args[OPT_ARG_SENDDTMF]; 01889 dtmfcalled = strsep(&dtmf_progress, ":"); 01890 dtmfcalling = strsep(&dtmf_progress, ":"); 01891 } 01892 01893 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { 01894 if (ast_bridge_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) 01895 goto done; 01896 } 01897 01898 if (ast_test_flag64(&opts, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) 01899 ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &cid_name, &cid_num); 01900 if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) 01901 cid_tag = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_TAG]); 01902 if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) 01903 cid_pres = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_PRES]); 01904 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr) 01905 ast_cdr_reset(chan->cdr, NULL); 01906 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) 01907 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten); 01908 01909 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) { 01910 res = setup_privacy_args(&pa, &opts, opt_args, chan); 01911 if (res <= 0) 01912 goto out; 01913 res = -1; /* reset default */ 01914 } 01915 01916 if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) { 01917 __ast_answer(chan, 0, 0); 01918 } 01919 01920 if (continue_exec) 01921 *continue_exec = 0; 01922 01923 /* If a channel group has been specified, get it for use when we create peer channels */ 01924 01925 ast_channel_lock(chan); 01926 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) { 01927 outbound_group = ast_strdupa(outbound_group); 01928 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL); 01929 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) { 01930 outbound_group = ast_strdupa(outbound_group); 01931 } 01932 ast_channel_unlock(chan); 01933 ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE | 01934 OPT_CANCEL_TIMEOUT | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID); 01935 01936 /* loop through the list of dial destinations */ 01937 rest = args.peers; 01938 while ((cur = strsep(&rest, "&")) ) { 01939 struct chanlist *tmp; 01940 struct ast_channel *tc; /* channel for this destination */ 01941 /* Get a technology/[device:]number pair */ 01942 char *number = cur; 01943 char *interface = ast_strdupa(number); 01944 char *tech = strsep(&number, "/"); 01945 /* find if we already dialed this interface */ 01946 struct ast_dialed_interface *di; 01947 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; 01948 num_dialed++; 01949 if (ast_strlen_zero(number)) { 01950 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); 01951 goto out; 01952 } 01953 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 01954 goto out; 01955 if (opts.flags) { 01956 ast_copy_flags64(tmp, &opts, 01957 OPT_CANCEL_ELSEWHERE | 01958 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 01959 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 01960 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 01961 OPT_CALLEE_PARK | OPT_CALLER_PARK | 01962 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 01963 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID); 01964 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML); 01965 } 01966 ast_copy_string(numsubst, number, sizeof(numsubst)); 01967 /* Request the peer */ 01968 01969 ast_channel_lock(chan); 01970 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); 01971 /* 01972 * Seed the chanlist's connected line information with previously 01973 * acquired connected line info from the incoming channel. The 01974 * previously acquired connected line info could have been set 01975 * through the CONNECTED_LINE dialplan function. 01976 */ 01977 ast_party_connected_line_copy(&tmp->connected, &chan->connected); 01978 ast_channel_unlock(chan); 01979 01980 if (datastore) 01981 dialed_interfaces = datastore->data; 01982 else { 01983 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { 01984 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 01985 chanlist_free(tmp); 01986 goto out; 01987 } 01988 01989 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01990 01991 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { 01992 ast_datastore_free(datastore); 01993 chanlist_free(tmp); 01994 goto out; 01995 } 01996 01997 datastore->data = dialed_interfaces; 01998 AST_LIST_HEAD_INIT(dialed_interfaces); 01999 02000 ast_channel_lock(chan); 02001 ast_channel_datastore_add(chan, datastore); 02002 ast_channel_unlock(chan); 02003 } 02004 02005 AST_LIST_LOCK(dialed_interfaces); 02006 AST_LIST_TRAVERSE(dialed_interfaces, di, list) { 02007 if (!strcasecmp(di->interface, interface)) { 02008 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", 02009 di->interface); 02010 break; 02011 } 02012 } 02013 AST_LIST_UNLOCK(dialed_interfaces); 02014 02015 if (di) { 02016 fulldial++; 02017 chanlist_free(tmp); 02018 continue; 02019 } 02020 02021 /* It is always ok to dial a Local interface. We only keep track of 02022 * which "real" interfaces have been dialed. The Local channel will 02023 * inherit this list so that if it ends up dialing a real interface, 02024 * it won't call one that has already been called. */ 02025 if (strcasecmp(tech, "Local")) { 02026 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) { 02027 AST_LIST_UNLOCK(dialed_interfaces); 02028 chanlist_free(tmp); 02029 goto out; 02030 } 02031 strcpy(di->interface, interface); 02032 02033 AST_LIST_LOCK(dialed_interfaces); 02034 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); 02035 AST_LIST_UNLOCK(dialed_interfaces); 02036 } 02037 02038 tc = ast_request(tech, chan->nativeformats, chan, numsubst, &cause); 02039 if (!tc) { 02040 /* If we can't, just go on to the next call */ 02041 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", 02042 tech, cause, ast_cause2str(cause)); 02043 handle_cause(cause, &num); 02044 if (!rest) /* we are on the last destination */ 02045 chan->hangupcause = cause; 02046 chanlist_free(tmp); 02047 if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) { 02048 if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) { 02049 ast_cc_extension_monitor_add_dialstring(chan, interface, ""); 02050 } 02051 } 02052 continue; 02053 } 02054 ast_channel_get_device_name(tc, device_name, sizeof(device_name)); 02055 if (!ignore_cc) { 02056 ast_cc_extension_monitor_add_dialstring(chan, interface, device_name); 02057 } 02058 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst); 02059 02060 ast_channel_lock(tc); 02061 while (ast_channel_trylock(chan)) { 02062 CHANNEL_DEADLOCK_AVOIDANCE(tc); 02063 } 02064 /* Setup outgoing SDP to match incoming one */ 02065 if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) { 02066 ast_rtp_instance_early_bridge_make_compatible(tc, chan); 02067 } 02068 02069 /* Inherit specially named variables from parent channel */ 02070 ast_channel_inherit_variables(chan, tc); 02071 ast_channel_datastore_inherit(chan, tc); 02072 02073 tc->appl = "AppDial"; 02074 tc->data = "(Outgoing Line)"; 02075 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup)); 02076 02077 /* If the new channel has no callerid, try to guess what it should be */ 02078 if (!tc->caller.id.number.valid) { 02079 if (chan->connected.id.number.valid) { 02080 struct ast_party_caller caller; 02081 02082 ast_party_caller_set_init(&caller, &tc->caller); 02083 caller.id = chan->connected.id; 02084 caller.ani = chan->connected.ani; 02085 ast_channel_set_caller_event(tc, &caller, NULL); 02086 } else if (!ast_strlen_zero(chan->dialed.number.str)) { 02087 ast_set_callerid(tc, chan->dialed.number.str, NULL, NULL); 02088 } else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) { 02089 ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL); 02090 } 02091 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02092 } 02093 02094 if (ast_test_flag64(peerflags, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) { 02095 struct ast_party_connected_line connected; 02096 int pres; 02097 02098 ast_party_connected_line_set_init(&connected, &tc->connected); 02099 if (cid_pres) { 02100 pres = ast_parse_caller_presentation(cid_pres); 02101 if (pres < 0) { 02102 pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02103 } 02104 } else { 02105 pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02106 } 02107 if (cid_num) { 02108 connected.id.number.valid = 1; 02109 connected.id.number.str = cid_num; 02110 connected.id.number.presentation = pres; 02111 } 02112 if (cid_name) { 02113 connected.id.name.valid = 1; 02114 connected.id.name.str = cid_name; 02115 connected.id.name.presentation = pres; 02116 } 02117 connected.id.tag = cid_tag; 02118 ast_channel_set_connected_line(tc, &connected, NULL); 02119 } else { 02120 ast_connected_line_copy_from_caller(&tc->connected, &chan->caller); 02121 } 02122 02123 ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting); 02124 02125 tc->dialed.transit_network_select = chan->dialed.transit_network_select; 02126 02127 if (!ast_strlen_zero(chan->accountcode)) { 02128 ast_string_field_set(tc, peeraccount, chan->accountcode); 02129 } 02130 if (ast_strlen_zero(tc->musicclass)) 02131 ast_string_field_set(tc, musicclass, chan->musicclass); 02132 02133 /* Pass ADSI CPE and transfer capability */ 02134 tc->adsicpe = chan->adsicpe; 02135 tc->transfercapability = chan->transfercapability; 02136 02137 /* If we have an outbound group, set this peer channel to it */ 02138 if (outbound_group) 02139 ast_app_group_set_channel(tc, outbound_group); 02140 /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */ 02141 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE)) 02142 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02143 02144 /* Check if we're forced by configuration */ 02145 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)) 02146 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02147 02148 02149 /* Inherit context and extension */ 02150 ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext); 02151 if (!ast_strlen_zero(chan->macroexten)) 02152 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten)); 02153 else 02154 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten)); 02155 02156 ast_channel_unlock(tc); 02157 res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */ 02158 02159 /* Save the info in cdr's that we called them */ 02160 if (chan->cdr) 02161 ast_cdr_setdestchan(chan->cdr, tc->name); 02162 02163 /* check the results of ast_call */ 02164 if (res) { 02165 /* Again, keep going even if there's an error */ 02166 ast_debug(1, "ast call on peer returned %d\n", res); 02167 ast_verb(3, "Couldn't call %s\n", numsubst); 02168 if (tc->hangupcause) { 02169 chan->hangupcause = tc->hangupcause; 02170 } 02171 ast_channel_unlock(chan); 02172 ast_cc_call_failed(chan, tc, interface); 02173 ast_hangup(tc); 02174 tc = NULL; 02175 chanlist_free(tmp); 02176 continue; 02177 } else { 02178 const char *tmpexten = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02179 senddialevent(chan, tc, numsubst); 02180 ast_verb(3, "Called %s\n", numsubst); 02181 ast_channel_unlock(chan); 02182 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 02183 char cidname[AST_MAX_EXTENSION]; 02184 ast_set_callerid(tc, tmpexten, get_cid_name(cidname, sizeof(cidname), chan), NULL); 02185 } 02186 } 02187 /* Put them in the list of outgoing thingies... We're ready now. 02188 XXX If we're forcibly removed, these outgoing calls won't get 02189 hung up XXX */ 02190 ast_set_flag64(tmp, DIAL_STILLGOING); 02191 tmp->chan = tc; 02192 tmp->next = outgoing; 02193 outgoing = tmp; 02194 /* If this line is up, don't try anybody else */ 02195 if (outgoing->chan->_state == AST_STATE_UP) 02196 break; 02197 } 02198 02199 if (ast_strlen_zero(args.timeout)) { 02200 to = -1; 02201 } else { 02202 to = atoi(args.timeout); 02203 if (to > 0) 02204 to *= 1000; 02205 else { 02206 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout); 02207 to = -1; 02208 } 02209 } 02210 02211 if (!outgoing) { 02212 strcpy(pa.status, "CHANUNAVAIL"); 02213 if (fulldial == num_dialed) { 02214 res = -1; 02215 goto out; 02216 } 02217 } else { 02218 /* Our status will at least be NOANSWER */ 02219 strcpy(pa.status, "NOANSWER"); 02220 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) { 02221 moh = 1; 02222 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) { 02223 char *original_moh = ast_strdupa(chan->musicclass); 02224 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]); 02225 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL); 02226 ast_string_field_set(chan, musicclass, original_moh); 02227 } else { 02228 ast_moh_start(chan, NULL, NULL); 02229 } 02230 ast_indicate(chan, AST_CONTROL_PROGRESS); 02231 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) { 02232 if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 02233 if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){ 02234 ast_indicate(chan, AST_CONTROL_RINGING); 02235 sentringing++; 02236 } else { 02237 ast_indicate(chan, AST_CONTROL_PROGRESS); 02238 } 02239 } else { 02240 ast_indicate(chan, AST_CONTROL_RINGING); 02241 sentringing++; 02242 } 02243 } 02244 } 02245 02246 peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress, ignore_cc); 02247 02248 /* The ast_channel_datastore_remove() function could fail here if the 02249 * datastore was moved to another channel during a masquerade. If this is 02250 * the case, don't free the datastore here because later, when the channel 02251 * to which the datastore was moved hangs up, it will attempt to free this 02252 * datastore again, causing a crash 02253 */ 02254 if (!ast_channel_datastore_remove(chan, datastore)) 02255 ast_datastore_free(datastore); 02256 if (!peer) { 02257 if (result) { 02258 res = result; 02259 } else if (to) { /* Musta gotten hung up */ 02260 res = -1; 02261 } else { /* Nobody answered, next please? */ 02262 res = 0; 02263 } 02264 02265 /* SIP, in particular, sends back this error code to indicate an 02266 * overlap dialled number needs more digits. */ 02267 if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) { 02268 res = AST_PBX_INCOMPLETE; 02269 } 02270 02271 /* almost done, although the 'else' block is 400 lines */ 02272 } else { 02273 const char *number; 02274 02275 if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) 02276 ast_answer(chan); 02277 02278 strcpy(pa.status, "ANSWER"); 02279 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02280 /* Ah ha! Someone answered within the desired timeframe. Of course after this 02281 we will always return with -1 so that it is hung up properly after the 02282 conversation. */ 02283 hanguptree(outgoing, peer, 1); 02284 outgoing = NULL; 02285 /* If appropriate, log that we have a destination channel and set the answer time */ 02286 if (chan->cdr) { 02287 ast_cdr_setdestchan(chan->cdr, peer->name); 02288 ast_cdr_setanswer(chan->cdr, peer->cdr->answer); 02289 } 02290 if (peer->name) 02291 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name); 02292 02293 ast_channel_lock(peer); 02294 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 02295 if (!number) 02296 number = numsubst; 02297 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); 02298 ast_channel_unlock(peer); 02299 02300 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { 02301 ast_debug(1, "app_dial: sendurl=%s.\n", args.url); 02302 ast_channel_sendurl( peer, args.url ); 02303 } 02304 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) { 02305 if (do_privacy(chan, peer, &opts, opt_args, &pa)) { 02306 res = 0; 02307 goto out; 02308 } 02309 } 02310 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) { 02311 res = 0; 02312 } else { 02313 int digit = 0; 02314 struct ast_channel *chans[2]; 02315 struct ast_channel *active_chan; 02316 02317 chans[0] = chan; 02318 chans[1] = peer; 02319 02320 /* we need to stream the announcment while monitoring the caller for a hangup */ 02321 02322 /* stream the file */ 02323 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language); 02324 if (res) { 02325 res = 0; 02326 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]); 02327 } 02328 02329 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY); 02330 while (peer->stream) { 02331 int ms; 02332 02333 ms = ast_sched_wait(peer->sched); 02334 02335 if (ms < 0 && !peer->timingfunc) { 02336 ast_stopstream(peer); 02337 break; 02338 } 02339 if (ms < 0) 02340 ms = 1000; 02341 02342 active_chan = ast_waitfor_n(chans, 2, &ms); 02343 if (active_chan) { 02344 struct ast_frame *fr = ast_read(active_chan); 02345 if (!fr) { 02346 ast_hangup(peer); 02347 res = -1; 02348 goto done; 02349 } 02350 switch(fr->frametype) { 02351 case AST_FRAME_DTMF_END: 02352 digit = fr->subclass.integer; 02353 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) { 02354 ast_stopstream(peer); 02355 res = ast_senddigit(chan, digit, 0); 02356 } 02357 break; 02358 case AST_FRAME_CONTROL: 02359 switch (fr->subclass.integer) { 02360 case AST_CONTROL_HANGUP: 02361 ast_frfree(fr); 02362 ast_hangup(peer); 02363 res = -1; 02364 goto done; 02365 default: 02366 break; 02367 } 02368 break; 02369 default: 02370 /* Ignore all others */ 02371 break; 02372 } 02373 ast_frfree(fr); 02374 } 02375 ast_sched_runq(peer->sched); 02376 } 02377 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY); 02378 } 02379 02380 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { 02381 /* chan and peer are going into the PBX, they both 02382 * should probably get CDR records. */ 02383 ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED); 02384 ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED); 02385 02386 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]); 02387 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); 02388 /* peer goes to the same context and extension as chan, so just copy info from chan*/ 02389 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02390 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02391 peer->priority = chan->priority + 2; 02392 ast_pbx_start(peer); 02393 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0); 02394 if (continue_exec) 02395 *continue_exec = 1; 02396 res = 0; 02397 goto done; 02398 } 02399 02400 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) { 02401 struct ast_app *theapp; 02402 const char *macro_result; 02403 02404 res = ast_autoservice_start(chan); 02405 if (res) { 02406 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02407 res = -1; 02408 } 02409 02410 theapp = pbx_findapp("Macro"); 02411 02412 if (theapp && !res) { /* XXX why check res here ? */ 02413 /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */ 02414 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02415 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02416 02417 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]); 02418 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]); 02419 ast_debug(1, "Macro exited with status %d\n", res); 02420 res = 0; 02421 } else { 02422 ast_log(LOG_ERROR, "Could not find application Macro\n"); 02423 res = -1; 02424 } 02425 02426 if (ast_autoservice_stop(chan) < 0) { 02427 res = -1; 02428 } 02429 02430 ast_channel_lock(peer); 02431 02432 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) { 02433 char *macro_transfer_dest; 02434 02435 if (!strcasecmp(macro_result, "BUSY")) { 02436 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02437 ast_set_flag64(peerflags, OPT_GO_ON); 02438 res = -1; 02439 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { 02440 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02441 ast_set_flag64(peerflags, OPT_GO_ON); 02442 res = -1; 02443 } else if (!strcasecmp(macro_result, "CONTINUE")) { 02444 /* hangup peer and keep chan alive assuming the macro has changed 02445 the context / exten / priority or perhaps 02446 the next priority in the current exten is desired. 02447 */ 02448 ast_set_flag64(peerflags, OPT_GO_ON); 02449 res = -1; 02450 } else if (!strcasecmp(macro_result, "ABORT")) { 02451 /* Hangup both ends unless the caller has the g flag */ 02452 res = -1; 02453 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { 02454 res = -1; 02455 /* perform a transfer to a new extension */ 02456 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/ 02457 replace_macro_delimiter(macro_transfer_dest); 02458 if (!ast_parseable_goto(chan, macro_transfer_dest)) 02459 ast_set_flag64(peerflags, OPT_GO_ON); 02460 } 02461 } 02462 } 02463 02464 ast_channel_unlock(peer); 02465 } 02466 02467 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) { 02468 struct ast_app *theapp; 02469 const char *gosub_result; 02470 char *gosub_args, *gosub_argstart; 02471 int res9 = -1; 02472 02473 res9 = ast_autoservice_start(chan); 02474 if (res9) { 02475 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02476 res9 = -1; 02477 } 02478 02479 theapp = pbx_findapp("Gosub"); 02480 02481 if (theapp && !res9) { 02482 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]); 02483 02484 /* Set where we came from */ 02485 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context)); 02486 ast_copy_string(peer->exten, "s", sizeof(peer->exten)); 02487 peer->priority = 0; 02488 02489 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ','); 02490 if (gosub_argstart) { 02491 const char *what_is_s = "s"; 02492 *gosub_argstart = 0; 02493 if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) && 02494 ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02495 what_is_s = "~~s~~"; 02496 } 02497 if (asprintf(&gosub_args, "%s,%s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s, gosub_argstart + 1) < 0) { 02498 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02499 gosub_args = NULL; 02500 } 02501 *gosub_argstart = ','; 02502 } else { 02503 const char *what_is_s = "s"; 02504 if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) && 02505 ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02506 what_is_s = "~~s~~"; 02507 } 02508 if (asprintf(&gosub_args, "%s,%s,1", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s) < 0) { 02509 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02510 gosub_args = NULL; 02511 } 02512 } 02513 02514 if (gosub_args) { 02515 res9 = pbx_exec(peer, theapp, gosub_args); 02516 if (!res9) { 02517 struct ast_pbx_args args; 02518 /* A struct initializer fails to compile for this case ... */ 02519 memset(&args, 0, sizeof(args)); 02520 args.no_hangup_chan = 1; 02521 ast_pbx_run_args(peer, &args); 02522 } 02523 ast_free(gosub_args); 02524 ast_debug(1, "Gosub exited with status %d\n", res9); 02525 } else { 02526 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n"); 02527 } 02528 02529 } else if (!res9) { 02530 ast_log(LOG_ERROR, "Could not find application Gosub\n"); 02531 res9 = -1; 02532 } 02533 02534 if (ast_autoservice_stop(chan) < 0) { 02535 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n"); 02536 res9 = -1; 02537 } 02538 02539 ast_channel_lock(peer); 02540 02541 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) { 02542 char *gosub_transfer_dest; 02543 const char *gosub_retval = pbx_builtin_getvar_helper(peer, "GOSUB_RETVAL"); 02544 02545 /* Inherit return value from the peer, so it can be used in the master */ 02546 if (gosub_retval) { 02547 pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", gosub_retval); 02548 } 02549 02550 if (!strcasecmp(gosub_result, "BUSY")) { 02551 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02552 ast_set_flag64(peerflags, OPT_GO_ON); 02553 res = -1; 02554 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) { 02555 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02556 ast_set_flag64(peerflags, OPT_GO_ON); 02557 res = -1; 02558 } else if (!strcasecmp(gosub_result, "CONTINUE")) { 02559 /* hangup peer and keep chan alive assuming the macro has changed 02560 the context / exten / priority or perhaps 02561 the next priority in the current exten is desired. 02562 */ 02563 ast_set_flag64(peerflags, OPT_GO_ON); 02564 res = -1; 02565 } else if (!strcasecmp(gosub_result, "ABORT")) { 02566 /* Hangup both ends unless the caller has the g flag */ 02567 res = -1; 02568 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) { 02569 res = -1; 02570 /* perform a transfer to a new extension */ 02571 if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/ 02572 replace_macro_delimiter(gosub_transfer_dest); 02573 if (!ast_parseable_goto(chan, gosub_transfer_dest)) 02574 ast_set_flag64(peerflags, OPT_GO_ON); 02575 } 02576 } 02577 } 02578 02579 ast_channel_unlock(peer); 02580 } 02581 02582 if (!res) { 02583 if (!ast_tvzero(calldurationlimit)) { 02584 struct timeval whentohangup = calldurationlimit; 02585 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup); 02586 } 02587 if (!ast_strlen_zero(dtmfcalled)) { 02588 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled); 02589 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0); 02590 } 02591 if (!ast_strlen_zero(dtmfcalling)) { 02592 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling); 02593 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0); 02594 } 02595 } 02596 02597 if (res) { /* some error */ 02598 res = -1; 02599 } else { 02600 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER)) 02601 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02602 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER)) 02603 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02604 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP)) 02605 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT); 02606 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP)) 02607 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT); 02608 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR)) 02609 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 02610 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR)) 02611 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 02612 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK)) 02613 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL); 02614 if (ast_test_flag64(peerflags, OPT_CALLER_PARK)) 02615 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL); 02616 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR)) 02617 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON); 02618 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR)) 02619 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON); 02620 if (ast_test_flag64(peerflags, OPT_GO_ON)) 02621 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN); 02622 02623 config.end_bridge_callback = end_bridge_callback; 02624 config.end_bridge_callback_data = chan; 02625 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; 02626 02627 if (moh) { 02628 moh = 0; 02629 ast_moh_stop(chan); 02630 } else if (sentringing) { 02631 sentringing = 0; 02632 ast_indicate(chan, -1); 02633 } 02634 /* Be sure no generators are left on it and reset the visible indication */ 02635 ast_deactivate_generator(chan); 02636 chan->visible_indication = 0; 02637 /* Make sure channels are compatible */ 02638 res = ast_channel_make_compatible(chan, peer); 02639 if (res < 0) { 02640 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name); 02641 ast_hangup(peer); 02642 res = -1; 02643 goto done; 02644 } 02645 if (opermode) { 02646 struct oprmode oprmode; 02647 02648 oprmode.peer = peer; 02649 oprmode.mode = opermode; 02650 02651 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0); 02652 } 02653 res = ast_bridge_call(chan, peer, &config); 02654 } 02655 02656 strcpy(peer->context, chan->context); 02657 02658 if (ast_test_flag64(&opts, OPT_PEER_H) 02659 && ast_exists_extension(peer, peer->context, "h", 1, 02660 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02661 int autoloopflag; 02662 int found; 02663 int res9; 02664 02665 strcpy(peer->exten, "h"); 02666 peer->priority = 1; 02667 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02668 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP); 02669 02670 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, 02671 peer->priority, 02672 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL), 02673 &found, 1)) == 0) { 02674 peer->priority++; 02675 } 02676 02677 if (found && res9) { 02678 /* Something bad happened, or a hangup has been requested. */ 02679 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02680 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name); 02681 } 02682 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */ 02683 } 02684 if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) { 02685 if(!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) { 02686 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]); 02687 ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]); 02688 } else { /* F() */ 02689 int res; 02690 res = ast_goto_if_exists(peer, chan->context, chan->exten, (chan->priority) + 1); 02691 if (res == AST_PBX_GOTO_FAILED) { 02692 ast_hangup(peer); 02693 goto out; 02694 } 02695 } 02696 ast_pbx_start(peer); 02697 } else { 02698 if (!ast_check_hangup(chan)) 02699 chan->hangupcause = peer->hangupcause; 02700 ast_hangup(peer); 02701 } 02702 } 02703 out: 02704 if (moh) { 02705 moh = 0; 02706 ast_moh_stop(chan); 02707 } else if (sentringing) { 02708 sentringing = 0; 02709 ast_indicate(chan, -1); 02710 } 02711 02712 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02713 ast_filedelete(pa.privintro, NULL); 02714 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02715 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro); 02716 } else { 02717 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro); 02718 } 02719 } 02720 02721 ast_channel_early_bridge(chan, NULL); 02722 hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */ 02723 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02724 senddialendevent(chan, pa.status); 02725 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status); 02726 02727 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) { 02728 if (!ast_tvzero(calldurationlimit)) 02729 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup)); 02730 res = 0; 02731 } 02732 02733 done: 02734 if (config.warning_sound) { 02735 ast_free((char *)config.warning_sound); 02736 } 02737 if (config.end_sound) { 02738 ast_free((char *)config.end_sound); 02739 } 02740 if (config.start_sound) { 02741 ast_free((char *)config.start_sound); 02742 } 02743 ast_ignore_cc(chan); 02744 return res; 02745 }
static int dial_handle_playtones | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 1757 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().
01758 { 01759 struct ast_tone_zone_sound *ts = NULL; 01760 int res; 01761 const char *str = data; 01762 01763 if (ast_strlen_zero(str)) { 01764 ast_debug(1,"Nothing to play\n"); 01765 return -1; 01766 } 01767 01768 ts = ast_get_indication_tone(chan->zone, str); 01769 01770 if (ts && ts->data[0]) { 01771 res = ast_playtones_start(chan, 0, ts->data, 0); 01772 } else { 01773 res = -1; 01774 } 01775 01776 if (ts) { 01777 ts = ast_tone_zone_sound_unref(ts); 01778 } 01779 01780 if (res) { 01781 ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str); 01782 } 01783 01784 return res; 01785 }
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 1728 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().
01729 { 01730 char buf[80]; 01731 time_t end; 01732 struct ast_channel *chan = data; 01733 01734 if (!chan->cdr) { 01735 return; 01736 } 01737 01738 time(&end); 01739 01740 ast_channel_lock(chan); 01741 if (chan->cdr->answer.tv_sec) { 01742 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec); 01743 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 01744 } 01745 01746 if (chan->cdr->start.tv_sec) { 01747 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec); 01748 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 01749 } 01750 ast_channel_unlock(chan); 01751 }
static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
struct ast_channel * | originator, | |||
struct ast_channel * | terminator | |||
) | [static] |
Definition at line 1753 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec(), and dial_exec_full().
01753 { 01754 bconfig->end_bridge_callback_data = originator; 01755 }
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 2880 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().
02881 { 02882 int res; 02883 struct ast_context *con; 02884 02885 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial"); 02886 if (!con) 02887 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n"); 02888 else 02889 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial"); 02890 02891 res = ast_register_application_xml(app, dial_exec); 02892 res |= ast_register_application_xml(rapp, retrydial_exec); 02893 02894 return res; 02895 }
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 2756 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().
02757 { 02758 char *parse; 02759 const char *context = NULL; 02760 int sleepms = 0, loops = 0, res = -1; 02761 struct ast_flags64 peerflags = { 0, }; 02762 AST_DECLARE_APP_ARGS(args, 02763 AST_APP_ARG(announce); 02764 AST_APP_ARG(sleep); 02765 AST_APP_ARG(retries); 02766 AST_APP_ARG(dialdata); 02767 ); 02768 02769 if (ast_strlen_zero(data)) { 02770 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 02771 return -1; 02772 } 02773 02774 parse = ast_strdupa(data); 02775 AST_STANDARD_APP_ARGS(args, parse); 02776 02777 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep))) 02778 sleepms *= 1000; 02779 02780 if (!ast_strlen_zero(args.retries)) { 02781 loops = atoi(args.retries); 02782 } 02783 02784 if (!args.dialdata) { 02785 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp); 02786 goto done; 02787 } 02788 02789 if (sleepms < 1000) 02790 sleepms = 10000; 02791 02792 if (!loops) 02793 loops = -1; /* run forever */ 02794 02795 ast_channel_lock(chan); 02796 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 02797 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL; 02798 ast_channel_unlock(chan); 02799 02800 res = 0; 02801 while (loops) { 02802 int continue_exec; 02803 02804 chan->data = "Retrying"; 02805 if (ast_test_flag(chan, AST_FLAG_MOH)) 02806 ast_moh_stop(chan); 02807 02808 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec); 02809 if (continue_exec) 02810 break; 02811 02812 if (res == 0) { 02813 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) { 02814 if (!ast_strlen_zero(args.announce)) { 02815 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 02816 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 02817 ast_waitstream(chan, AST_DIGIT_ANY); 02818 } else 02819 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 02820 } 02821 if (!res && sleepms) { 02822 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02823 ast_moh_start(chan, NULL, NULL); 02824 res = ast_waitfordigit(chan, sleepms); 02825 } 02826 } else { 02827 if (!ast_strlen_zero(args.announce)) { 02828 if (ast_fileexists(args.announce, NULL, chan->language) > 0) { 02829 if (!(res = ast_streamfile(chan, args.announce, chan->language))) 02830 res = ast_waitstream(chan, ""); 02831 } else 02832 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 02833 } 02834 if (sleepms) { 02835 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02836 ast_moh_start(chan, NULL, NULL); 02837 if (!res) 02838 res = ast_waitfordigit(chan, sleepms); 02839 } 02840 } 02841 } 02842 02843 if (res < 0 || res == AST_PBX_INCOMPLETE) { 02844 break; 02845 } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 02846 if (onedigit_goto(chan, context, (char) res, 1)) { 02847 res = 0; 02848 break; 02849 } 02850 } 02851 loops--; 02852 } 02853 if (loops == 0) 02854 res = 0; 02855 else if (res == 1) 02856 res = 0; 02857 02858 if (ast_test_flag(chan, AST_FLAG_MOH)) 02859 ast_moh_stop(chan); 02860 done: 02861 return res; 02862 }
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 1626 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().
01628 { 01629 char callerid[60]; 01630 int res; 01631 char *l; 01632 int silencethreshold; 01633 01634 if (chan->caller.id.number.valid 01635 && !ast_strlen_zero(chan->caller.id.number.str)) { 01636 l = ast_strdupa(chan->caller.id.number.str); 01637 ast_shrink_phone_number(l); 01638 if (ast_test_flag64(opts, OPT_PRIVACY) ) { 01639 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l); 01640 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l); 01641 } else { 01642 ast_verb(3, "Privacy Screening, clid is '%s'\n", l); 01643 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01644 } 01645 } else { 01646 char *tnam, *tn2; 01647 01648 tnam = ast_strdupa(chan->name); 01649 /* clean the channel name so slashes don't try to end up in disk file name */ 01650 for (tn2 = tnam; *tn2; tn2++) { 01651 if (*tn2 == '/') /* any other chars to be afraid of? */ 01652 *tn2 = '='; 01653 } 01654 ast_verb(3, "Privacy-- callerid is empty\n"); 01655 01656 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); 01657 l = callerid; 01658 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01659 } 01660 01661 ast_copy_string(pa->privcid, l, sizeof(pa->privcid)); 01662 01663 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) { 01664 /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */ 01665 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid); 01666 pa->privdb_val = AST_PRIVACY_ALLOW; 01667 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) { 01668 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val); 01669 } 01670 01671 if (pa->privdb_val == AST_PRIVACY_DENY) { 01672 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); 01673 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status)); 01674 return 0; 01675 } else if (pa->privdb_val == AST_PRIVACY_KILL) { 01676 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status)); 01677 return 0; /* Is this right? */ 01678 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) { 01679 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status)); 01680 return 0; /* is this right??? */ 01681 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) { 01682 /* Get the user's intro, store it in priv-callerintros/$CID, 01683 unless it is already there-- this should be done before the 01684 call is actually dialed */ 01685 01686 /* make sure the priv-callerintros dir actually exists */ 01687 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR); 01688 if ((res = ast_mkdir(pa->privintro, 0755))) { 01689 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res)); 01690 return -1; 01691 } 01692 01693 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); 01694 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) { 01695 /* the DELUX version of this code would allow this caller the 01696 option to hear and retape their previously recorded intro. 01697 */ 01698 } else { 01699 int duration; /* for feedback from play_and_wait */ 01700 /* the file doesn't exist yet. Let the caller submit his 01701 vocal intro for posterity */ 01702 /* priv-recordintro script: 01703 01704 "At the tone, please say your name:" 01705 01706 */ 01707 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE); 01708 ast_answer(chan); 01709 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 */ 01710 /* don't think we'll need a lock removed, we took care of 01711 conflicts by naming the pa.privintro file */ 01712 if (res == -1) { 01713 /* Delete the file regardless since they hung up during recording */ 01714 ast_filedelete(pa->privintro, NULL); 01715 if (ast_fileexists(pa->privintro, NULL, NULL) > 0) 01716 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro); 01717 else 01718 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro); 01719 return -1; 01720 } 01721 if (!ast_streamfile(chan, "vm-dialout", chan->language) ) 01722 ast_waitstream(chan, ""); 01723 } 01724 } 01725 return 1; /* success */ 01726 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2864 of file app_dial.c.
References ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), and ast_unregister_application().
02865 { 02866 int res; 02867 struct ast_context *con; 02868 02869 res = ast_unregister_application(app); 02870 res |= ast_unregister_application(rapp); 02871 02872 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) { 02873 ast_context_remove_extension2(con, "s", 1, NULL, 0); 02874 ast_context_destroy(con, "app_dial"); /* leave nothing behind */ 02875 } 02876 02877 return res; 02878 }
static int valid_priv_reply | ( | struct ast_flags64 * | opts, | |
int | res | |||
) | [static] |
Definition at line 1480 of file app_dial.c.
References ast_test_flag64, OPT_PRIVACY, and OPT_SCREENING.
01481 { 01482 if (res < '1') 01483 return 0; 01484 if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5') 01485 return 1; 01486 if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4') 01487 return 1; 01488 return 0; 01489 }
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 if (single) { 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 frametype: %d\n", 01329 f->frametype); 01330 } 01331 break; 01332 case AST_FRAME_HTML: 01333 if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) 01334 && ast_channel_sendhtml(in, f->subclass.integer, f->data.ptr, f->datalen) == -1) { 01335 ast_log(LOG_WARNING, "Unable to send URL\n"); 01336 } 01337 break; 01338 default: 01339 break; 01340 } 01341 } 01342 ast_frfree(f); 01343 } /* end for */ 01344 if (winner == in) { 01345 struct ast_frame *f = ast_read(in); 01346 #if 0 01347 if (f && (f->frametype != AST_FRAME_VOICE)) 01348 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 01349 else if (!f || (f->frametype != AST_FRAME_VOICE)) 01350 printf("Hangup received on %s\n", in->name); 01351 #endif 01352 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) { 01353 /* Got hung up */ 01354 *to = -1; 01355 strcpy(pa->status, "CANCEL"); 01356 ast_cdr_noanswer(in->cdr); 01357 if (f) { 01358 if (f->data.uint32) { 01359 in->hangupcause = f->data.uint32; 01360 } 01361 ast_frfree(f); 01362 } 01363 if (is_cc_recall) { 01364 ast_cc_completed(in, "CC completed, although the caller hung up (cancelled)"); 01365 } 01366 return NULL; 01367 } 01368 01369 /* now f is guaranteed non-NULL */ 01370 if (f->frametype == AST_FRAME_DTMF) { 01371 if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) { 01372 const char *context; 01373 ast_channel_lock(in); 01374 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 01375 if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) { 01376 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer); 01377 *to = 0; 01378 ast_cdr_noanswer(in->cdr); 01379 *result = f->subclass.integer; 01380 strcpy(pa->status, "CANCEL"); 01381 ast_frfree(f); 01382 ast_channel_unlock(in); 01383 if (is_cc_recall) { 01384 ast_cc_completed(in, "CC completed, but the caller used DTMF to exit"); 01385 } 01386 return NULL; 01387 } 01388 ast_channel_unlock(in); 01389 } 01390 01391 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && 01392 detect_disconnect(in, f->subclass.integer, featurecode)) { 01393 ast_verb(3, "User requested call disconnect.\n"); 01394 *to = 0; 01395 strcpy(pa->status, "CANCEL"); 01396 ast_cdr_noanswer(in->cdr); 01397 ast_frfree(f); 01398 if (is_cc_recall) { 01399 ast_cc_completed(in, "CC completed, but the caller hung up with DTMF"); 01400 } 01401 return NULL; 01402 } 01403 } 01404 01405 /* Forward HTML stuff */ 01406 if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML)) 01407 if (ast_channel_sendhtml(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen) == -1) 01408 ast_log(LOG_WARNING, "Unable to send URL\n"); 01409 01410 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) { 01411 if (ast_write(outgoing->chan, f)) 01412 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n"); 01413 } 01414 if (single && (f->frametype == AST_FRAME_CONTROL)) { 01415 if ((f->subclass.integer == AST_CONTROL_HOLD) || 01416 (f->subclass.integer == AST_CONTROL_UNHOLD) || 01417 (f->subclass.integer == AST_CONTROL_VIDUPDATE) || 01418 (f->subclass.integer == AST_CONTROL_SRCUPDATE)) { 01419 ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass.integer, outgoing->chan->name); 01420 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01421 } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) { 01422 if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) { 01423 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01424 } 01425 } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) { 01426 if (ast_channel_redirecting_macro(in, outgoing->chan, f, 0, 1)) { 01427 ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); 01428 } 01429 } 01430 } 01431 ast_frfree(f); 01432 } 01433 if (!*to) 01434 ast_verb(3, "Nobody picked up in %d ms\n", orig); 01435 if (!*to || ast_check_hangup(in)) 01436 ast_cdr_noanswer(in->cdr); 01437 } 01438 01439 #ifdef HAVE_EPOLL 01440 for (epollo = outgoing; epollo; epollo = epollo->next) { 01441 if (epollo->chan) 01442 ast_poll_channel_del(in, epollo->chan); 01443 } 01444 #endif 01445 01446 if (is_cc_recall) { 01447 ast_cc_completed(in, "Recall completed!"); 01448 } 01449 return peer; 01450 }
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 2897 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 2897 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.