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