medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit c128c176f486781e71809fc26f5c39aa1ea597b1
parent 42557991478771d8eef311ffb1e1ac01f26fff9e
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat Dec 24 16:26:06 +0200

Broadcast player positions in the server

Diffstat:
server/main.cc | 181++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 102 insertions(+), 79 deletions(-)
diff --git a/server/main.cc b/server/main.cc @@ -1,34 +1,28 @@ -// all socket includes -#include <sys/types.h> -#include <sys/socket.h> -// #include <netdb.h> -#include <arpa/inet.h> -#include <fcntl.h> -#include <errno.h> - -#include <unistd.h> - #include <stdio.h> +#include <errno.h> #include "intrinsics.h" #include "log.h" #include "stream.h" +#include "pool.h" #include "hashtable.h" +#include "linear_algebra.h" +#include "int_conversions.h" #include "rng/well512.h" +#include "platform_net.h" #define PORT 13337 #define MAX_PLAYERS 128 -HashTable< MAX_PLAYERS * 8 > map; - struct PlayerState { - int pos; + u64 sid; + v3 pos; + sockaddr_storage addr; u16 next_free; - bool connected; }; -static PlayerState states[ MAX_PLAYERS ]; -static u16 first_free = 0; +static Pool< PlayerState, MAX_PLAYERS > states; +static HashTable< PlayerState *, MAX_PLAYERS * 2 > sids_to_states; bool set_nonblocking( int fd ) { int flags = fcntl( fd, F_GETFL, 0 ); @@ -37,18 +31,34 @@ bool set_nonblocking( int fd ) { return ok != -1; } -bool receive( int fd, char * buf, size_t * bytes_read, size_t buf_len ) { +enum AddressType { + ADDRESSTYPE_IPV4, + ADDRESSTYPE_IPV6, +}; + +struct IPv4 { u8 bytes[ 4 ]; }; +struct IPv6 { u8 bytes[ 16 ]; }; + +struct Address { + AddressType type; + union { + IPv4 ipv4; + IPv6 ipv6; + }; + u16 port; +}; + +bool receive( int fd, char * buf, size_t * bytes_read, size_t buf_len, sockaddr_storage * addr ) { // http://stackoverflow.com/questions/18995361/can-recvfrom-function-from-socket-extract-the-sender-ip-address char ip[ INET6_ADDRSTRLEN ]; - sockaddr_storage client_addr; - socklen_t client_addr_len = sizeof( client_addr ); - ssize_t len = recvfrom( fd, buf, buf_len, 0, ( sockaddr * ) &client_addr, &client_addr_len ); + socklen_t addr_len = sizeof( *addr ); + ssize_t len = recvfrom( fd, buf, buf_len, 0, ( sockaddr * ) addr, &addr_len ); if( len == -1 ) { if( errno == EAGAIN ) return false; err( 1, "recv" ); } - *bytes_read = len; + *bytes_read = to_unsigned( len ); // char hbuf[ INET6_ADDRSTRLEN ], sbuf[NI_MAXSERV]; // if (getnameinfo( ( const sockaddr * ) &client_addr, client_addr_len, hbuf, sizeof(hbuf), sbuf, @@ -56,45 +66,27 @@ bool receive( int fd, char * buf, size_t * bytes_read, size_t buf_len ) { // printf("host=%s, serv=%s\n", hbuf, sbuf); - inet_ntop( client_addr.ss_family, - client_addr.ss_family == AF_INET ? - ( void * ) &( ( sockaddr_in * ) &client_addr )->sin_addr : - ( void * ) &( ( sockaddr_in6 * ) &client_addr )->sin6_addr, + inet_ntop( addr->ss_family, + addr->ss_family == AF_INET ? + ( void * ) &( ( sockaddr_in * ) &addr )->sin_addr : + ( void * ) &( ( sockaddr_in6 * ) &addr )->sin6_addr, ip, sizeof( ip ) ); - printf( "%s: %.*s\n", ip, len, buf ); - if( client_addr.ss_family == AF_INET ) { - sockaddr_in * sadin = ( sockaddr_in * ) &client_addr; - printf( "%d\n", ntohs( sadin->sin_port ) ); + // printf( "%s: %.*s\n", ip, len, buf ); + if( addr->ss_family == AF_INET ) { + sockaddr_in * sadin = ( sockaddr_in * ) &addr; + // printf( "%d\n", ntohs( sadin->sin_port ) ); } else { - sockaddr_in6 * sadin6 = ( sockaddr_in6 * ) &client_addr; - printf( "%d\n", ntohs( sadin6->sin6_port ) ); + sockaddr_in6 * sadin6 = ( sockaddr_in6 * ) &addr; + // printf( "%d\n", ntohs( sadin6->sin6_port ) ); } return true; } -enum NetAddressType { - NETADDRESS_IPV4, - NETADDRESS_IPV6, -}; - -struct IPV4Address { - u8 ip[ 4 ]; -}; - -struct IPV6Address { - u8 ip[ 16 ]; -}; - -struct NetAddress { - NetAddressType type; - union { - IPV4Address ipv4; - IPV6Address ipv6; - }; - u16 port; -}; +static void send( int fd, const PlayerState * state, const WriteStream & ws ) { + sendto( fd, ws.start, ws.len(), 0, ( sockaddr * ) &state->addr, sizeof( state->addr ) ); +} int main() { int server_fd_ipv4 = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); @@ -108,8 +100,8 @@ int main() { } int one = 1; - setsockopt( server_fd_ipv4, SOL_SOCKET, SO_REUSEADDR, ( const void * ) &one, sizeof( one ) ); - setsockopt( server_fd_ipv6, SOL_SOCKET, SO_REUSEADDR, ( const void * ) &one, sizeof( one ) ); + setsockopt( server_fd_ipv4, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ); + setsockopt( server_fd_ipv6, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ); sockaddr_in server_addr_ipv4 = { }; server_addr_ipv4.sin_family = AF_INET; @@ -141,43 +133,74 @@ int main() { RNGWell512 rng; rng_well512_init( &rng ); - for( size_t i = 0; i < ARRAY_COUNT( states ); i++ ) { - states[ i ].pos = 0; - states[ i ].next_free = u16( i + 1 ); - states[ i ].connected = false; - } - for( ;; ) { - char buf[ 1400 ]; - memset( buf, 0, sizeof( buf ) ); + printf( "frame\n" ); + + sockaddr_storage addr; + char read_buf[ 1400 ]; size_t len; - while( receive( server_fd_ipv4, buf, &len, sizeof( buf ) ) ) { - ReadStream stream( buf, len );; - u64 sid = read_u64( &stream ); - if( !stream.ok ) continue; + while( receive( server_fd_ipv4, read_buf, &len, sizeof( read_buf ), &addr ) ) { + ReadStream r( read_buf, len ); + + // u16 command = read_u16( &r ); + u64 sid = read_u64( &r ); + if( !r.ok ) continue; if( sid == u64( -1 ) ) { + v3 pos; + read( &r, &pos ); + if( !r.ok ) continue; + u64 new_sid = rng_next_u64( &rng ); - printf( "new connection %lx\n", new_sid ); - u64 id = first_free; - first_free = states[ id ].next_free; - states[ id ].connected = true; - map.add( new_sid, id ); + printf( "new connection %08lx\n", new_sid ); + PlayerState * state = states.acquire(); + ASSERT( state ); + + state->sid = new_sid; + state->pos = pos; + state->addr = addr; + + sids_to_states.add( new_sid, state ); + + char write_buf[ 1400 ]; + WriteStream w( write_buf, sizeof( write_buf ) ); + write( &w, new_sid ); + + if( w.ok ) { + send( server_fd_ipv4, state, w ); + } } else { - u64 id; - if( map.get( sid, &id ) ) { - states[ id ].pos++; + PlayerState * state = NULL; + if( sids_to_states.get( sid, &state ) ) { + v3 pos; + read( &r, &pos ); + if( !r.ok ) continue; + + state->pos = pos; } } } - // while( receive( server_fd_ipv6, buf, &len, sizeof( buf ) ) ); - printf( "frame\n" ); - for( size_t i = 0; i < ARRAY_COUNT( states ); i++ ) { - if( states[ i ].connected ) { - printf( "%zu: %d\n", i, states[ i ].pos ); + char write_buf[ 1400 ]; + WriteStream w( write_buf ); + + void * player_count_storage = reserve_u16( &w ); + u16 player_count = 0; + + for( const PlayerState * state : states ) { + write( &w, state->sid ); + write( &w, state->pos ); + player_count++; + } + + // TODO: endianness + memcpy( player_count_storage, &player_count, sizeof( player_count ) ); + + if( w.ok ) { + for( const PlayerState * state : states ) { + send( server_fd_ipv4, state, w ); } }