move sock into sys layer

This commit is contained in:
jacob 2025-07-14 17:04:39 -05:00
parent f27ec95481
commit a504b27767
9 changed files with 442 additions and 489 deletions

View File

@ -837,14 +837,12 @@ 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("gp_")) || StringBeginsWith(name, Lit("gp_")) ||
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("gp_dx12.c")) || StringEqual(name, Lit("gp_dx12.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

@ -19,7 +19,6 @@
#include "math.h" #include "math.h"
#include "gp.h" #include "gp.h"
#include "phys.h" #include "phys.h"
#include "sock.h"
#include "host.h" #include "host.h"
#include "bitbuff.h" #include "bitbuff.h"
@ -282,8 +281,7 @@ void sys_app_startup(struct string args_str)
gp_startup(); gp_startup();
/* Subsystems */ /* Subsystems */
struct sock_startup_receipt sock_sr = sock_startup(); struct host_startup_receipt host_sr = host_startup();
struct host_startup_receipt host_sr = host_startup(&sock_sr);
struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup(); struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup();
struct ttf_startup_receipt ttf_sr = ttf_startup(); struct ttf_startup_receipt ttf_sr = ttf_startup();
struct font_startup_receipt font_sr = font_startup(&asset_cache_sr, &ttf_sr); struct font_startup_receipt font_sr = font_startup(&asset_cache_sr, &ttf_sr);

View File

@ -58,7 +58,7 @@ struct host_channel {
struct host_channel *next_free; struct host_channel *next_free;
struct sock_address address; struct sys_address address;
u64 address_hash; u64 address_hash;
struct host_channel *next_address_hash; struct host_channel *next_address_hash;
struct host_channel *prev_address_hash; struct host_channel *prev_address_hash;
@ -105,7 +105,7 @@ struct host_channel_lookup_bin {
struct host_rcv_packet { struct host_rcv_packet {
struct sock *sock; struct sock *sock;
struct sock_address address; struct sys_address address;
struct string data; struct string data;
struct host_rcv_packet *next; struct host_rcv_packet *next;
}; };
@ -162,10 +162,9 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma);
* Startup * Startup
* ========================== */ * ========================== */
struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr) struct host_startup_receipt host_startup(void)
{ {
__prof; __prof;
(UNUSED)sock_sr;
return (struct host_startup_receipt) { 0 }; return (struct host_startup_receipt) { 0 };
} }
@ -195,14 +194,14 @@ struct host *host_alloc(u16 listen_port)
host->num_msg_assembler_lookup_bins = NUM_MSG_ASSEMBLER_LOOKUP_BINS; host->num_msg_assembler_lookup_bins = NUM_MSG_ASSEMBLER_LOOKUP_BINS;
host->msg_assembler_lookup_bins = arena_push_array(host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins); host->msg_assembler_lookup_bins = arena_push_array(host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins);
host->sock = sock_alloc(listen_port, MEBI(2), MEBI(2)); host->sock = sys_sock_alloc(listen_port, MEBI(2), MEBI(2));
return host; return host;
} }
void host_release(struct host *host) void host_release(struct host *host)
{ {
sock_release(host->sock); sys_sock_release(host->sock);
buddy_ctx_release(host->buddy); buddy_ctx_release(host->buddy);
arena_release(host->rcv_buffer_write->arena); arena_release(host->rcv_buffer_write->arena);
@ -216,17 +215,17 @@ void host_release(struct host *host)
* Channel * Channel
* ========================== */ * ========================== */
INTERNAL u64 hash_from_address(struct sock_address address) INTERNAL u64 hash_from_address(struct sys_address address)
{ {
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&address)); return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&address));
} }
INTERNAL struct host_channel *host_channel_from_address(struct host *host, struct sock_address address) INTERNAL struct host_channel *host_channel_from_address(struct host *host, struct sys_address address)
{ {
u64 hash = hash_from_address(address); u64 hash = hash_from_address(address);
struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins]; struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins];
for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) { for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) {
if (channel->address_hash == hash && sock_address_eq(channel->address, address)) { if (channel->address_hash == hash && sys_address_eq(channel->address, address)) {
return channel; return channel;
} }
} }
@ -274,7 +273,7 @@ INTERNAL struct host_channel_list host_channels_from_id(struct arena *arena, str
return res; return res;
} }
INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sock_address address) INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sys_address address)
{ {
struct host_channel_id id = ZI; struct host_channel_id id = ZI;
struct host_channel *channel; struct host_channel *channel;
@ -582,7 +581,7 @@ INTERNAL struct host_cmd *host_cmd_alloc_and_append(struct host *host)
return cmd; return cmd;
} }
void host_queue_connect_to_address(struct host *host, struct sock_address connect_address) void host_queue_connect_to_address(struct host *host, struct sys_address connect_address)
{ {
struct host_channel *channel = host_channel_from_address(host, connect_address); struct host_channel *channel = host_channel_from_address(host, connect_address);
if (!channel->valid) { if (!channel->valid) {
@ -647,14 +646,10 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
struct host_rcv_packet *last_packet = 0; struct host_rcv_packet *last_packet = 0;
{ {
__profn("Read socket"); __profn("Read socket");
struct sock_array socks = ZI; struct sys_sock *sock = host->sock;
socks.socks = &host->sock; struct sys_sock_read_result res = ZI;
socks.count = 1; while ((res = sys_sock_read(scratch.arena, sock)).valid) {
struct sys_address address = res.address;
struct sock *sock = host->sock;
struct sock_read_result res = ZI;
while ((res = sock_read(scratch.arena, sock)).valid) {
struct sock_address address = res.address;
struct string data = res.data; struct string data = res.data;
if (data.len > 0) { if (data.len > 0) {
struct host_rcv_packet *packet = arena_push(scratch.arena, struct host_rcv_packet); struct host_rcv_packet *packet = arena_push(scratch.arena, struct host_rcv_packet);
@ -675,7 +670,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
__profn("Process host packets"); __profn("Process host packets");
for (struct host_rcv_packet *packet = first_packet; packet; packet = packet->next) { for (struct host_rcv_packet *packet = first_packet; packet; packet = packet->next) {
//struct sock *sock = packet->sock; //struct sock *sock = packet->sock;
struct sock_address address = packet->address; struct sys_address address = packet->address;
struct bitbuff bb = bitbuff_from_string(packet->data); struct bitbuff bb = bitbuff_from_string(packet->data);
struct bitbuff_reader br = br_from_bitbuff(&bb); struct bitbuff_reader br = br_from_bitbuff(&bb);
u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */ u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */
@ -712,7 +707,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
{ {
/* A foreign host is trying to connect to us */ /* A foreign host is trying to connect to us */
if (!channel->valid) { if (!channel->valid) {
logf_info("Host received conection attempt from %F", FMT_STR(sock_string_from_address(scratch.arena, address))); logf_info("Host received conection attempt from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */ /* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
channel = host_channel_alloc(host, address); channel = host_channel_alloc(host, address);
} }
@ -725,7 +720,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
{ {
/* We successfully connected to a foreign host and they are ready to receive messages */ /* We successfully connected to a foreign host and they are ready to receive messages */
if (channel->valid && !channel->connected) { if (channel->valid && !channel->connected) {
logf_info("Host received connection from %F", FMT_STR(sock_string_from_address(scratch.arena, address))); logf_info("Host received connection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
struct host_event *event = push_event(arena, &events); struct host_event *event = push_event(arena, &events);
event->kind = HOST_EVENT_KIND_CHANNEL_OPENED; event->kind = HOST_EVENT_KIND_CHANNEL_OPENED;
event->channel_id = channel->id; event->channel_id = channel->id;
@ -737,7 +732,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
{ {
/* A foreign host disconnected from us */ /* A foreign host disconnected from us */
if (channel->valid) { if (channel->valid) {
logf_info("Host received disconnection from %F", FMT_STR(sock_string_from_address(scratch.arena, address))); logf_info("Host received disconnection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
struct host_event *event = push_event(arena, &events); struct host_event *event = push_event(arena, &events);
event->kind = HOST_EVENT_KIND_CHANNEL_CLOSED; event->kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
event->channel_id = channel->id; event->channel_id = channel->id;
@ -1021,19 +1016,19 @@ void host_update_end(struct host *host)
{ {
__profn("Send host packets"); __profn("Send host packets");
for (u64 i = 0; i < host->num_channels_reserved; ++i) { for (u64 i = 0; i < host->num_channels_reserved; ++i) {
struct sock *sock = host->sock; struct sys_sock *sock = host->sock;
struct host_channel *channel = &host->channels[i]; struct host_channel *channel = &host->channels[i];
u64 total_sent = 0; u64 total_sent = 0;
if (channel->valid) { if (channel->valid) {
struct sock_address address = channel->address; struct sys_address address = channel->address;
/* Send reliable packets to channel */ /* Send reliable packets to channel */
for (struct host_snd_packet *packet = channel->first_reliable_packet; packet; packet = packet->next) { for (struct host_snd_packet *packet = channel->first_reliable_packet; packet; packet = packet->next) {
sock_write(sock, address, STRING(packet->data_len, packet->data)); sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
total_sent += packet->data_len; total_sent += packet->data_len;
} }
/* Send unreliable packets to channel */ /* Send unreliable packets to channel */
for (struct host_snd_packet *packet = channel->first_unreliable_packet; packet; packet = packet->next) { for (struct host_snd_packet *packet = channel->first_unreliable_packet; packet; packet = packet->next) {
sock_write(sock, address, STRING(packet->data_len, packet->data)); sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
total_sent += packet->data_len; total_sent += packet->data_len;
} }
/* Release unreliable packets */ /* Release unreliable packets */

View File

@ -2,7 +2,6 @@
#define HOST_H #define HOST_H
#include "sys.h" #include "sys.h"
#include "sock.h"
#include "snc.h" #include "snc.h"
#define HOST_CHANNEL_ID_NIL (struct host_channel_id) { .gen = 0, .idx = 0 } #define HOST_CHANNEL_ID_NIL (struct host_channel_id) { .gen = 0, .idx = 0 }
@ -67,7 +66,7 @@ struct host_event_list {
struct host { struct host {
struct arena *arena; struct arena *arena;
struct sock *sock; struct sys_sock *sock;
struct buddy_ctx *buddy; /* For storing msg assembler data */ struct buddy_ctx *buddy; /* For storing msg assembler data */
@ -104,7 +103,7 @@ struct host {
* ========================== */ * ========================== */
struct host_startup_receipt { i32 _; }; struct host_startup_receipt { i32 _; };
struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr); struct host_startup_receipt host_startup(void);
/* ========================== * /* ========================== *
* Host * Host
@ -118,7 +117,7 @@ void host_release(struct host *host);
* Queue * Queue
* ========================== */ * ========================== */
void host_queue_connect_to_address(struct host *host, struct sock_address connect_address); void host_queue_connect_to_address(struct host *host, struct sys_address connect_address);
void host_queue_disconnect(struct host *host, struct host_channel_id channel_id); void host_queue_disconnect(struct host *host, struct host_channel_id channel_id);

View File

@ -1,49 +0,0 @@
#ifndef SOCK_H
#define SOCK_H
#include "memory.h"
enum sock_address_family {
SOCK_ADDRESS_FAMILY_IPV4,
SOCK_ADDRESS_FAMILY_IPV6
};
struct sock;
struct sock_array {
struct sock **socks;
u64 count;
};
struct sock_address {
b32 valid;
enum sock_address_family family;
/* NOTE: ipnb & portnb are stored in network byte order */
u8 ipnb[16];
u16 portnb;
};
struct sock_read_result {
b32 valid; /* Since data.len = 0 can be valid */
struct sock_address address;
struct string data;
};
struct sock_startup_receipt { i32 _; };
struct sock_startup_receipt sock_startup(void);
struct sock_address sock_address_from_string(struct string str);
struct sock_address sock_address_from_port(u16 port);
struct string sock_string_from_address(struct arena *arena, struct sock_address address);
INLINE b32 sock_address_eq(struct sock_address a, struct sock_address b)
{
return MEMEQ_STRUCT(&a, &b);
}
struct sock *sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
void sock_release(struct sock *sock);
struct sock_read_result sock_read(struct arena *arena, struct sock *sock);
void sock_write(struct sock *sock, struct sock_address address, struct string data);
#endif

View File

@ -1,398 +0,0 @@
#include "sock.h"
#include "sys.h"
#include "arena.h"
#include "log.h"
#include "string.h"
#include "gstat.h"
#include "snc.h"
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
struct win32_address {
i32 size;
i32 family;
union {
struct sockaddr_storage sas;
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
};
struct win32_sock {
SOCKET sock;
struct win32_sock *next_free;
};
/* ========================== *
* Global state
* ========================== */
GLOBAL struct {
WSADATA wsa_data;
struct arena *win32_socks_arena;
struct snc_mutex win32_socks_mutex;
struct win32_sock *first_free_win32_sock;
} G = ZI, DEBUG_ALIAS(G, G_sock_win32);
/* ========================== *
* Startup
* ========================== */
struct sock_startup_receipt sock_startup(void)
{
__prof;
/* Startup winsock */
WSAStartup(MAKEWORD(2, 2), &G.wsa_data);
G.win32_socks_arena = arena_alloc(GIBI(64));
return (struct sock_startup_receipt) { 0 };
}
/* ========================== *
* Address
* ========================== */
INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char *port_cstr)
{
struct sock_address res = ZI;
struct addrinfo hints = ZI;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *ai_res = 0;
i32 status = getaddrinfo(ip_cstr, port_cstr, &hints, &ai_res);
if (status == 0) {
while (ai_res) {
if (ai_res->ai_family == AF_INET) {
struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_res->ai_addr;
res.valid = 1;
res.family = SOCK_ADDRESS_FAMILY_IPV4;
res.portnb = sockaddr->sin_port;
STATIC_ASSERT(sizeof(sockaddr->sin_addr) == 4);
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
break;
} else if (ai_res->ai_family == AF_INET6) {
/* TODO: Enable ipv6 */
#if 0
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
res.valid = 1;
res.family = SOCK_ADDRESS_FAMILY_IPV6;
res.portnb = sockaddr->sin6_port;
STATIC_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
break;
#endif
}
ai_res = ai_res->ai_next;
}
freeaddrinfo(ai_res);
}
return res;
}
struct sock_address sock_address_from_string(struct string str)
{
/* Parse string into ip & port */
u8 ip_buff[1024];
u8 port_buff[countof(ip_buff)];
char *ip_cstr = 0;
char *port_cstr = 0;
{
u64 colon_count = 0;
for (u64 i = 0; i < str.len; ++i) {
u8 c = str.text[i];
if (c == ':') {
++colon_count;
}
}
u64 ip_len = 0;
u64 port_len = 0;
u64 parse_len = min_u64(min_u64(str.len, countof(ip_buff) - 1), countof(port_buff) - 1);
if (colon_count > 1 && str.text[0] == '[') {
/* Parse ipv6 with port */
b32 parse_addr = 1;
for (u64 i = 1; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ']') {
parse_addr = 0;
} else {
ip_buff[ip_len] = c;
++ip_len;
}
} else if (c != ':') {
port_buff[port_len] = c;
++port_len;
}
}
} else if (colon_count == 1) {
/* Parse address with port */
b32 parse_addr = 1;
for (u64 i = 0; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ':') {
parse_addr = 0;
} else {
ip_buff[ip_len] = c;
++ip_len;
}
} else {
port_buff[port_len] = c;
++port_len;
}
}
} else {
/* Copy address without port */
ip_len = min_u64(str.len, countof(ip_buff) - 1);
MEMCPY(ip_buff, str.text, ip_len);
}
if (ip_len > 0) {
ip_buff[ip_len] = 0;
ip_cstr = (char *)ip_buff;
}
if (port_len > 0) {
port_buff[port_len] = 0;
port_cstr = (char *)port_buff;
}
}
struct sock_address res = sock_address_from_ip_port_cstr(ip_cstr, port_cstr);
return res;
}
struct sock_address sock_address_from_port(u16 port)
{
u8 port_buff[128];
char *port_cstr = 0;
{
u8 port_buff_reverse[countof(port_buff)];
u64 port_len = 0;
while (port > 0 && port_len < (countof(port_buff) - 1)) {
u8 digit = port % 10;
port /= 10;
port_buff_reverse[port_len] = '0' + digit;
++port_len;
}
for (u64 i = 0; i < port_len; ++i) {
u64 j = port_len - 1 - i;
port_buff[i] = port_buff_reverse[j];
}
if (port_len > 0) {
port_buff[port_len] = 0;
port_cstr = (char *)port_buff;
}
}
struct sock_address res = sock_address_from_ip_port_cstr(0, port_cstr);
return res;
}
struct string sock_string_from_address(struct arena *arena, struct sock_address address)
{
struct string res = ZI;
if (address.family == SOCK_ADDRESS_FAMILY_IPV6) {
/* TODO */
} else {
u8 ip[4];
for (u32 i = 0; i < 4; ++i) {
ip[i] = ntohs(address.ipnb[i]);
}
u16 port = ntohs(address.portnb);
res = string_format(arena, LIT("%F.%F.%F.%F:%F"), FMT_UINT(ip[0]), FMT_UINT(ip[1]), FMT_UINT(ip[2]), FMT_UINT(ip[3]), FMT_UINT(port));
}
return res;
}
INTERNAL struct win32_address win32_address_from_sock_address(struct sock_address addr)
{
struct win32_address res = ZI;
if (addr.family == SOCK_ADDRESS_FAMILY_IPV4) {
res.family = AF_INET;
res.size = sizeof(struct sockaddr_in);
res.sin.sin_port = addr.portnb;
res.sin.sin_family = res.family;
MEMCPY(&res.sin.sin_addr, addr.ipnb, 4);
} else {
res.family = AF_INET6;
res.sin6.sin6_port = addr.portnb;
res.sin6.sin6_family = res.family;
res.size = sizeof(struct sockaddr_in6);
MEMCPY(&res.sin6.sin6_addr.s6_addr, addr.ipnb, 16);
}
return res;
}
#if 0
/* If supplied address has ip INADDR_ANY (0), convert ip to localhost */
INTERNAL struct win32_address win32_address_convert_any_to_localhost(struct win32_address addr)
{
if (addr.family == AF_INET) {
u8 *bytes = (u8 *)&addr.sin.sin_addr;
b32 is_any = 1;
for (u64 i = 0; i < 4; ++i) {
if (bytes[i] != 0) {
is_any = 0;
break;
}
}
if (is_any) {
bytes[0] = 127;
bytes[3] = 1;
}
} else if (addr.family == AF_INET6) {
u8 *bytes = (u8 *)&addr.sin.sin_addr;
b32 is_any = 1;
for (u64 i = 0; i < 16; ++i) {
if (bytes[i] != 0) {
is_any = 0;
break;
}
}
if (is_any) {
bytes[15] = 1;
}
}
return addr;
}
#endif
INTERNAL struct sock_address sock_address_from_win32_address(struct win32_address ws_addr)
{
struct sock_address res = ZI;
if (ws_addr.family == AF_INET) {
res.family = SOCK_ADDRESS_FAMILY_IPV4;
res.portnb = ws_addr.sin.sin_port;
MEMCPY(res.ipnb, &ws_addr.sin.sin_addr, 4);
res.valid = 1;
} else if (ws_addr.family == AF_INET6) {
res.family = SOCK_ADDRESS_FAMILY_IPV6;
res.portnb = ws_addr.sin6.sin6_port;
MEMCPY(res.ipnb, &ws_addr.sin6.sin6_addr.s6_addr, 16);
res.valid = 1;
}
return res;
}
/* ========================== *
* Sock
* ========================== */
struct sock *sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
{
struct win32_sock *ws = 0;
{
struct snc_lock lock = snc_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_no_zero(G.win32_socks_arena, struct win32_sock);
}
snc_unlock(&lock);
}
MEMZERO_STRUCT(ws);
struct sock_address addr = sock_address_from_port(listen_port);
struct win32_address bind_address = win32_address_from_sock_address(addr);
ws->sock = socket(bind_address.family, SOCK_DGRAM, IPPROTO_UDP);
{
i32 sb = sndbuf_size;
i32 rb = rcvbuf_size;
setsockopt(ws->sock, SOL_SOCKET, SO_SNDBUF, (char *)&sb, sizeof(sb));
setsockopt(ws->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rb, sizeof(rb));
}
bind(ws->sock, &bind_address.sa, bind_address.size);
u32 imode = 1;
ioctlsocket(ws->sock, FIONBIO, (unsigned long *)&imode);
return (struct sock *)ws;
}
void sock_release(struct sock *sock)
{
struct win32_sock *ws = (struct win32_sock *)sock;
closesocket(ws->sock);
struct snc_lock lock = snc_lock_e(&G.win32_socks_mutex);
{
ws->next_free = G.first_free_win32_sock;
G.first_free_win32_sock = ws;
}
snc_unlock(&lock);
}
/* ========================== *
* Read
* ========================== */
struct sock_read_result sock_read(struct arena *arena, struct sock *sock)
{
struct win32_sock *ws = (struct win32_sock *)sock;
u64 read_buff_size = KIBI(64);
struct string read_buff = ZI;
read_buff.len = read_buff_size;
read_buff.text = arena_push_array_no_zero(arena, u8, read_buff_size);
struct sock_read_result res = ZI;
struct win32_address ws_addr = ZI;
ws_addr.size = sizeof(ws_addr.sas);
i32 size = recvfrom(ws->sock, (char *)read_buff.text, read_buff.len, 0, &ws_addr.sa, &ws_addr.size);
ws_addr.family = ws_addr.sin.sin_family;
res.address = sock_address_from_win32_address(ws_addr);
if (size >= 0) {
gstat_add(GSTAT_SOCK_BYTES_RECEIVED, size);
res.data.text = read_buff.text;
res.data.len = size;
res.valid = 1;
/* Pop arena back to end of msg */
arena_pop_to(arena, arena->pos - read_buff_size + size);
} else {
#if RTC
i32 err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT && err != WSAECONNRESET) {
ASSERT(0);
}
#endif
}
return res;
}
/* ========================== *
* Write
* ========================== */
void sock_write(struct sock *sock, struct sock_address address, struct string data)
{
struct win32_sock *ws = (struct win32_sock *)sock;
struct win32_address ws_addr = win32_address_from_sock_address(address);
i32 size = sendto(ws->sock, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
if (size > 0) {
gstat_add(GSTAT_SOCK_BYTES_SENT, size);
}
#if RTC
if (size != (i32)data.len) {
i32 err = WSAGetLastError();
(UNUSED)err;
ASSERT(0);
}
#endif
}

View File

@ -527,6 +527,44 @@ void sys_message_box(enum sys_message_box_kind kind, struct string message);
void sys_set_clipboard_text(struct string str); void sys_set_clipboard_text(struct string str);
struct string sys_get_clipboard_text(struct arena *arena); struct string sys_get_clipboard_text(struct arena *arena);
/* ========================== *
* Address
* ========================== */
enum sys_address_family {
SYS_ADDRESS_FAMILY_IPV4,
SYS_ADDRESS_FAMILY_IPV6
};
struct sys_address {
b32 valid;
enum sys_address_family family;
/* NOTE: ipnb & portnb are stored in network byte order */
u8 ipnb[16];
u16 portnb;
};
struct sys_address sys_address_from_string(struct string str);
struct sys_address sys_address_from_port(u16 port);
struct string sys_string_from_address(struct arena *arena, struct sys_address address);
b32 sys_address_eq(struct sys_address a, struct sys_address b);
/* ========================== *
* Sock
* ========================== */
struct sys_sock_read_result {
b32 valid; /* Since data.len = 0 can be valid */
struct sys_address address;
struct string data;
};
struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
void sys_sock_release(struct sys_sock *sock);
struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *sock);
void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct string data);
/* ========================== * /* ========================== *
* Util * Util
* ========================== */ * ========================== */

View File

@ -9,17 +9,22 @@
#include "util.h" #include "util.h"
#include "uni.h" #include "uni.h"
#include "resource.h" #include "resource.h"
#include "gstat.h"
#pragma warning(push, 0) #pragma warning(push, 0)
# define UNICODE # define UNICODE
# define WIN32_LEAN_AND_MEAN
# include <Windows.h> # include <Windows.h>
# include <WinSock2.h>
# include <TlHelp32.h>
# include <WS2tcpip.h>
# include <windowsx.h> # include <windowsx.h>
# include <ShlObj_core.h> # include <ShlObj_core.h>
# include <fileapi.h> # include <fileapi.h>
# include <dwmapi.h> # include <dwmapi.h>
# include <bcrypt.h> # include <bcrypt.h>
# include <avrt.h> # include <avrt.h>
# include <TlHelp32.h> # include <shellapi.h>
#pragma warning(pop) #pragma warning(pop)
#pragma comment(lib, "kernel32") #pragma comment(lib, "kernel32")
@ -31,6 +36,7 @@
#pragma comment(lib, "bcrypt") #pragma comment(lib, "bcrypt")
#pragma comment(lib, "synchronization") #pragma comment(lib, "synchronization")
#pragma comment(lib, "avrt") #pragma comment(lib, "avrt")
#pragma comment(lib, "ws2_32.lib")
#define SYS_WINDOW_EVENT_LISTENERS_MAX 512 #define SYS_WINDOW_EVENT_LISTENERS_MAX 512
#define WINDOW_CLASS_NAME L"power_play_window_class" #define WINDOW_CLASS_NAME L"power_play_window_class"
@ -115,6 +121,22 @@ struct win32_window {
struct win32_window *next_free; struct win32_window *next_free;
}; };
struct win32_address {
i32 size;
i32 family;
union {
struct sockaddr_storage sas;
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
};
struct win32_sock {
SOCKET sock;
struct win32_sock *next_free;
};
struct alignas(64) wait_list { struct alignas(64) wait_list {
u64 value; u64 value;
i16 first_waiter; i16 first_waiter;
@ -292,6 +314,12 @@ GLOBAL struct {
struct arena *windows_arena; struct arena *windows_arena;
struct win32_window *first_free_window; struct win32_window *first_free_window;
/* Sockets pool */
WSADATA wsa_data;
struct arena *socks_arena;
struct snc_mutex socks_mutex;
struct win32_sock *first_free_sock;
/* Exit funcs */ /* Exit funcs */
@ -3129,6 +3157,347 @@ u32 sys_num_logical_processors(void)
return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
} }
/* ========================== *
* Address
* ========================== */
INTERNAL struct sys_address sys_address_from_ip_port_cstr(char *ip_cstr, char *port_cstr)
{
struct sys_address res = ZI;
struct addrinfo hints = ZI;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *ai_res = 0;
i32 status = getaddrinfo(ip_cstr, port_cstr, &hints, &ai_res);
if (status == 0) {
while (ai_res) {
if (ai_res->ai_family == AF_INET) {
struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_res->ai_addr;
res.valid = 1;
res.family = SYS_ADDRESS_FAMILY_IPV4;
res.portnb = sockaddr->sin_port;
STATIC_ASSERT(sizeof(sockaddr->sin_addr) == 4);
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
break;
} else if (ai_res->ai_family == AF_INET6) {
/* TODO: Enable ipv6 */
#if 0
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
res.valid = 1;
res.family = SYS_ADDRESS_FAMILY_IPV6;
res.portnb = sockaddr->sin6_port;
STATIC_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
break;
#endif
}
ai_res = ai_res->ai_next;
}
freeaddrinfo(ai_res);
}
return res;
}
struct sys_address sys_address_from_string(struct string str)
{
/* Parse string into ip & port */
u8 ip_buff[1024];
u8 port_buff[countof(ip_buff)];
char *ip_cstr = 0;
char *port_cstr = 0;
{
u64 colon_count = 0;
for (u64 i = 0; i < str.len; ++i) {
u8 c = str.text[i];
if (c == ':') {
++colon_count;
}
}
u64 ip_len = 0;
u64 port_len = 0;
u64 parse_len = min_u64(min_u64(str.len, countof(ip_buff) - 1), countof(port_buff) - 1);
if (colon_count > 1 && str.text[0] == '[') {
/* Parse ipv6 with port */
b32 parse_addr = 1;
for (u64 i = 1; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ']') {
parse_addr = 0;
} else {
ip_buff[ip_len] = c;
++ip_len;
}
} else if (c != ':') {
port_buff[port_len] = c;
++port_len;
}
}
} else if (colon_count == 1) {
/* Parse address with port */
b32 parse_addr = 1;
for (u64 i = 0; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ':') {
parse_addr = 0;
} else {
ip_buff[ip_len] = c;
++ip_len;
}
} else {
port_buff[port_len] = c;
++port_len;
}
}
} else {
/* Copy address without port */
ip_len = min_u64(str.len, countof(ip_buff) - 1);
MEMCPY(ip_buff, str.text, ip_len);
}
if (ip_len > 0) {
ip_buff[ip_len] = 0;
ip_cstr = (char *)ip_buff;
}
if (port_len > 0) {
port_buff[port_len] = 0;
port_cstr = (char *)port_buff;
}
}
struct sys_address res = sys_address_from_ip_port_cstr(ip_cstr, port_cstr);
return res;
}
struct sys_address sys_address_from_port(u16 port)
{
u8 port_buff[128];
char *port_cstr = 0;
{
u8 port_buff_reverse[countof(port_buff)];
u64 port_len = 0;
while (port > 0 && port_len < (countof(port_buff) - 1)) {
u8 digit = port % 10;
port /= 10;
port_buff_reverse[port_len] = '0' + digit;
++port_len;
}
for (u64 i = 0; i < port_len; ++i) {
u64 j = port_len - 1 - i;
port_buff[i] = port_buff_reverse[j];
}
if (port_len > 0) {
port_buff[port_len] = 0;
port_cstr = (char *)port_buff;
}
}
struct sys_address res = sys_address_from_ip_port_cstr(0, port_cstr);
return res;
}
struct string sys_string_from_address(struct arena *arena, struct sys_address address)
{
struct string res = ZI;
if (address.family == SYS_ADDRESS_FAMILY_IPV6) {
/* TODO */
} else {
u8 ip[4];
for (u32 i = 0; i < 4; ++i) {
ip[i] = ntohs(address.ipnb[i]);
}
u16 port = ntohs(address.portnb);
res = string_format(arena, LIT("%F.%F.%F.%F:%F"), FMT_UINT(ip[0]), FMT_UINT(ip[1]), FMT_UINT(ip[2]), FMT_UINT(ip[3]), FMT_UINT(port));
}
return res;
}
b32 sys_address_eq(struct sys_address a, struct sys_address b)
{
return MEMEQ_STRUCT(&a, &b);
}
INTERNAL struct win32_address win32_address_from_sys_address(struct sys_address addr)
{
struct win32_address res = ZI;
if (addr.family == SYS_ADDRESS_FAMILY_IPV4) {
res.family = AF_INET;
res.size = sizeof(struct sockaddr_in);
res.sin.sin_port = addr.portnb;
res.sin.sin_family = res.family;
MEMCPY(&res.sin.sin_addr, addr.ipnb, 4);
} else {
res.family = AF_INET6;
res.sin6.sin6_port = addr.portnb;
res.sin6.sin6_family = res.family;
res.size = sizeof(struct sockaddr_in6);
MEMCPY(&res.sin6.sin6_addr.s6_addr, addr.ipnb, 16);
}
return res;
}
#if 0
/* If supplied address has ip INADDR_ANY (0), convert ip to localhost */
INTERNAL struct win32_address win32_address_convert_any_to_localhost(struct win32_address addr)
{
if (addr.family == AF_INET) {
u8 *bytes = (u8 *)&addr.sin.sin_addr;
b32 is_any = 1;
for (u64 i = 0; i < 4; ++i) {
if (bytes[i] != 0) {
is_any = 0;
break;
}
}
if (is_any) {
bytes[0] = 127;
bytes[3] = 1;
}
} else if (addr.family == AF_INET6) {
u8 *bytes = (u8 *)&addr.sin.sin_addr;
b32 is_any = 1;
for (u64 i = 0; i < 16; ++i) {
if (bytes[i] != 0) {
is_any = 0;
break;
}
}
if (is_any) {
bytes[15] = 1;
}
}
return addr;
}
#endif
INTERNAL struct sys_address sys_address_from_win32_address(struct win32_address ws_addr)
{
struct sys_address res = ZI;
if (ws_addr.family == AF_INET) {
res.family = SYS_ADDRESS_FAMILY_IPV4;
res.portnb = ws_addr.sin.sin_port;
MEMCPY(res.ipnb, &ws_addr.sin.sin_addr, 4);
res.valid = 1;
} else if (ws_addr.family == AF_INET6) {
res.family = SYS_ADDRESS_FAMILY_IPV6;
res.portnb = ws_addr.sin6.sin6_port;
MEMCPY(res.ipnb, &ws_addr.sin6.sin6_addr.s6_addr, 16);
res.valid = 1;
}
return res;
}
/* ========================== *
* Sock
* ========================== */
struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
{
struct win32_sock *ws = 0;
{
struct snc_lock lock = snc_lock_e(&G.socks_mutex);
if (G.first_free_sock) {
ws = G.first_free_sock;
G.first_free_sock = ws->next_free;
} else {
ws = arena_push_no_zero(G.socks_arena, struct win32_sock);
}
snc_unlock(&lock);
}
MEMZERO_STRUCT(ws);
struct sys_address addr = sys_address_from_port(listen_port);
struct win32_address bind_address = win32_address_from_sys_address(addr);
ws->sock = socket(bind_address.family, SOCK_DGRAM, IPPROTO_UDP);
{
i32 sb = sndbuf_size;
i32 rb = rcvbuf_size;
u32 imode = 1;
setsockopt(ws->sock, SOL_SOCKET, SO_SNDBUF, (char *)&sb, sizeof(sb));
setsockopt(ws->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rb, sizeof(rb));
ioctlsocket(ws->sock, FIONBIO, (unsigned long *)&imode);
}
bind(ws->sock, &bind_address.sa, bind_address.size);
return (struct sys_sock *)ws;
}
void sys_sock_release(struct sys_sock *sock)
{
struct win32_sock *ws = (struct win32_sock *)sock;
closesocket(ws->sock);
struct snc_lock lock = snc_lock_e(&G.socks_mutex);
{
ws->next_free = G.first_free_sock;
G.first_free_sock = ws;
}
snc_unlock(&lock);
}
struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *sock)
{
struct win32_sock *ws = (struct win32_sock *)sock;
u64 read_buff_size = KIBI(64);
struct string read_buff = ZI;
read_buff.len = read_buff_size;
read_buff.text = arena_push_array_no_zero(arena, u8, read_buff_size);
struct sys_sock_read_result res = ZI;
struct win32_address ws_addr = ZI;
ws_addr.size = sizeof(ws_addr.sas);
i32 size = recvfrom(ws->sock, (char *)read_buff.text, read_buff.len, 0, &ws_addr.sa, &ws_addr.size);
ws_addr.family = ws_addr.sin.sin_family;
res.address = sys_address_from_win32_address(ws_addr);
if (size >= 0) {
gstat_add(GSTAT_SOCK_BYTES_RECEIVED, size);
res.data.text = read_buff.text;
res.data.len = size;
res.valid = 1;
/* Pop arena back to end of msg */
arena_pop_to(arena, arena->pos - read_buff_size + size);
} else {
#if RTC
i32 err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT && err != WSAECONNRESET) {
ASSERT(0);
}
#endif
}
return res;
}
void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct string data)
{
struct win32_sock *ws = (struct win32_sock *)sock;
struct win32_address ws_addr = win32_address_from_sys_address(address);
i32 size = sendto(ws->sock, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
if (size > 0) {
gstat_add(GSTAT_SOCK_BYTES_SENT, size);
}
#if RTC
if (size != (i32)data.len) {
i32 err = WSAGetLastError();
(UNUSED)err;
ASSERT(0);
}
#endif
}
/* ========================== * /* ========================== *
* Entry point * Entry point
* ========================== */ * ========================== */
@ -3273,15 +3642,19 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
/* Query system info */ /* Query system info */
GetSystemInfo(&G.info); GetSystemInfo(&G.info);
/* Set up threads */ /* Init threads pool */
G.threads_arena = arena_alloc(GIBI(64)); G.threads_arena = arena_alloc(GIBI(64));
/* Set up watches */ /* Init watches pool */
G.watches_arena = arena_alloc(GIBI(64)); G.watches_arena = arena_alloc(GIBI(64));
/* Set up windows */ /* Init windows pool */
G.windows_arena = arena_alloc(GIBI(64)); G.windows_arena = arena_alloc(GIBI(64));
/* Init winsock */
WSAStartup(MAKEWORD(2, 2), &G.wsa_data);
G.socks_arena = arena_alloc(GIBI(64));
/* Initialize vk table */ /* Initialize vk table */
win32_init_vk_btn_table(); win32_init_vk_btn_table();

View File

@ -16,7 +16,6 @@
#include "collider.h" #include "collider.h"
#include "rand.h" #include "rand.h"
#include "log.h" #include "log.h"
#include "sock.h"
#include "host.h" #include "host.h"
#include "bitbuff.h" #include "bitbuff.h"
#include "gstat.h" #include "gstat.h"
@ -2163,7 +2162,7 @@ INTERNAL SYS_JOB_DEF(local_sim_job, _)
struct host *host; struct host *host;
if (G.connect_address_str.len > 0) { if (G.connect_address_str.len > 0) {
host = host_alloc(0); host = host_alloc(0);
struct sock_address addr = sock_address_from_string(G.connect_address_str); struct sys_address addr = sys_address_from_string(G.connect_address_str);
host_queue_connect_to_address(host, addr); host_queue_connect_to_address(host, addr);
} else { } else {
host = host_alloc(12345); host = host_alloc(12345);