@ -36,45 +36,46 @@ void protocol_zt::set_nonblock(int fd)
void protocol_zt : : set_nodelay ( int fd )
{
const int yes = 1 ;
lwip_setsockopt ( fd , IPPROTO_TCP , TCP_NODELAY , ( void * ) & yes , sizeof ( yes ) ) ;
lwip_setsockopt ( fd , IPPROTO_TCP , TCP_NODELAY , ( void * ) & yes , sizeof ( yes ) ) ;
}
void protocol_zt : : set_reuseaddr ( int fd )
{
const int yes = 1 ;
lwip_setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , ( void * ) & yes , sizeof ( yes ) ) ;
lwip_setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , ( void * ) & yes , sizeof ( yes ) ) ;
}
bool protocol_zt : : network_online ( )
{
if ( ! zerotier_network_ready ( ) )
if ( ! zerotier_network_ready ( ) )
return false ;
struct sockaddr_in6 in6 { } ;
struct sockaddr_in6 in6 {
} ;
in6 . sin6_port = htons ( default_port ) ;
in6 . sin6_family = AF_INET6 ;
in6 . sin6_addr = in6addr_any ;
if ( fd_udp = = - 1 ) {
if ( fd_udp = = - 1 ) {
fd_udp = lwip_socket ( AF_INET6 , SOCK_DGRAM , 0 ) ;
set_reuseaddr ( fd_udp ) ;
auto ret = lwip_bind ( fd_udp , ( struct sockaddr * ) & in6 , sizeof ( in6 ) ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
SDL_Log ( " lwip, (udp) bind: %s \n " , strerror ( errno ) ) ;
throw protocol_exception ( ) ;
}
set_nonblock ( fd_udp ) ;
}
if ( fd_tcp = = - 1 ) {
if ( fd_tcp = = - 1 ) {
fd_tcp = lwip_socket ( AF_INET6 , SOCK_STREAM , 0 ) ;
set_reuseaddr ( fd_tcp ) ;
auto r1 = lwip_bind ( fd_tcp , ( struct sockaddr * ) & in6 , sizeof ( in6 ) ) ;
if ( r1 < 0 ) {
if ( r1 < 0 ) {
SDL_Log ( " lwip, (tcp) bind: %s \n " , strerror ( errno ) ) ;
throw protocol_exception ( ) ;
}
auto r2 = lwip_listen ( fd_tcp , 10 ) ;
if ( r2 < 0 ) {
if ( r2 < 0 ) {
SDL_Log ( " lwip, listen: %s \n " , strerror ( errno ) ) ;
throw protocol_exception ( ) ;
}
@ -84,15 +85,16 @@ bool protocol_zt::network_online()
return true ;
}
bool protocol_zt : : send ( const endpoint & peer , const buffer_t & data )
bool protocol_zt : : send ( const endpoint & peer , const buffer_t & data )
{
peer_list [ peer ] . send_queue . push_back ( frame_queue : : make_frame ( data ) ) ;
return true ;
}
bool protocol_zt : : send_oob ( const endpoint & peer , const buffer_t & data )
bool protocol_zt : : send_oob ( const endpoint & peer , const buffer_t & data )
{
struct sockaddr_in6 in6 { } ;
struct sockaddr_in6 in6 {
} ;
in6 . sin6_port = htons ( default_port ) ;
in6 . sin6_family = AF_INET6 ;
std : : copy ( peer . addr . begin ( ) , peer . addr . end ( ) , in6 . sin6_addr . s6_addr ) ;
@ -100,35 +102,36 @@ bool protocol_zt::send_oob(const endpoint& peer, const buffer_t& data)
return true ;
}
bool protocol_zt : : send_oob_mc ( const buffer_t & data )
bool protocol_zt : : send_oob_mc ( const buffer_t & data )
{
endpoint mc ;
std : : copy ( dvl_multicast_addr , dvl_multicast_addr + 16 , mc . addr . begin ( ) ) ;
std : : copy ( dvl_multicast_addr , dvl_multicast_addr + 16 , mc . addr . begin ( ) ) ;
return send_oob ( mc , data ) ;
}
bool protocol_zt : : send_queued_peer ( const endpoint & peer )
bool protocol_zt : : send_queued_peer ( const endpoint & peer )
{
if ( peer_list [ peer ] . fd = = - 1 ) {
if ( peer_list [ peer ] . fd = = - 1 ) {
peer_list [ peer ] . fd = lwip_socket ( AF_INET6 , SOCK_STREAM , 0 ) ;
set_nodelay ( peer_list [ peer ] . fd ) ;
set_nonblock ( peer_list [ peer ] . fd ) ;
struct sockaddr_in6 in6 { } ;
struct sockaddr_in6 in6 {
} ;
in6 . sin6_port = htons ( default_port ) ;
in6 . sin6_family = AF_INET6 ;
std : : copy ( peer . addr . begin ( ) , peer . addr . end ( ) , in6 . sin6_addr . s6_addr ) ;
lwip_connect ( peer_list [ peer ] . fd , ( const struct sockaddr * ) & in6 , sizeof ( in6 ) ) ;
}
while ( ! peer_list [ peer ] . send_queue . empty ( ) ) {
while ( ! peer_list [ peer ] . send_queue . empty ( ) ) {
auto len = peer_list [ peer ] . send_queue . front ( ) . size ( ) ;
auto r = lwip_send ( peer_list [ peer ] . fd , peer_list [ peer ] . send_queue . front ( ) . data ( ) , len , 0 ) ;
if ( r < 0 ) {
if ( r < 0 ) {
// handle error
return false ;
} else if ( decltype ( len ) ( r ) < len ) {
// partial send
auto it = peer_list [ peer ] . send_queue . front ( ) . begin ( ) ;
peer_list [ peer ] . send_queue . front ( ) . erase ( it , it + r ) ;
peer_list [ peer ] . send_queue . front ( ) . erase ( it , it + r ) ;
return true ;
} else if ( decltype ( len ) ( r ) = = len ) {
peer_list [ peer ] . send_queue . pop_front ( ) ;
@ -139,15 +142,15 @@ bool protocol_zt::send_queued_peer(const endpoint& peer)
return true ;
}
bool protocol_zt : : recv_peer ( const endpoint & peer )
bool protocol_zt : : recv_peer ( const endpoint & peer )
{
unsigned char buf [ PKTBUF_LEN ] ;
while ( true ) {
while ( true ) {
auto len = lwip_recv ( peer_list [ peer ] . fd , buf , sizeof ( buf ) , 0 ) ;
if ( len > = 0 ) {
peer_list [ peer ] . recv_queue . write ( buffer_t ( buf , buf + len ) ) ;
if ( len > = 0 ) {
peer_list [ peer ] . recv_queue . write ( buffer_t ( buf , buf + len ) ) ;
} else {
if ( errno = = EAGAIN | | errno = = EWOULDBLOCK ) {
if ( errno = = EAGAIN | | errno = = EWOULDBLOCK ) {
return true ;
} else {
return false ;
@ -158,8 +161,8 @@ bool protocol_zt::recv_peer(const endpoint& peer)
bool protocol_zt : : send_queued_all ( )
{
for ( auto & peer : peer_list ) {
if ( ! send_queued_peer ( peer . first ) ) {
for ( auto & peer : peer_list ) {
if ( ! send_queued_peer ( peer . first ) ) {
// disconnect this peer
}
}
@ -168,9 +171,9 @@ bool protocol_zt::send_queued_all()
bool protocol_zt : : recv_from_peers ( )
{
for ( auto & peer : peer_list ) {
if ( peer . second . fd ! = - 1 ) {
if ( ! recv_peer ( peer . first ) ) {
for ( auto & peer : peer_list ) {
if ( peer . second . fd ! = - 1 ) {
if ( ! recv_peer ( peer . first ) ) {
// error, disconnect?
}
}
@ -181,29 +184,31 @@ bool protocol_zt::recv_from_peers()
bool protocol_zt : : recv_from_udp ( )
{
unsigned char buf [ PKTBUF_LEN ] ;
struct sockaddr_in6 in6 { } ;
struct sockaddr_in6 in6 {
} ;
socklen_t addrlen = sizeof ( in6 ) ;
auto len = lwip_recvfrom ( fd_udp , buf , sizeof ( buf ) , 0 , ( struct sockaddr * ) & in6 , & addrlen ) ;
if ( len < 0 )
if ( len < 0 )
return false ;
buffer_t data ( buf , buf + len ) ;
buffer_t data ( buf , buf + len ) ;
endpoint ep ;
std : : copy ( in6 . sin6_addr . s6_addr , in6 . sin6_addr . s6_addr + 16 , ep . addr . begin ( ) ) ;
std : : copy ( in6 . sin6_addr . s6_addr , in6 . sin6_addr . s6_addr + 16 , ep . addr . begin ( ) ) ;
oob_recv_queue . push_back ( std : : make_pair ( std : : move ( ep ) , std : : move ( data ) ) ) ;
return true ;
}
bool protocol_zt : : accept_all ( )
{
struct sockaddr_in6 in6 { } ;
struct sockaddr_in6 in6 {
} ;
socklen_t addrlen = sizeof ( in6 ) ;
while ( true ) {
while ( true ) {
auto newfd = lwip_accept ( fd_tcp , ( struct sockaddr * ) & in6 , & addrlen ) ;
if ( newfd < 0 )
if ( newfd < 0 )
break ;
endpoint ep ;
std : : copy ( in6 . sin6_addr . s6_addr , in6 . sin6_addr . s6_addr + 16 , ep . addr . begin ( ) ) ;
if ( peer_list [ ep ] . fd ! = - 1 ) {
std : : copy ( in6 . sin6_addr . s6_addr , in6 . sin6_addr . s6_addr + 16 , ep . addr . begin ( ) ) ;
if ( peer_list [ ep ] . fd ! = - 1 ) {
SDL_Log ( " protocol_zt::accept_all: WARNING: overwriting connection \n " ) ;
lwip_close ( peer_list [ ep ] . fd ) ;
}
@ -214,22 +219,22 @@ bool protocol_zt::accept_all()
return true ;
}
bool protocol_zt : : recv ( endpoint & peer , buffer_t & data )
bool protocol_zt : : recv ( endpoint & peer , buffer_t & data )
{
accept_all ( ) ;
send_queued_all ( ) ;
recv_from_peers ( ) ;
recv_from_udp ( ) ;
if ( ! oob_recv_queue . empty ( ) ) {
if ( ! oob_recv_queue . empty ( ) ) {
peer = oob_recv_queue . front ( ) . first ;
data = oob_recv_queue . front ( ) . second ;
oob_recv_queue . pop_front ( ) ;
return true ;
}
for ( auto & p : peer_list ) {
if ( p . second . recv_queue . packet_ready ( ) ) {
for ( auto & p : peer_list ) {
if ( p . second . recv_queue . packet_ready ( ) ) {
peer = p . first ;
data = p . second . recv_queue . read_packet ( ) ;
return true ;
@ -238,11 +243,11 @@ bool protocol_zt::recv(endpoint& peer, buffer_t& data)
return false ;
}
void protocol_zt : : disconnect ( const endpoint & peer )
void protocol_zt : : disconnect ( const endpoint & peer )
{
if ( peer_list . count ( peer ) ) {
if ( peer_list [ peer ] . fd ! = - 1 ) {
if ( lwip_close ( peer_list [ peer ] . fd ) < 0 ) {
if ( peer_list . count ( peer ) ) {
if ( peer_list [ peer ] . fd ! = - 1 ) {
if ( lwip_close ( peer_list [ peer ] . fd ) < 0 ) {
SDL_Log ( " lwip_close: %s \n " , strerror ( errno ) ) ;
}
}
@ -252,16 +257,16 @@ void protocol_zt::disconnect(const endpoint& peer)
void protocol_zt : : close_all ( )
{
if ( fd_tcp ! = - 1 ) {
if ( fd_tcp ! = - 1 ) {
lwip_close ( fd_tcp ) ;
fd_tcp = - 1 ;
}
if ( fd_udp ! = - 1 ) {
if ( fd_udp ! = - 1 ) {
lwip_close ( fd_udp ) ;
fd_udp = - 1 ;
}
for ( auto & i : peer_list ) {
if ( i . second . fd ! = - 1 )
for ( auto & i : peer_list ) {
if ( i . second . fd ! = - 1 )
lwip_close ( i . second . fd ) ;
}
peer_list . clear ( ) ;
@ -272,15 +277,15 @@ protocol_zt::~protocol_zt()
close_all ( ) ;
}
void protocol_zt : : endpoint : : from_string ( const std : : string & str )
void protocol_zt : : endpoint : : from_string ( const std : : string & str )
{
ip_addr_t a ;
if ( ! ipaddr_aton ( str . c_str ( ) , & a ) )
if ( ! ipaddr_aton ( str . c_str ( ) , & a ) )
return ;
if ( ! IP_IS_V6_VAL ( a ) )
if ( ! IP_IS_V6_VAL ( a ) )
return ;
const unsigned char * r = reinterpret_cast < const unsigned char * > ( a . u_addr . ip6 . addr ) ;
std : : copy ( r , r + 16 , addr . begin ( ) ) ;
const unsigned char * r = reinterpret_cast < const unsigned char * > ( a . u_addr . ip6 . addr ) ;
std : : copy ( r , r + 16 , addr . begin ( ) ) ;
}
uint64_t protocol_zt : : current_ms ( )
@ -294,9 +299,9 @@ std::string protocol_zt::make_default_gamename()
std : : string allowed_chars = " abcdefghkopqrstuvwxyz " ;
std : : random_device rd ;
std : : uniform_int_distribution < int > dist ( 0 , allowed_chars . size ( ) - 1 ) ;
for ( int i = 0 ; i < 5 ; + + i ) {
for ( int i = 0 ; i < 5 ; + + i ) {
ret + = allowed_chars . at ( dist ( rd ) ) ;
}
}
return ret ;
}