@ -375,6 +375,25 @@ ASTERISK_REGISTER_FILE()
< para > Enable privacy mode . Use < replaceable > x < / replaceable > as the family / key in the AstDB database if
it is provided . The current extension is used if a database family / key is not specified . < / para >
< / option >
< option name = " Q " >
< argument name = " cause " required = " true " / >
< para > Specify the Q .850 / Q .931 < replaceable > cause < / replaceable > to send on
unanswered channels when another channel answers the call .
As with < literal > Hangup ( ) < / literal > , < replaceable > cause < / replaceable >
can be a numeric cause code or a name such as
< literal > NO_ANSWER < / literal > ,
< literal > USER_BUSY < / literal > ,
< literal > CALL_REJECTED < / literal > or
< literal > ANSWERED_ELSEWHERE < / literal > ( the default if Q isn ' t specified ) .
You can also specify < literal > 0 < / literal > or < literal > NONE < / literal >
to send no cause . See the < filename > causes . h < / filename > file for the
full list of valid causes and names .
< / para >
< note >
< para > chan_sip does not support setting the cause on a CANCEL to anything
other than ANSWERED_ELSEWHERE . < / para >
< / note >
< / option >
< option name = " r " >
< para > Default : Indicate ringing to the calling party , even if the called party isn ' t actually ringing . Pass no audio to the calling
party until the called channel has answered . < / para >
@ -520,6 +539,9 @@ ASTERISK_REGISTER_FILE()
< example title = " Dial with call length limit " >
same = > n , Dial ( PJSIP / alice , , L ( 60000 : 30000 : 10000 ) )
< / example >
< example title = " Dial alice and bob and send NO_ANSWER to bob instead of ANSWERED_ELSEWHERE when alice answers " >
same = > n , Dial ( PJSIP / alice & amp ; PJSIP / bob , , Q ( NO_ANSWER ) )
< / example >
< example title = " Dial with pre-dial subroutines " >
[ default ]
@ -684,6 +706,7 @@ enum {
# define OPT_PREDIAL_CALLEE (1LLU << 41)
# define OPT_PREDIAL_CALLER (1LLU << 42)
# define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
# define OPT_HANGUPCAUSE (1LLU << 44)
enum {
OPT_ARG_ANNOUNCE = 0 ,
@ -705,6 +728,7 @@ enum {
OPT_ARG_FORCE_CID_PRES ,
OPT_ARG_PREDIAL_CALLEE ,
OPT_ARG_PREDIAL_CALLER ,
OPT_ARG_HANGUPCAUSE ,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE
} ;
@ -738,6 +762,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
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 ( ' Q ' , OPT_HANGUPCAUSE , OPT_ARG_HANGUPCAUSE ) ,
AST_APP_OPTION_ARG ( ' r ' , OPT_RINGBACK , OPT_ARG_RINGBACK ) ,
AST_APP_OPTION ( ' R ' , OPT_RING_WITH_EARLY_MEDIA ) ,
AST_APP_OPTION_ARG ( ' S ' , OPT_DURATION_STOP , OPT_ARG_DURATION_STOP ) ,
@ -796,7 +821,7 @@ static void chanlist_free(struct chanlist *outgoing)
ast_free ( outgoing ) ;
}
static void hanguptree ( struct dial_head * out_chans , struct ast_channel * exception , int answered_elsewher e)
static void hanguptree ( struct dial_head * out_chans , struct ast_channel * exception , int h angupcau se)
{
/* Hang up a tree of stuff */
struct chanlist * outgoing ;
@ -804,9 +829,9 @@ static void hanguptree(struct dial_head *out_chans, struct ast_channel *exceptio
while ( ( outgoing = AST_LIST_REMOVE_HEAD ( out_chans , node ) ) ) {
/* Hangup any existing lines we have open */
if ( outgoing - > chan & & ( outgoing - > chan ! = exception ) ) {
if ( answered_elsewhere ) {
if ( hangupcause > = 0 ) {
/* This is for the channel drivers */
ast_channel_hangupcause_set ( outgoing - > chan , AST_CAUSE_ANSWERED_ELSEWHERE ) ;
ast_channel_hangupcause_set ( outgoing - > chan , hangupcause ) ;
}
ast_hangup ( outgoing - > chan ) ;
}
@ -2768,6 +2793,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
} else {
const char * number ;
int dial_end_raised = 0 ;
int cause = - 1 ;
if ( ast_test_flag64 ( & opts , OPT_CALLER_ANSWER ) )
ast_answer ( chan ) ;
@ -2778,7 +2804,23 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with - 1 so that it is hung up properly after the
conversation . */
hanguptree ( & out_chans , peer , 1 ) ;
if ( ast_test_flag64 ( & opts , OPT_HANGUPCAUSE )
& & ! ast_strlen_zero ( opt_args [ OPT_ARG_HANGUPCAUSE ] ) ) {
cause = ast_str2cause ( opt_args [ OPT_ARG_HANGUPCAUSE ] ) ;
if ( cause < = 0 ) {
if ( ! strcasecmp ( opt_args [ OPT_ARG_HANGUPCAUSE ] , " NONE " ) ) {
cause = 0 ;
} else if ( sscanf ( opt_args [ OPT_ARG_HANGUPCAUSE ] , " %30d " , & cause ) ! = 1
| | cause < 0 ) {
ast_log ( LOG_WARNING , " Invalid cause given to Dial(...Q(<cause>)): \" %s \" \n " ,
opt_args [ OPT_ARG_HANGUPCAUSE ] ) ;
cause = - 1 ;
}
}
}
hanguptree ( & out_chans , peer , cause > = 0 ? cause : AST_CAUSE_ANSWERED_ELSEWHERE ) ;
/* If appropriate, log that we have a destination channel and set the answer time */
if ( ast_channel_name ( peer ) )
pbx_builtin_setvar_helper ( chan , " DIALEDPEERNAME " , ast_channel_name ( peer ) ) ;
@ -3182,7 +3224,11 @@ out:
}
ast_channel_early_bridge ( chan , NULL ) ;
hanguptree ( & out_chans , NULL , ast_channel_hangupcause ( chan ) = = AST_CAUSE_ANSWERED_ELSEWHERE | | ast_test_flag64 ( & opts , OPT_CANCEL_ELSEWHERE ) ? 1 : 0 ) ; /* forward 'answered elsewhere' if we received it */
/* forward 'answered elsewhere' if we received it */
hanguptree ( & out_chans , NULL ,
ast_channel_hangupcause ( chan ) = = AST_CAUSE_ANSWERED_ELSEWHERE
| | ast_test_flag64 ( & opts , OPT_CANCEL_ELSEWHERE )
? AST_CAUSE_ANSWERED_ELSEWHERE : - 1 ) ;
pbx_builtin_setvar_helper ( chan , " DIALSTATUS " , pa . status ) ;
ast_debug ( 1 , " Exiting with DIALSTATUS=%s. \n " , pa . status ) ;