socket progress
This commit is contained in:
parent
d7f1ac06cb
commit
062285b1b3
2
build.c
2
build.c
@ -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")) ||
|
||||||
|
|||||||
46
src/app.c
46
src/app.c
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
49
src/game.c
49
src/game.c
@ -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
|
||||||
|
|||||||
@ -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
62
src/sock.h
Normal 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
494
src/sock_win32.c
Normal 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();
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
{
|
{
|
||||||
|
|||||||
18
src/string.c
18
src/string.c
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
136
src/sys_win32.c
136
src/sys_win32.c
@ -1620,49 +1620,49 @@ 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;
|
||||||
if (G.threads_first_free) {
|
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
|
||||||
t = G.threads_first_free;
|
{
|
||||||
G.threads_first_free = t->next;
|
if (G.threads_first_free) {
|
||||||
} else {
|
t = G.threads_first_free;
|
||||||
t = arena_push(&G.threads_arena, struct win32_thread);
|
G.threads_first_free = t->next;
|
||||||
|
} else {
|
||||||
|
t = arena_push(&G.threads_arena, struct win32_thread);
|
||||||
|
}
|
||||||
|
MEMZERO_STRUCT(t);
|
||||||
|
if (!G.threads_first) {
|
||||||
|
G.threads_first = t;
|
||||||
|
} else {
|
||||||
|
G.threads_last->next = t;
|
||||||
|
}
|
||||||
|
t->prev = G.threads_last;
|
||||||
|
G.threads_last = t;
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(t);
|
sys_mutex_unlock(&lock);
|
||||||
if (!G.threads_first) {
|
|
||||||
G.threads_first = t;
|
|
||||||
} else {
|
|
||||||
G.threads_last->next = t;
|
|
||||||
}
|
|
||||||
t->prev = G.threads_last;
|
|
||||||
G.threads_last = t;
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
sys_assert_locked_e(lock, &G.threads_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
|
||||||
(UNUSED)lock;
|
{
|
||||||
|
if (t->prev) {
|
||||||
if (t->prev) {
|
t->prev->next = t->next;
|
||||||
t->prev->next = t->next;
|
}
|
||||||
|
if (t->next) {
|
||||||
|
t->next->prev = t->prev;
|
||||||
|
}
|
||||||
|
if (G.threads_first == t) {
|
||||||
|
G.threads_first = t->next;
|
||||||
|
}
|
||||||
|
if (G.threads_last == t) {
|
||||||
|
G.threads_last = t->prev;
|
||||||
|
}
|
||||||
|
t->next = G.threads_first_free;
|
||||||
}
|
}
|
||||||
if (t->next) {
|
sys_mutex_unlock(&lock);
|
||||||
t->next->prev = t->prev;
|
|
||||||
}
|
|
||||||
if (G.threads_first == t) {
|
|
||||||
G.threads_first = t->next;
|
|
||||||
}
|
|
||||||
if (G.threads_last == t) {
|
|
||||||
G.threads_last = t->prev;
|
|
||||||
}
|
|
||||||
*t = (struct win32_thread) {
|
|
||||||
.next = G.threads_first_free
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,51 +1707,38 @@ 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 */
|
|
||||||
struct win32_thread *t = win32_thread_alloc_locked(&lock);
|
|
||||||
t->entry_point = entry_point;
|
|
||||||
t->thread_data = thread_data;
|
|
||||||
|
|
||||||
/* Copy thread name to params */
|
/* Allocate thread object */
|
||||||
cstr_buff_from_string(STRING_FROM_ARRAY(t->thread_name_cstr), thread_name);
|
struct win32_thread *t = win32_thread_alloc();
|
||||||
|
t->entry_point = entry_point;
|
||||||
|
t->thread_data = thread_data;
|
||||||
|
|
||||||
t->handle = CreateThread(
|
/* Copy thread name to params */
|
||||||
NULL,
|
cstr_buff_from_string(STRING_FROM_ARRAY(t->thread_name_cstr), thread_name);
|
||||||
SYS_THREAD_STACK_SIZE,
|
|
||||||
win32_thread_proc,
|
|
||||||
t,
|
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!t->handle) {
|
t->handle = CreateThread(
|
||||||
sys_panic(LIT("Failed to create thread"));
|
NULL,
|
||||||
}
|
SYS_THREAD_STACK_SIZE,
|
||||||
|
win32_thread_proc,
|
||||||
|
t,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
res.handle = (u64)t;
|
if (!t->handle) {
|
||||||
|
sys_panic(LIT("Failed to create thread"));
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&lock);
|
|
||||||
|
|
||||||
|
res.handle = (u64)t;
|
||||||
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;
|
struct win32_thread *t = (struct win32_thread *)thread->handle;
|
||||||
|
HANDLE handle = t->handle;
|
||||||
|
|
||||||
/* Lookup */
|
/* Wait for thread to stop */
|
||||||
struct sys_lock lock = sys_mutex_lock_s(&G.threads_mutex);
|
|
||||||
{
|
|
||||||
struct win32_thread *t = (struct win32_thread *)thread->handle;
|
|
||||||
if (t) {
|
|
||||||
handle = t->handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sys_mutex_unlock(&lock);
|
|
||||||
|
|
||||||
/* Wait */
|
|
||||||
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)
|
||||||
|
|||||||
37
src/user.c
37
src/user.c
@ -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
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user