medfall

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

commit 5e60b92fe7c2bd6d64fe0416386fea14c3482a6e
parent 28d1b3c8efc958e5dcdc0e38f1d765fc902539ee
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat Sep 10 18:39:44 -0700

Add initial server code

Diffstat:
.gitignore | 1+
Makefile | 2+-
server/main.cc | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 192 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore @@ -1,6 +1,7 @@ medfall pp sound +srv test_lockfree logs diff --git a/Makefile b/Makefile @@ -1,4 +1,4 @@ -BINS := medfall pp sound +BINS := medfall pp sound srv MODULES := bsp.so btt.so hm.so sm.so STBS := truetype image image_write perlin diff --git a/server/main.cc b/server/main.cc @@ -0,0 +1,190 @@ +// 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 "intrinsics.h" +#include "log.h" +#include "stream.h" +#include "hashtable.h" +#include "rng/well512.h" + +#define PORT 13337 +#define MAX_PLAYERS 128 + +HashTable< MAX_PLAYERS * 8 > map; + +struct PlayerState { + int pos; + u16 next_free; + bool connected; +}; + +static PlayerState states[ MAX_PLAYERS ]; +static u16 first_free = 0; + +bool set_nonblocking( int fd ) { + int flags = fcntl( fd, F_GETFL, 0 ); + if( flags == -1 ) return false; + int ok = fcntl( fd, F_SETFL, flags | O_NONBLOCK ); + return ok != -1; +} + +bool receive( int fd, char * buf, size_t * bytes_read, size_t buf_len ) { + // 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 ); + if( len == -1 ) { + if( errno == EAGAIN ) return false; + err( 1, "recv" ); + } + + *bytes_read = len; + + // char hbuf[ INET6_ADDRSTRLEN ], sbuf[NI_MAXSERV]; + // if (getnameinfo( ( const sockaddr * ) &client_addr, client_addr_len, hbuf, sizeof(hbuf), sbuf, + // sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) + // 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, + 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 ) ); + } + else { + sockaddr_in6 * sadin6 = ( sockaddr_in6 * ) &client_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; +}; + +int main() { + int server_fd_ipv4 = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + int server_fd_ipv6 = socket( AF_INET6, SOCK_DGRAM, IPPROTO_UDP ); + + if( server_fd_ipv4 == -1 ) { + err( 1, "socket ipv4" ); + } + if( server_fd_ipv6 == -1 ) { + err( 1, "socket ipv6" ); + } + + 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 ) ); + + sockaddr_in server_addr_ipv4 = { }; + server_addr_ipv4.sin_family = AF_INET; + server_addr_ipv4.sin_addr.s_addr = INADDR_ANY; + server_addr_ipv4.sin_port = htons( PORT ); + + sockaddr_in6 server_addr_ipv6 = { }; + server_addr_ipv6.sin6_family = AF_INET6; + server_addr_ipv6.sin6_addr = in6addr_any; + server_addr_ipv6.sin6_port = htons( PORT ); + + int ok_ipv4 = bind( server_fd_ipv4, ( sockaddr * ) &server_addr_ipv4, sizeof( server_addr_ipv4 ) ); + int ok_ipv6 = bind( server_fd_ipv6, ( sockaddr * ) &server_addr_ipv6, sizeof( server_addr_ipv6 ) ); + + if( ok_ipv4 == -1 ) { + err( 1, "bind ipv4" ); + } + if( ok_ipv6 == -1 ) { + err( 1, "bind ipv6" ); + } + + if( !set_nonblocking( server_fd_ipv4 ) ) { + err( 1, "nonblocking ipv4" ); + } + if( !set_nonblocking( server_fd_ipv6 ) ) { + err( 1, "nonblocking ipv6" ); + } + + 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 ) ); + size_t len; + while( receive( server_fd_ipv4, buf, &len, sizeof( buf ) ) ) { + Stream stream; + stream.ptr = buf; + // stream.len = len + + u64 sid; + stream = read_u64( stream, &sid ); + + if( sid == u64( -1 ) ) { + 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 ); + } + else { + u64 id; + if( map.get( sid, &id ) ) { + states[ id ].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 ); + } + } + + usleep( 200 * 1000 ); + } + + return 0; +}