@ -249,13 +249,12 @@ struct ast_fax_debug_info {
struct fax_gateway {
struct fax_gateway {
/*! \brief FAX Session */
/*! \brief FAX Session */
struct ast_fax_session * s ;
struct ast_fax_session * s ;
struct ast_fax_session * peer_v21_session ;
struct ast_fax_session * chan_v21_session ;
/*! \brief reserved fax session token */
/*! \brief reserved fax session token */
struct ast_fax_tech_token * token ;
struct ast_fax_tech_token * token ;
/*! \brief the start of our timeout counter */
/*! \brief the start of our timeout counter */
struct timeval timeout_start ;
struct timeval timeout_start ;
/*! \brief DSP Processor */
struct ast_dsp * chan_dsp ;
struct ast_dsp * peer_dsp ;
/*! \brief framehook used in gateway mode */
/*! \brief framehook used in gateway mode */
int framehook ;
int framehook ;
/*! \brief bridged */
/*! \brief bridged */
@ -636,7 +635,13 @@ static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size
ast_build_string ( & buf , & size , " GATEWAY " ) ;
ast_build_string ( & buf , & size , " GATEWAY " ) ;
first = 0 ;
first = 0 ;
}
}
if ( caps & AST_FAX_TECH_V21_DETECT ) {
if ( ! first ) {
ast_build_string ( & buf , & size , " , " ) ;
}
ast_build_string ( & buf , & size , " V21 " ) ;
first = 0 ;
}
return out ;
return out ;
}
}
@ -2439,21 +2444,35 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
return ( ! channel_alive ) ? - 1 : 0 ;
return ( ! channel_alive ) ? - 1 : 0 ;
}
}
/*! \brief destroy a FAX gateway session structure */
/*! \brief destroy the v21 detection parts of a fax gateway session */
static void destroy_ gateway( void * data )
static void destroy_ v21_sessions( struct fax_gateway * gateway )
{
{
struct fax_gateway * gateway = data ;
if ( gateway - > chan_v21_session ) {
ao2_lock ( faxregistry . container ) ;
ao2_unlink ( faxregistry . container , gateway - > chan_v21_session ) ;
ao2_unlock ( faxregistry . container ) ;
if ( gateway - > chan_dsp ) {
ao2_ref ( gateway - > chan_v21_session , - 1 ) ;
ast_dsp_free ( gateway - > chan_dsp ) ;
gateway - > chan_v21_session = NULL ;
gateway - > chan_dsp = NULL ;
}
}
if ( gateway - > peer_dsp ) {
if ( gateway - > peer_v21_session ) {
ast_dsp_free ( gateway - > peer_dsp ) ;
ao2_lock ( faxregistry . container ) ;
gateway - > peer_dsp = NULL ;
ao2_unlink ( faxregistry . container , gateway - > peer_v21_session ) ;
ao2_unlock ( faxregistry . container ) ;
ao2_ref ( gateway - > peer_v21_session , - 1 ) ;
gateway - > peer_v21_session = NULL ;
}
}
}
/*! \brief destroy a FAX gateway session structure */
static void destroy_gateway ( void * data )
{
struct fax_gateway * gateway = data ;
destroy_v21_sessions ( gateway ) ;
if ( gateway - > s ) {
if ( gateway - > s ) {
fax_session_release ( gateway - > s , gateway - > token ) ;
fax_session_release ( gateway - > s , gateway - > token ) ;
gateway - > token = NULL ;
gateway - > token = NULL ;
@ -2468,35 +2487,38 @@ static void destroy_gateway(void *data)
}
}
/*! \brief Create a new fax gateway object.
/*! \brief Create a new fax gateway object.
* \ param chan the channel the gateway object will be attached to
* \ param details the fax session details
* \ param details the fax session details
* \ return NULL or a fax gateway object
* \ return NULL or a fax gateway object
*/
*/
static struct fax_gateway * fax_gateway_new ( struct ast_ fax_session_details * details )
static struct fax_gateway * fax_gateway_new ( struct ast_ channel * chan , struct ast_ fax_session_details * details )
{
{
struct fax_gateway * gateway = ao2_alloc ( sizeof ( * gateway ) , destroy_gateway ) ;
struct fax_gateway * gateway = ao2_alloc ( sizeof ( * gateway ) , destroy_gateway ) ;
struct ast_fax_session_details * v21_details ;
if ( ! gateway ) {
if ( ! gateway ) {
return NULL ;
return NULL ;
}
}
gateway - > chan_dsp = ast_dsp_new ( ) ;
if ( ! ( v21_details = session_details_new ( ) ) ) {
if ( ! gateway - > chan_dsp ) {
ao2_ref ( gateway , - 1 ) ;
ao2_ref ( gateway , - 1 ) ;
return NULL ;
return NULL ;
}
}
gateway - > peer_dsp = ast_dsp_new ( ) ;
v21_details - > caps = AST_FAX_TECH_V21_DETECT ;
if ( ! gateway - > peer_dsp ) {
if ( ! ( gateway - > chan_v21_session = fax_session_new ( v21_details , chan , NULL , NULL ) ) ) {
ao2_ref ( v21_details , - 1 ) ;
ao2_ref ( gateway , - 1 ) ;
ao2_ref ( gateway , - 1 ) ;
return NULL ;
return NULL ;
}
}
gateway - > framehook = - 1 ;
if ( ! ( gateway - > peer_v21_session = fax_session_new ( v21_details , chan , NULL , NULL ) ) ) {
ao2_ref ( v21_details , - 1 ) ;
ast_dsp_set_features ( gateway - > chan_dsp , DSP_FEATURE_FAX_DETECT ) ;
ao2_ref ( gateway , - 1 ) ;
ast_dsp_set_faxmode ( gateway - > chan_dsp , DSP_FAXMODE_DETECT_V21 ) ;
return NULL ;
}
ao2_ref ( v21_details , - 1 ) ;
ast_dsp_set_features ( gateway - > peer_dsp , DSP_FEATURE_FAX_DETECT ) ;
gateway - > framehook = - 1 ;
ast_dsp_set_faxmode ( gateway - > peer_dsp , DSP_FAXMODE_DETECT_V21 ) ;
details - > caps = AST_FAX_TECH_GATEWAY ;
details - > caps = AST_FAX_TECH_GATEWAY ;
if ( details - > gateway_timeout & & ! ( gateway - > s = fax_session_reserve ( details , & gateway - > token ) ) ) {
if ( details - > gateway_timeout & & ! ( gateway - > s = fax_session_reserve ( details , & gateway - > token ) ) ) {
@ -2591,24 +2613,20 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st
static struct ast_frame * fax_gateway_detect_v21 ( struct fax_gateway * gateway , struct ast_channel * chan , struct ast_channel * peer , struct ast_channel * active , struct ast_frame * f )
static struct ast_frame * fax_gateway_detect_v21 ( struct fax_gateway * gateway , struct ast_channel * chan , struct ast_channel * peer , struct ast_channel * active , struct ast_frame * f )
{
{
struct ast_frame * dfr = ast_frdup ( f ) ;
struct ast_dsp * active_dsp = ( active = = chan ) ? gateway - > chan_dsp : gateway - > peer_dsp ;
struct ast_channel * other = ( active = = chan ) ? peer : chan ;
struct ast_channel * other = ( active = = chan ) ? peer : chan ;
struct ast_fax_session * active_v21_session = ( active = = chan ) ? gateway - > chan_v21_session : gateway - > peer_v21_session ;
if ( gateway - > detected_v21 ) {
if ( ! active_v21_session | | gateway - > detected_v21 ) {
return f ;
return f ;
}
}
if ( ! dfr ) {
if ( active_v21_session - > tech - > write ( active_v21_session , f ) = = 0 & &
return f ;
active_v21_session - > details - > option . v21_detected ) {
}
gateway - > detected_v21 = 1 ;
if ( ! ( dfr = ast_dsp_process ( active , active_dsp , dfr ) ) ) {
return f ;
}
}
if ( dfr- > frametype = = AST_FRAME_DTMF & & dfr - > subclass . integer = = ' g ' ) {
if ( gateway - > detected_v21 ) {
gateway - > detected_v21 = 1 ;
destroy_v21_sessions ( gateway ) ;
if ( ast_channel_get_t38_state ( other ) = = T38_STATE_UNKNOWN ) {
if ( ast_channel_get_t38_state ( other ) = = T38_STATE_UNKNOWN ) {
ast_debug ( 1 , " detected v21 preamble from %s \n " , active - > name ) ;
ast_debug ( 1 , " detected v21 preamble from %s \n " , active - > name ) ;
return fax_gateway_request_t38 ( gateway , chan , f ) ;
return fax_gateway_request_t38 ( gateway , chan , f ) ;
@ -2617,7 +2635,6 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
}
}
}
}
ast_frfree ( dfr ) ;
return f ;
return f ;
}
}
@ -3120,7 +3137,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
set_channel_variables ( chan , details ) ;
set_channel_variables ( chan , details ) ;
/* set up the frame hook*/
/* set up the frame hook*/
gateway = fax_gateway_new ( details) ;
gateway = fax_gateway_new ( chan, details) ;
if ( ! gateway ) {
if ( ! gateway ) {
ast_string_field_set ( details , result , " FAILED " ) ;
ast_string_field_set ( details , result , " FAILED " ) ;
ast_string_field_set ( details , resultstr , " error initializing gateway session " ) ;
ast_string_field_set ( details , resultstr , " error initializing gateway session " ) ;
@ -3628,6 +3645,36 @@ static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli
return CLI_SUCCESS ;
return CLI_SUCCESS ;
}
}
static const char * cli_session_type ( struct ast_fax_session * s )
{
if ( s - > details - > caps & AST_FAX_TECH_AUDIO ) {
return " G.711 " ;
}
if ( s - > details - > caps & AST_FAX_TECH_T38 ) {
return " T.38 " ;
}
return " none " ;
}
static const char * cli_session_operation ( struct ast_fax_session * s )
{
if ( s - > details - > caps & AST_FAX_TECH_GATEWAY ) {
return " gateway " ;
}
if ( s - > details - > caps & AST_FAX_TECH_SEND ) {
return " send " ;
}
if ( s - > details - > caps & AST_FAX_TECH_RECEIVE ) {
return " receive " ;
}
if ( s - > details - > caps & AST_FAX_TECH_V21_DETECT ) {
return " V.21 " ;
}
return " none " ;
}
/*! \brief display fax sessions */
/*! \brief display fax sessions */
static char * cli_fax_show_sessions ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
static char * cli_fax_show_sessions ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
{
@ -3658,10 +3705,8 @@ static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_
ast_cli ( a - > fd , " %-20.20s %-10.10s %-10d %-5.5s %-10.10s %-15.15s %-30s \n " ,
ast_cli ( a - > fd , " %-20.20s %-10.10s %-10d %-5.5s %-10.10s %-15.15s %-30s \n " ,
s - > channame , s - > tech - > type , s - > id ,
s - > channame , s - > tech - > type , s - > id ,
( s - > details - > caps & AST_FAX_TECH_AUDIO ) ? " G.711 " : " T.38 " ,
cli_session_type ( s ) ,
( s - > details - > caps & AST_FAX_TECH_GATEWAY )
cli_session_operation ( s ) ,
? " gateway "
: ( s - > details - > caps & AST_FAX_TECH_SEND ) ? " send " : " receive " ,
ast_fax_state_to_str ( s - > state ) , S_OR ( filenames , " " ) ) ;
ast_fax_state_to_str ( s - > state ) , S_OR ( filenames , " " ) ) ;
ast_free ( filenames ) ;
ast_free ( filenames ) ;