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