#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_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) } |
| 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 } |
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 = AST_BUILDOPT_SUM, .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 | ) |
Definition at line 657 of file app_dial.c.
Referenced by dial_exec_full(), do_forward(), and wait_for_answer().
| #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 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 };
| 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 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 3072 of file app_dial.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3072 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.
Referenced by wait_for_answer().
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 2922 of file app_dial.c.
References dial_exec_full().
Referenced by load_module().
02923 { 02924 struct ast_flags64 peerflags; 02925 02926 memset(&peerflags, 0, sizeof(peerflags)); 02927 02928 return dial_exec_full(chan, data, &peerflags, NULL); 02929 }
| static int dial_exec_full | ( | struct ast_channel * | chan, | |
| const char * | data, | |||
| struct ast_flags64 * | peerflags, | |||
| int * | continue_exec | |||
| ) | [static] |
< TRUE if force CallerID on call forward only. Legacy behaviour.
Forced CallerID party information to send.
This will not have any malloced strings so do not free it.
Definition at line 1863 of file app_dial.c.
References ast_channel::_state, 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_accountcode(), 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_language(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_musicclass(), ast_channel_name(), 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_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, chanlist_free(), CHANNEL_DEADLOCK_AVOIDANCE, ast_channel::connected, chanlist::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, ast_channel::dialed, dialed_interface_info, end_bridge_callback(), ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, end_bridge_callback_data_fixup(), ast_bridge_config::end_bridge_callback_data_fixup, ast_bridge_config::end_sound, errno, ast_channel::exten, ast_bridge_config::features_callee, ast_bridge_config::features_caller, 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_dialed_interface::interface, ast_dialed_interface::list, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, oprmode::mode, moh, ast_party_id::name, ast_channel::nativeformats, chanlist::next, ast_pbx_args::no_hangup_chan, 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(), ast_bridge_config::start_sound, 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, ast_channel::visible_indication, wait_for_answer(), ast_bridge_config::warning_sound, and ast_channel::whentohangup.
Referenced by dial_exec(), and retrydial_exec().
01864 { 01865 int res = -1; /* default: error */ 01866 char *rest, *cur; /* scan the list of destinations */ 01867 struct chanlist *outgoing = NULL; /* list of destinations */ 01868 struct ast_channel *peer; 01869 int to; /* timeout */ 01870 struct cause_args num = { chan, 0, 0, 0 }; 01871 int cause; 01872 char numsubst[256]; 01873 01874 struct ast_bridge_config config = { { 0, } }; 01875 struct timeval calldurationlimit = { 0, }; 01876 char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL; 01877 struct privacy_args pa = { 01878 .sentringing = 0, 01879 .privdb_val = 0, 01880 .status = "INVALIDARGS", 01881 }; 01882 int sentringing = 0, moh = 0; 01883 const char *outbound_group = NULL; 01884 int result = 0; 01885 char *parse; 01886 int opermode = 0; 01887 int delprivintro = 0; 01888 AST_DECLARE_APP_ARGS(args, 01889 AST_APP_ARG(peers); 01890 AST_APP_ARG(timeout); 01891 AST_APP_ARG(options); 01892 AST_APP_ARG(url); 01893 ); 01894 struct ast_flags64 opts = { 0, }; 01895 char *opt_args[OPT_ARG_ARRAY_SIZE]; 01896 struct ast_datastore *datastore = NULL; 01897 int fulldial = 0, num_dialed = 0; 01898 int ignore_cc = 0; 01899 char device_name[AST_CHANNEL_NAME]; 01900 char forced_clid_name[AST_MAX_EXTENSION]; 01901 char stored_clid_name[AST_MAX_EXTENSION]; 01902 int force_forwards_only; /*!< TRUE if force CallerID on call forward only. Legacy behaviour.*/ 01903 /*! 01904 * \brief Forced CallerID party information to send. 01905 * \note This will not have any malloced strings so do not free it. 01906 */ 01907 struct ast_party_id forced_clid; 01908 /*! 01909 * \brief Stored CallerID information if needed. 01910 * 01911 * \note If OPT_ORIGINAL_CLID set then this is the o option 01912 * CallerID. Otherwise it is the dialplan extension and hint 01913 * name. 01914 * 01915 * \note This will not have any malloced strings so do not free it. 01916 */ 01917 struct ast_party_id stored_clid; 01918 /*! 01919 * \brief CallerID party information to store. 01920 * \note This will not have any malloced strings so do not free it. 01921 */ 01922 struct ast_party_caller caller; 01923 01924 /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */ 01925 pbx_builtin_setvar_helper(chan, "DIALSTATUS", ""); 01926 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); 01927 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ""); 01928 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); 01929 pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); 01930 01931 if (ast_strlen_zero(data)) { 01932 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01933 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01934 return -1; 01935 } 01936 01937 parse = ast_strdupa(data); 01938 01939 AST_STANDARD_APP_ARGS(args, parse); 01940 01941 if (!ast_strlen_zero(args.options) && 01942 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) { 01943 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01944 goto done; 01945 } 01946 01947 if (ast_strlen_zero(args.peers)) { 01948 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); 01949 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01950 goto done; 01951 } 01952 01953 if (ast_cc_call_init(chan, &ignore_cc)) { 01954 goto done; 01955 } 01956 01957 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) { 01958 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]); 01959 01960 if (delprivintro < 0 || delprivintro > 1) { 01961 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro); 01962 delprivintro = 0; 01963 } 01964 } 01965 01966 if (!ast_test_flag64(&opts, OPT_RINGBACK)) { 01967 opt_args[OPT_ARG_RINGBACK] = NULL; 01968 } 01969 01970 if (ast_test_flag64(&opts, OPT_OPERMODE)) { 01971 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]); 01972 ast_verb(3, "Setting operator services mode to %d.\n", opermode); 01973 } 01974 01975 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) { 01976 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]); 01977 if (!calldurationlimit.tv_sec) { 01978 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]); 01979 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 01980 goto done; 01981 } 01982 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0); 01983 } 01984 01985 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { 01986 dtmf_progress = opt_args[OPT_ARG_SENDDTMF]; 01987 dtmfcalled = strsep(&dtmf_progress, ":"); 01988 dtmfcalling = strsep(&dtmf_progress, ":"); 01989 } 01990 01991 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { 01992 if (ast_bridge_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) 01993 goto done; 01994 } 01995 01996 /* Setup the forced CallerID information to send if used. */ 01997 ast_party_id_init(&forced_clid); 01998 force_forwards_only = 0; 01999 if (ast_test_flag64(&opts, OPT_FORCECLID)) { 02000 if (ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) { 02001 ast_channel_lock(chan); 02002 forced_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02003 ast_channel_unlock(chan); 02004 forced_clid_name[0] = '\0'; 02005 forced_clid.name.str = (char *) get_cid_name(forced_clid_name, 02006 sizeof(forced_clid_name), chan); 02007 force_forwards_only = 1; 02008 } else { 02009 /* Note: The opt_args[OPT_ARG_FORCECLID] string value is altered here. */ 02010 ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &forced_clid.name.str, 02011 &forced_clid.number.str); 02012 } 02013 if (!ast_strlen_zero(forced_clid.name.str)) { 02014 forced_clid.name.valid = 1; 02015 } 02016 if (!ast_strlen_zero(forced_clid.number.str)) { 02017 forced_clid.number.valid = 1; 02018 } 02019 } 02020 if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) 02021 && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) { 02022 forced_clid.tag = opt_args[OPT_ARG_FORCE_CID_TAG]; 02023 } 02024 forced_clid.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 02025 if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) 02026 && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) { 02027 int pres; 02028 02029 pres = ast_parse_caller_presentation(opt_args[OPT_ARG_FORCE_CID_PRES]); 02030 if (0 <= pres) { 02031 forced_clid.number.presentation = pres; 02032 } 02033 } 02034 02035 /* Setup the stored CallerID information if needed. */ 02036 ast_party_id_init(&stored_clid); 02037 if (ast_test_flag64(&opts, OPT_ORIGINAL_CLID)) { 02038 if (ast_strlen_zero(opt_args[OPT_ARG_ORIGINAL_CLID])) { 02039 ast_channel_lock(chan); 02040 ast_party_id_set_init(&stored_clid, &chan->caller.id); 02041 if (!ast_strlen_zero(chan->caller.id.name.str)) { 02042 stored_clid.name.str = ast_strdupa(chan->caller.id.name.str); 02043 } 02044 if (!ast_strlen_zero(chan->caller.id.number.str)) { 02045 stored_clid.number.str = ast_strdupa(chan->caller.id.number.str); 02046 } 02047 if (!ast_strlen_zero(chan->caller.id.subaddress.str)) { 02048 stored_clid.subaddress.str = ast_strdupa(chan->caller.id.subaddress.str); 02049 } 02050 if (!ast_strlen_zero(chan->caller.id.tag)) { 02051 stored_clid.tag = ast_strdupa(chan->caller.id.tag); 02052 } 02053 ast_channel_unlock(chan); 02054 } else { 02055 /* Note: The opt_args[OPT_ARG_ORIGINAL_CLID] string value is altered here. */ 02056 ast_callerid_parse(opt_args[OPT_ARG_ORIGINAL_CLID], &stored_clid.name.str, 02057 &stored_clid.number.str); 02058 if (!ast_strlen_zero(stored_clid.name.str)) { 02059 stored_clid.name.valid = 1; 02060 } 02061 if (!ast_strlen_zero(stored_clid.number.str)) { 02062 stored_clid.number.valid = 1; 02063 } 02064 } 02065 } else { 02066 /* 02067 * In case the new channel has no preset CallerID number by the 02068 * channel driver, setup the dialplan extension and hint name. 02069 */ 02070 stored_clid_name[0] = '\0'; 02071 stored_clid.name.str = (char *) get_cid_name(stored_clid_name, 02072 sizeof(stored_clid_name), chan); 02073 if (ast_strlen_zero(stored_clid.name.str)) { 02074 stored_clid.name.str = NULL; 02075 } else { 02076 stored_clid.name.valid = 1; 02077 } 02078 ast_channel_lock(chan); 02079 stored_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten)); 02080 stored_clid.number.valid = 1; 02081 ast_channel_unlock(chan); 02082 } 02083 02084 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr) 02085 ast_cdr_reset(chan->cdr, NULL); 02086 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) 02087 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten); 02088 02089 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) { 02090 res = setup_privacy_args(&pa, &opts, opt_args, chan); 02091 if (res <= 0) 02092 goto out; 02093 res = -1; /* reset default */ 02094 } 02095 02096 if (continue_exec) 02097 *continue_exec = 0; 02098 02099 /* If a channel group has been specified, get it for use when we create peer channels */ 02100 02101 ast_channel_lock(chan); 02102 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) { 02103 outbound_group = ast_strdupa(outbound_group); 02104 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL); 02105 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) { 02106 outbound_group = ast_strdupa(outbound_group); 02107 } 02108 ast_channel_unlock(chan); 02109 ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE | 02110 OPT_CANCEL_TIMEOUT | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID); 02111 02112 /* loop through the list of dial destinations */ 02113 rest = args.peers; 02114 while ((cur = strsep(&rest, "&")) ) { 02115 struct chanlist *tmp; 02116 struct ast_channel *tc; /* channel for this destination */ 02117 /* Get a technology/[device:]number pair */ 02118 char *number = cur; 02119 char *interface = ast_strdupa(number); 02120 char *tech = strsep(&number, "/"); 02121 /* find if we already dialed this interface */ 02122 struct ast_dialed_interface *di; 02123 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; 02124 num_dialed++; 02125 if (ast_strlen_zero(number)) { 02126 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); 02127 goto out; 02128 } 02129 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 02130 goto out; 02131 if (opts.flags) { 02132 ast_copy_flags64(tmp, &opts, 02133 OPT_CANCEL_ELSEWHERE | 02134 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 02135 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 02136 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 02137 OPT_CALLEE_PARK | OPT_CALLER_PARK | 02138 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR | 02139 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID); 02140 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML); 02141 } 02142 ast_copy_string(numsubst, number, sizeof(numsubst)); 02143 /* Request the peer */ 02144 02145 ast_channel_lock(chan); 02146 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); 02147 /* 02148 * Seed the chanlist's connected line information with previously 02149 * acquired connected line info from the incoming channel. The 02150 * previously acquired connected line info could have been set 02151 * through the CONNECTED_LINE dialplan function. 02152 */ 02153 ast_party_connected_line_copy(&tmp->connected, &chan->connected); 02154 ast_channel_unlock(chan); 02155 02156 if (datastore) 02157 dialed_interfaces = datastore->data; 02158 else { 02159 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { 02160 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 02161 chanlist_free(tmp); 02162 goto out; 02163 } 02164 02165 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 02166 02167 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { 02168 ast_datastore_free(datastore); 02169 chanlist_free(tmp); 02170 goto out; 02171 } 02172 02173 datastore->data = dialed_interfaces; 02174 AST_LIST_HEAD_INIT(dialed_interfaces); 02175 02176 ast_channel_lock(chan); 02177 ast_channel_datastore_add(chan, datastore); 02178 ast_channel_unlock(chan); 02179 } 02180 02181 AST_LIST_LOCK(dialed_interfaces); 02182 AST_LIST_TRAVERSE(dialed_interfaces, di, list) { 02183 if (!strcasecmp(di->interface, interface)) { 02184 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", 02185 di->interface); 02186 break; 02187 } 02188 } 02189 AST_LIST_UNLOCK(dialed_interfaces); 02190 02191 if (di) { 02192 fulldial++; 02193 chanlist_free(tmp); 02194 continue; 02195 } 02196 02197 /* It is always ok to dial a Local interface. We only keep track of 02198 * which "real" interfaces have been dialed. The Local channel will 02199 * inherit this list so that if it ends up dialing a real interface, 02200 * it won't call one that has already been called. */ 02201 if (strcasecmp(tech, "Local")) { 02202 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) { 02203 AST_LIST_UNLOCK(dialed_interfaces); 02204 chanlist_free(tmp); 02205 goto out; 02206 } 02207 strcpy(di->interface, interface); 02208 02209 AST_LIST_LOCK(dialed_interfaces); 02210 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); 02211 AST_LIST_UNLOCK(dialed_interfaces); 02212 } 02213 02214 tc = ast_request(tech, chan->nativeformats, chan, numsubst, &cause); 02215 if (!tc) { 02216 /* If we can't, just go on to the next call */ 02217 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", 02218 tech, cause, ast_cause2str(cause)); 02219 handle_cause(cause, &num); 02220 if (!rest) /* we are on the last destination */ 02221 chan->hangupcause = cause; 02222 chanlist_free(tmp); 02223 if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) { 02224 if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) { 02225 ast_cc_extension_monitor_add_dialstring(chan, interface, ""); 02226 } 02227 } 02228 continue; 02229 } 02230 ast_channel_get_device_name(tc, device_name, sizeof(device_name)); 02231 if (!ignore_cc) { 02232 ast_cc_extension_monitor_add_dialstring(chan, interface, device_name); 02233 } 02234 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst); 02235 02236 ast_channel_lock(tc); 02237 while (ast_channel_trylock(chan)) { 02238 CHANNEL_DEADLOCK_AVOIDANCE(tc); 02239 } 02240 /* Setup outgoing SDP to match incoming one */ 02241 if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) { 02242 ast_rtp_instance_early_bridge_make_compatible(tc, chan); 02243 } 02244 02245 /* Inherit specially named variables from parent channel */ 02246 ast_channel_inherit_variables(chan, tc); 02247 ast_channel_datastore_inherit(chan, tc); 02248 02249 tc->appl = "AppDial"; 02250 tc->data = "(Outgoing Line)"; 02251 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup)); 02252 02253 /* Determine CallerID to store in outgoing channel. */ 02254 ast_party_caller_set_init(&caller, &tc->caller); 02255 if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) { 02256 caller.id = stored_clid; 02257 ast_channel_set_caller_event(tc, &caller, NULL); 02258 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02259 } else if (ast_strlen_zero(S_COR(tc->caller.id.number.valid, 02260 tc->caller.id.number.str, NULL))) { 02261 /* 02262 * The new channel has no preset CallerID number by the channel 02263 * driver. Use the dialplan extension and hint name. 02264 */ 02265 caller.id = stored_clid; 02266 if (!caller.id.name.valid 02267 && !ast_strlen_zero(S_COR(chan->connected.id.name.valid, 02268 chan->connected.id.name.str, NULL))) { 02269 /* 02270 * No hint name available. We have a connected name supplied by 02271 * the dialplan we can use instead. 02272 */ 02273 caller.id.name.valid = 1; 02274 caller.id.name = chan->connected.id.name; 02275 } 02276 ast_channel_set_caller_event(tc, &caller, NULL); 02277 ast_set_flag64(tmp, DIAL_CALLERID_ABSENT); 02278 } else if (ast_strlen_zero(S_COR(tc->caller.id.name.valid, tc->caller.id.name.str, 02279 NULL))) { 02280 /* The new channel has no preset CallerID name by the channel driver. */ 02281 if (!ast_strlen_zero(S_COR(chan->connected.id.name.valid, 02282 chan->connected.id.name.str, NULL))) { 02283 /* 02284 * We have a connected name supplied by the dialplan we can 02285 * use instead. 02286 */ 02287 caller.id.name.valid = 1; 02288 caller.id.name = chan->connected.id.name; 02289 ast_channel_set_caller_event(tc, &caller, NULL); 02290 } 02291 } 02292 02293 /* Determine CallerID for outgoing channel to send. */ 02294 if (ast_test_flag64(peerflags, OPT_FORCECLID) && !force_forwards_only) { 02295 struct ast_party_connected_line connected; 02296 02297 ast_party_connected_line_set_init(&connected, &tc->connected); 02298 connected.id = forced_clid; 02299 ast_channel_set_connected_line(tc, &connected, NULL); 02300 } else { 02301 ast_connected_line_copy_from_caller(&tc->connected, &chan->caller); 02302 } 02303 02304 ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting); 02305 02306 tc->dialed.transit_network_select = chan->dialed.transit_network_select; 02307 02308 if (!ast_strlen_zero(ast_channel_accountcode(chan))) { 02309 ast_channel_peeraccount_set(tc, ast_channel_accountcode(chan)); 02310 } 02311 if (ast_strlen_zero(ast_channel_musicclass(tc))) 02312 ast_channel_musicclass_set(tc, ast_channel_musicclass(chan)); 02313 02314 /* Pass ADSI CPE and transfer capability */ 02315 tc->adsicpe = chan->adsicpe; 02316 tc->transfercapability = chan->transfercapability; 02317 02318 /* If we have an outbound group, set this peer channel to it */ 02319 if (outbound_group) 02320 ast_app_group_set_channel(tc, outbound_group); 02321 /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */ 02322 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE)) 02323 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02324 02325 /* Check if we're forced by configuration */ 02326 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)) 02327 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE); 02328 02329 02330 /* Inherit context and extension */ 02331 ast_channel_dialcontext_set(tc, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext); 02332 if (!ast_strlen_zero(chan->macroexten)) 02333 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten)); 02334 else 02335 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten)); 02336 02337 ast_channel_unlock(tc); 02338 ast_channel_unlock(chan); 02339 res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */ 02340 ast_channel_lock(chan); 02341 02342 /* Save the info in cdr's that we called them */ 02343 if (chan->cdr) 02344 ast_cdr_setdestchan(chan->cdr, ast_channel_name(tc)); 02345 02346 /* check the results of ast_call */ 02347 if (res) { 02348 /* Again, keep going even if there's an error */ 02349 ast_debug(1, "ast call on peer returned %d\n", res); 02350 ast_verb(3, "Couldn't call %s/%s\n", tech, numsubst); 02351 if (tc->hangupcause) { 02352 chan->hangupcause = tc->hangupcause; 02353 } 02354 ast_channel_unlock(chan); 02355 ast_cc_call_failed(chan, tc, interface); 02356 ast_hangup(tc); 02357 tc = NULL; 02358 chanlist_free(tmp); 02359 continue; 02360 } else { 02361 senddialevent(chan, tc, numsubst); 02362 ast_verb(3, "Called %s/%s\n", tech, numsubst); 02363 ast_channel_unlock(chan); 02364 } 02365 /* Put them in the list of outgoing thingies... We're ready now. 02366 XXX If we're forcibly removed, these outgoing calls won't get 02367 hung up XXX */ 02368 ast_set_flag64(tmp, DIAL_STILLGOING); 02369 tmp->chan = tc; 02370 tmp->next = outgoing; 02371 outgoing = tmp; 02372 /* If this line is up, don't try anybody else */ 02373 if (outgoing->chan->_state == AST_STATE_UP) 02374 break; 02375 } 02376 02377 if (ast_strlen_zero(args.timeout)) { 02378 to = -1; 02379 } else { 02380 to = atoi(args.timeout); 02381 if (to > 0) 02382 to *= 1000; 02383 else { 02384 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout); 02385 to = -1; 02386 } 02387 } 02388 02389 if (!outgoing) { 02390 strcpy(pa.status, "CHANUNAVAIL"); 02391 if (fulldial == num_dialed) { 02392 res = -1; 02393 goto out; 02394 } 02395 } else { 02396 /* Our status will at least be NOANSWER */ 02397 strcpy(pa.status, "NOANSWER"); 02398 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) { 02399 moh = 1; 02400 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) { 02401 char *original_moh = ast_strdupa(ast_channel_musicclass(chan)); 02402 ast_channel_musicclass_set(chan, opt_args[OPT_ARG_MUSICBACK]); 02403 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL); 02404 ast_channel_musicclass_set(chan, original_moh); 02405 } else { 02406 ast_moh_start(chan, NULL, NULL); 02407 } 02408 ast_indicate(chan, AST_CONTROL_PROGRESS); 02409 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) { 02410 if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { 02411 if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){ 02412 ast_indicate(chan, AST_CONTROL_RINGING); 02413 sentringing++; 02414 } else { 02415 ast_indicate(chan, AST_CONTROL_PROGRESS); 02416 } 02417 } else { 02418 ast_indicate(chan, AST_CONTROL_RINGING); 02419 sentringing++; 02420 } 02421 } 02422 } 02423 02424 peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, 02425 dtmf_progress, ignore_cc, &forced_clid, &stored_clid); 02426 02427 /* The ast_channel_datastore_remove() function could fail here if the 02428 * datastore was moved to another channel during a masquerade. If this is 02429 * the case, don't free the datastore here because later, when the channel 02430 * to which the datastore was moved hangs up, it will attempt to free this 02431 * datastore again, causing a crash 02432 */ 02433 ast_channel_lock(chan); 02434 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); /* make sure we weren't cleaned up already */ 02435 if (datastore && !ast_channel_datastore_remove(chan, datastore)) { 02436 ast_datastore_free(datastore); 02437 } 02438 ast_channel_unlock(chan); 02439 if (!peer) { 02440 if (result) { 02441 res = result; 02442 } else if (to) { /* Musta gotten hung up */ 02443 res = -1; 02444 } else { /* Nobody answered, next please? */ 02445 res = 0; 02446 } 02447 } else { 02448 const char *number; 02449 02450 if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) 02451 ast_answer(chan); 02452 02453 strcpy(pa.status, "ANSWER"); 02454 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02455 /* Ah ha! Someone answered within the desired timeframe. Of course after this 02456 we will always return with -1 so that it is hung up properly after the 02457 conversation. */ 02458 hanguptree(outgoing, peer, 1); 02459 outgoing = NULL; 02460 /* If appropriate, log that we have a destination channel and set the answer time */ 02461 if (chan->cdr) { 02462 ast_cdr_setdestchan(chan->cdr, ast_channel_name(peer)); 02463 ast_cdr_setanswer(chan->cdr, peer->cdr->answer); 02464 } 02465 if (ast_channel_name(peer)) 02466 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer)); 02467 02468 ast_channel_lock(peer); 02469 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 02470 if (!number) 02471 number = numsubst; 02472 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); 02473 ast_channel_unlock(peer); 02474 02475 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { 02476 ast_debug(1, "app_dial: sendurl=%s.\n", args.url); 02477 ast_channel_sendurl( peer, args.url ); 02478 } 02479 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) { 02480 if (do_privacy(chan, peer, &opts, opt_args, &pa)) { 02481 res = 0; 02482 goto out; 02483 } 02484 } 02485 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) { 02486 res = 0; 02487 } else { 02488 int digit = 0; 02489 struct ast_channel *chans[2]; 02490 struct ast_channel *active_chan; 02491 02492 chans[0] = chan; 02493 chans[1] = peer; 02494 02495 /* we need to stream the announcment while monitoring the caller for a hangup */ 02496 02497 /* stream the file */ 02498 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], ast_channel_language(peer)); 02499 if (res) { 02500 res = 0; 02501 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]); 02502 } 02503 02504 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY); 02505 while (peer->stream) { 02506 int ms; 02507 02508 ms = ast_sched_wait(peer->sched); 02509 02510 if (ms < 0 && !peer->timingfunc) { 02511 ast_stopstream(peer); 02512 break; 02513 } 02514 if (ms < 0) 02515 ms = 1000; 02516 02517 active_chan = ast_waitfor_n(chans, 2, &ms); 02518 if (active_chan) { 02519 struct ast_frame *fr = ast_read(active_chan); 02520 if (!fr) { 02521 ast_hangup(peer); 02522 res = -1; 02523 goto done; 02524 } 02525 switch(fr->frametype) { 02526 case AST_FRAME_DTMF_END: 02527 digit = fr->subclass.integer; 02528 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) { 02529 ast_stopstream(peer); 02530 res = ast_senddigit(chan, digit, 0); 02531 } 02532 break; 02533 case AST_FRAME_CONTROL: 02534 switch (fr->subclass.integer) { 02535 case AST_CONTROL_HANGUP: 02536 ast_frfree(fr); 02537 ast_hangup(peer); 02538 res = -1; 02539 goto done; 02540 default: 02541 break; 02542 } 02543 break; 02544 default: 02545 /* Ignore all others */ 02546 break; 02547 } 02548 ast_frfree(fr); 02549 } 02550 ast_sched_runq(peer->sched); 02551 } 02552 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY); 02553 } 02554 02555 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { 02556 /* chan and peer are going into the PBX, they both 02557 * should probably get CDR records. */ 02558 ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED); 02559 ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED); 02560 02561 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]); 02562 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); 02563 /* peer goes to the same context and extension as chan, so just copy info from chan*/ 02564 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02565 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02566 peer->priority = chan->priority + 2; 02567 ast_pbx_start(peer); 02568 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0); 02569 if (continue_exec) 02570 *continue_exec = 1; 02571 res = 0; 02572 goto done; 02573 } 02574 02575 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) { 02576 struct ast_app *theapp; 02577 const char *macro_result; 02578 02579 res = ast_autoservice_start(chan); 02580 if (res) { 02581 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02582 res = -1; 02583 } 02584 02585 theapp = pbx_findapp("Macro"); 02586 02587 if (theapp && !res) { /* XXX why check res here ? */ 02588 /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */ 02589 ast_copy_string(peer->context, chan->context, sizeof(peer->context)); 02590 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten)); 02591 02592 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]); 02593 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]); 02594 ast_debug(1, "Macro exited with status %d\n", res); 02595 res = 0; 02596 } else { 02597 ast_log(LOG_ERROR, "Could not find application Macro\n"); 02598 res = -1; 02599 } 02600 02601 if (ast_autoservice_stop(chan) < 0) { 02602 res = -1; 02603 } 02604 02605 ast_channel_lock(peer); 02606 02607 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) { 02608 char *macro_transfer_dest; 02609 02610 if (!strcasecmp(macro_result, "BUSY")) { 02611 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02612 ast_set_flag64(peerflags, OPT_GO_ON); 02613 res = -1; 02614 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) { 02615 ast_copy_string(pa.status, macro_result, sizeof(pa.status)); 02616 ast_set_flag64(peerflags, OPT_GO_ON); 02617 res = -1; 02618 } else if (!strcasecmp(macro_result, "CONTINUE")) { 02619 /* hangup peer and keep chan alive assuming the macro has changed 02620 the context / exten / priority or perhaps 02621 the next priority in the current exten is desired. 02622 */ 02623 ast_set_flag64(peerflags, OPT_GO_ON); 02624 res = -1; 02625 } else if (!strcasecmp(macro_result, "ABORT")) { 02626 /* Hangup both ends unless the caller has the g flag */ 02627 res = -1; 02628 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) { 02629 res = -1; 02630 /* perform a transfer to a new extension */ 02631 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/ 02632 replace_macro_delimiter(macro_transfer_dest); 02633 if (!ast_parseable_goto(chan, macro_transfer_dest)) 02634 ast_set_flag64(peerflags, OPT_GO_ON); 02635 } 02636 } 02637 } 02638 02639 ast_channel_unlock(peer); 02640 } 02641 02642 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) { 02643 struct ast_app *theapp; 02644 const char *gosub_result; 02645 char *gosub_args, *gosub_argstart; 02646 int res9 = -1; 02647 02648 res9 = ast_autoservice_start(chan); 02649 if (res9) { 02650 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n"); 02651 res9 = -1; 02652 } 02653 02654 theapp = pbx_findapp("Gosub"); 02655 02656 if (theapp && !res9) { 02657 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]); 02658 02659 /* Set where we came from */ 02660 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context)); 02661 ast_copy_string(peer->exten, "s", sizeof(peer->exten)); 02662 peer->priority = 0; 02663 02664 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ','); 02665 if (gosub_argstart) { 02666 const char *what_is_s = "s"; 02667 *gosub_argstart = 0; 02668 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)) && 02669 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 what_is_s = "~~s~~"; 02671 } 02672 if (asprintf(&gosub_args, "%s,%s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s, gosub_argstart + 1) < 0) { 02673 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02674 gosub_args = NULL; 02675 } 02676 *gosub_argstart = ','; 02677 } else { 02678 const char *what_is_s = "s"; 02679 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)) && 02680 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 what_is_s = "~~s~~"; 02682 } 02683 if (asprintf(&gosub_args, "%s,%s,1", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s) < 0) { 02684 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 02685 gosub_args = NULL; 02686 } 02687 } 02688 02689 if (gosub_args) { 02690 res9 = pbx_exec(peer, theapp, gosub_args); 02691 if (!res9) { 02692 struct ast_pbx_args args; 02693 /* A struct initializer fails to compile for this case ... */ 02694 memset(&args, 0, sizeof(args)); 02695 args.no_hangup_chan = 1; 02696 ast_pbx_run_args(peer, &args); 02697 } 02698 ast_free(gosub_args); 02699 ast_debug(1, "Gosub exited with status %d\n", res9); 02700 } else { 02701 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n"); 02702 } 02703 02704 } else if (!res9) { 02705 ast_log(LOG_ERROR, "Could not find application Gosub\n"); 02706 res9 = -1; 02707 } 02708 02709 if (ast_autoservice_stop(chan) < 0) { 02710 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n"); 02711 res9 = -1; 02712 } 02713 02714 ast_channel_lock(peer); 02715 02716 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) { 02717 char *gosub_transfer_dest; 02718 const char *gosub_retval = pbx_builtin_getvar_helper(peer, "GOSUB_RETVAL"); 02719 02720 /* Inherit return value from the peer, so it can be used in the master */ 02721 if (gosub_retval) { 02722 pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", gosub_retval); 02723 } 02724 02725 if (!strcasecmp(gosub_result, "BUSY")) { 02726 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02727 ast_set_flag64(peerflags, OPT_GO_ON); 02728 res = -1; 02729 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) { 02730 ast_copy_string(pa.status, gosub_result, sizeof(pa.status)); 02731 ast_set_flag64(peerflags, OPT_GO_ON); 02732 res = -1; 02733 } else if (!strcasecmp(gosub_result, "CONTINUE")) { 02734 /* hangup peer and keep chan alive assuming the macro has changed 02735 the context / exten / priority or perhaps 02736 the next priority in the current exten is desired. 02737 */ 02738 ast_set_flag64(peerflags, OPT_GO_ON); 02739 res = -1; 02740 } else if (!strcasecmp(gosub_result, "ABORT")) { 02741 /* Hangup both ends unless the caller has the g flag */ 02742 res = -1; 02743 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) { 02744 res = -1; 02745 /* perform a transfer to a new extension */ 02746 if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/ 02747 replace_macro_delimiter(gosub_transfer_dest); 02748 if (!ast_parseable_goto(chan, gosub_transfer_dest)) 02749 ast_set_flag64(peerflags, OPT_GO_ON); 02750 } 02751 } 02752 } 02753 02754 ast_channel_unlock(peer); 02755 } 02756 02757 if (!res) { 02758 if (!ast_tvzero(calldurationlimit)) { 02759 struct timeval whentohangup = calldurationlimit; 02760 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup); 02761 } 02762 if (!ast_strlen_zero(dtmfcalled)) { 02763 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled); 02764 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0); 02765 } 02766 if (!ast_strlen_zero(dtmfcalling)) { 02767 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling); 02768 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0); 02769 } 02770 } 02771 02772 if (res) { /* some error */ 02773 res = -1; 02774 } else { 02775 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER)) 02776 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT); 02777 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER)) 02778 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT); 02779 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP)) 02780 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT); 02781 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP)) 02782 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT); 02783 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR)) 02784 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON); 02785 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR)) 02786 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); 02787 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK)) 02788 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL); 02789 if (ast_test_flag64(peerflags, OPT_CALLER_PARK)) 02790 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL); 02791 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR)) 02792 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON); 02793 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR)) 02794 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON); 02795 if (ast_test_flag64(peerflags, OPT_GO_ON)) 02796 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN); 02797 02798 config.end_bridge_callback = end_bridge_callback; 02799 config.end_bridge_callback_data = chan; 02800 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; 02801 02802 if (moh) { 02803 moh = 0; 02804 ast_moh_stop(chan); 02805 } else if (sentringing) { 02806 sentringing = 0; 02807 ast_indicate(chan, -1); 02808 } 02809 /* Be sure no generators are left on it and reset the visible indication */ 02810 ast_deactivate_generator(chan); 02811 chan->visible_indication = 0; 02812 /* Make sure channels are compatible */ 02813 res = ast_channel_make_compatible(chan, peer); 02814 if (res < 0) { 02815 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(chan), ast_channel_name(peer)); 02816 ast_hangup(peer); 02817 res = -1; 02818 goto done; 02819 } 02820 if (opermode) { 02821 struct oprmode oprmode; 02822 02823 oprmode.peer = peer; 02824 oprmode.mode = opermode; 02825 02826 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0); 02827 } 02828 res = ast_bridge_call(chan, peer, &config); 02829 } 02830 02831 strcpy(peer->context, chan->context); 02832 02833 if (ast_test_flag64(&opts, OPT_PEER_H) 02834 && ast_exists_extension(peer, peer->context, "h", 1, 02835 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) { 02836 int autoloopflag; 02837 int found; 02838 int res9; 02839 02840 strcpy(peer->exten, "h"); 02841 peer->priority = 1; 02842 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02843 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP); 02844 02845 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, 02846 peer->priority, 02847 S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL), 02848 &found, 1)) == 0) { 02849 peer->priority++; 02850 } 02851 02852 if (found && res9) { 02853 /* Something bad happened, or a hangup has been requested. */ 02854 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, ast_channel_name(peer)); 02855 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, ast_channel_name(peer)); 02856 } 02857 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */ 02858 } 02859 if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) { 02860 if(!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) { 02861 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]); 02862 ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]); 02863 } else { /* F() */ 02864 int res; 02865 res = ast_goto_if_exists(peer, chan->context, chan->exten, (chan->priority) + 1); 02866 if (res == AST_PBX_GOTO_FAILED) { 02867 ast_hangup(peer); 02868 goto out; 02869 } 02870 } 02871 ast_pbx_start(peer); 02872 } else { 02873 if (!ast_check_hangup(chan)) 02874 chan->hangupcause = peer->hangupcause; 02875 ast_hangup(peer); 02876 } 02877 } 02878 out: 02879 if (moh) { 02880 moh = 0; 02881 ast_moh_stop(chan); 02882 } else if (sentringing) { 02883 sentringing = 0; 02884 ast_indicate(chan, -1); 02885 } 02886 02887 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02888 ast_filedelete(pa.privintro, NULL); 02889 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) { 02890 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro); 02891 } else { 02892 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro); 02893 } 02894 } 02895 02896 ast_channel_early_bridge(chan, NULL); 02897 hanguptree(outgoing, NULL, 0); /* In this case, there's no answer anywhere */ 02898 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); 02899 senddialendevent(chan, pa.status); 02900 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status); 02901 02902 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) { 02903 if (!ast_tvzero(calldurationlimit)) 02904 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup)); 02905 res = 0; 02906 } 02907 02908 done: 02909 if (config.warning_sound) { 02910 ast_free((char *)config.warning_sound); 02911 } 02912 if (config.end_sound) { 02913 ast_free((char *)config.end_sound); 02914 } 02915 if (config.start_sound) { 02916 ast_free((char *)config.start_sound); 02917 } 02918 ast_ignore_cc(chan); 02919 return res; 02920 }
| static int dial_handle_playtones | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 1833 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().
01834 { 01835 struct ast_tone_zone_sound *ts = NULL; 01836 int res; 01837 const char *str = data; 01838 01839 if (ast_strlen_zero(str)) { 01840 ast_debug(1,"Nothing to play\n"); 01841 return -1; 01842 } 01843 01844 ts = ast_get_indication_tone(chan->zone, str); 01845 01846 if (ts && ts->data[0]) { 01847 res = ast_playtones_start(chan, 0, ts->data, 0); 01848 } else { 01849 res = -1; 01850 } 01851 01852 if (ts) { 01853 ts = ast_tone_zone_sound_unref(ts); 01854 } 01855 01856 if (res) { 01857 ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str); 01858 } 01859 01860 return res; 01861 }
| 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::appl, ast_call(), AST_CAUSE_BUSY, AST_CEL_FORWARD, ast_cel_report_event(), ast_channel_accountcode(), ast_channel_call_forward(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_name(), 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_strlen_zero(), ast_test_flag64, ast_verb, ast_channel::caller, CAN_EARLY_BRIDGE, cause, cause_args::chan, chanlist::chan, CHANNEL_DEADLOCK_AVOIDANCE, ast_channel::connected, ast_channel::context, ast_channel::data, DIAL_STILLGOING, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, handle_cause(), ast_party_connected_line::id, ast_party_caller::id, LOG_NOTICE, ast_channel::macroexten, 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.
Referenced by wait_for_answer().
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, ast_channel_call_forward(c), 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", ast_channel_call_forward(c), 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, ast_channel_call_forward(c), 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", ast_channel_name(in), tech, stuff, ast_channel_name(c)); 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", ast_channel_name(in), 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", ast_channel_name(o->chan)); 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_channel_accountcode_set(c, ast_channel_accountcode(in)); 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 1804 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(), dial_exec_full(), and try_calling().
01805 { 01806 char buf[80]; 01807 time_t end; 01808 struct ast_channel *chan = data; 01809 01810 if (!chan->cdr) { 01811 return; 01812 } 01813 01814 time(&end); 01815 01816 ast_channel_lock(chan); 01817 if (chan->cdr->answer.tv_sec) { 01818 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec); 01819 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 01820 } 01821 01822 if (chan->cdr->start.tv_sec) { 01823 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec); 01824 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 01825 } 01826 ast_channel_unlock(chan); 01827 }
| static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
| struct ast_channel * | originator, | |||
| struct ast_channel * | terminator | |||
| ) | [static] |
Definition at line 1829 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec(), dial_exec_full(), and try_calling().
01829 { 01830 bconfig->end_bridge_callback_data = originator; 01831 }
| 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(), do_forward(), and wait_for_answer().
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 3055 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().
03056 { 03057 int res; 03058 struct ast_context *con; 03059 03060 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial"); 03061 if (!con) 03062 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n"); 03063 else 03064 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial"); 03065 03066 res = ast_register_application_xml(app, dial_exec); 03067 res |= ast_register_application_xml(rapp, retrydial_exec); 03068 03069 return res; 03070 }
| 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(), and wait_for_answer().
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 2931 of file app_dial.c.
References args, AST_APP_ARG, ast_channel_language(), 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(), context, 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().
02932 { 02933 char *parse; 02934 const char *context = NULL; 02935 int sleepms = 0, loops = 0, res = -1; 02936 struct ast_flags64 peerflags = { 0, }; 02937 AST_DECLARE_APP_ARGS(args, 02938 AST_APP_ARG(announce); 02939 AST_APP_ARG(sleep); 02940 AST_APP_ARG(retries); 02941 AST_APP_ARG(dialdata); 02942 ); 02943 02944 if (ast_strlen_zero(data)) { 02945 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 02946 return -1; 02947 } 02948 02949 parse = ast_strdupa(data); 02950 AST_STANDARD_APP_ARGS(args, parse); 02951 02952 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep))) 02953 sleepms *= 1000; 02954 02955 if (!ast_strlen_zero(args.retries)) { 02956 loops = atoi(args.retries); 02957 } 02958 02959 if (!args.dialdata) { 02960 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp); 02961 goto done; 02962 } 02963 02964 if (sleepms < 1000) 02965 sleepms = 10000; 02966 02967 if (!loops) 02968 loops = -1; /* run forever */ 02969 02970 ast_channel_lock(chan); 02971 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 02972 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL; 02973 ast_channel_unlock(chan); 02974 02975 res = 0; 02976 while (loops) { 02977 int continue_exec; 02978 02979 chan->data = "Retrying"; 02980 if (ast_test_flag(chan, AST_FLAG_MOH)) 02981 ast_moh_stop(chan); 02982 02983 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec); 02984 if (continue_exec) 02985 break; 02986 02987 if (res == 0) { 02988 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) { 02989 if (!ast_strlen_zero(args.announce)) { 02990 if (ast_fileexists(args.announce, NULL, ast_channel_language(chan)) > 0) { 02991 if (!(res = ast_streamfile(chan, args.announce, ast_channel_language(chan)))) 02992 ast_waitstream(chan, AST_DIGIT_ANY); 02993 } else 02994 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 02995 } 02996 if (!res && sleepms) { 02997 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02998 ast_moh_start(chan, NULL, NULL); 02999 res = ast_waitfordigit(chan, sleepms); 03000 } 03001 } else { 03002 if (!ast_strlen_zero(args.announce)) { 03003 if (ast_fileexists(args.announce, NULL, ast_channel_language(chan)) > 0) { 03004 if (!(res = ast_streamfile(chan, args.announce, ast_channel_language(chan)))) 03005 res = ast_waitstream(chan, ""); 03006 } else 03007 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce); 03008 } 03009 if (sleepms) { 03010 if (!ast_test_flag(chan, AST_FLAG_MOH)) 03011 ast_moh_start(chan, NULL, NULL); 03012 if (!res) 03013 res = ast_waitfordigit(chan, sleepms); 03014 } 03015 } 03016 } 03017 03018 if (res < 0 || res == AST_PBX_INCOMPLETE) { 03019 break; 03020 } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 03021 if (onedigit_goto(chan, context, (char) res, 1)) { 03022 res = 0; 03023 break; 03024 } 03025 } 03026 loops--; 03027 } 03028 if (loops == 0) 03029 res = 0; 03030 else if (res == 1) 03031 res = 0; 03032 03033 if (ast_test_flag(chan, AST_FLAG_MOH)) 03034 ast_moh_stop(chan); 03035 done: 03036 return res; 03037 }
| static void senddialendevent | ( | struct ast_channel * | src, | |
| const char * | dialstatus | |||
| ) | [static] |
Definition at line 813 of file app_dial.c.
References ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, and EVENT_FLAG_CALL.
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 ast_channel_name(src), ast_channel_uniqueid(src), 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_channel_name(), ast_channel_uniqueid(), 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_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, 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 ast_channel_name(src), ast_channel_name(dst), 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 ast_channel_uniqueid(src), ast_channel_uniqueid(dst), 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_channel_language(), ast_channel_name(), 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, LOG_NOTICE, LOG_WARNING, 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 01710 if (chan->caller.id.number.valid 01711 && !ast_strlen_zero(chan->caller.id.number.str)) { 01712 l = ast_strdupa(chan->caller.id.number.str); 01713 ast_shrink_phone_number(l); 01714 if (ast_test_flag64(opts, OPT_PRIVACY) ) { 01715 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l); 01716 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l); 01717 } else { 01718 ast_verb(3, "Privacy Screening, clid is '%s'\n", l); 01719 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01720 } 01721 } else { 01722 char *tnam, *tn2; 01723 01724 tnam = ast_strdupa(ast_channel_name(chan)); 01725 /* clean the channel name so slashes don't try to end up in disk file name */ 01726 for (tn2 = tnam; *tn2; tn2++) { 01727 if (*tn2 == '/') /* any other chars to be afraid of? */ 01728 *tn2 = '='; 01729 } 01730 ast_verb(3, "Privacy-- callerid is empty\n"); 01731 01732 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); 01733 l = callerid; 01734 pa->privdb_val = AST_PRIVACY_UNKNOWN; 01735 } 01736 01737 ast_copy_string(pa->privcid, l, sizeof(pa->privcid)); 01738 01739 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) { 01740 /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */ 01741 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid); 01742 pa->privdb_val = AST_PRIVACY_ALLOW; 01743 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) { 01744 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val); 01745 } 01746 01747 if (pa->privdb_val == AST_PRIVACY_DENY) { 01748 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); 01749 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status)); 01750 return 0; 01751 } else if (pa->privdb_val == AST_PRIVACY_KILL) { 01752 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status)); 01753 return 0; /* Is this right? */ 01754 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) { 01755 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status)); 01756 return 0; /* is this right??? */ 01757 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) { 01758 /* Get the user's intro, store it in priv-callerintros/$CID, 01759 unless it is already there-- this should be done before the 01760 call is actually dialed */ 01761 01762 /* make sure the priv-callerintros dir actually exists */ 01763 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR); 01764 if ((res = ast_mkdir(pa->privintro, 0755))) { 01765 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res)); 01766 return -1; 01767 } 01768 01769 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); 01770 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) { 01771 /* the DELUX version of this code would allow this caller the 01772 option to hear and retape their previously recorded intro. 01773 */ 01774 } else { 01775 int duration; /* for feedback from play_and_wait */ 01776 /* the file doesn't exist yet. Let the caller submit his 01777 vocal intro for posterity */ 01778 /* priv-recordintro script: 01779 01780 "At the tone, please say your name:" 01781 01782 */ 01783 int silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE); 01784 ast_answer(chan); 01785 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 */ 01786 /* don't think we'll need a lock removed, we took care of 01787 conflicts by naming the pa.privintro file */ 01788 if (res == -1) { 01789 /* Delete the file regardless since they hung up during recording */ 01790 ast_filedelete(pa->privintro, NULL); 01791 if (ast_fileexists(pa->privintro, NULL, NULL) > 0) 01792 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro); 01793 else 01794 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro); 01795 return -1; 01796 } 01797 if (!ast_streamfile(chan, "vm-dialout", ast_channel_language(chan)) ) 01798 ast_waitstream(chan, ""); 01799 } 01800 } 01801 return 1; /* success */ 01802 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3039 of file app_dial.c.
References ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), and ast_unregister_application().
03040 { 03041 int res; 03042 struct ast_context *con; 03043 03044 res = ast_unregister_application(app); 03045 res |= ast_unregister_application(rapp); 03046 03047 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) { 03048 ast_context_remove_extension2(con, "s", 1, NULL, 0); 03049 ast_context_destroy(con, "app_dial"); /* leave nothing behind */ 03050 } 03051 03052 return res; 03053 }
| 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, read] |
Definition at line 1004 of file app_dial.c.
References ast_channel::_state, ast_cdr::answer, chanlist::aoc_s_rate_list, ast_aoc_decode(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_aoc_get_msg_type(), AST_AOC_S, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, ast_cc_completed(), ast_cc_failed(), ast_cc_is_recall(), AST_CDR_ANSWERED, ast_cdr_failed(), ast_cdr_noanswer(), ast_channel_call_forward(), ast_channel_connected_line_macro(), ast_channel_early_bridge(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_name(), ast_channel_redirecting_macro(), ast_channel_sendhtml(), ast_channel_unlock, ast_channel_update_connected_line(), ast_check_hangup(), ast_clear_flag64, ast_connected_line_copy_from_caller(), ast_connected_line_parse_data(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_copy_flags64, ast_copy_string(), ast_deactivate_generator(), ast_debug, ast_dtmf_stream(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, ast_handle_cc_control_frame(), ast_hangup(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_WATCHERS, ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_connected_line_set(), ast_party_connected_line_set_init(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), AST_STATE_UP, ast_str_alloca, ast_strlen_zero(), ast_test_flag64, ast_tvnow(), ast_verb, ast_waitfor_n(), ast_write(), cause_args::busy, ast_channel::caller, CAN_EARLY_BRIDGE, ast_channel::cdr, chanlist::chan, cause_args::congestion, chanlist::connected, context, ast_frame::data, ast_frame::datalen, detect_disconnect(), DIAL_CALLERID_ABSENT, DIAL_NOFORWARDHTML, DIAL_STILLGOING, ast_cdr::disposition, do_forward(), ast_channel::exten, f, FEATURE_MAX_LEN, ast_frame::frametype, handle_cause(), ast_channel::hangupcause, ast_frame_subclass::integer, LOG_WARNING, chanlist::next, cause_args::nochan, onedigit_goto(), OPT_ARG_RINGBACK, 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_DTMF_EXIT, OPT_IGNORE_CONNECTEDLINE, OPT_MUSICBACK, OPT_RINGBACK, pbx_builtin_getvar_helper(), chanlist::pending_connected_update, ast_frame::ptr, privacy_args::sentringing, ast_party_connected_line::source, privacy_args::status, ast_frame::subclass, and ast_frame::uint32.
Referenced by dial_exec_full(), and try_calling().
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", ast_channel_name(c), ast_channel_name(in)); 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_channel_dialcontext_set(c, ""); 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(ast_channel_call_forward(c))) { 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", ast_channel_name(c), ast_channel_name(in)); 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_channel_dialcontext_set(c, ""); 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", ast_channel_name(c)); 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", ast_channel_name(c)); 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", ast_channel_name(c)); 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", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(in)); 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", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(in)); 01330 } else if (single) { 01331 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(c), ast_channel_name(in)); 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", ast_channel_name(c)); 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", ast_channel_name(c)); 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", ast_channel_name(c)); 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 ast_channel_name(in), f->subclass.integer, ast_channel_name(o->chan)); 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 3072 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 3072 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.
1.5.6