user game network communication beginning to work

This commit is contained in:
jacob 2025-02-06 20:33:06 -06:00
parent 84e64b5cce
commit 808edf6e57
8 changed files with 412 additions and 651 deletions

View File

@ -164,6 +164,12 @@ void bw_write_v2(struct byte_writer *bw, struct v2 v)
bw_write_f32(bw, v.y); bw_write_f32(bw, v.y);
} }
void bw_write_string(struct byte_writer *bw, struct string str)
{
bw_write_var_uint(bw, str.len);
bw_write_buffer(bw, str);
}
/* ========================== * /* ========================== *
* Reader * Reader
* ========================== */ * ========================== */
@ -313,3 +319,16 @@ struct v2 br_read_v2(struct byte_reader *br)
res.y = br_read_f32(br); res.y = br_read_f32(br);
return res; return res;
} }
struct string br_read_string(struct arena *arena, struct byte_reader *br)
{
struct string res = ZI;
u64 len = br_read_var_uint(br);
u8 *text = br_seek(br, len);
if (text != NULL) {
res.len = len;
res.text = arena_push_array(arena, u8, len);
MEMCPY(res.text, text, len);
}
return res;
}

View File

@ -39,6 +39,7 @@ void bw_write_var_sint(struct byte_writer *bw, i64 v);
void bw_write_f32(struct byte_writer *bw, f32 v); void bw_write_f32(struct byte_writer *bw, f32 v);
void bw_write_f64(struct byte_writer *bw, f64 v); void bw_write_f64(struct byte_writer *bw, f64 v);
void bw_write_v2(struct byte_writer *bw, struct v2 v); void bw_write_v2(struct byte_writer *bw, struct v2 v);
void bw_write_string(struct byte_writer *bw, struct string str);
/* Returns a string containing written bytes only */ /* Returns a string containing written bytes only */
INLINE struct string bw_get_written(struct byte_writer *bw) INLINE struct string bw_get_written(struct byte_writer *bw)
@ -80,6 +81,7 @@ i64 br_read_var_sint(struct byte_reader *br);
f32 br_read_f32(struct byte_reader *br); f32 br_read_f32(struct byte_reader *br);
f64 br_read_f64(struct byte_reader *br); f64 br_read_f64(struct byte_reader *br);
struct v2 br_read_v2(struct byte_reader *br); struct v2 br_read_v2(struct byte_reader *br);
struct string br_read_string(struct arena *arena, struct byte_reader *br);
INLINE u64 br_bytes_left(const struct byte_reader *br) INLINE u64 br_bytes_left(const struct byte_reader *br)
{ {

View File

@ -72,8 +72,8 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
G.client_store = client_store_alloc(); G.client_store = client_store_alloc();
/* Intialize host */ /* Intialize host */
struct sock_address bind_address = sock_address_from_any_local_interface_with_port(12345); //struct sock_address bind_address = sock_address_from_port(12345);
G.host = host_alloc(bind_address); G.host = host_alloc(12345);
/* Initialize empty world */ /* Initialize empty world */
reset_world(); reset_world();
@ -1460,10 +1460,12 @@ struct string game_string_from_events(struct arena *arena, struct game_event_lis
for (struct game_event *event = events.first; event; event = event->next) { for (struct game_event *event = events.first; event; event = event->next) {
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64)); struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
u64 start = bw_pos(&bw); u64 start = bw_pos(&bw);
bw_write_i8(&bw, event->kind);
switch (event->kind) { switch (event->kind) {
case GAME_EVENT_KIND_SNAPSHOT_FULL: case GAME_EVENT_KIND_SNAPSHOT_FULL:
{ {
bw_write_string(&bw, event->snapshot_data);
} break; } break;
default: break; default: break;
@ -1505,6 +1507,7 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
switch (game_event->kind) { switch (game_event->kind) {
case GAME_EVENT_KIND_SNAPSHOT_FULL: case GAME_EVENT_KIND_SNAPSHOT_FULL:
{ {
game_event->snapshot_data = br_read_string(arena, &br);
} break; } break;
default: break; default: break;
@ -1533,17 +1536,54 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
struct string game_string_from_tick(struct arena *arena, struct world *tick) struct string game_string_from_tick(struct arena *arena, struct world *tick)
{ {
(UNUSED)arena; struct byte_writer bw = bw_from_arena(arena);
(UNUSED)tick;
struct string res = ZI; bw_write_var_uint(&bw, tick->continuity_gen);
return res; bw_write_var_uint(&bw, tick->tick_id);
bw_write_var_sint(&bw, tick->publishtime_ns);
bw_write_f64(&bw, tick->timescale);
bw_write_var_sint(&bw, tick->dt_ns);
bw_write_var_sint(&bw, tick->time_ns);
u64 num_entities = tick->entity_store->reserved;
bw_write_var_uint(&bw, num_entities);
struct string entities_src = ZI;
entities_src.text = (u8 *)tick->entity_store->entities;
entities_src.len = sizeof(struct entity) * num_entities;
bw_write_buffer(&bw, entities_src);
return bw_get_written(&bw);
} }
void game_tick_from_string(struct string str, struct world *tick_out) void game_tick_from_string(struct string str, struct world *tick_out)
{ {
(UNUSED)str; struct byte_reader br = br_from_buffer(str);
(UNUSED)tick_out;
tick_out->continuity_gen = br_read_var_uint(&br);
tick_out->tick_id = br_read_var_uint(&br);
tick_out->publishtime_ns = br_read_var_sint(&br);
tick_out->timescale = br_read_f64(&br);
tick_out->dt_ns = br_read_var_sint(&br);
tick_out->time_ns = br_read_var_sint(&br);
u64 num_entities = br_read_var_uint(&br);
arena_push_array(&tick_out->entity_store->arena, struct entity, num_entities - tick_out->entity_store->reserved);
tick_out->entity_store->reserved = num_entities;
struct entity *entities_src = br_seek(&br, num_entities * sizeof(struct entity));
if (entities_src) {
for (u64 i = 0; i < num_entities; ++i) {
struct entity *src = &entities_src[i];
struct entity *dst = &tick_out->entity_store->entities[i];
*dst = *src;
DEBUGBREAKABLE;
}
}
DEBUGBREAKABLE;
} }
/* ========================== * /* ========================== *

View File

@ -63,6 +63,7 @@ struct host_channel {
struct host_msg_assembler *least_recent_msg_assembler; struct host_msg_assembler *least_recent_msg_assembler;
struct host_msg_assembler *most_recent_msg_assembler; struct host_msg_assembler *most_recent_msg_assembler;
u64 last_sent_msg_id;
u64 their_acked_seq; u64 their_acked_seq;
u64 our_acked_seq; u64 our_acked_seq;
}; };
@ -151,7 +152,7 @@ struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr)
* Host * Host
* ========================== */ * ========================== */
struct host *host_alloc(struct sock_address bind_address) struct host *host_alloc(u16 listen_port)
{ {
struct arena arena = arena_alloc(GIGABYTE(64)); struct arena arena = arena_alloc(GIGABYTE(64));
struct host *host = arena_push_zero(&arena, struct host); struct host *host = arena_push_zero(&arena, struct host);
@ -163,10 +164,13 @@ struct host *host_alloc(struct sock_address bind_address)
host->channels = arena_dry_push(&host->channel_arena, struct host_channel); host->channels = arena_dry_push(&host->channel_arena, struct host_channel);
host->channel_lookup_buckets = arena_push_array_zero(&host->arena, struct host_channel_lookup_bucket, NUM_CHANNEL_LOOKUP_BUCKETS); host->num_channel_lookup_buckets = NUM_CHANNEL_LOOKUP_BUCKETS;
host->msg_assembler_lookup_buckets = arena_push_array_zero(&host->arena, struct host_msg_assembler_lookup_bucket, NUM_MSG_ASSEMBLER_LOOKUP_BUCKETS); host->channel_lookup_buckets = arena_push_array_zero(&host->arena, struct host_channel_lookup_bucket, host->num_channel_lookup_buckets);
host->sock = sock_alloc(bind_address, SOCK_FLAG_NON_BLOCKING); host->num_msg_assembler_lookup_buckets = NUM_MSG_ASSEMBLER_LOOKUP_BUCKETS;
host->msg_assembler_lookup_buckets = arena_push_array_zero(&host->arena, struct host_msg_assembler_lookup_bucket, host->num_msg_assembler_lookup_buckets);
host->sock = sock_alloc(listen_port, SOCK_FLAG_NON_BLOCKING);
return host; return host;
} }
@ -219,7 +223,7 @@ INTERNAL struct host_channel_list host_channels_from_id(struct arena *arena, str
if (host_channel_id_eq(channel_id, HOST_CHANNEL_ID_ALL)) { if (host_channel_id_eq(channel_id, HOST_CHANNEL_ID_ALL)) {
for (u64 i = 0; i < host->num_channels_reserved; ++i) { for (u64 i = 0; i < host->num_channels_reserved; ++i) {
struct host_channel *channel = &host->channels[i]; struct host_channel *channel = &host->channels[i];
if (channel->valid && channel->connected) { if (channel->valid) {
struct host_channel_node *n = arena_push_zero(arena, struct host_channel_node); struct host_channel_node *n = arena_push_zero(arena, struct host_channel_node);
n->channel = channel; n->channel = channel;
if (res.last) { if (res.last) {
@ -258,6 +262,7 @@ INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sock_
++host->num_channels_reserved; ++host->num_channels_reserved;
} }
MEMZERO_STRUCT(channel); MEMZERO_STRUCT(channel);
channel->valid = true;
channel->id = id; channel->id = id;
channel->host = host; channel->host = host;
channel->address = address; channel->address = address;
@ -378,6 +383,18 @@ INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel
} }
channel->most_recent_msg_assembler = ma; channel->most_recent_msg_assembler = ma;
/* Insert into lookup table */
u64 hash = hash_from_channel_msg(channel->id, msg_id);
ma->hash = hash;
struct host_msg_assembler_lookup_bucket *bucket = &host->msg_assembler_lookup_buckets[hash % host->num_msg_assembler_lookup_buckets];
if (bucket->last) {
bucket->last->next_hash = ma;
ma->prev_hash = bucket->last;
} else {
bucket->first = ma;
}
bucket->last = ma;
return ma; return ma;
} }
@ -386,7 +403,7 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
struct host *host = ma->host; struct host *host = ma->host;
struct host_channel *channel = ma->channel; struct host_channel *channel = ma->channel;
/* FIXME: Data should be in a buddy allocator or something */ /* FIXME: Data should be in buddy allocator or something */
arena_release(&ma->testarena); arena_release(&ma->testarena);
/* Release from channel list */ /* Release from channel list */
@ -405,6 +422,24 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
} }
} }
/* Release from lookup table */
struct host_msg_assembler_lookup_bucket *bucket = &host->msg_assembler_lookup_buckets[ma->hash % host->num_msg_assembler_lookup_buckets];
{
struct host_msg_assembler *prev = ma->prev_hash;
struct host_msg_assembler *next = ma->next_hash;
if (prev) {
prev->next_hash = next;
} else {
bucket->first = next;
}
if (next) {
next->prev_hash = prev;
} else {
bucket->last = prev;
}
}
ma->next_free = host->first_free_msg_assembler; ma->next_free = host->first_free_msg_assembler;
host->first_free_msg_assembler = ma; host->first_free_msg_assembler = ma;
} }
@ -484,21 +519,17 @@ void host_queue_connect_to_address(struct host *host, struct sock_address connec
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)
{ {
(UNUSED)host;
(UNUSED)channel_id;
struct host_cmd *cmd = host_cmd_alloc_and_append(host); struct host_cmd *cmd = host_cmd_alloc_and_append(host);
cmd->kind = HOST_CMD_KIND_DISCONNECT; cmd->kind = HOST_CMD_KIND_DISCONNECT;
cmd->channel_id = channel_id;
} }
void host_queue_write(struct host *host, struct host_channel_id channel_id, struct string msg) void host_queue_write(struct host *host, struct host_channel_id channel_id, struct string msg)
{ {
(UNUSED)host;
(UNUSED)channel_id;
(UNUSED)msg;
struct host_cmd *cmd = host_cmd_alloc_and_append(host); struct host_cmd *cmd = host_cmd_alloc_and_append(host);
cmd->kind = HOST_CMD_KIND_WRITE; cmd->kind = HOST_CMD_KIND_WRITE;
cmd->channel_id = channel_id;
cmd->write_msg = string_copy(&host->cmd_arena, msg);
} }
/* ========================== * /* ========================== *
@ -596,42 +627,44 @@ void host_update(struct host *host)
case HOST_PACKET_KIND_MSG_CHUNK: case HOST_PACKET_KIND_MSG_CHUNK:
{ {
/* Packet is chunk <chunk_id> out of <chunk_count> belonging to message <msg_id> */ if (channel->valid) {
u64 msg_id = br_read_var_uint(&br); /* Packet is chunk <chunk_id> out of <chunk_count> belonging to message <msg_id> */
u64 chunk_id = br_read_var_uint(&br); u64 msg_id = br_read_var_uint(&br);
u64 chunk_count = br_read_var_uint(&br); u64 chunk_id = br_read_var_uint(&br);
u64 chunk_count = br_read_var_uint(&br);
b32 is_last_chunk = (chunk_id + 1) == chunk_count; b32 is_last_chunk = (chunk_id + 1) == chunk_count;
u64 data_len = is_last_chunk ? (br_read_u8(&br) + 1) : PACKET_CHUNK_MAX_LEN; u64 data_len = is_last_chunk ? (br_read_u8(&br) + 1) : PACKET_CHUNK_MAX_LEN;
struct host_msg_assembler *ma = host_get_msg_assembler(host, channel->id, msg_id); struct host_msg_assembler *ma = host_get_msg_assembler(host, channel->id, msg_id);
if (!ma) { if (!ma) {
ma = host_msg_assembler_alloc(channel, msg_id, chunk_count, now_ns); ma = host_msg_assembler_alloc(channel, msg_id, chunk_count, now_ns);
} }
if (chunk_count == ma->num_chunks_total && chunk_id < chunk_count) { if (chunk_count == ma->num_chunks_total && chunk_id < chunk_count) {
if (!host_msg_assembler_is_chunk_filled(ma, chunk_id)) { if (!host_msg_assembler_is_chunk_filled(ma, chunk_id)) {
u8 *src = br_seek(&br, data_len); u8 *src = br_seek(&br, data_len);
if (src) { if (src) {
u8 *dst = &ma->data[chunk_id * PACKET_CHUNK_MAX_LEN]; u8 *dst = &ma->data[chunk_id * PACKET_CHUNK_MAX_LEN];
MEMCPY(dst, src, data_len); MEMCPY(dst, src, data_len);
if (is_last_chunk) { if (is_last_chunk) {
ma->last_chunk_len = data_len; ma->last_chunk_len = data_len;
} }
host_msg_assembler_set_chunk_received(ma, chunk_id); host_msg_assembler_set_chunk_received(ma, chunk_id);
++ma->num_chunks_received; ++ma->num_chunks_received;
ma->touched_ns = now_ns; ma->touched_ns = now_ns;
if (ma->num_chunks_received == chunk_count) { if (ma->num_chunks_received == chunk_count) {
/* All chunks filled, message has finished assembling */ /* All chunks filled, message has finished assembling */
/* TODO: Message ordering */ /* TODO: Message ordering */
struct host_queued_event *queued_event = host_queued_event_alloc_and_append(host); struct host_queued_event *queued_event = host_queued_event_alloc_and_append(host);
struct string data = ZI; struct string data = ZI;
data.len = ((chunk_count - 1) * PACKET_CHUNK_MAX_LEN) + ma->last_chunk_len; data.len = ((chunk_count - 1) * PACKET_CHUNK_MAX_LEN) + ma->last_chunk_len;
data.text = arena_push_array(&host->queued_event_arena, u8, data.len); data.text = arena_push_array(&host->queued_event_arena, u8, data.len);
MEMCPY(data.text, ma->data, data.len); MEMCPY(data.text, ma->data, data.len);
queued_event->event.kind = HOST_EVENT_KIND_MSG; queued_event->event.kind = HOST_EVENT_KIND_MSG;
queued_event->event.msg = data; queued_event->event.msg = data;
queued_event->event.channel_id = channel->id; queued_event->event.channel_id = channel->id;
}
} }
} }
} }
@ -696,6 +729,7 @@ void host_update(struct host *host)
u8 packet_flags = 0; u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false); struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data)); struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_TRY_CONNECT); bw_write_i8(&bw, HOST_PACKET_KIND_TRY_CONNECT);
bw_write_u8(&bw, packet_flags); bw_write_u8(&bw, packet_flags);
bw_write_var_uint(&bw, channel->our_acked_seq); bw_write_var_uint(&bw, channel->our_acked_seq);
@ -707,6 +741,7 @@ void host_update(struct host *host)
u8 packet_flags = 0; u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false); struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data)); struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS); bw_write_i8(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS);
bw_write_u8(&bw, packet_flags); bw_write_u8(&bw, packet_flags);
bw_write_var_uint(&bw, channel->our_acked_seq); bw_write_var_uint(&bw, channel->our_acked_seq);
@ -718,6 +753,7 @@ void host_update(struct host *host)
u8 packet_flags = 0; u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false); struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data)); struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_DISCONNECT); bw_write_i8(&bw, HOST_PACKET_KIND_DISCONNECT);
bw_write_u8(&bw, packet_flags); bw_write_u8(&bw, packet_flags);
bw_write_var_uint(&bw, channel->our_acked_seq); bw_write_var_uint(&bw, channel->our_acked_seq);
@ -736,6 +772,7 @@ void host_update(struct host *host)
} }
chunk_count += 1; chunk_count += 1;
u64 msg_id = ++channel->last_sent_msg_id;
for (u64 i = 0; i < chunk_count; ++i) { for (u64 i = 0; i < chunk_count; ++i) {
u64 data_len = PACKET_CHUNK_MAX_LEN; u64 data_len = PACKET_CHUNK_MAX_LEN;
b32 is_last_chunk = i + 1 == chunk_count; b32 is_last_chunk = i + 1 == chunk_count;
@ -745,12 +782,16 @@ void host_update(struct host *host)
u8 *data = msg.text + (i * PACKET_CHUNK_MAX_LEN); u8 *data = msg.text + (i * PACKET_CHUNK_MAX_LEN);
struct host_packet *host_packet = host_channel_packet_alloc(channel, is_reliable); struct host_packet *host_packet = host_channel_packet_alloc(channel, is_reliable);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data)); struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_MSG_CHUNK); bw_write_i8(&bw, HOST_PACKET_KIND_MSG_CHUNK);
bw_write_u8(&bw, packet_flags); bw_write_u8(&bw, packet_flags);
bw_write_var_uint(&bw, channel->our_acked_seq); bw_write_var_uint(&bw, channel->our_acked_seq);
if (is_reliable) { if (is_reliable) {
bw_write_var_uint(&bw, host_packet->seq); bw_write_var_uint(&bw, host_packet->seq);
} }
bw_write_var_uint(&bw, msg_id);
bw_write_var_uint(&bw, i);
bw_write_var_uint(&bw, chunk_count);
if (is_last_chunk) { if (is_last_chunk) {
/* FIXME: Ensure data_len can never be 0 */ /* FIXME: Ensure data_len can never be 0 */
bw_write_u8(&bw, data_len - 1); bw_write_u8(&bw, data_len - 1);
@ -769,21 +810,23 @@ void host_update(struct host *host)
/* TODO: Aggregate small packets */ /* TODO: Aggregate small packets */
for (u64 i = 0; i < host->num_channels_reserved; ++i) { for (u64 i = 0; i < host->num_channels_reserved; ++i) {
struct host_channel *channel = &host->channels[i]; struct host_channel *channel = &host->channels[i];
struct sock_address address = channel->address; if (channel->valid) {
/* Send unreliable packets to channel */ struct sock_address address = channel->address;
for (struct host_packet *host_packet = channel->first_unreliable_packet; host_packet; host_packet = host_packet->next) { /* Send unreliable packets to channel */
sock_write(sock, address, STRING(host_packet->data_len, host_packet->data)); for (struct host_packet *host_packet = channel->first_unreliable_packet; host_packet; host_packet = host_packet->next) {
} sock_write(sock, address, STRING(host_packet->data_len, host_packet->data));
/* Send un-acked reliable packets to channel */ }
for (struct host_packet *host_packet = channel->first_reliable_packet; host_packet; host_packet = host_packet->next) { /* Send un-acked reliable packets to channel */
sock_write(sock, address, STRING(host_packet->data_len, host_packet->data)); for (struct host_packet *host_packet = channel->first_reliable_packet; host_packet; host_packet = host_packet->next) {
} sock_write(sock, address, STRING(host_packet->data_len, host_packet->data));
/* Release unreliable packets */ }
if (channel->first_unreliable_packet) { /* Release unreliable packets */
host->first_free_packet = channel->first_unreliable_packet; if (channel->first_unreliable_packet) {
channel->last_unreliable_packet->next = host->first_free_packet; host->first_free_packet = channel->first_unreliable_packet;
channel->first_unreliable_packet = NULL; channel->last_unreliable_packet->next = host->first_free_packet;
channel->last_unreliable_packet = NULL; channel->first_unreliable_packet = NULL;
channel->last_unreliable_packet = NULL;
}
} }
} }

View File

@ -87,7 +87,7 @@ struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr);
* Host * Host
* ========================== */ * ========================== */
struct host *host_alloc(struct sock_address bind_address); struct host *host_alloc(u16 listen_port);
void host_release(struct host *host); void host_release(struct host *host);

View File

@ -13,22 +13,20 @@ enum sock_flag {
}; };
struct sock { struct sock {
i32 _; u64 handle;
}; };
enum sock_address_kind { enum sock_address_family {
SOCK_ADDRESS_KIND_NONE, SOCK_ADDRESS_FAMILY_IPV4,
SOCK_ADDRESS_KIND_UNBINDABLE, SOCK_ADDRESS_FAMILY_IPV6
/* Network addresses */
SOCK_ADDRESS_KIND_ANY_LOCAL_INTERFACE,
SOCK_ADDRESS_KIND_RAW
}; };
struct sock_address { struct sock_address {
enum sock_address_kind kind; b32 valid;
u8 ip[16]; enum sock_address_family family;
u16 port; /* NOTE: ipnb & portnb are stored in network byte order */
u8 ipnb[16];
u16 portnb;
}; };
struct sock_read_result { struct sock_read_result {
@ -41,11 +39,9 @@ struct sock_startup_receipt { i32 _; };
struct sock_startup_receipt sock_startup(void); struct sock_startup_receipt sock_startup(void);
struct sock_address sock_address_from_string(struct string str); struct sock_address sock_address_from_string(struct string str);
struct sock_address sock_address_from_any_local_interface_with_port(u16 port); struct sock_address sock_address_from_port(u16 port);
struct sock_address sock_address_from_any_local_interface_with_dynamic_port(void);
struct sock_address sock_address_unbindable(void);
struct sock sock_alloc(struct sock_address bind_address, u32 sock_flags); struct sock sock_alloc(u16 listen_port, u32 flags);
void sock_release(struct sock *sock); void sock_release(struct sock *sock);
struct sock_read_result sock_read(struct sock *sock, struct string read_buff); struct sock_read_result sock_read(struct sock *sock, struct string read_buff);
void sock_write(struct sock *sock, struct sock_address address, struct string data); void sock_write(struct sock *sock, struct sock_address address, struct string data);

View File

@ -1,11 +1,9 @@
#if 1
#include "sock.h" #include "sock.h"
#include "sys.h" #include "sys.h"
#include "log.h" #include "log.h"
#include "arena.h" #include "arena.h"
#include "scratch.h" #include "scratch.h"
#include "string.h"
#include <WinSock2.h> #include <WinSock2.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
@ -14,6 +12,17 @@
//#define MAX_IP_STR_LEN 46 //#define MAX_IP_STR_LEN 46
struct winsock_address {
i32 size;
i32 family;
union {
struct sockaddr_storage sas;
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
};
struct sock_startup_receipt sock_startup(void) struct sock_startup_receipt sock_startup(void)
{ {
WSADATA wsa_data; WSADATA wsa_data;
@ -22,590 +31,241 @@ struct sock_startup_receipt sock_startup(void)
return (struct sock_startup_receipt) { 0 }; return (struct sock_startup_receipt) { 0 };
} }
struct sock_address sock_address_from_string(struct string str) INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char *port_cstr)
{ {
(UNUSED)str;
struct sock_address res = ZI; struct sock_address res = ZI;
#if 0
struct addrinfo *servinfo;
struct addrinfo hints = ZI; struct addrinfo hints = ZI;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; hints.ai_flags = AI_PASSIVE;
status = getaddrinfo(NULL, "3490", &hints, &servinfo) struct addrinfo *ai_res = NULL;
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.family = SOCK_ADDRESS_FAMILY_IPV4;
res.portnb = sockaddr->sin_port;
CT_ASSERT(sizeof(sockaddr->sin_addr) == 4);
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
break;
} else if (ai_res->ai_family == AF_INET6) {
/* FIXME: Why must this be disabled to work? */
#if 0
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
res.family = SOCK_ADDRESS_FAMILY_IPV6;
res.portnb = sockaddr->sin6_port;
CT_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
#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 */
char *address_cstr = NULL;
char *port_cstr = NULL;
{
u64 colon_count = 0;
for (u64 i = 0; i < str.len; ++i) {
u8 c = str.text[i];
if (c == ':') {
++colon_count;
}
}
u8 address_buff[1024];
u8 port_buff[ARRAY_COUNT(address_buff)];
u64 address_len = 0;
u64 port_len = 0;
u64 parse_len = min_u64(min_u64(str.len, ARRAY_COUNT(address_buff) - 1), ARRAY_COUNT(port_buff) - 1);
if (colon_count > 1 && str.text[0] == '[') {
/* Parse ipv6 with port */
b32 parse_addr = true;
for (u64 i = 1; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ']') {
parse_addr = false;
} else {
address_buff[address_len] = c;
++address_len;
}
} else if (c != ':') {
port_buff[port_len] = c;
++port_len;
}
}
} else if (colon_count == 1) {
/* Parse address with port */
b32 parse_addr = true;
for (u64 i = 0; i < parse_len; ++i) {
u8 c = str.text[i];
if (parse_addr) {
if (c == ':') {
parse_addr = false;
} else {
address_buff[address_len] = c;
++address_len;
}
} else {
port_buff[port_len] = c;
++port_len;
}
}
} else {
/* Copy address without port */
address_len = min_u64(str.len, ARRAY_COUNT(address_buff) - 1);
MEMCPY(address_buff, str.text, address_len);
}
if (address_len > 0) {
address_buff[address_len] = 0;
address_cstr = (char *)address_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(address_cstr, port_cstr);
return res;
}
struct sock_address sock_address_from_port(u16 port)
{
char *port_cstr = NULL;
{
u8 port_buff[128];
u8 port_buff_reverse[ARRAY_COUNT(port_buff)];
u64 port_len = 0;
while (port > 0 && port_len < (ARRAY_COUNT(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(NULL, port_cstr);
return res;
}
INTERNAL struct winsock_address winsock_address_from_sock_address(struct sock_address addr)
{
struct winsock_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;
}
INTERNAL struct sock_address sock_address_from_winsock_address(struct winsock_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 = true;
} 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 = true;
}
return res;
}
struct sock sock_alloc(u16 listen_port, u32 flags)
{
struct sock_address addr = sock_address_from_port(listen_port);
struct winsock_address ws_addr = winsock_address_from_sock_address(addr);
SOCKET ws = socket(ws_addr.family, SOCK_DGRAM, IPPROTO_UDP);
if (flags & SOCK_FLAG_NON_BLOCKING) {
u_long mode = 1;
ioctlsocket(ws, FIONBIO, &mode);
}
//setsockopt(ws, SOL_SOCKET, SO_REUSEADDR
#if 0
if (listen_port != 0) {
bind(ws, &ws_addr.sa, ws_addr.size);
}
#else
bind(ws, &ws_addr.sa, ws_addr.size);
#endif #endif
struct sock res = ZI;
res.handle = *(u64 *)&ws;
return res; return res;
} }
struct sock_address sock_address_from_any_local_interface_with_port(u16 port)
{
(UNUSED)port;
struct sock_address res = ZI;
return res;
}
struct sock_address sock_address_from_any_local_interface_with_dynamic_port(void)
{
struct sock_address res = ZI;
return res;
}
struct sock_address sock_address_unbindable(void)
{
struct sock_address res = ZI;
return res;
}
struct sock sock_alloc(struct sock_address bind_address, u32 sock_flags)
{
(UNUSED)bind_address;
(UNUSED)sock_flags;
struct sock sock = ZI;
return sock;
}
void sock_release(struct sock *sock) void sock_release(struct sock *sock)
{ {
(UNUSED)sock; SOCKET ws = *(SOCKET *)&sock->handle;
closesocket(ws);
} }
struct sock_read_result sock_read(struct sock *sock, struct string read_buff) struct sock_read_result sock_read(struct sock *sock, struct string read_buff)
{ {
(UNUSED)sock; SOCKET ws = *(SOCKET *)&sock->handle;
(UNUSED)read_buff;
struct sock_read_result res = ZI; struct sock_read_result res = ZI;
struct winsock_address ws_addr = ZI;
ws_addr.size = sizeof(ws_addr.sas);
i32 size = recvfrom(ws, (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_winsock_address(ws_addr);
if (size > 0) {
res.data.text = read_buff.text;
res.data.len = size;
res.valid = true;
} else {
#if RTC
i32 err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAECONNRESET) {
ASSERT(false);
}
#endif
}
return res; return res;
} }
void sock_write(struct sock *sock, struct sock_address address, struct string data) void sock_write(struct sock *sock, struct sock_address address, struct string data)
{ {
(UNUSED)sock; SOCKET ws = *(SOCKET *)&sock->handle;
(UNUSED)address; struct winsock_address ws_addr = winsock_address_from_sock_address(address);
(UNUSED)data; sendto(ws, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
} }
#else
#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();
}
#endif

View File

@ -158,8 +158,9 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
G.sys_events_arena = arena_alloc(GIGABYTE(64)); G.sys_events_arena = arena_alloc(GIGABYTE(64));
world_alloc(&G.world); world_alloc(&G.world);
struct sock_address bind_addr = sock_address_from_any_local_interface_with_dynamic_port(); //struct sock_address bind_addr = sock_address_from_any_local_interface_with_dynamic_port();
G.host = host_alloc(bind_addr); //G.host = host_alloc(0);
G.host = host_alloc(5920);
G.world_to_ui_xf = XFORM_IDENT; G.world_to_ui_xf = XFORM_IDENT;
G.world_cmd_buffer = renderer_cmd_buffer_alloc(); G.world_cmd_buffer = renderer_cmd_buffer_alloc();
@ -617,7 +618,7 @@ INTERNAL void user_update(void)
{ {
static f64 last_try_connect = 0; static f64 last_try_connect = 0;
f64 now = SECONDS_FROM_NS(sys_time_ns()); f64 now = SECONDS_FROM_NS(sys_time_ns());
if (last_try_connect == 0 || (now - last_try_connect) > 5) { if (last_try_connect == 0 || (now - last_try_connect) > 0.1) {
struct sock_address connect_addr = sock_address_from_string(LIT("127.0.0.1:12345")); struct sock_address connect_addr = sock_address_from_string(LIT("127.0.0.1:12345"));
host_queue_connect_to_address(G.host, connect_addr); host_queue_connect_to_address(G.host, connect_addr);
last_try_connect = now; last_try_connect = now;