@ -1456,7 +1456,6 @@ static int sipdebug_text;
/*! \brief T38 States for a call */
/*! \brief T38 States for a call */
enum t38state {
enum t38state {
T38_DISABLED = 0 , /*!< Not enabled */
T38_DISABLED = 0 , /*!< Not enabled */
T38_LOCAL_DIRECT , /*!< Offered from local */
T38_LOCAL_REINVITE , /*!< Offered from local - REINVITE */
T38_LOCAL_REINVITE , /*!< Offered from local - REINVITE */
T38_PEER_DIRECT , /*!< Offered from peer */
T38_PEER_DIRECT , /*!< Offered from peer */
T38_PEER_REINVITE , /*!< Offered from peer - REINVITE */
T38_PEER_REINVITE , /*!< Offered from peer - REINVITE */
@ -1470,6 +1469,7 @@ struct t38properties {
int peercapability ; /*!< Peers T38 capability */
int peercapability ; /*!< Peers T38 capability */
int jointcapability ; /*!< Supported T38 capability at both ends */
int jointcapability ; /*!< Supported T38 capability at both ends */
enum t38state state ; /*!< T.38 state */
enum t38state state ; /*!< T.38 state */
unsigned int direct : 1 ; /*!< Whether the T38 came from the initial invite or not */
} ;
} ;
/*! \brief Parameters to know status of transfer */
/*! \brief Parameters to know status of transfer */
@ -2294,7 +2294,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p, int codec,
static void add_noncodec_to_sdp ( const struct sip_pvt * p , int format ,
static void add_noncodec_to_sdp ( const struct sip_pvt * p , int format ,
struct ast_str * * m_buf , struct ast_str * * a_buf ,
struct ast_str * * m_buf , struct ast_str * * a_buf ,
int debug ) ;
int debug ) ;
static enum sip_result add_sdp ( struct sip_request * resp , struct sip_pvt * p , int oldsdp );
static enum sip_result add_sdp ( struct sip_request * resp , struct sip_pvt * p , int oldsdp , int add_audio , int add_t38 );
static void do_setnat ( struct sip_pvt * p , int natflags ) ;
static void do_setnat ( struct sip_pvt * p , int natflags ) ;
static void stop_media_flows ( struct sip_pvt * p ) ;
static void stop_media_flows ( struct sip_pvt * p ) ;
@ -3897,7 +3897,6 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
/* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */
/* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */
if ( ast_test_flag ( & p - > t38 . t38support , SIP_PAGE2_T38SUPPORT ) ) {
if ( ast_test_flag ( & p - > t38 . t38support , SIP_PAGE2_T38SUPPORT ) ) {
switch ( p - > t38 . state ) {
switch ( p - > t38 . state ) {
case T38_LOCAL_DIRECT :
case T38_LOCAL_REINVITE :
case T38_LOCAL_REINVITE :
case T38_PEER_DIRECT :
case T38_PEER_DIRECT :
case T38_PEER_REINVITE :
case T38_PEER_REINVITE :
@ -4619,6 +4618,10 @@ static void change_t38_state(struct sip_pvt *p, int state)
if ( old = = state )
if ( old = = state )
return ;
return ;
if ( state = = T38_PEER_DIRECT ) {
p - > t38 . direct = 1 ;
}
p - > t38 . state = state ;
p - > t38 . state = state ;
ast_debug ( 2 , " T38 state changed to %d on channel %s \n " , p - > t38 . state , chan ? chan - > name : " <none> " ) ;
ast_debug ( 2 , " T38 state changed to %d on channel %s \n " , p - > t38 . state , chan ? chan - > name : " <none> " ) ;
@ -4998,9 +5001,6 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
} else if ( ! strcasecmp ( ast_var_name ( current ) , " SIPTRANSFER_REPLACES " ) ) {
} else if ( ! strcasecmp ( ast_var_name ( current ) , " SIPTRANSFER_REPLACES " ) ) {
/* We're replacing a call. */
/* We're replacing a call. */
p - > options - > replaces = ast_var_value ( current ) ;
p - > options - > replaces = ast_var_value ( current ) ;
} else if ( ! strcasecmp ( ast_var_name ( current ) , " T38CALL " ) ) {
p - > t38 . state = T38_LOCAL_DIRECT ;
ast_debug ( 1 , " T38State change to %d on channel %s \n " , p - > t38 . state , ast - > name ) ;
}
}
}
}
@ -5770,16 +5770,10 @@ static int sip_answer(struct ast_channel *ast)
ast_setstate ( ast , AST_STATE_UP ) ;
ast_setstate ( ast , AST_STATE_UP ) ;
ast_debug ( 1 , " SIP answering channel: %s \n " , ast - > name ) ;
ast_debug ( 1 , " SIP answering channel: %s \n " , ast - > name ) ;
if ( p - > t38 . state = = T38_PEER_DIRECT ) {
change_t38_state ( p , T38_ENABLED ) ;
res = transmit_response_with_t38_sdp ( p , " 200 OK " , & p - > initreq , XMIT_CRITICAL ) ;
ast_set_flag ( & p - > flags [ 1 ] , SIP_PAGE2_DIALOG_ESTABLISHED ) ;
} else {
ast_rtp_new_source ( p - > rtp ) ;
ast_rtp_new_source ( p - > rtp ) ;
res = transmit_response_with_sdp ( p , " 200 OK " , & p - > initreq , XMIT_CRITICAL , FALSE ) ;
res = transmit_response_with_sdp ( p , " 200 OK " , & p - > initreq , XMIT_CRITICAL , FALSE ) ;
ast_set_flag ( & p - > flags [ 1 ] , SIP_PAGE2_DIALOG_ESTABLISHED ) ;
ast_set_flag ( & p - > flags [ 1 ] , SIP_PAGE2_DIALOG_ESTABLISHED ) ;
}
}
}
sip_pvt_unlock ( p ) ;
sip_pvt_unlock ( p ) ;
return res ;
return res ;
}
}
@ -5815,10 +5809,14 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
p - > invitestate = INV_EARLY_MEDIA ;
p - > invitestate = INV_EARLY_MEDIA ;
transmit_response_with_sdp ( p , " 183 Session Progress " , & p - > initreq , XMIT_UNRELIABLE , FALSE ) ;
transmit_response_with_sdp ( p , " 183 Session Progress " , & p - > initreq , XMIT_UNRELIABLE , FALSE ) ;
ast_set_flag ( & p - > flags [ 0 ] , SIP_PROGRESS_SENT ) ;
ast_set_flag ( & p - > flags [ 0 ] , SIP_PROGRESS_SENT ) ;
}
} else if ( p - > t38 . state = = T38_ENABLED & & ! p - > t38 . direct ) {
change_t38_state ( p , T38_DISABLED ) ;
transmit_reinvite_with_sdp ( p , FALSE , FALSE ) ;
} else {
p - > lastrtptx = time ( NULL ) ;
p - > lastrtptx = time ( NULL ) ;
res = ast_rtp_write ( p - > rtp , frame ) ;
res = ast_rtp_write ( p - > rtp , frame ) ;
}
}
}
sip_pvt_unlock ( p ) ;
sip_pvt_unlock ( p ) ;
}
}
break ;
break ;
@ -5872,8 +5870,16 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
we simply forget the frames if we get modem frames before the bridge is up .
we simply forget the frames if we get modem frames before the bridge is up .
Fax will re - transmit .
Fax will re - transmit .
*/
*/
if ( p - > udptl & & ast - > _state = = AST_STATE_UP )
if ( ast - > _state = = AST_STATE_UP ) {
if ( ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_T38SUPPORT ) & & p - > t38 . state = = T38_DISABLED ) {
if ( ! p - > pendinginvite ) {
change_t38_state ( p , T38_LOCAL_REINVITE ) ;
transmit_reinvite_with_sdp ( p , TRUE , FALSE ) ;
}
} else if ( p - > udptl & & p - > t38 . state = = T38_ENABLED ) {
res = ast_udptl_write ( p - > udptl , frame ) ;
res = ast_udptl_write ( p - > udptl , frame ) ;
}
}
sip_pvt_unlock ( p ) ;
sip_pvt_unlock ( p ) ;
}
}
break ;
break ;
@ -6295,10 +6301,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if ( i - > rtp )
if ( i - > rtp )
ast_jb_configure ( tmp , & global_jbconf ) ;
ast_jb_configure ( tmp , & global_jbconf ) ;
/* If the INVITE contains T.38 SDP information set the proper channel variable so a created outgoing call will also have T.38 */
if ( i - > udptl & & i - > t38 . state = = T38_PEER_DIRECT )
pbx_builtin_setvar_helper ( tmp , " _T38CALL " , " 1 " ) ;
/* Set channel variables for this call from configuration */
/* Set channel variables for this call from configuration */
for ( v = i - > chanvars ; v ; v = v - > next ) {
for ( v = i - > chanvars ; v ; v = v - > next ) {
char valuebuf [ 1024 ] ;
char valuebuf [ 1024 ] ;
@ -8010,7 +8012,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Remote party offers T38, we need to update state */
/* Remote party offers T38, we need to update state */
if ( t38action = = SDP_T38_ACCEPT ) {
if ( t38action = = SDP_T38_ACCEPT ) {
if ( p - > t38 . state = = T38_LOCAL_ DIRECT | | p - > t38 . state = = T38_LOCAL_ REINVITE)
if ( p - > t38 . state = = T38_LOCAL_ REINVITE)
change_t38_state ( p , T38_ENABLED ) ;
change_t38_state ( p , T38_ENABLED ) ;
} else if ( t38action = = SDP_T38_INITIATE ) {
} else if ( t38action = = SDP_T38_INITIATE ) {
if ( p - > owner & & p - > lastinvite ) {
if ( p - > owner & & p - > lastinvite ) {
@ -9127,92 +9129,6 @@ static int t38_get_rate(int t38cap)
}
}
}
}
/*! \brief Add T.38 Session Description Protocol message */
static int add_t38_sdp ( struct sip_request * resp , struct sip_pvt * p )
{
int len = 0 ;
int x = 0 ;
struct sockaddr_in udptlsin ;
struct ast_str * m_modem = ast_str_alloca ( 1024 ) ;
struct ast_str * a_modem = ast_str_alloca ( 1024 ) ;
struct sockaddr_in udptldest = { 0 , } ;
int debug ;
debug = sip_debug_test_pvt ( p ) ;
len = 0 ;
if ( ! p - > udptl ) {
ast_log ( LOG_WARNING , " No way to add SDP without an UDPTL structure \n " ) ;
return - 1 ;
}
if ( ! p - > sessionid ) {
p - > sessionid = ( int ) ast_random ( ) ;
p - > sessionversion = p - > sessionid ;
} else
p - > sessionversion + + ;
/* Our T.38 end is */
ast_udptl_get_us ( p - > udptl , & udptlsin ) ;
/* Determine T.38 UDPTL destination */
if ( p - > udptlredirip . sin_addr . s_addr ) {
udptldest . sin_port = p - > udptlredirip . sin_port ;
udptldest . sin_addr = p - > udptlredirip . sin_addr ;
} else {
udptldest . sin_addr = p - > ourip . sin_addr ;
udptldest . sin_port = udptlsin . sin_port ;
}
if ( debug )
ast_debug ( 1 , " T.38 UDPTL is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( udptlsin . sin_port ) ) ;
/* We break with the "recommendation" and send our IP, in order that our
peer doesn ' t have to ast_gethostbyname ( ) us */
if ( debug ) {
ast_debug ( 1 , " Our T38 capability (%d), peer T38 capability (%d), joint capability (%d) \n " ,
p - > t38 . capability ,
p - > t38 . peercapability ,
p - > t38 . jointcapability ) ;
}
ast_str_append ( & m_modem , 0 , " v=0 \r \n " ) ;
ast_str_append ( & m_modem , 0 , " o=%s %d %d IN IP4 %s \r \n " , ast_strlen_zero ( global_sdpowner ) ? " - " : global_sdpowner , p - > sessionid , p - > sessionversion , ast_inet_ntoa ( udptldest . sin_addr ) ) ;
ast_str_append ( & m_modem , 0 , " s=%s \r \n " , ast_strlen_zero ( global_sdpsession ) ? " - " : global_sdpsession ) ;
ast_str_append ( & m_modem , 0 , " c=IN IP4 %s \r \n " , ast_inet_ntoa ( udptldest . sin_addr ) ) ;
ast_str_append ( & m_modem , 0 , " t=0 0 \r \n " ) ;
ast_str_append ( & m_modem , 0 , " m=image %d udptl t38 \r \n " , ntohs ( udptldest . sin_port ) ) ;
if ( ( p - > t38 . jointcapability & T38FAX_VERSION ) = = T38FAX_VERSION_0 )
ast_str_append ( & a_modem , 0 , " a=T38FaxVersion:0 \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_VERSION ) = = T38FAX_VERSION_1 )
ast_str_append ( & a_modem , 0 , " a=T38FaxVersion:1 \r \n " ) ;
if ( ( x = t38_get_rate ( p - > t38 . jointcapability ) ) )
ast_str_append ( & a_modem , 0 , " a=T38MaxBitRate:%d \r \n " , x ) ;
if ( ( p - > t38 . jointcapability & T38FAX_FILL_BIT_REMOVAL ) = = T38FAX_FILL_BIT_REMOVAL )
ast_str_append ( & a_modem , 0 , " a=T38FaxFillBitRemoval \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_TRANSCODING_MMR ) = = T38FAX_TRANSCODING_MMR )
ast_str_append ( & a_modem , 0 , " a=T38FaxTranscodingMMR \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_TRANSCODING_JBIG ) = = T38FAX_TRANSCODING_JBIG )
ast_str_append ( & a_modem , 0 , " a=T38FaxTranscodingJBIG \r \n " ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxRateManagement:%s \r \n " , ( p - > t38 . jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF ) ? " localTCF " : " transferredTCF " ) ;
x = ast_udptl_get_local_max_datagram ( p - > udptl ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxMaxBuffer:%d \r \n " , x ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxMaxDatagram:%d \r \n " , x ) ;
if ( p - > t38 . jointcapability ! = T38FAX_UDP_EC_NONE )
ast_str_append ( & a_modem , 0 , " a=T38FaxUdpEC:%s \r \n " , ( p - > t38 . jointcapability & T38FAX_UDP_EC_REDUNDANCY ) ? " t38UDPRedundancy " : " t38UDPFEC " ) ;
len = m_modem - > used + a_modem - > used ;
add_header ( resp , " Content-Type " , " application/sdp " ) ;
add_header_contentLength ( resp , len ) ;
add_line ( resp , m_modem - > str ) ;
add_line ( resp , a_modem - > str ) ;
/* Update lastrtprx when we send our SDP */
p - > lastrtprx = p - > lastrtptx = time ( NULL ) ;
return 0 ;
}
/*! \brief Add RFC 2833 DTMF offer to SDP */
/*! \brief Add RFC 2833 DTMF offer to SDP */
static void add_noncodec_to_sdp ( const struct sip_pvt * p , int format ,
static void add_noncodec_to_sdp ( const struct sip_pvt * p , int format ,
struct ast_str * * m_buf , struct ast_str * * a_buf ,
struct ast_str * * m_buf , struct ast_str * * a_buf ,
@ -9275,7 +9191,7 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo,
is used in Session - Timers where RE - INVITEs are used for refreshing SIP sessions
is used in Session - Timers where RE - INVITEs are used for refreshing SIP sessions
without modifying the media session in any way .
without modifying the media session in any way .
*/
*/
static enum sip_result add_sdp ( struct sip_request * resp , struct sip_pvt * p , int oldsdp )
static enum sip_result add_sdp ( struct sip_request * resp , struct sip_pvt * p , int oldsdp , int add_audio , int add_t38 )
{
{
int len = 0 ;
int len = 0 ;
int alreadysent = 0 ;
int alreadysent = 0 ;
@ -9284,8 +9200,10 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
struct sockaddr_in vsin ;
struct sockaddr_in vsin ;
struct sockaddr_in tsin ;
struct sockaddr_in tsin ;
struct sockaddr_in dest ;
struct sockaddr_in dest ;
struct sockaddr_in udptlsin ;
struct sockaddr_in vdest = { 0 , } ;
struct sockaddr_in vdest = { 0 , } ;
struct sockaddr_in tdest = { 0 , } ;
struct sockaddr_in tdest = { 0 , } ;
struct sockaddr_in udptldest = { 0 , } ;
/* SDP fields */
/* SDP fields */
char * version = " v=0 \r \n " ; /* Protocol version */
char * version = " v=0 \r \n " ; /* Protocol version */
@ -9294,16 +9212,18 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
char connection [ 256 ] ; /* Connection data */
char connection [ 256 ] ; /* Connection data */
char * session_time = " t=0 0 \r \n " ; /* Time the session is active */
char * session_time = " t=0 0 \r \n " ; /* Time the session is active */
char bandwidth [ 256 ] = " " ; /* Max bitrate */
char bandwidth [ 256 ] = " " ; /* Max bitrate */
char * hold ;
char * hold = " " ;
struct ast_str * m_audio = ast_str_alloca ( 256 ) ; /* Media declaration line for audio */
struct ast_str * m_audio = ast_str_alloca ( 256 ) ; /* Media declaration line for audio */
struct ast_str * m_video = ast_str_alloca ( 256 ) ; /* Media declaration line for video */
struct ast_str * m_video = ast_str_alloca ( 256 ) ; /* Media declaration line for video */
struct ast_str * m_text = ast_str_alloca ( 256 ) ; /* Media declaration line for text */
struct ast_str * m_text = ast_str_alloca ( 256 ) ; /* Media declaration line for text */
struct ast_str * m_modem = ast_str_alloca ( 256 ) ; /* Media declaration line for modem */
struct ast_str * a_audio = ast_str_alloca ( 1024 ) ; /* Attributes for audio */
struct ast_str * a_audio = ast_str_alloca ( 1024 ) ; /* Attributes for audio */
struct ast_str * a_video = ast_str_alloca ( 1024 ) ; /* Attributes for video */
struct ast_str * a_video = ast_str_alloca ( 1024 ) ; /* Attributes for video */
struct ast_str * a_text = ast_str_alloca ( 1024 ) ; /* Attributes for text */
struct ast_str * a_text = ast_str_alloca ( 1024 ) ; /* Attributes for text */
struct ast_str * a_modem = ast_str_alloca ( 1024 ) ; /* Attributes for modem */
int x ;
int x ;
int capability ;
int capability = 0 ;
int needaudio = FALSE ;
int needaudio = FALSE ;
int needvideo = FALSE ;
int needvideo = FALSE ;
int needtext = FALSE ;
int needtext = FALSE ;
@ -9334,6 +9254,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
p - > sessionversion + + ;
p - > sessionversion + + ;
}
}
get_our_media_address ( p , needvideo , & sin , & vsin , & tsin , & dest , & vdest ) ;
snprintf ( owner , sizeof ( owner ) , " o=%s %d %d IN IP4 %s \r \n " , ast_strlen_zero ( global_sdpowner ) ? " - " : global_sdpowner , p - > sessionid , p - > sessionversion , ast_inet_ntoa ( dest . sin_addr ) ) ;
snprintf ( connection , sizeof ( connection ) , " c=IN IP4 %s \r \n " , ast_inet_ntoa ( dest . sin_addr ) ) ;
if ( add_audio ) {
capability = p - > jointcapability ;
capability = p - > jointcapability ;
/* XXX note, Video and Text are negated - 'true' means 'no' */
/* XXX note, Video and Text are negated - 'true' means 'no' */
@ -9361,9 +9287,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug ( 2 , " This call needs video offers, but there's no video support enabled! \n " ) ;
ast_debug ( 2 , " This call needs video offers, but there's no video support enabled! \n " ) ;
}
}
/* Get our media addresses */
get_our_media_address ( p , needvideo , & sin , & vsin , & tsin , & dest , & vdest ) ;
if ( debug )
if ( debug )
ast_verbose ( " Audio is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( sin . sin_port ) ) ;
ast_verbose ( " Audio is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( sin . sin_port ) ) ;
@ -9406,7 +9329,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
tdest . sin_port = tsin . sin_port ;
tdest . sin_port = tsin . sin_port ;
}
}
ast_str_append ( & m_text , 0 , " m=text %d RTP/AVP " , ntohs ( tdest . sin_port ) ) ;
ast_str_append ( & m_text , 0 , " m=text %d RTP/AVP " , ntohs ( tdest . sin_port ) ) ;
if ( debug ) /* XXX should I use tdest below ? */
if ( debug ) /* XXX should I use tdest below ? */
ast_verbose ( " Text is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( tsin . sin_port ) ) ;
ast_verbose ( " Text is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( tsin . sin_port ) ) ;
@ -9417,8 +9339,6 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
/* We break with the "recommendation" and send our IP, in order that our
/* We break with the "recommendation" and send our IP, in order that our
peer doesn ' t have to ast_gethostbyname ( ) us */
peer doesn ' t have to ast_gethostbyname ( ) us */
snprintf ( owner , sizeof ( owner ) , " o=%s %d %d IN IP4 %s \r \n " , ast_strlen_zero ( global_sdpowner ) ? " - " : global_sdpowner , p - > sessionid , p - > sessionversion , ast_inet_ntoa ( dest . sin_addr ) ) ;
snprintf ( connection , sizeof ( connection ) , " c=IN IP4 %s \r \n " , ast_inet_ntoa ( dest . sin_addr ) ) ;
ast_str_append ( & m_audio , 0 , " m=audio %d RTP/AVP " , ntohs ( dest . sin_port ) ) ;
ast_str_append ( & m_audio , 0 , " m=audio %d RTP/AVP " , ntohs ( dest . sin_port ) ) ;
if ( ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_CALL_ONHOLD ) = = SIP_PAGE2_CALL_ONHOLD_ONEDIR )
if ( ast_test_flag ( & p - > flags [ 1 ] , SIP_PAGE2_CALL_ONHOLD ) = = SIP_PAGE2_CALL_ONHOLD_ONEDIR )
@ -9505,6 +9425,55 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
m_text - > len - m_text - > used < 2 | | a_text - > len - a_text - > used < 2 | |
m_text - > len - m_text - > used < 2 | | a_text - > len - a_text - > used < 2 | |
a_audio - > len - a_audio - > used < 2 | | a_video - > len - a_video - > used < 2 )
a_audio - > len - a_audio - > used < 2 | | a_video - > len - a_video - > used < 2 )
ast_log ( LOG_WARNING , " SIP SDP may be truncated due to undersized buffer!! \n " ) ;
ast_log ( LOG_WARNING , " SIP SDP may be truncated due to undersized buffer!! \n " ) ;
}
if ( add_t38 ) {
/* Our T.38 end is */
ast_udptl_get_us ( p - > udptl , & udptlsin ) ;
/* Determine T.38 UDPTL destination */
if ( p - > udptlredirip . sin_addr . s_addr ) {
udptldest . sin_port = p - > udptlredirip . sin_port ;
udptldest . sin_addr = p - > udptlredirip . sin_addr ;
} else {
udptldest . sin_addr = p - > ourip . sin_addr ;
udptldest . sin_port = udptlsin . sin_port ;
}
if ( debug )
ast_debug ( 1 , " T.38 UDPTL is at %s port %d \n " , ast_inet_ntoa ( p - > ourip . sin_addr ) , ntohs ( udptlsin . sin_port ) ) ;
/* We break with the "recommendation" and send our IP, in order that our
peer doesn ' t have to ast_gethostbyname ( ) us */
if ( debug ) {
ast_debug ( 1 , " Our T38 capability (%d), peer T38 capability (%d), joint capability (%d) \n " ,
p - > t38 . capability ,
p - > t38 . peercapability ,
p - > t38 . jointcapability ) ;
}
ast_str_append ( & m_modem , 0 , " m=image %d udptl t38 " , ntohs ( udptldest . sin_port ) ) ;
if ( ( p - > t38 . jointcapability & T38FAX_VERSION ) = = T38FAX_VERSION_0 )
ast_str_append ( & a_modem , 0 , " a=T38FaxVersion:0 \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_VERSION ) = = T38FAX_VERSION_1 )
ast_str_append ( & a_modem , 0 , " a=T38FaxVersion:1 \r \n " ) ;
if ( ( x = t38_get_rate ( p - > t38 . jointcapability ) ) )
ast_str_append ( & a_modem , 0 , " a=T38MaxBitRate:%d \r \n " , x ) ;
if ( ( p - > t38 . jointcapability & T38FAX_FILL_BIT_REMOVAL ) = = T38FAX_FILL_BIT_REMOVAL )
ast_str_append ( & a_modem , 0 , " a=T38FaxFillBitRemoval \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_TRANSCODING_MMR ) = = T38FAX_TRANSCODING_MMR )
ast_str_append ( & a_modem , 0 , " a=T38FaxTranscodingMMR \r \n " ) ;
if ( ( p - > t38 . jointcapability & T38FAX_TRANSCODING_JBIG ) = = T38FAX_TRANSCODING_JBIG )
ast_str_append ( & a_modem , 0 , " a=T38FaxTranscodingJBIG \r \n " ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxRateManagement:%s \r \n " , ( p - > t38 . jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF ) ? " localTCF " : " transferredTCF " ) ;
x = ast_udptl_get_local_max_datagram ( p - > udptl ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxMaxBuffer:%d \r \n " , x ) ;
ast_str_append ( & a_modem , 0 , " a=T38FaxMaxDatagram:%d \r \n " , x ) ;
if ( p - > t38 . jointcapability ! = T38FAX_UDP_EC_NONE )
ast_str_append ( & a_modem , 0 , " a=T38FaxUdpEC:%s \r \n " , ( p - > t38 . jointcapability & T38FAX_UDP_EC_REDUNDANCY ) ? " t38UDPRedundancy " : " t38UDPFEC " ) ;
}
if ( needaudio )
if ( needaudio )
ast_str_append ( & m_audio , 0 , " \r \n " ) ;
ast_str_append ( & m_audio , 0 , " \r \n " ) ;
@ -9512,6 +9481,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_str_append ( & m_video , 0 , " \r \n " ) ;
ast_str_append ( & m_video , 0 , " \r \n " ) ;
if ( needtext )
if ( needtext )
ast_str_append ( & m_text , 0 , " \r \n " ) ;
ast_str_append ( & m_text , 0 , " \r \n " ) ;
if ( add_t38 )
ast_str_append ( & m_modem , 0 , " \r \n " ) ;
len = strlen ( version ) + strlen ( subject ) + strlen ( owner ) +
len = strlen ( version ) + strlen ( subject ) + strlen ( owner ) +
strlen ( connection ) + strlen ( session_time ) ;
strlen ( connection ) + strlen ( session_time ) ;
@ -9521,6 +9492,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
len + = m_video - > used + a_video - > used + strlen ( bandwidth ) + strlen ( hold ) ;
len + = m_video - > used + a_video - > used + strlen ( bandwidth ) + strlen ( hold ) ;
if ( needtext ) /* only if text response is appropriate */
if ( needtext ) /* only if text response is appropriate */
len + = m_text - > used + a_text - > used + strlen ( hold ) ;
len + = m_text - > used + a_text - > used + strlen ( hold ) ;
if ( add_t38 )
len + = m_modem - > used + a_modem - > used ;
add_header ( resp , " Content-Type " , " application/sdp " ) ;
add_header ( resp , " Content-Type " , " application/sdp " ) ;
add_header_contentLength ( resp , len ) ;
add_header_contentLength ( resp , len ) ;
@ -9546,6 +9519,10 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
add_line ( resp , a_text - > str ) ;
add_line ( resp , a_text - > str ) ;
add_line ( resp , hold ) ; /* Repeat hold for the text stream */
add_line ( resp , hold ) ; /* Repeat hold for the text stream */
}
}
if ( add_t38 ) {
add_line ( resp , m_modem - > str ) ;
add_line ( resp , a_modem - > str ) ;
}
/* Update lastrtprx when we send our SDP */
/* Update lastrtprx when we send our SDP */
p - > lastrtprx = p - > lastrtptx = time ( NULL ) ; /* XXX why both ? */
p - > lastrtprx = p - > lastrtptx = time ( NULL ) ; /* XXX why both ? */
@ -9568,7 +9545,7 @@ static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct s
respprep ( & resp , p , msg , req ) ;
respprep ( & resp , p , msg , req ) ;
if ( p - > udptl ) {
if ( p - > udptl ) {
ast_udptl_offered_from_local ( p - > udptl , 0 ) ;
ast_udptl_offered_from_local ( p - > udptl , 0 ) ;
add_ t38_ sdp( & resp , p ) ;
add_ sdp( & resp , p , 0 , 0 , 1 ) ;
} else
} else
ast_log ( LOG_ERROR , " Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s \n " , p - > callid ) ;
ast_log ( LOG_ERROR , " Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s \n " , p - > callid ) ;
if ( retrans & & ! p - > pendinginvite )
if ( retrans & & ! p - > pendinginvite )
@ -9618,7 +9595,11 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const
ast_rtp_codec_setpref ( p - > rtp , & p - > prefs ) ;
ast_rtp_codec_setpref ( p - > rtp , & p - > prefs ) ;
}
}
try_suggested_sip_codec ( p ) ;
try_suggested_sip_codec ( p ) ;
add_sdp ( & resp , p , oldsdp ) ;
if ( p - > t38 . state = = T38_PEER_DIRECT | | p - > t38 . state = = T38_ENABLED ) {
add_sdp ( & resp , p , oldsdp , TRUE , TRUE ) ;
} else {
add_sdp ( & resp , p , oldsdp , TRUE , FALSE ) ;
}
} else
} else
ast_log ( LOG_ERROR , " Can't add SDP to response, since we have no RTP session allocated. Call-ID %s \n " , p - > callid ) ;
ast_log ( LOG_ERROR , " Can't add SDP to response, since we have no RTP session allocated. Call-ID %s \n " , p - > callid ) ;
if ( reliable & & ! p - > pendinginvite )
if ( reliable & & ! p - > pendinginvite )
@ -9700,9 +9681,9 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
if ( p - > do_history )
if ( p - > do_history )
append_history ( p , " ReInv " , " Re-invite sent " ) ;
append_history ( p , " ReInv " , " Re-invite sent " ) ;
if ( t38version )
if ( t38version )
add_ t38_ sdp( & req , p ) ;
add_ sdp( & req , p , oldsdp , FALSE , TRUE ) ;
else
else
add_sdp ( & req , p , oldsdp );
add_sdp ( & req , p , oldsdp , TRUE , FALSE );
/* Use this as the basis */
/* Use this as the basis */
initialize_initreq ( p , & req ) ;
initialize_initreq ( p , & req ) ;
@ -10105,12 +10086,12 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
ast_channel_unlock ( chan ) ;
ast_channel_unlock ( chan ) ;
}
}
if ( sdp ) {
if ( sdp ) {
if ( p - > udptl & & ( p - > t38 . state = = T38_LOCAL_DIRECT | | p - > t38 . state = = T38_LOCAL_REINVITE ) ) {
if ( p - > udptl & & p - > t38 . state = = T38_LOCAL_REINVITE ) {
ast_udptl_offered_from_local ( p - > udptl , 1 ) ;
ast_udptl_offered_from_local ( p - > udptl , 1 ) ;
ast_debug ( 1 , " T38 is in state %d on channel %s \n " , p - > t38 . state , p - > owner ? p - > owner - > name : " <none> " ) ;
ast_debug ( 1 , " T38 is in state %d on channel %s \n " , p - > t38 . state , p - > owner ? p - > owner - > name : " <none> " ) ;
add_ t38_ sdp( & req , p ) ;
add_ sdp( & req , p , FALSE , FALSE , TRUE ) ;
} else if ( p - > rtp )
} else if ( p - > rtp )
add_sdp ( & req , p , FALSE );
add_sdp ( & req , p , FALSE , TRUE , FALSE );
} else {
} else {
if ( ! p - > notify_headers ) {
if ( ! p - > notify_headers ) {
add_header_contentLength ( & req , 0 ) ;
add_header_contentLength ( & req , 0 ) ;
@ -16799,20 +16780,6 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
/* Trigger a reinvite back to audio */
/* Trigger a reinvite back to audio */
transmit_reinvite_with_sdp ( p , FALSE , FALSE ) ;
transmit_reinvite_with_sdp ( p , FALSE , FALSE ) ;
} else if ( p - > udptl & & p - > t38 . state = = T38_LOCAL_DIRECT ) {
/* We tried to send T.38 out in an initial INVITE and the remote side rejected it,
right now we can ' t fall back to audio so totally abort .
*/
/* Try to reset RTP timers */
ast_rtp_set_rtptimers_onhold ( p - > rtp ) ;
ast_log ( LOG_ERROR , " Got error on T.38 initial invite. Bailing out. \n " ) ;
change_t38_state ( p , T38_DISABLED ) ;
/* The dialog is now terminated */
if ( p - > owner & & ! req - > ignore )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
pvt_set_needdestroy ( p , " got error on T.38 initial invite " ) ;
sip_alreadygone ( p ) ;
} else {
} else {
/* We can't set up this call, so give up */
/* We can't set up this call, so give up */
if ( p - > owner & & ! req - > ignore )
if ( p - > owner & & ! req - > ignore )