commit 4386499e5f020116b526765840ab55e7600b903a parent 5c65ef6dd31964c0a97cf67544122dfeb48047d4 Author: Michael Savage <mikejsavage@gmail.com> Date: Fri Aug 4 14:26:57 -0700 Even more sockets work Diffstat:
hm.cc | | | 10 | +++++----- |
http.cc | | | 7 | +++---- |
platform_network.h | | | 142 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
server/main.cc | | | 15 | ++++++--------- |
unix_network.h | | | 29 | +++++++++++++++++++++-------- |
diff --git a/hm.cc b/hm.cc @@ -118,7 +118,7 @@ GAME_INIT( game_init ) { load_trees( &mem->persistent_arena ); - sock = sock_new_udp( NET_IPV4, NET_NONBLOCKING ); + sock = net_new_udp( NET_NONBLOCKING ); if( !dns_first( "localhost", &server_addr ) ) { FATAL( "dns_first" ); @@ -424,7 +424,7 @@ GAME_FRAME( game_frame ) { char buf[ 1400 ]; NetAddress recv_addr; size_t len; - if( !sock_tryrecv_udp( sock, buf, sizeof( buf ), &recv_addr, &len ) ) { + if( !net_tryrecv( sock, buf, sizeof( buf ), &recv_addr, &len ) ) { len = 0; } if( recv_addr != server_addr ) { @@ -439,7 +439,7 @@ GAME_FRAME( game_frame ) { write( &ws, sid ); write( &ws, game->pos ); - sock_send_udp( sock, ws.start, ws.len(), server_addr ); + net_send( sock, ws.start, ws.len(), server_addr ); u16 player_count = read_u16( &rs ); ReadStreamCheckpoint rsc = rs.checkpoint(); @@ -499,10 +499,10 @@ GAME_FRAME( game_frame ) { char write_buf[ 1400 ]; WriteStream ws( write_buf ); - write_u64( &ws, u64( -1 ) ); + write_u64( &ws, ~u64( 0 ) ); write( &ws, game->pos ); - sock_send_udp( sock, ws.start, ws.len(), server_addr ); + net_send( sock, ws.start, ws.len(), server_addr ); last_connection_attempt = current_time; } diff --git a/http.cc b/http.cc @@ -50,12 +50,11 @@ bool dns_first( const char * host, NetAddress * address ) { } GetResult http_get( const NetAddress & addr, const char * host, const char * path, std::string * body, HttpProgressCallback progress_cb, void * cb_data ) { - TCPSocket sock = sock_new_tcp( addr.type, NET_BLOCKING ); - SCOPE_EXIT( sock_destroy( &sock ) ); - - if( !sock_connect( sock, addr ) ) { + TCPSocket sock; + if( !sock_new_tcp( &sock, addr, NET_BLOCKING ) ) { return GET_ERROR_CANT_CONNECT; } + SCOPE_EXIT( sock_destroy( &sock ) ); // TODO: should just be a dynamic string char request[ 1024 ]; diff --git a/platform_network.h b/platform_network.h @@ -37,13 +37,11 @@ inline bool operator!=( const NetAddress & lhs, const NetAddress & rhs ) { } struct UDPSocket { - int fd; - IPvX ipvx; + int ipv4, ipv6; }; struct TCPSocket { int fd; - IPvX ipvx; }; inline NetAddress sockaddr_to_netaddress( const sockaddr_storage & ss ) { @@ -96,94 +94,103 @@ inline struct sockaddr_storage netaddress_to_sockaddr( const NetAddress & addr, #error new platform #endif -inline UDPSocket sock_new_udp( IPvX ipvx, NonblockingBool nonblocking ) { +inline UDPSocket net_new_udp( NonblockingBool nonblocking, u16 port = 0 ) { UDPSocket sock; - int domain = ipvx == NET_IPV4 ? AF_INET : AF_INET6; - sock.fd = socket( domain, SOCK_DGRAM, IPPROTO_UDP ); - sock.ipvx = ipvx; - if( sock.fd == INVALID_SOCKET ) { + sock.ipv4 = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + if( sock.ipv4 == INVALID_SOCKET ) { FATAL( "socket" ); } - - if( nonblocking == NET_NONBLOCKING ) { - sock_fd_nonblocking( sock.fd ); - } - - return sock; -} - -inline TCPSocket sock_new_tcp( IPvX ipvx, NonblockingBool nonblocking ) { - TCPSocket sock; - - int domain = ipvx == NET_IPV4 ? AF_INET : AF_INET6; - sock.fd = socket( domain, SOCK_STREAM, IPPROTO_TCP ); - sock.ipvx = ipvx; - if( sock.fd == INVALID_SOCKET ) { + sock.ipv6 = socket( AF_INET6, SOCK_DGRAM, IPPROTO_UDP ); + if( sock.ipv6 == INVALID_SOCKET ) { FATAL( "socket" ); } if( nonblocking == NET_NONBLOCKING ) { - sock_fd_nonblocking( sock.fd ); + sock_fd_nonblocking( sock.ipv4 ); + sock_fd_nonblocking( sock.ipv6 ); } - return sock; -} - -inline void sock_bind( int fd, IPvX ipvx, u16 port ) { - { + if( port != 0 ) { int one = 1; - int ok = setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ); - if( ok == -1 ) { - FATAL( "setsockopt" ); + { + int ok = setsockopt( sock.ipv4, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ); + if( ok == -1 ) { + FATAL( "setsockopt" ); + } } - } - if( ipvx == NET_IPV4 ) { - sockaddr_in my_addr; - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons( port ); - my_addr.sin_addr.s_addr = htonl( INADDR_ANY ); - int ok = bind( fd, ( sockaddr * ) &my_addr, sizeof( my_addr ) ); - if( ok == SOCKET_ERROR ) { - FATAL( "bind" ); + { + int ok = setsockopt( sock.ipv6, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ); + if( ok == -1 ) { + FATAL( "setsockopt" ); + } } - } - else { - sockaddr_in6 my_addr; - my_addr.sin6_family = AF_INET6; - my_addr.sin6_port = htons( port ); - my_addr.sin6_addr = in6addr_any; - int ok = bind( fd, ( sockaddr * ) &my_addr, sizeof( my_addr ) ); - if( ok == SOCKET_ERROR ) { - FATAL( "bind" ); + + { + int ok = setsockopt( sock.ipv6, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof( one ) ); + if( ok == -1 ) { + FATAL( "setsockopt" ); + } } - } -} -inline void sock_bind( UDPSocket sock, u16 port ) { - sock_bind( sock.fd, sock.ipvx, port ); -} + { + sockaddr_in my_addr4; + my_addr4.sin_family = AF_INET; + my_addr4.sin_port = htons( port ); + my_addr4.sin_addr.s_addr = htonl( INADDR_ANY ); + int ok = bind( sock.ipv4, ( sockaddr * ) &my_addr4, sizeof( my_addr4 ) ); + if( ok == SOCKET_ERROR ) { + FATAL( "bind" ); + } + } -inline void sock_bind( TCPSocket sock, u16 port ) { - sock_bind( sock.fd, sock.ipvx, port ); + { + sockaddr_in6 my_addr6; + my_addr6.sin6_family = AF_INET6; + my_addr6.sin6_port = htons( port ); + my_addr6.sin6_addr = in6addr_any; + int ok = bind( sock.ipv6, ( sockaddr * ) &my_addr6, sizeof( my_addr6 ) ); + if( ok == SOCKET_ERROR ) { + FATAL( "bind" ); + } + } + } + + return sock; } -inline bool sock_connect( TCPSocket sock, const NetAddress & addr ) { +inline bool sock_new_tcp( TCPSocket * sock, const NetAddress & addr, NonblockingBool nonblocking ) { socklen_t sa_size; struct sockaddr_storage sa = netaddress_to_sockaddr( addr, &sa_size ); - int ok = connect( sock.fd, ( const sockaddr * ) &sa, sa_size ); + + sock->fd = socket( sa.ss_family, SOCK_STREAM, IPPROTO_TCP ); + if( sock->fd == INVALID_SOCKET ) { + FATAL( "socket" ); + } + + int ok = connect( sock->fd, ( const sockaddr * ) &sa, sa_size ); if( ok == -1 ) { + int ok_close = closesocket( sock->fd ); + if( ok_close == -1 ) { + FATAL( "closesocket" ); + } // TODO: check for actual coding errors too return false; } + + if( nonblocking == NET_NONBLOCKING ) { + sock_fd_nonblocking( sock->fd ); + } + return true; } -inline void sock_send_udp( UDPSocket sock, const void * data, size_t len, const NetAddress & addr ) { +inline void net_send( UDPSocket sock, const void * data, size_t len, const NetAddress & addr ) { socklen_t sa_size; struct sockaddr_storage sa = netaddress_to_sockaddr( addr, &sa_size ); - ssize_t ok = sendto( sock.fd, data, checked_cast< int >( len ), 0, ( struct sockaddr * ) &sa, sa_size ); + int fd = addr.type == NET_IPV4 ? sock.ipv4 : sock.ipv6; + ssize_t ok = sendto( fd, data, checked_cast< int >( len ), 0, ( struct sockaddr * ) &sa, sa_size ); if( ok == SOCKET_ERROR ) { FATAL( "sendto" ); } @@ -199,12 +206,17 @@ inline ssize_t sock_recv_tcp( TCPSocket sock, void * buf, size_t buf_size ) { return recv( sock.fd, buf, buf_size, 0 ); } -inline void sock_destroy( UDPSocket * sock ) { - int ok = closesocket( sock->fd ); - if( ok == -1 ) { +inline void net_destroy( UDPSocket * sock ) { + int ok4 = closesocket( sock->ipv4 ); + if( ok4 == -1 ) { FATAL( "closesocket" ); } - sock->fd = INVALID_SOCKET; + int ok6 = closesocket( sock->ipv6 ); + if( ok6 == -1 ) { + FATAL( "closesocket" ); + } + sock->ipv4 = INVALID_SOCKET; + sock->ipv6 = INVALID_SOCKET; } inline void sock_destroy( TCPSocket * sock ) { diff --git a/server/main.cc b/server/main.cc @@ -31,10 +31,7 @@ static Pool< PlayerState, MAX_PLAYERS > states; static HashTable< PlayerState *, MAX_PLAYERS * 2 > sids_to_states; int main() { - UDPSocket ipv4 = sock_new_udp( NET_IPV4, NET_NONBLOCKING ); - UDPSocket ipv6 = sock_new_udp( NET_IPV6, NET_NONBLOCKING ); - sock_bind( ipv4, PORT ); - sock_bind( ipv6, PORT ); + UDPSocket sock = net_new_udp( NET_NONBLOCKING, PORT ); RNGWell512 rng; rng_well512_init( &rng ); @@ -44,17 +41,17 @@ int main() { const double now = get_time(); NetAddress addr; - char read_buf[ 1400 ]; + u8 read_buf[ 1400 ]; size_t len; - while( sock_tryrecv_udp( ipv4, read_buf, sizeof( read_buf ), &addr, &len ) ) { + while( net_tryrecv( sock, read_buf, sizeof( read_buf ), &addr, &len ) ) { ReadStream r( read_buf, len ); // u16 command = read_u16( &r ); u64 sid = read_u64( &r ); if( !r.ok ) continue; - if( sid == u64( -1 ) ) { + if( sid == ~u64( 0 ) ) { v3 pos; read( &r, &pos ); if( !r.ok ) continue; @@ -76,7 +73,7 @@ int main() { write( &w, new_sid ); if( w.ok ) { - sock_send_udp( ipv4, w.start, w.len(), state->addr ); + net_send( sock, w.start, w.len(), state->addr ); } } else { @@ -113,7 +110,7 @@ int main() { if( w.ok ) { for( const PlayerState & state : states.elems ) { - sock_send_udp( ipv4, w.start, w.len(), state.addr ); + net_send( sock, w.start, w.len(), state.addr ); } } diff --git a/unix_network.h b/unix_network.h @@ -30,16 +30,29 @@ inline void sock_fd_nonblocking( int fd ) { if( ok == -1 ) FATAL( "fcntl F_SETFL" ); } -inline bool sock_tryrecv_udp( UDPSocket sock, char * buf, size_t len, NetAddress * addr, size_t * bytes_received ) { +inline bool net_tryrecv( UDPSocket sock, void * buf, size_t len, NetAddress * addr, size_t * bytes_received ) { struct sockaddr_storage sa; - socklen_t sa_size = sock.ipvx == NET_IPV4 ? sizeof( struct sockaddr_in ) : sizeof( struct sockaddr_in6 ); - ssize_t received = recvfrom( sock.fd, buf, len, 0, ( struct sockaddr * ) &sa, &sa_size ); - if( received == -1 ) { - if( errno == EAGAIN ) return false; + socklen_t sa_size = sizeof( struct sockaddr_in ); + ssize_t received4 = recvfrom( sock.ipv4, buf, len, 0, ( struct sockaddr * ) &sa, &sa_size ); + if( received4 != -1 ) { + *addr = sockaddr_to_netaddress( sa ); + *bytes_received = size_t( received4 ); + return true; + } + if( received4 == -1 && errno != EAGAIN ) { + FATAL( "recvfrom" ); + } + + sa_size = sizeof( struct sockaddr_in6 ); + ssize_t received6 = recvfrom( sock.ipv6, buf, len, 0, ( struct sockaddr * ) &sa, &sa_size ); + if( received6 != -1 ) { + *addr = sockaddr_to_netaddress( sa ); + *bytes_received = size_t( received6 ); + return true; + } + if( received6 == -1 && errno != EAGAIN ) { FATAL( "recvfrom" ); } - *addr = sockaddr_to_netaddress( sa ); - *bytes_received = size_t( received ); - return true; + return false; }