medfall

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

commit 1b343b694065eccb6fdfdfa2920acfb1f7d420cf
parent d6eaf557777baac7f4da9f9865f530fa8eea0869
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Wed Dec 28 00:19:16 +0200

Add platform sockets wrappers (only UDP for now)

Diffstat:
hm.cc | 39+++++++++------------------------------
http.cc | 2+-
http.h | 2+-
platform_net.h | 21---------------------
platform_network.h | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
server/main.cc | 17+++--------------
unix_network.h | 37+++++++++++++++++++++++++++++++++++++
win32_network.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 168 insertions(+), 67 deletions(-)
diff --git a/hm.cc b/hm.cc @@ -1,6 +1,5 @@ #include <stdlib.h> #include <math.h> -#include <errno.h> #include "game.h" #include "intrinsics.h" @@ -16,7 +15,7 @@ #include "http.h" #include "profiler.h" #include "platform_io.h" -#include "platform_net.h" +#include "platform_network.h" static const char * vert_src = GLSL( in vec3 position; @@ -80,19 +79,14 @@ static v3 angles_to_vector_xy( v3 angles ) { static UB ub_sphere; -static int sock; +static Socket sock; static u64 sid; static bool connected = false; static struct sockaddr_in addr; -static 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; -} - extern "C" GAME_INIT( game_init ) { + net_init(); + game->pos = v3( 1500, 1500, 250 ); game->angles = radians( v3( -90, 45, 0 ) ); terrain_init( &game->tm, "terrains/gta.png.parts", &mem->persistent_arena, &game->background_tasks ); @@ -141,13 +135,7 @@ extern "C" GAME_INIT( game_init ) { skybox_init( &game->skybox ); - sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if( sock == -1 ) { - FATAL( "socket" ); - } - if( !set_nonblocking( sock ) ) { - FATAL( "set_nonblocking" ); - } + sock_init( &sock, NET_IPV4, NET_UDP, NET_NONBLOCKING ); struct sockaddr_storage addrs = { }; if( !dns_first( "localhost", &addrs ) ) { @@ -165,10 +153,7 @@ extern "C" GAME_INIT( game_init ) { write_u64( &ws, -1 ); write( &ws, pos ); - int ok = sendto( sock, ws.start, ws.len(), 0, ( sockaddr * ) &addr, sizeof( addr ) ); - if( ok == -1 ) { - FATAL( "sendto" ); - } + sock_send_udp( sock, ws, addr ); } static m4 camera_to_view( v3 position, v3 angles ) { @@ -318,11 +303,8 @@ extern "C" GAME_FRAME( game_frame ) { char buf[ 1400 ]; sockaddr_storage a; socklen_t addr_len = sizeof( a ); - ssize_t len = recvfrom( sock, buf, sizeof( buf ), 0, ( sockaddr * ) &a, &addr_len ); - if( len == -1 ) { - if( errno != EAGAIN ) { - FATAL( "recvfrom" ); - } + size_t len; + if( !sock_tryrecv_udp( sock, buf, sizeof( buf ), &a, &addr_len, &len ) ) { len = 0; } @@ -334,10 +316,7 @@ extern "C" GAME_FRAME( game_frame ) { write( &ws, sid ); write( &ws, game->pos ); - int ok = sendto( sock, ws.start, ws.len(), 0, ( sockaddr * ) &addr, sizeof( addr ) ); - if( ok == -1 ) { - FATAL( "sendto" ); - } + sock_send_udp( sock, ws, addr ); u16 player_count = read_u16( &rs ); ReadStreamCheckpoint rsc = rs.checkpoint(); diff --git a/http.cc b/http.cc @@ -7,7 +7,7 @@ #include "intrinsics.h" #include "platform_io.h" -#include "platform_net.h" +#include "platform_network.h" #include "http.h" bool dns_first( const char * host, struct sockaddr_storage * address ) { diff --git a/http.h b/http.h @@ -4,7 +4,7 @@ #include <string> #include "intrinsics.h" -#include "platform_net.h" +#include "platform_network.h" enum GetResult { GET_OK, diff --git a/platform_net.h b/platform_net.h @@ -1,21 +0,0 @@ -#ifndef _PLATFORM_NET_H_ -#define _PLATFORM_NET_H_ - -#include "platform.h" - -#if PLATFORM_WINDOWS -#include <winsock2.h> -#include <ws2tcpip.h> -#elif PLATFORM_UNIX -#include <arpa/inet.h> -#include <sys/types.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <netdb.h> -#define closesocket close -#else -#error new platform -#endif - -#endif // _PLATFORM_NET_H_ diff --git a/platform_network.h b/platform_network.h @@ -0,0 +1,70 @@ +#pragma once + +#include "platform.h" +#include "log.h" +#include "stream.h" + +enum TransportProtocol { NET_UDP, NET_TCP }; +enum IPvX { NET_IPV4, NET_IPV6 }; +enum NonblockingBool { NET_BLOCKING, NET_NONBLOCKING }; + +struct Socket { + int fd; + TransportProtocol transport; + IPvX ipvx; +}; + +#if PLATFORM_WINDOWS +#include "win32_network.h" +#elif PLATFORM_UNIX +#include "unix_network.h" +#else +#error new platform +#endif + +inline void sock_init( Socket * sock, IPvX ipvx, TransportProtocol transport, NonblockingBool nonblocking ) { + int domain = AF_INET; + if( ipvx == NET_IPV6 ) { + domain = AF_INET6; + } + + int type = SOCK_DGRAM; + int protocol = IPPROTO_UDP; + if( transport == NET_TCP ) { + type = SOCK_STREAM; + protocol = IPPROTO_TCP; + } + + sock->fd = socket( domain, type, protocol ); + sock->transport = transport; + sock->ipvx = ipvx; + if( sock->fd == INVALID_SOCKET ) { + FATAL( "socket" ); + } + + if( nonblocking == NET_NONBLOCKING ) { + sock_fd_nonblocking( sock->fd ); + } +} + +inline void sock_send_udp( Socket sock, const char * data, size_t len, const sockaddr_in & addr ) { + ASSERT( sock.transport == NET_UDP ); + + int ok = sendto( sock.fd, data, len, 0, ( sockaddr * ) &addr, sizeof( addr ) ); + if( ok == SOCKET_ERROR ) { + FATAL( "sendto" ); + } +} + +inline void sock_send_udp( Socket sock, const WriteStream & ws, const sockaddr_in & addr ) { + ASSERT( ws.ok ); + sock_send_udp( sock, ws.start, ws.len(), addr ); +} + +inline void sock_destroy( Socket * sock ) { + int ok = close( sock->fd ); + if( ok == -1 ) { + FATAL( "close" ); + } + sock->fd = -1; +} diff --git a/server/main.cc b/server/main.cc @@ -9,7 +9,7 @@ #include "linear_algebra.h" #include "int_conversions.h" #include "rng/well512.h" -#include "platform_net.h" +#include "platform_network.h" #define PORT 13337 #define MAX_PLAYERS 128 @@ -24,13 +24,6 @@ struct PlayerState { 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 ); - if( flags == -1 ) return false; - int ok = fcntl( fd, F_SETFL, flags | O_NONBLOCK ); - return ok != -1; -} - enum AddressType { ADDRESSTYPE_IPV4, ADDRESSTYPE_IPV6, @@ -123,12 +116,8 @@ int main() { err( 1, "bind ipv6" ); } - if( !set_nonblocking( server_fd_ipv4 ) ) { - err( 1, "nonblocking ipv4" ); - } - if( !set_nonblocking( server_fd_ipv6 ) ) { - err( 1, "nonblocking ipv6" ); - } + sock_fd_nonblocking( server_fd_ipv4 ); + sock_fd_nonblocking( server_fd_ipv6 ); RNGWell512 rng; rng_well512_init( &rng ); diff --git a/unix_network.h b/unix_network.h @@ -0,0 +1,37 @@ +#pragma once + +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> + +#define INVALID_SOCKET ( -1 ) +#define SOCKET_ERROR ( -1 ) + +#define closesocket close + +inline void net_init() { } +inline void net_term() { } + +inline void sock_fd_nonblocking( int fd ) { + int flags = fcntl( fd, F_GETFL, 0 ); + if( flags == -1 ) FATAL( "fcntl F_GETFL" ); + int ok = fcntl( fd, F_SETFL, flags | O_NONBLOCK ); + if( ok == -1 ) FATAL( "fcntl F_SETFL" ); +} + +inline bool sock_tryrecv_udp( Socket sock, char * buf, size_t len, sockaddr_storage * addr, socklen_t * addr_len, size_t * bytes_received ) { + ASSERT( sock.transport == NET_UDP ); + + ssize_t received = recvfrom( sock.fd, buf, len, 0, ( sockaddr * ) addr, addr_len ); + if( received == -1 ) { + if( errno == EAGAIN ) return false; + FATAL( "recvfrom" ); + } + + *bytes_received = size_t( received ); + return true; +} diff --git a/win32_network.h b/win32_network.h @@ -0,0 +1,47 @@ +#pragma once + +#include <winsock2.h> +#include <ws2tcpip.h> + +struct Socket { + SOCKET fd; + TransportProtocol transport; + IPvX ipvx; +}; + +inline void net_init() { + WSADATA wsa_data; + if( WSAStartup( MAKEWORD( 2, 2 ), &wsa_data ) == SOCKET_ERROR ) { + FATAL( "WSAStartup" ); + } +} + +inline void net_term() { + if( WSACleanup() == SOCKET_ERROR ) { + FATAL( "WSACleanup" ); + } +} + +inline void sock_fd_nonblocking( int fd ) { + u_long one = 1; + int ok = ioctlsocket( fd, FIONBIO, &one ); + if( ok == SOCKET_ERROR ) { + FATAL( "ioctlsocket" ); + } +} + +inline bool sock_tryrecv_udp( Socket sock, char * buf, size_t len, sockaddr_storage * addr, socklen_t * addr_len, size_t * bytes_received ) { + ASSERT( sock.transport == NET_UDP ); + + ssize_t received = recvfrom( sock.fd, buf, len, 0, ( sockaddr * ) addr, addr_len ); + if( received == SOCKET_ERROR ) { + int error = WSAGetLastError(); + if( error == WSAEWOULDBLOCK || error == WSAECONNRESET ) { + return false; + } + FATAL( "recvfrom" ); + } + + *bytes_received = size_t( received ); + return true; +}