@ -88,9 +88,12 @@
< / argument >
< xi : include xpointer = " xpointer(/docs/info[@name='Dial_Resource']) " / >
< / parameter >
< parameter name = " timeout " required = " false " >
< parameter name = " timeout " required = " false " argsep = " ^ " >
< para > Specifies the number of seconds we attempt to dial the specified devices . < / para >
< para > If not specified , this defaults to 136 years . < / para >
< para > If a second argument is specified , this controls the number of seconds we attempt to dial the specified devices
without receiving early media or ringing . If neither progress , ringing , nor voice frames have been received when this
timeout expires , the call will be treated as a CHANUNAVAIL . This can be used to skip destinations that may not be responsive . < / para >
< / parameter >
< parameter name = " options " required = " false " >
< optionlist >
@ -1254,7 +1257,7 @@ static void set_duration_var(struct ast_channel *chan, const char *var_base, int
}
static struct ast_channel * wait_for_answer ( struct ast_channel * in ,
struct dial_head * out_chans , int * to , struct ast_flags64 * peerflags ,
struct dial_head * out_chans , int * to _answer, int * to_progress , struct ast_flags64 * peerflags ,
char * opt_args [ ] ,
struct privacy_args * pa ,
const struct cause_args * num_in , int * result , char * dtmf_progress ,
@ -1267,7 +1270,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
{
struct cause_args num = * num_in ;
int prestart = num . busy + num . congestion + num . nochan ;
int orig = * to ;
int orig_answer_to = * to_answer ;
int progress_to_dup = * to_progress ;
int orig_progress_to = * to_progress ;
struct ast_channel * peer = NULL ;
struct chanlist * outgoing = AST_LIST_FIRST ( out_chans ) ;
/* single is set if only one destination is enabled */
@ -1295,7 +1300,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
* there is no point in continuing . The bridge
* will just fail if it gets that far .
*/
* to = - 1 ;
* to _answer = - 1 ;
strcpy ( pa - > status , " CONGESTION " ) ;
ast_channel_publish_dial ( in , outgoing - > chan , NULL , pa - > status ) ;
SCOPE_EXIT_RTN_VALUE ( NULL , " %s: can't be made compat with %s \n " ,
@ -1311,7 +1316,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
is_cc_recall = ast_cc_is_recall ( in , & cc_recall_core_id , NULL ) ;
while ( ( * to = ast_remaining_ms ( start , orig ) ) & & ! peer ) {
while ( ( * to _answer = ast_remaining_ms ( start , orig _answer_to) ) & & ( * to_progress = ast_remaining_ms ( start , progress_to_dup ) ) & & ! peer ) {
struct chanlist * o ;
int pos = 0 ; /* how many channels do we handle */
int numlines = prestart ;
@ -1337,13 +1342,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
} else {
ast_verb ( 3 , " No one is available to answer at this time (%d:%d/%d/%d) \n " , numlines , num . busy , num . congestion , num . nochan ) ;
}
* to = 0 ;
* to _answer = 0 ;
if ( is_cc_recall ) {
ast_cc_failed ( cc_recall_core_id , " Everyone is busy/congested for the recall. How sad " ) ;
}
SCOPE_EXIT_RTN_VALUE ( NULL , " %s: No outgoing channels available \n " , ast_channel_name ( in ) ) ;
}
winner = ast_waitfor_n ( watchers , pos , to ) ;
winner = ast_waitfor_n ( watchers , pos , to _answer ) ;
AST_LIST_TRAVERSE ( out_chans , o , node ) {
int res = 0 ;
struct ast_frame * f ;
@ -1421,7 +1426,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_channel_unlock ( in ) ;
}
do_forward ( o , & num , peerflags , single , caller_entertained , & orig ,
do_forward ( o , & num , peerflags , single , caller_entertained , & orig _answer_to ,
forced_clid , stored_clid ) ;
if ( o - > chan ) {
@ -1559,6 +1564,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
* fine for ringing frames to get sent through .
*/
+ + num_ringing ;
* to_progress = - 1 ;
progress_to_dup = - 1 ;
if ( ignore_cc | | cc_frame_received | | num_ringing = = numlines ) {
ast_verb ( 3 , " %s is ringing \n " , ast_channel_name ( c ) ) ;
/* Setup early media if appropriate */
@ -1602,6 +1609,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_indicate ( in , AST_CONTROL_PROGRESS ) ;
}
}
* to_progress = - 1 ;
progress_to_dup = - 1 ;
if ( ! sent_progress ) {
struct timeval now , then ;
int64_t diff ;
@ -1792,6 +1801,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
if ( caller_entertained ) {
break ;
}
* to_progress = - 1 ;
progress_to_dup = - 1 ;
/* Fall through */
case AST_FRAME_TEXT :
if ( single & & ast_write ( in , f ) ) {
@ -1820,7 +1831,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
# endif
if ( ! f | | ( ( f - > frametype = = AST_FRAME_CONTROL ) & & ( f - > subclass . integer = = AST_CONTROL_HANGUP ) ) ) {
/* Got hung up */
* to = - 1 ;
* to _answer = - 1 ;
strcpy ( pa - > status , " CANCEL " ) ;
pa - > canceled = 1 ;
publish_dial_end_event ( in , out_chans , NULL , pa - > status ) ;
@ -1844,7 +1855,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
context = pbx_builtin_getvar_helper ( in , " EXITCONTEXT " ) ;
if ( onedigit_goto ( in , context , ( char ) f - > subclass . integer , 1 ) ) {
ast_verb ( 3 , " User hit %c to disconnect call. \n " , f - > subclass . integer ) ;
* to = 0 ;
* to _answer = 0 ;
* result = f - > subclass . integer ;
strcpy ( pa - > status , " CANCEL " ) ;
pa - > canceled = 1 ;
@ -1863,7 +1874,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
if ( ast_test_flag64 ( peerflags , OPT_CALLER_HANGUP ) & &
detect_disconnect ( in , f - > subclass . integer , & featurecode ) ) {
ast_verb ( 3 , " User requested call disconnect. \n " ) ;
* to = 0 ;
* to _answer = 0 ;
strcpy ( pa - > status , " CANCEL " ) ;
pa - > canceled = 1 ;
publish_dial_end_event ( in , out_chans , NULL , pa - > status ) ;
@ -1975,9 +1986,14 @@ skip_frame:;
}
wait_over :
if ( ! * to | | ast_check_hangup ( in ) ) {
ast_verb ( 3 , " Nobody picked up in %d ms \n " , orig ) ;
if ( ! * to _answer | | ast_check_hangup ( in ) ) {
ast_verb ( 3 , " Nobody picked up in %d ms \n " , orig _answer_to ) ;
publish_dial_end_event ( in , out_chans , NULL , " NOANSWER " ) ;
} else if ( ! * to_progress ) {
ast_verb ( 3 , " No early media received in %d ms \n " , orig_progress_to ) ;
publish_dial_end_event ( in , out_chans , NULL , " CHANUNAVAIL " ) ;
strcpy ( pa - > status , " CHANUNAVAIL " ) ;
* to_answer = 0 ; /* Reset to prevent hangup */
}
if ( is_cc_recall ) {
@ -2349,7 +2365,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
struct chanlist * outgoing ;
struct chanlist * tmp ;
struct ast_channel * peer = NULL ;
int to ; /* timeout */
int to _answer, to_progress ; /* timeout s */
struct cause_args num = { chan , 0 , 0 , 0 } ;
int cause , hanguptreecause = - 1 ;
@ -2963,14 +2979,31 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
AST_LIST_TRAVERSE_SAFE_END ;
if ( ast_strlen_zero ( args . timeout ) ) {
to = - 1 ;
to_answer = - 1 ;
to_progress = - 1 ;
} else {
to = atoi ( args . timeout ) ;
if ( to > 0 )
to * = 1000 ;
else {
ast_log ( LOG_WARNING , " Invalid timeout specified: '%s'. Setting timeout to infinite \n " , args . timeout ) ;
to = - 1 ;
char * anstimeout = strsep ( & args . timeout , " ^ " ) ;
if ( ! ast_strlen_zero ( anstimeout ) ) {
to_answer = atoi ( anstimeout ) ;
if ( to_answer > 0 ) {
to_answer * = 1000 ;
} else {
ast_log ( LOG_WARNING , " Invalid answer timeout specified: '%s'. Setting timeout to infinite \n " , args . timeout ) ;
to_answer = - 1 ;
}
} else {
to_answer = - 1 ;
}
if ( ! ast_strlen_zero ( args . timeout ) ) {
to_progress = atoi ( args . timeout ) ;
if ( to_progress > 0 ) {
to_progress * = 1000 ;
} else {
ast_log ( LOG_WARNING , " Invalid progress timeout specified: '%s'. Setting timeout to infinite \n " , args . timeout ) ;
to_progress = - 1 ;
}
} else {
to_progress = - 1 ;
}
}
@ -3010,7 +3043,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
}
peer = wait_for_answer ( chan , & out_chans , & to , peerflags , opt_args , & pa , & num , & result ,
peer = wait_for_answer ( chan , & out_chans , & to _answer, & to_progress , peerflags , opt_args , & pa , & num , & result ,
dtmf_progress , mf_progress , mf_wink , sf_progress , sf_wink ,
( ast_test_flag64 ( & opts , OPT_HEARPULSING ) ? 1 : 0 ) ,
ignore_cc , & forced_clid , & stored_clid , & config ) ;
@ -3018,7 +3051,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
if ( ! peer ) {
if ( result ) {
res = result ;
} else if ( to ) { /* Musta gotten hung up */
} else if ( to _answer ) { /* Musta gotten hung up */
res = - 1 ;
} else { /* Nobody answered, next please? */
res = 0 ;