@ -112,72 +112,6 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
srslog : : fetch_basic_logger ( LOGSERVICE ) . debug ( " Opened %s socket=%d " , net_utils : : protocol_to_string ( protocol ) , fd ) ;
if ( protocol = = protocol_type : : SCTP ) {
// Sets the data_io_event to be able to use sendrecv_info
// Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown
// Also subscribes to SCTP_PEER_ADDR_CHANGE, to handle ungraceful shutdown of the link.
struct sctp_event_subscribe evnts = { } ;
evnts . sctp_data_io_event = 1 ;
evnts . sctp_shutdown_event = 1 ;
evnts . sctp_address_event = 1 ;
if ( setsockopt ( fd , IPPROTO_SCTP , SCTP_EVENTS , & evnts , sizeof ( evnts ) ) ! = 0 ) {
srslog : : fetch_basic_logger ( LOGSERVICE ) . error ( " Failed to subscribe to SCTP_SHUTDOWN event: %s " , strerror ( errno ) ) ;
perror ( " Could not register socket to SCTP events \n " ) ;
close ( fd ) ;
return - 1 ;
}
/*
* Modify SCTP default parameters for quicker detection of broken links .
* This includes changes to the SCTP_INITMSG parameters ( to control the timeout of the connect ( ) syscall )
* And changes to the maximum re - transmission timeout ( rto_max ) , for quicker detection of broken links .
*/
// Set RTO_MAX to quickly detect broken links.
sctp_rtoinfo rto_opts ;
socklen_t rto_sz = sizeof ( sctp_rtoinfo ) ;
rto_opts . srto_assoc_id = 0 ;
if ( getsockopt ( fd , SOL_SCTP , SCTP_RTOINFO , & rto_opts , & rto_sz ) < 0 ) {
printf ( " Error getting RTO_INFO sockopts \n " ) ;
close ( fd ) ;
return - 1 ;
}
rto_opts . srto_max = 6000 ; // 6 seconds
srslog : : fetch_basic_logger ( LOGSERVICE )
. debug (
" Setting RTO_INFO options on SCTP socket. Association %d, Initial RTO %d, Minimum RTO %d, Maximum RTO %d " ,
rto_opts . srto_assoc_id ,
rto_opts . srto_initial ,
rto_opts . srto_min ,
rto_opts . srto_max ) ;
if ( setsockopt ( fd , SOL_SCTP , SCTP_RTOINFO , & rto_opts , rto_sz ) < 0 ) {
perror ( " Error setting RTO_INFO sockopts \n " ) ;
close ( fd ) ;
return - 1 ;
}
// Set SCTP INITMSG options to reduce blocking timeout of connect()
sctp_initmsg init_opts ;
socklen_t init_sz = sizeof ( sctp_initmsg ) ;
if ( getsockopt ( fd , SOL_SCTP , SCTP_INITMSG , & init_opts , & init_sz ) < 0 ) {
printf ( " Error getting sockopts \n " ) ;
close ( fd ) ;
return - 1 ;
}
init_opts . sinit_max_attempts = 3 ;
init_opts . sinit_max_init_timeo = 5000 ; // 5 seconds
srslog : : fetch_basic_logger ( LOGSERVICE )
. debug ( " Setting SCTP_INITMSG options on SCTP socket. Max attempts %d, Max init attempts timeout %d " ,
init_opts . sinit_max_attempts ,
init_opts . sinit_max_init_timeo ) ;
if ( setsockopt ( fd , SOL_SCTP , SCTP_INITMSG , & init_opts , init_sz ) < 0 ) {
perror ( " Error setting SCTP_INITMSG sockopts \n " ) ;
close ( fd ) ;
return - 1 ;
}
}
return fd ;
@ -264,6 +198,104 @@ bool start_listen(int fd)
return true ;
}
bool reuse_addr ( int fd )
{
if ( fd < 0 ) {
srslog : : fetch_basic_logger ( LOGSERVICE ) . error ( " Trying reuse_addr a closed socket. Socket=%d " , fd ) ;
return false ;
}
int enable = 1 ;
if ( setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , & enable , sizeof ( int ) ) < 0 ) {
srslog : : fetch_basic_logger ( LOGSERVICE ) . error ( " Failed to set SO_REUSEADDR. Socket=%d " , fd ) ;
return false ;
}
srslog : : fetch_basic_logger ( LOGSERVICE ) . debug ( " Successfully set SO_REUSEADDR. Socket=%d " , fd ) ;
return true ;
}
bool sctp_subscribe_to_events ( int fd )
{
if ( fd < 0 ) {
srslog : : fetch_basic_logger ( LOGSERVICE ) . error ( " Trying subscribe to SCTP events on a closed socket. Socket=%d " , fd ) ;
return false ;
}
// Sets the data_io_event to be able to use sendrecv_info
// Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown
// Also subscribes to SCTP_PEER_ADDR_CHANGE, to handle ungraceful shutdown of the link.
struct sctp_event_subscribe evnts = { } ;
evnts . sctp_data_io_event = 1 ;
evnts . sctp_shutdown_event = 1 ;
evnts . sctp_address_event = 1 ;
if ( setsockopt ( fd , IPPROTO_SCTP , SCTP_EVENTS , & evnts , sizeof ( evnts ) ) ! = 0 ) {
srslog : : fetch_basic_logger ( LOGSERVICE ) . error ( " Failed to subscribe to SCTP_SHUTDOWN event: %s " , strerror ( errno ) ) ;
perror ( " Could not register socket to SCTP events \n " ) ;
close ( fd ) ;
return false ;
}
return true ;
}
bool sctp_set_rto_opts ( int fd )
{
/*
* Modify SCTP default parameters for quicker detection of broken links .
* This includes changes to the SCTP_INITMSG parameters ( to control the timeout of the connect ( ) syscall )
* And changes to the maximum re - transmission timeout ( rto_max ) , for quicker detection of broken links .
*/
// Set RTO_MAX to quickly detect broken links.
sctp_rtoinfo rto_opts ;
socklen_t rto_sz = sizeof ( sctp_rtoinfo ) ;
rto_opts . srto_assoc_id = 0 ;
if ( getsockopt ( fd , SOL_SCTP , SCTP_RTOINFO , & rto_opts , & rto_sz ) < 0 ) {
printf ( " Error getting RTO_INFO sockopts \n " ) ;
close ( fd ) ;
return false ;
}
rto_opts . srto_max = 6000 ; // 6 seconds
srslog : : fetch_basic_logger ( LOGSERVICE )
. debug ( " Setting RTO_INFO options on SCTP socket. Association %d, Initial RTO %d, Minimum RTO %d, Maximum RTO %d " ,
rto_opts . srto_assoc_id ,
rto_opts . srto_initial ,
rto_opts . srto_min ,
rto_opts . srto_max ) ;
if ( setsockopt ( fd , SOL_SCTP , SCTP_RTOINFO , & rto_opts , rto_sz ) < 0 ) {
perror ( " Error setting RTO_INFO sockopts \n " ) ;
close ( fd ) ;
return false ;
}
return true ;
}
bool sctp_set_init_msg_opts ( int fd )
{
// Set SCTP INITMSG options to reduce blocking timeout of connect()
sctp_initmsg init_opts ;
socklen_t init_sz = sizeof ( sctp_initmsg ) ;
if ( getsockopt ( fd , SOL_SCTP , SCTP_INITMSG , & init_opts , & init_sz ) < 0 ) {
printf ( " Error getting sockopts \n " ) ;
close ( fd ) ;
return false ;
}
init_opts . sinit_max_attempts = 3 ;
init_opts . sinit_max_init_timeo = 5000 ; // 5 seconds
srslog : : fetch_basic_logger ( LOGSERVICE )
. debug ( " Setting SCTP_INITMSG options on SCTP socket. Max attempts %d, Max init attempts timeout %d " ,
init_opts . sinit_max_attempts ,
init_opts . sinit_max_init_timeo ) ;
if ( setsockopt ( fd , SOL_SCTP , SCTP_INITMSG , & init_opts , init_sz ) < 0 ) {
perror ( " Error setting SCTP_INITMSG sockopts \n " ) ;
close ( fd ) ;
return false ;
}
return true ;
}
} // namespace net_utils
/********************************************
@ -330,25 +362,25 @@ bool unique_socket::start_listen()
return net_utils : : start_listen ( sockfd ) ;
}
/***********************************************************************
* SCTP socket
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
namespace net_utils {
bool sctp_init_socket ( unique_socket * socket , net_utils : : socket_type socktype , const char * bind_addr_str , int bind_port )
bool unique_socket : : reuse_addr ( )
{
if ( not socket - > open_socket ( net_utils : : addr_family : : ipv4 , socktype , net_utils : : protocol_type : : SCTP ) ) {
return false ;
return net_utils : : reuse_addr ( sockfd ) ;
}
if ( not socket - > bind_addr ( bind_addr_str , bind_port ) ) {
socket - > close ( ) ;
return false ;
bool unique_socket : : sctp_subscribe_to_events ( )
{
return net_utils : : sctp_subscribe_to_events ( sockfd ) ;
}
return true ;
bool unique_socket : : sctp_set_rto_opts ( )
{
return net_utils : : sctp_set_rto_opts ( sockfd ) ;
}
} // namespace net_utils
bool unique_socket : : sctp_set_init_msg_opts ( )
{
return net_utils : : sctp_set_init_msg_opts ( sockfd ) ;
}
/***************************************************************
* Rx Multisocket Handler