@ -225,6 +225,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< enum name = " statusstr " >
< para > R / O Verbose Result Status of the FAX transmission . < / para >
< / enum >
< enum name = " t38timeout " >
< para > R / W The timeout used for T .38 negotiation . < / para >
< / enum >
< / enumlist >
< / parameter >
< / syntax >
@ -521,6 +524,7 @@ static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
# define RES_FAX_MAXRATE 14400
# define RES_FAX_STATUSEVENTS 0
# define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
# define RES_FAX_T38TIMEOUT 5000
struct fax_options {
enum ast_fax_modems modems ;
@ -528,6 +532,7 @@ struct fax_options {
uint32_t ecm : 1 ;
unsigned int minrate ;
unsigned int maxrate ;
unsigned int t38timeout ;
} ;
static struct fax_options general_options ;
@ -538,6 +543,7 @@ static const struct fax_options default_options = {
. statusevents = RES_FAX_STATUSEVENTS ,
. modems = RES_FAX_MODEM ,
. ecm = AST_FAX_OPTFLAG_TRUE ,
. t38timeout = RES_FAX_T38TIMEOUT ,
} ;
AST_RWLOCK_DEFINE_STATIC ( options_lock ) ;
@ -713,6 +719,7 @@ static struct ast_fax_session_details *session_details_new(void)
d - > modems = options . modems ;
d - > minrate = options . minrate ;
d - > maxrate = options . maxrate ;
d - > t38timeout = options . t38timeout ;
d - > gateway_id = - 1 ;
d - > faxdetect_id = - 1 ;
d - > gateway_timeout = 0 ;
@ -1716,7 +1723,10 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
break ;
}
if ( t38negotiated & & ! was_t38 ) {
fax - > tech - > switch_to_t38 ( fax ) ;
if ( fax - > tech - > switch_to_t38 ( fax ) ) {
GENERIC_FAX_EXEC_ERROR ( fax , chan , " UNKNOWN " , " T.38 switch failed " ) ;
break ;
}
details - > caps & = ~ AST_FAX_TECH_AUDIO ;
expected_frametype = AST_FRAME_MODEM ;
expected_framesubclass . integer = AST_MODEM_T38 ;
@ -1904,8 +1914,8 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_
/* request T.38 */
ast_debug ( 1 , " Negotiating T.38 for receive on %s \n " , ast_channel_name ( chan ) ) ;
/* wait up to five seconds for negotiation to complete */
timeout_ms = 5000 ;
/* wait for negotiation to complete */
timeout_ms = details - > t38timeout ;
/* set parameters based on the session's parameters */
t38_parameters_fax_to_ast ( & t38_parameters , & details - > our_t38_parameters ) ;
@ -3923,6 +3933,7 @@ static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_
ast_cli ( a - > fd , " \t Maximum Bit Rate: %u \n " , options . maxrate ) ;
ast_fax_modem_to_str ( options . modems , modems , sizeof ( modems ) ) ;
ast_cli ( a - > fd , " \t Modem Modulations Allowed: %s \n " , modems ) ;
ast_cli ( a - > fd , " \t T.38 Negotiation Timeout: %u \n " , options . t38timeout ) ;
ast_cli ( a - > fd , " \n \n FAX Technology Modules: \n \n " ) ;
AST_RWLIST_RDLOCK ( & faxmodules ) ;
AST_RWLIST_TRAVERSE ( & faxmodules , fax , list ) {
@ -4234,6 +4245,23 @@ static void get_general_options(struct fax_options *options)
ast_rwlock_unlock ( & options_lock ) ;
}
static int set_t38timeout ( const char * value , unsigned int * t38timeout )
{
unsigned int timeout ;
if ( sscanf ( value , " %u " , & timeout ) ! = 1 ) {
ast_log ( LOG_ERROR , " Unable to get timeout from '%s' \n " , value ) ;
return - 1 ;
} else if ( timeout ) {
* t38timeout = timeout ;
} else {
ast_log ( LOG_ERROR , " T.38 negotiation timeout must be non-zero \n " ) ;
return - 1 ;
}
return 0 ;
}
/*! \brief configure res_fax */
static int set_config ( int reload )
{
@ -4303,6 +4331,11 @@ static int set_config(int reload)
} else if ( ( ! strcasecmp ( v - > name , " modem " ) ) | | ( ! strcasecmp ( v - > name , " modems " ) ) ) {
options . modems = 0 ;
update_modem_bits ( & options . modems , v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " t38timeout " ) ) {
if ( set_t38timeout ( v - > value , & options . t38timeout ) ) {
res = - 1 ;
goto end ;
}
}
}
@ -4395,6 +4428,8 @@ static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data
ast_copy_string ( buf , details - > resultstr , len ) ;
} else if ( ( ! strcasecmp ( data , " modem " ) ) | | ( ! strcasecmp ( data , " modems " ) ) ) {
ast_fax_modem_to_str ( details - > modems , buf , len ) ;
} else if ( ! strcasecmp ( data , " t38timeout " ) ) {
snprintf ( buf , len , " %u " , details - > t38timeout ) ;
} else {
ast_log ( LOG_WARNING , " channel '%s' can't read FAXOPT(%s) because it is unhandled! \n " , ast_channel_name ( chan ) , data ) ;
res = - 1 ;
@ -4521,6 +4556,10 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
if ( ! details - > minrate ) {
details - > minrate = ast_fax_minrate ( ) ;
}
} else if ( ! strcasecmp ( data , " t38timeout " ) ) {
if ( set_t38timeout ( value , & details - > t38timeout ) ) {
res = - 1 ;
}
} else if ( ( ! strcasecmp ( data , " modem " ) ) | | ( ! strcasecmp ( data , " modems " ) ) ) {
update_modem_bits ( & details - > modems , value ) ;
} else {