@ -1828,7 +1828,7 @@ struct sip_pvt {
int laststate ; /*!< SUBSCRIBE: Last known extension state */
int dialogver ; /*!< SUBSCRIBE: Version for subscription dialog-info */
struct ast_dsp * dsp ; /*!< Inband DTMF Detection dsp */
struct ast_dsp * dsp ; /*!< Inband DTMF or Fax CNG tone Detection dsp */
struct sip_peer * relatedpeer ; /*!< If this dialog is related to a peer, which one
Used in peerpoke , mwi subscriptions */
@ -4442,23 +4442,40 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
return res ;
}
static void enable_d igit _detect( struct sip_pvt * p )
static void enable_d sp _detect( struct sip_pvt * p )
{
int features = 0 ;
if ( p - > dsp ) {
return ;
}
if ( ( ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_INBAND ) | |
( ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_AUTO ) ) {
if ( ! p - > rtp | | ast_rtp_instance_dtmf_mode_set ( p - > rtp , AST_RTP_DTMF_MODE_INBAND ) ) {
features | = DSP_FEATURE_DIGIT_DETECT ;
}
}
if ( ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_FAX_DETECT ) ) {
features | = DSP_FEATURE_FAX_DETECT ;
}
if ( ! features ) {
return ;
}
if ( ! ( p - > dsp = ast_dsp_new ( ) ) ) {
return ;
}
ast_dsp_set_features ( p - > dsp , DSP_FEATURE_DIGIT_DETECT ) ;
ast_dsp_set_features ( p - > dsp , features ) ;
if ( global_relaxdtmf ) {
ast_dsp_set_digitmode ( p - > dsp , DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF ) ;
}
}
static void disable_digit_detect ( struct sip_pvt * p )
static void disable_d sp _detect( struct sip_pvt * p )
{
if ( p - > dsp ) {
ast_dsp_free ( p - > dsp ) ;
@ -4489,9 +4506,9 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d
ast_debug ( 1 , " %sabling digit detection on %s \n " , * cp ? " En " : " Dis " , chan - > name ) ;
if ( * cp ) {
enable_d igit _detect( p ) ;
enable_d sp _detect( p ) ;
} else {
disable_d igit _detect( p ) ;
disable_d sp _detect( p ) ;
}
res = 0 ;
}
@ -6329,7 +6346,7 @@ static int sip_hangup(struct ast_channel *ast)
append_history ( p , needcancel ? " Cancel " : " Hangup " , " Cause %s " , p - > owner ? ast_cause2str ( p - > hangupcause ) : " Unknown " ) ;
/* Disconnect */
disable_d igit _detect( p ) ;
disable_d sp _detect( p ) ;
p - > owner = NULL ;
ast - > tech_pvt = dialog_unref ( ast - > tech_pvt , " unref ast->tech_pvt " ) ;
@ -6996,10 +7013,12 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
else
ast_debug ( 3 , " This channel will not be able to handle video. \n " ) ;
enable_dsp_detect ( i ) ;
if ( ( ast_test_flag ( & i - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_INBAND ) | |
( ast_test_flag ( & i - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_AUTO ) ) {
if ( ! i - > rtp | | ast_rtp_instance_dtmf_mode_set ( i - > rtp , AST_RTP_DTMF_MODE_INBAND ) ) {
enable_d igit _detect( i ) ;
enable_d sp _detect( i ) ;
}
} else if ( ast_test_flag ( & i - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_RFC2833 ) {
if ( i - > rtp ) {
@ -7321,9 +7340,17 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
if ( f & & p - > dsp ) {
f = ast_dsp_process ( p - > owner , p - > dsp , f ) ;
if ( f & & f - > frametype = = AST_FRAME_DTMF ) {
if ( ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_T38SUPPORT ) & & f - > subclass . integer = = ' f ' ) {
ast_debug ( 1 , " Fax CNG detected on %s \n " , ast - > name ) ;
if ( f - > subclass . integer = = ' f ' ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Fax CNG detected on %s \n " , ast - > name ) ;
* faxdetect = 1 ;
/* If we only needed this DSP for fax detection purposes we can just drop it now */
if ( ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_INBAND ) {
ast_dsp_set_features ( p - > dsp , DSP_FEATURE_DIGIT_DETECT ) ;
} else {
ast_dsp_free ( p - > dsp ) ;
p - > dsp = NULL ;
}
} else {
ast_debug ( 1 , " * Detected inband DTMF '%c' \n " , f - > subclass . integer ) ;
}
@ -7344,20 +7371,26 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
fr = sip_rtp_read ( ast , p , & faxdetected ) ;
p - > lastrtprx = time ( NULL ) ;
/* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */
/* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */
if ( faxdetected & & ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_T38SUPPORT ) & & ( p - > t38 . state = = T38_DISABLED ) & & ! ( ast_bridged_channel ( ast ) ) ) {
if ( ! ast_test_flag ( & p - > flags [ 0 ] , SIP_GOTREFER ) ) {
if ( ! p - > pendinginvite ) {
ast_debug ( 3 , " Sending reinvite on SIP (%s) for T.38 negotiation. \n " , ast - > name ) ;
change_t38_state ( p , T38_LOCAL_REINVITE ) ;
transmit_reinvite_with_sdp ( p , TRUE , FALSE ) ;
}
} else if ( ! ast_test_flag ( & p - > flags [ 0 ] , SIP_PENDINGBYE ) ) {
ast_debug ( 3 , " Deferring reinvite on SIP (%s) - it will be re-negotiated for T.38 \n " , ast - > name ) ;
ast_set_flag ( & p - > flags [ 0 ] , SIP_NEEDREINVITE ) ;
}
}
/* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */
if ( faxdetected & & ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_FAX_DETECT ) ) {
ast_channel_lock ( ast ) ;
if ( strcmp ( ast - > exten , " fax " ) ) {
const char * target_context = S_OR ( ast - > macrocontext , ast - > context ) ;
ast_channel_unlock ( ast ) ;
if ( ast_exists_extension ( ast , target_context , " fax " , 1 , ast - > cid . cid_num ) ) {
ast_verbose ( VERBOSE_PREFIX_2 " Redirecting '%s' to fax extension \n " , ast - > name ) ;
pbx_builtin_setvar_helper ( ast , " FAXEXTEN " , ast - > exten ) ;
if ( ast_async_goto ( ast , target_context , " fax " , 1 ) ) {
ast_log ( LOG_NOTICE , " Failed to async goto '%s' into fax of '%s' \n " , ast - > name , target_context ) ;
}
fr = & ast_null_frame ;
} else {
ast_log ( LOG_NOTICE , " Fax detected but no fax extension \n " ) ;
}
} else {
ast_channel_unlock ( ast ) ;
}
}
/* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */
if ( fr & & fr - > frametype = = AST_FRAME_VOICE & & p - > invitestate ! = INV_EARLY_MEDIA & & ast - > _state ! = AST_STATE_UP ) {
@ -26521,9 +26554,9 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data)
ast_rtp_instance_set_prop ( p - > rtp , AST_RTP_PROPERTY_DTMF , ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_RFC2833 ) ;
if ( ( ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_INBAND ) | |
( ast_test_flag ( & p - > flags [ 0 ] , SIP_DTMF ) = = SIP_DTMF_AUTO ) ) {
enable_d igit _detect( p ) ;
enable_d sp _detect( p ) ;
} else {
disable_d igit _detect( p ) ;
disable_d sp _detect( p ) ;
}
sip_pvt_unlock ( p ) ;
ast_channel_unlock ( chan ) ;