socket progress

This commit is contained in:
jacob 2025-01-31 10:26:07 -06:00
parent d7f1ac06cb
commit 062285b1b3
15 changed files with 779 additions and 90 deletions

View File

@ -725,12 +725,14 @@ void OnBuild(StringList cli_args)
Bool is_cpp = !is_dir && !is_c && StringEqual(extension, Lit("cpp")); Bool is_cpp = !is_dir && !is_c && StringEqual(extension, Lit("cpp"));
if (is_c || is_cpp) { if (is_c || is_cpp) {
if (StringBeginsWith(name, Lit("sys_")) || if (StringBeginsWith(name, Lit("sys_")) ||
StringBeginsWith(name, Lit("sock_")) ||
StringBeginsWith(name, Lit("renderer_")) || StringBeginsWith(name, Lit("renderer_")) ||
StringBeginsWith(name, Lit("playback_")) || StringBeginsWith(name, Lit("playback_")) ||
StringBeginsWith(name, Lit("mp3_")) || StringBeginsWith(name, Lit("mp3_")) ||
StringBeginsWith(name, Lit("ttf_"))) { StringBeginsWith(name, Lit("ttf_"))) {
if (PlatformWindows) { if (PlatformWindows) {
ignore = !(StringEqual(name, Lit("sys_win32.c")) || ignore = !(StringEqual(name, Lit("sys_win32.c")) ||
StringEqual(name, Lit("sock_win32.c")) ||
StringEqual(name, Lit("renderer_d3d11.c")) || StringEqual(name, Lit("renderer_d3d11.c")) ||
StringEqual(name, Lit("playback_wasapi.c")) || StringEqual(name, Lit("playback_wasapi.c")) ||
StringEqual(name, Lit("mp3_mmf.c")) || StringEqual(name, Lit("mp3_mmf.c")) ||

View File

@ -22,6 +22,7 @@
#include "renderer.h" #include "renderer.h"
#include "phys.h" #include "phys.h"
#include "rng.h" #include "rng.h"
#include "sock.h"
struct exit_callback { struct exit_callback {
app_exit_callback_func *func; app_exit_callback_func *func;
@ -122,6 +123,45 @@ void app_register_exit_callback(app_exit_callback_func *func)
* Entry point * Entry point
* ========================== */ * ========================== */
INTERNAL SOCK_RECEIVE_CALLBACK_FUNC_DEF(server_recv, address, msg)
{
(UNUSED)address;
(UNUSED)msg;
DEBUGBREAKABLE;
}
INTERNAL SOCK_RECEIVE_CALLBACK_FUNC_DEF(client_recv, address, msg)
{
(UNUSED)address;
(UNUSED)msg;
DEBUGBREAKABLE;
}
void app_entry_point(void) void app_entry_point(void)
{ {
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
@ -205,6 +245,7 @@ void app_entry_point(void)
} }
/* Startup systems */ /* Startup systems */
struct sock_startup_receipt sock_sr = sock_startup();
struct resource_startup_receipt resource_sr = resource_startup(); struct resource_startup_receipt resource_sr = resource_startup();
struct rng_startup_receipt rng_sr = rng_startup(&resource_sr); struct rng_startup_receipt rng_sr = rng_startup(&resource_sr);
struct renderer_startup_receipt renderer_sr = renderer_startup(&window); struct renderer_startup_receipt renderer_sr = renderer_startup(&window);
@ -217,10 +258,11 @@ void app_entry_point(void)
struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr); struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr);
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr); struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
struct phys_startup_receipt phys_sr = phys_startup(); struct phys_startup_receipt phys_sr = phys_startup();
struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr); struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr, &sock_sr);
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &game_sr, &asset_cache_sr, &mixer_sr, &window); struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &game_sr, &asset_cache_sr, &mixer_sr, &sock_sr, &window);
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr); struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
(UNUSED)sock_sr;
(UNUSED)user_sr; (UNUSED)user_sr;
(UNUSED)playback_sr; (UNUSED)playback_sr;
(UNUSED)rng_sr; (UNUSED)rng_sr;

View File

@ -377,8 +377,8 @@ GLOBAL const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
#if COMPILER_CLANG #if COMPILER_CLANG
#define U128(hi64, lo64) (((u128)(hi64) << 64) | (lo64)) #define U128(hi64, lo64) (((u128)(hi64) << 64) | (lo64))
#define U128_HI64(a) ((u64)((a) >> 64)) #define U128_HI(a) ((u64)((a) >> 64))
#define U128_LO64(a) ((u64)(a)) #define U128_LO(a) ((u64)(a))
typedef __uint128_t u128; typedef __uint128_t u128;
@ -395,8 +395,8 @@ INLINE u128 u128_mul(u128 a, u128 b) { return a * b; }
#else #else
# define U128(hi64, lo64) ((u128) { .hi = (hi64), .lo = (lo64) }) # define U128(hi64, lo64) ((u128) { .hi = (hi64), .lo = (lo64) })
#endif #endif
#define U128_HI64(a) ((a).hi) #define U128_HI(a) ((a).hi)
#define U128_LO64(a) ((a).lo) #define U128_LO(a) ((a).lo)
typedef struct { u64 hi; u64 lo; } u128; typedef struct { u64 hi; u64 lo; } u128;

View File

@ -97,7 +97,7 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
struct font_task_params *params = (struct font_task_params *)vparams; struct font_task_params *params = (struct font_task_params *)vparams;
struct string path = string_from_cstr_len(params->path_cstr, params->path_len); struct string path = STRING(params->path_len, (u8 *)params->path_cstr);
f32 point_size = params->point_size; f32 point_size = params->point_size;
struct asset *asset = params->asset; struct asset *asset = params->asset;

View File

@ -15,6 +15,7 @@
#include "rng.h" #include "rng.h"
#include "space.h" #include "space.h"
#include "byteio.h" #include "byteio.h"
#include "sock.h"
GLOBAL struct { GLOBAL struct {
struct atomic_i32 game_thread_shutdown; struct atomic_i32 game_thread_shutdown;
@ -64,12 +65,14 @@ INTERNAL void reset_world(void);
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr, struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr, struct sprite_startup_receipt *sheet_sr,
struct sound_startup_receipt *sound_sr, struct sound_startup_receipt *sound_sr,
struct phys_startup_receipt *phys_sr) struct phys_startup_receipt *phys_sr,
struct sock_startup_receipt *sock_sr)
{ {
(UNUSED)mixer_sr; (UNUSED)mixer_sr;
(UNUSED)sheet_sr; (UNUSED)sheet_sr;
(UNUSED)sound_sr; (UNUSED)sound_sr;
(UNUSED)phys_sr; (UNUSED)phys_sr;
(UNUSED)sock_sr;
/* Initialize game input storage */ /* Initialize game input storage */
G.game_input_mutex = sys_mutex_alloc(); G.game_input_mutex = sys_mutex_alloc();
@ -459,6 +462,50 @@ INTERNAL void game_update(struct game_cmd_list game_cmds)
__prof; __prof;
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
{
static struct sock sock = ZI;
if (!sock.handle) {
struct sock_address bind_addr = ZI;
bind_addr.ip = SOCK_IP_ANY_INTERFACE;
bind_addr.port = 12345;
sock = sock_alloc(bind_addr, SOCK_FLAG_NON_BLOCKING_RECV);
}
}
/* ========================== * /* ========================== *
* Reset level if necessary * Reset level if necessary

View File

@ -6,6 +6,7 @@ struct mixer_startup_receipt;
struct sprite_startup_receipt; struct sprite_startup_receipt;
struct sound_startup_receipt; struct sound_startup_receipt;
struct phys_startup_receipt; struct phys_startup_receipt;
struct sock_startup_receipt;
/* Absolute layers */ /* Absolute layers */
#define GAME_LAYER_FLOOR_DECALS -300 #define GAME_LAYER_FLOOR_DECALS -300
@ -21,7 +22,8 @@ struct game_startup_receipt { i32 _; };
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr, struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
struct sprite_startup_receipt *sheet_sr, struct sprite_startup_receipt *sheet_sr,
struct sound_startup_receipt *sound_sr, struct sound_startup_receipt *sound_sr,
struct phys_startup_receipt *phys_sr); struct phys_startup_receipt *phys_sr,
struct sock_startup_receipt *sock_sr);
/* ========================== * /* ========================== *

62
src/sock.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef SOCK_H
#define SOCK_H
#define SOCK_IP_ANY_INTERFACE CPPCOMPAT_INITLIST_TYPE(struct sock_ip) { 0 }
#define SOCK_PORT_DYNAMIC (0)
struct sock_ip {
u8 b[16];
};
struct sock_address {
struct sock_ip ip;
u32 port;
};
struct sock {
u64 handle;
};
enum sock_flag {
SOCK_FLAG_NONE = (1 << 0),
SOCK_FLAG_NON_BLOCKING_RECV = (1 << 1)
};
/* ========================== *
* Startup
* ========================== */
struct sock_startup_receipt { i32 _; };
struct sock_startup_receipt sock_startup(void);
/* ========================== *
* Address
* ========================== */
b32 sock_ip_is_ipv4(struct sock_ip ip);
b32 sock_string_is_ipv4(struct string s);
struct sock_ip sock_ip_from_string(struct string s);
struct string sock_ip_to_string(struct arena *arena, struct sock_ip addr);
/* ========================== *
* Sock
* ========================== */
struct sock sock_alloc(struct sock_address addr, sock_receive_callback_func *receive_callback, u64 flags);
void sock_release(struct sock *sock);
void sock_write(struct sock *sock, struct sock_address address, struct string msg);
void sock_testsend(void);
void sock_testrecv(void);
#endif

494
src/sock_win32.c Normal file
View File

@ -0,0 +1,494 @@
#include "sock.h"
#include "sys.h"
#include "log.h"
#include "arena.h"
#include "scratch.h"
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#define MAX_IP_STR_LEN 46
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(win32_sock_receive_entry_point, arg);
struct win32_sock {
SOCKET socket;
struct sockaddr_in6 sa6;
sock_receive_callback_func *receive_callback;
struct sys_thread receive_thread;
struct win32_sock *next_free;
};
/* ========================== *
* Global state
* ========================== */
GLOBAL struct {
struct sys_mutex win32_socks_mutex;
struct arena win32_socks_arena;
struct win32_sock *first_free_win32_sock;
WSADATA wsa_data;
} G = ZI, DEBUG_ALIAS(G, G_sock_win32);
/* ========================== *
* Startup
* ========================== */
struct sock_startup_receipt sock_startup(void)
{
G.win32_socks_mutex = sys_mutex_alloc();
G.win32_socks_arena = arena_alloc(GIGABYTE(64));
/* Initialize Winsock */
WSAStartup(MAKEWORD(2, 2), &G.wsa_data);
//WSACleanup();
return (struct sock_startup_receipt) { 0 };
}
/* ========================== *
* Address
* ========================== */
#if 1
INTERNAL struct sockaddr_in6 win32_sa6_from_sock_address(struct sock_address sa)
{
struct sockaddr_in6 res = ZI;
res.sin6_family = AF_INET6;
res.sin6_port = htons(sa.port);
CT_ASSERT(sizeof(res.sin6_addr.s6_addr) == 16);
CT_ASSERT(sizeof(sa.ip) == 16);
b32 is_any = true;
for (u64 i = 0; i < 16; ++i) {
u8 b = sa.ip.b[i];
res.sin6_addr.s6_addr[i] = b;
is_any = (is_any && b == 0);
}
if (is_any) {
res.sin6_addr = in6addr_any;
}
return res;
}
INTERNAL struct sock_address sock_address_from_win32_sa6(struct sockaddr_in6 sa6)
{
struct sock_address res = ZI;
CT_ASSERT(sizeof(sa6.sin6_addr.s6_addr) == 16);
CT_ASSERT(sizeof(res.ip) == 16);
MEMCPY(res.ip.b, sa6.sin6_addr.s6_addr, 16);
res.port = ntohs(sa6.sin6_port);
return res;
}
b32 sock_ip_is_ipv4(struct sock_ip ip)
{
return ((ip.b[0] == 0x00) &&
(ip.b[1] == 0x00) &&
(ip.b[2] == 0x00) &&
(ip.b[3] == 0x00) &&
(ip.b[4] == 0x00) &&
(ip.b[5] == 0x00) &&
(ip.b[6] == 0x00) &&
(ip.b[7] == 0x00) &&
(ip.b[8] == 0x00) &&
(ip.b[9] == 0x00) &&
(ip.b[10] == 0xFF) &&
(ip.b[11] == 0xFF));
}
b32 sock_string_is_ipv4(struct string s)
{
b32 ipv4 = true;
for (u64 i = 0; i < s.len; ++i) {
u8 c = s.text[i];
if (c == '.') {
ipv4 = true;
break;
} else if (c == ':') {
ipv4 = false;
break;
}
}
return ipv4;
}
struct sock_ip sock_ip_from_string(struct string s)
{
struct temp_arena scratch = scratch_begin_no_conflict();
char *cstr = cstr_from_string(scratch.arena, s);
u8 buff[16] = ZI;
if (sock_string_is_ipv4(s)) {
buff[10] = 0xFF;
buff[11] = 0xFF;
inet_pton(AF_INET, cstr, buff + 12);
} else {
inet_pton(AF_INET6, cstr, buff);
}
struct sock_ip res = ZI;
CT_ASSERT(sizeof(res.b) == sizeof(buff));
MEMCPY(res.b, buff, sizeof(buff));
scratch_end(scratch);
return res;
}
struct string sock_ip_to_string(struct arena *arena, struct sock_ip ip)
{
char buff[MAX_IP_STR_LEN];
if (sock_ip_is_ipv4(ip)) {
inet_ntop(AF_INET, ip.b + 12, buff, sizeof(buff));
} else {
inet_ntop(AF_INET6, ip.b, buff, sizeof(buff));
}
struct string res = string_copy(arena, string_from_cstr_limit(buff, sizeof(buff)));
return res;
}
#else
INTERNAL struct sockaddr_in6 win32_sa6_from_sock_address(struct sock_address sa)
{
struct sockaddr_in6 res = ZI;
res.sin6_family = AF_INET6;
res.sin6_port = htons(sa.port);
if (u128_eq(sa.ip, SOCK_IP_ANY_INTERFACE)) {
res.sin6_addr = in6addr_any;
} else {
/* TODO: store address structure in network byte order by default */
u64 hi = U128_HI(sa.ip);
u64 lo = U128_LO(sa.ip);
u8 *dst = res.sin6_addr.s6_addr;
dst[0] = (hi >> 56) & 0xFF;
dst[1] = (hi >> 48) & 0xFF;
dst[2] = (hi >> 40) & 0xFF;
dst[3] = (hi >> 32) & 0xFF;
dst[4] = (hi >> 24) & 0xFF;
dst[5] = (hi >> 16) & 0xFF;
dst[6] = (hi >> 8) & 0xFF;
dst[7] = (hi >> 0) & 0xFF;
dst[8] = (lo >> 56) & 0xFF;
dst[9] = (lo >> 48) & 0xFF;
dst[10] = (lo >> 40) & 0xFF;
dst[11] = (lo >> 32) & 0xFF;
dst[12] = (lo >> 24) & 0xFF;
dst[13] = (lo >> 16) & 0xFF;
dst[14] = (lo >> 8) & 0xFF;
dst[15] = (lo >> 0) & 0xFF;
}
res.sin6_port = htons(12345);
return res;
}
INTERNAL struct sock_address sock_address_from_win32_sa6(struct sockaddr_in6 sa6)
{
struct sock_address res = ZI;
u8 *src = sa6.sin6_addr.s6_addr;
/* TODO: store address structure in network byte order by default */
u64 hi = ((u64)src[0] << 56) |
((u64)src[1] << 48) |
((u64)src[2] << 40) |
((u64)src[3] << 32) |
((u64)src[4] << 24) |
((u64)src[5] << 16) |
((u64)src[6] << 8) |
((u64)src[7] << 0);
u64 lo = ((u64)src[8] << 56) |
((u64)src[9] << 48) |
((u64)src[10] << 40) |
((u64)src[11] << 32) |
((u64)src[12] << 24) |
((u64)src[13] << 16) |
((u64)src[14] << 8) |
((u64)src[15] << 0);
res.ip = U128(hi, lo);
res.port = ntohs(sa6.sin6_port);
return res;
}
struct sock_address sock_address_from_string(struct string s)
{
u64 hi = 0;
u64 lo = 0;
b32 ipv4 = true;
for (u64 i = 0; i < s.len; ++i) {
u8 c = s.text[i];
if (c == '.') {
ipv4 = true;
break;
} else if (c == ':') {
ipv4 = false;
break;
}
}
if (ipv4) {
struct string seq = ZI;
seq.text = s.text;
u8 byte_index = 0;
u8 byte = 0;
u8 factor = 100;
for (u32 s_index = 0; s_index < s.len; ++s_index) {
u8 c = s.text[s_index];
if (c == '.' || s_index == (s.len - 1)) {
if (byte_index < 8) {
lo |= (byte << (byte_index * 8));
} else {
hi |= (byte << (byte_index * 8));
}
byte = 0;
factor = 100;
++byte_index;
} else {
byte += ((c + 48) * factor);
factor *= 0.1;
}
}
} else {
/* TODO */
ASSERT(false);
}
return U128(hi, lo);
}
#endif
/* ========================== *
* Sock
* ========================== */
INTERNAL struct win32_sock *win32_sock_alloc(void)
{
struct win32_sock *ws = NULL;
{
struct sys_lock lock = sys_mutex_lock_e(&G.win32_socks_mutex);
if (G.first_free_win32_sock) {
ws = G.first_free_win32_sock;
G.first_free_win32_sock = ws->next_free;
} else {
ws = arena_push(&G.win32_socks_arena, struct win32_sock);
}
sys_mutex_unlock(&lock);
}
MEMZERO_STRUCT(ws);
return ws;
}
INTERNAL void win32_sock_release(struct win32_sock *ws)
{
struct sys_lock lock = sys_mutex_lock_e(&G.win32_socks_mutex);
ws->next_free = G.first_free_win32_sock;
G.first_free_win32_sock = ws;
sys_mutex_unlock(&lock);
}
struct sock sock_alloc(struct sock_address bind_addr, u64 flags)
{
struct win32_sock *ws = win32_sock_alloc();
struct sockaddr_in6 sa6 = win32_sa6_from_sock_address(bind_addr);
ws->socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (bind_addr.) {
/* TODO: Error checking */
bind(ws->socket, (struct sockaddr *)&ws->sa6, sizeof(ws->sa6));
}
if (receive_callback) {
/* Spin up receive thread */
ws->receive_thread = sys_thread_alloc(win32_sock_receive_entry_point, ws, LIT("[P8] Sock receive thread"));
}
struct sock res = ZI;
res.handle = (u64)ws;
return res;
}
void sock_release(struct sock *sock)
{
/* TODO */
struct win32_sock *ws = (struct win32_sock *)sock->handle;
//ws->shutdown_receiver
//closesocket(ws->socket);
win32_sock_release(ws);
}
struct sock_packet {
struct sock_address addr;
struct string msg;
};
void sock_send(struct sock *sock, struct sock_packet p)
{
struct win32_sock *ws = (struct win32_sock *)sock->handle;
struct sockaddr_in6 sa6 = win32_sa6_from_sock_address(p.addr);
sendto(ws->socket, (char *)p.msg.text, p.msg.len, 0, (struct sockaddr *)&sa6, sizeof(sa6));
}
struct sock_packet sock_recv(struct sock *sock, u8 *buffer, u64 buffer_size)
{
struct sock_packet p = ZI;
struct win32_sock *ws = (struct win32_sock *)sock->handle;
return p;
}
/* ========================== *
* Receive thread
* ========================== */
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(win32_sock_receive_entry_point, arg)
{
struct win32_sock *ws = (struct win32_sock *)arg;
struct temp_arena scratch = scratch_begin_no_conflict();
u64 buffer_size = KILOBYTE(64);
u8 *buffer = arena_push_array(scratch.arena, u8, buffer_size);
struct sockaddr_in6 client_sa6 = ZI;
i32 client_sa6_size = sizeof(client_sa6);
struct sock_address dummy = ZI;
dummy.ip = sock_ip_from_string(LIT("127.0.0.1"));
dummy.port = 12345;
struct sockaddr_in6 dummy_sa6 = win32_sa6_from_sock_address(dummy);
char dummy_msg = 0;
sendto(ws->socket, &dummy_msg, 1, 0, (struct sockaddr *)&dummy_sa6, sizeof(dummy_sa6));
/* TODO: Allow thread shutdown */
volatile b32 shutdown = false;
while (!shutdown) {
i32 msg_len = recvfrom(ws->socket, (char *)buffer, buffer_size, 0, (struct sockaddr *)&client_sa6, &client_sa6_size);
if (msg_len == SOCKET_ERROR) {
i32 err = WSAGetLastError();
(UNUSED)err;
ASSERT(false);
} else if (msg_len > 0) {
if (ws->receive_callback) {
struct sock_address address = sock_address_from_win32_sa6(client_sa6);
ws->receive_callback(address, STRING(msg_len, buffer));
}
}
}
scratch_end(scratch);
}
/* ========================== *
* Test
* ========================== */
void sock_testsend(void)
{
SOCKET sock;
struct sockaddr_in serverAddr;
char *message = "Hello, UDP!";
/* Create socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* Set up the server address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345); /* Port */
// serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr) <= 0) {
sys_panic(LIT("Invalid address"));
}
/* Send a message */
sendto(sock, message, strlen(message), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
/* Clean up */
closesocket(sock);
WSACleanup();
}
void sock_testrecv(void)
{
SOCKET sock;
char clientIP[INET_ADDRSTRLEN];
struct sockaddr_in serverAddr, clientAddr;
char buffer[1024];
int clientAddrLen = sizeof(clientAddr);
/* Create socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* Set up the server address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345); /* Port */
serverAddr.sin_addr.s_addr = INADDR_ANY; /* Accept any incoming address */
/* Bind the socket to the address */
bind(sock, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
/* Receive a message */
volatile b32 run = true;
while (run) {
int recvLen = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&clientAddr, &clientAddrLen);
if (recvLen > 0) {
buffer[recvLen] = '\0'; /* Null-terminate the received message */
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, sizeof(clientIP));
struct string addr = string_from_cstr(clientIP);
struct string msg = STRING((u64)recvLen, (u8 *)buffer);
i32 port = ntohs(clientAddr.sin_port);
logf_info("Received from %F:%F - %F\n", FMT_STR(addr), FMT_SINT(port), FMT_STR(msg));
}
}
// Clean up
closesocket(sock);
WSACleanup();
}

View File

@ -86,7 +86,7 @@ INTERNAL WORK_TASK_FUNC_DEF(sound_load_asset_task, vparams)
__prof; __prof;
struct sound_task_params *params = (struct sound_task_params *)vparams; struct sound_task_params *params = (struct sound_task_params *)vparams;
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
struct string path = string_from_cstr_len(params->path_cstr, params->path_len); struct string path = STRING(params->path_len, (u8 *)params->path_cstr);
struct asset *asset = params->asset; struct asset *asset = params->asset;
u32 flags = params->flags; u32 flags = params->flags;

View File

@ -782,7 +782,7 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
struct cache_node **nonmatching_next = NULL; struct cache_node **nonmatching_next = NULL;
struct cache_node_hash hash = cache_node_hash_from_tag_hash(tag.hash, kind); struct cache_node_hash hash = cache_node_hash_from_tag_hash(tag.hash, kind);
u64 cache_bucket_index = U128_LO64(hash.v) % CACHE_BUCKETS_COUNT; u64 cache_bucket_index = U128_LO(hash.v) % CACHE_BUCKETS_COUNT;
struct cache_bucket *bucket = &G.cache.buckets[cache_bucket_index]; struct cache_bucket *bucket = &G.cache.buckets[cache_bucket_index];
/* Lookup */ /* Lookup */
@ -1076,7 +1076,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
/* Check if file changed for resource reloading */ /* Check if file changed for resource reloading */
if (!consider_for_eviction) { if (!consider_for_eviction) {
struct string path = string_from_cstr_len((char *)n->tag_path, n->tag_path_len); struct string path = STRING(n->tag_path_len, n->tag_path);
b32 file_changed = false; b32 file_changed = false;
struct sys_datetime current_file_time; struct sys_datetime current_file_time;
{ {

View File

@ -658,6 +658,21 @@ u64 cstr_len(char *cstr)
return end - cstr; return end - cstr;
} }
u64 cstr_len_limit(char *cstr, u64 limit)
{
char *end = cstr;
if (cstr) {
for (u64 i = 0; i < limit; ++i) {
if (*end) {
++end;
} else {
break;
}
}
}
return end - cstr;
}
char *cstr_from_string(struct arena *arena, struct string src) char *cstr_from_string(struct arena *arena, struct string src)
{ {
u8 *text = arena_push_array(arena, u8, src.len + 1); u8 *text = arena_push_array(arena, u8, src.len + 1);
@ -685,8 +700,9 @@ struct string string_from_cstr(char *cstr)
}; };
} }
struct string string_from_cstr_len(char *cstr, u64 len) struct string string_from_cstr_limit(char *cstr, u64 limit)
{ {
u64 len = cstr_len_limit(cstr, limit);
return (struct string) { return (struct string) {
.text = (u8 *)cstr, .text = (u8 *)cstr,
.len = len .len = len

View File

@ -111,10 +111,11 @@ struct string32 string32_from_string(struct arena *arena, struct string str8);
* ========================== */ * ========================== */
u64 cstr_len(char *cstr); u64 cstr_len(char *cstr);
u64 cstr_len_limit(char *cstr, u64 limit);
char *cstr_from_string(struct arena *arena, struct string src); char *cstr_from_string(struct arena *arena, struct string src);
char *cstr_buff_from_string(struct string dest_buff, struct string src); char *cstr_buff_from_string(struct string dest_buff, struct string src);
struct string string_from_cstr(char *cstr); struct string string_from_cstr(char *cstr);
struct string string_from_cstr_len(char *cstr, u64 len); struct string string_from_cstr_limit(char *cstr, u64 limit);
u64 wstr_len(wchar_t *wstr); u64 wstr_len(wchar_t *wstr);
wchar_t *wstr_from_string(struct arena *arena, struct string src); wchar_t *wstr_from_string(struct arena *arena, struct string src);

View File

@ -1620,12 +1620,11 @@ struct thread_local_store *sys_thread_get_thread_local_store(void)
* Threads * Threads
* ========================== */ * ========================== */
INTERNAL struct win32_thread *win32_thread_alloc_locked(struct sys_lock *lock) INTERNAL struct win32_thread *win32_thread_alloc(void)
{ {
sys_assert_locked_e(lock, &G.threads_mutex);
(UNUSED)lock;
struct win32_thread *t = NULL; struct win32_thread *t = NULL;
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
{
if (G.threads_first_free) { if (G.threads_first_free) {
t = G.threads_first_free; t = G.threads_first_free;
G.threads_first_free = t->next; G.threads_first_free = t->next;
@ -1640,14 +1639,15 @@ INTERNAL struct win32_thread *win32_thread_alloc_locked(struct sys_lock *lock)
} }
t->prev = G.threads_last; t->prev = G.threads_last;
G.threads_last = t; G.threads_last = t;
}
sys_mutex_unlock(&lock);
return t; return t;
} }
INTERNAL void win32_thread_release_locked(struct sys_lock *lock, struct win32_thread *t) INTERNAL void win32_thread_release(struct win32_thread *t)
{
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
{ {
sys_assert_locked_e(lock, &G.threads_mutex);
(UNUSED)lock;
if (t->prev) { if (t->prev) {
t->prev->next = t->next; t->prev->next = t->next;
} }
@ -1660,9 +1660,9 @@ INTERNAL void win32_thread_release_locked(struct sys_lock *lock, struct win32_th
if (G.threads_last == t) { if (G.threads_last == t) {
G.threads_last = t->prev; G.threads_last = t->prev;
} }
*t = (struct win32_thread) { t->next = G.threads_first_free;
.next = G.threads_first_free }
}; sys_mutex_unlock(&lock);
} }
INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt) INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
@ -1680,6 +1680,7 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
/* Set thread name */ /* Set thread name */
struct string thread_name = string_from_cstr(t->thread_name_cstr); struct string thread_name = string_from_cstr(t->thread_name_cstr);
if (thread_name.len > 0) { if (thread_name.len > 0) {
/* FIXME: Don't use scratch arena here, to avoid scratch TLS being initialized for threads that don't need them otherwise */
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
wchar_t *wc_thread_name = wstr_from_string(scratch.arena, thread_name); wchar_t *wc_thread_name = wstr_from_string(scratch.arena, thread_name);
SetThreadDescription(GetCurrentThread(), wc_thread_name); SetThreadDescription(GetCurrentThread(), wc_thread_name);
@ -1688,16 +1689,9 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
logf_info("New thread \"%F\" created with ID %F", FMT_STR(thread_name), FMT_UINT(sys_thread_id())); logf_info("New thread \"%F\" created with ID %F", FMT_STR(thread_name), FMT_UINT(sys_thread_id()));
/* Start thread */ /* Enter thread entry point */
t->entry_point(t->thread_data); t->entry_point(t->thread_data);
/* Release thread object */
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
{
win32_thread_release_locked(&lock, t);
}
sys_mutex_unlock(&lock);
/* Release TLS */ /* Release TLS */
win32_tls_release(&tls); win32_tls_release(&tls);
@ -1713,10 +1707,9 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
logf_info("Creating thread \"%F\"", FMT_STR(thread_name)); logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
struct sys_thread res = ZI; struct sys_thread res = ZI;
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
{
/* Allocate thread object */ /* Allocate thread object */
struct win32_thread *t = win32_thread_alloc_locked(&lock); struct win32_thread *t = win32_thread_alloc();
t->entry_point = entry_point; t->entry_point = entry_point;
t->thread_data = thread_data; t->thread_data = thread_data;
@ -1737,27 +1730,15 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
} }
res.handle = (u64)t; res.handle = (u64)t;
}
sys_mutex_unlock(&lock);
return res; return res;
} }
void sys_thread_wait_release(struct sys_thread *thread) void sys_thread_wait_release(struct sys_thread *thread)
{
HANDLE handle = 0;
/* Lookup */
struct sys_lock lock = sys_mutex_lock_s(&G.threads_mutex);
{ {
struct win32_thread *t = (struct win32_thread *)thread->handle; struct win32_thread *t = (struct win32_thread *)thread->handle;
if (t) { HANDLE handle = t->handle;
handle = t->handle;
}
}
sys_mutex_unlock(&lock);
/* Wait */ /* Wait for thread to stop */
if (handle) { if (handle) {
DWORD res = WaitForSingleObject(handle, INFINITE); DWORD res = WaitForSingleObject(handle, INFINITE);
CloseHandle(handle); CloseHandle(handle);
@ -1765,6 +1746,9 @@ void sys_thread_wait_release(struct sys_thread *thread)
ASSERT(res != WAIT_FAILED); ASSERT(res != WAIT_FAILED);
(UNUSED)res; (UNUSED)res;
} }
/* Release thread struct */
win32_thread_release(t);
} }
u32 sys_thread_id(void) u32 sys_thread_id(void)

View File

@ -19,6 +19,7 @@
#include "collider.h" #include "collider.h"
#include "rng.h" #include "rng.h"
#include "log.h" #include "log.h"
#include "sock.h"
struct bind_state { struct bind_state {
b32 is_held; /* Is this bind held down this frame */ b32 is_held; /* Is this bind held down this frame */
@ -136,6 +137,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct game_startup_receipt *game_sr, struct game_startup_receipt *game_sr,
struct asset_cache_startup_receipt *asset_cache_sr, struct asset_cache_startup_receipt *asset_cache_sr,
struct mixer_startup_receipt *mixer_sr, struct mixer_startup_receipt *mixer_sr,
struct sock_startup_receipt *sock_sr,
struct sys_window *window) struct sys_window *window)
{ {
(UNUSED)work_sr; (UNUSED)work_sr;
@ -146,6 +148,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
(UNUSED)game_sr; (UNUSED)game_sr;
(UNUSED)asset_cache_sr; (UNUSED)asset_cache_sr;
(UNUSED)mixer_sr; (UNUSED)mixer_sr;
(UNUSED)sock_sr;
G.arena = arena_alloc(GIGABYTE(64)); G.arena = arena_alloc(GIGABYTE(64));
G.sys_events_mutex = sys_mutex_alloc(); G.sys_events_mutex = sys_mutex_alloc();
@ -468,6 +471,40 @@ INTERNAL void user_update(void)
{ {
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
{
static struct sock sock = ZI;
if (!sock.handle) {
struct sock_address bind_addr = ZI;
bind_addr.ip = SOCK_IP_ANY_INTERFACE;
bind_addr.port = SOCK_PORT_DYNAMIC; /* Dynamic port */
sock = sock_alloc(bind_addr, SOCK_FLAG_NON_BLOCKING_RECV);
}
}
/* ========================== * /* ========================== *
* Begin frame * Begin frame
* ========================== */ * ========================== */

View File

@ -10,6 +10,7 @@ struct draw_startup_receipt;
struct game_startup_receipt; struct game_startup_receipt;
struct asset_cache_startup_receipt; struct asset_cache_startup_receipt;
struct mixer_startup_receipt; struct mixer_startup_receipt;
struct sock_startup_receipt;
enum user_bind_kind { enum user_bind_kind {
USER_BIND_KIND_NONE, USER_BIND_KIND_NONE,
@ -56,6 +57,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
struct game_startup_receipt *game_sr, struct game_startup_receipt *game_sr,
struct asset_cache_startup_receipt *asset_cache_sr, struct asset_cache_startup_receipt *asset_cache_sr,
struct mixer_startup_receipt *mixer_sr, struct mixer_startup_receipt *mixer_sr,
struct sock_startup_receipt *sock_sr,
struct sys_window *window); struct sys_window *window);
#endif #endif