host progress
This commit is contained in:
parent
808edf6e57
commit
d13a7c70e7
39
src/game.c
39
src/game.c
@ -1350,6 +1350,7 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds)
|
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
|
|
||||||
for (struct game_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
|
for (struct game_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
|
||||||
@ -1387,33 +1388,46 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
|
|||||||
|
|
||||||
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out)
|
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
for (u64 i = 0; i < host_events.count; ++i) {
|
for (u64 i = 0; i < host_events.count; ++i) {
|
||||||
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
|
||||||
struct host_event host_event = host_events.events[i];
|
struct host_event host_event = host_events.events[i];
|
||||||
enum host_event_kind host_event_kind = host_event.kind;
|
enum host_event_kind host_event_kind = host_event.kind;
|
||||||
cmd->channel_id = host_event.channel_id;
|
|
||||||
switch (host_event_kind) {
|
switch (host_event_kind) {
|
||||||
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
||||||
{
|
{
|
||||||
|
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
||||||
cmd->kind = GAME_CMD_KIND_CLIENT_CONNECT;
|
cmd->kind = GAME_CMD_KIND_CLIENT_CONNECT;
|
||||||
|
cmd->channel_id = host_event.channel_id;
|
||||||
|
if (cmds_out->last) {
|
||||||
|
cmds_out->last->next = cmd;
|
||||||
|
} else {
|
||||||
|
cmds_out->first = cmd;
|
||||||
|
}
|
||||||
|
cmds_out->last = cmd;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
||||||
{
|
{
|
||||||
|
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
||||||
cmd->kind = GAME_CMD_KIND_CLIENT_DISCONNECT;
|
cmd->kind = GAME_CMD_KIND_CLIENT_DISCONNECT;
|
||||||
cmd->disconnect_reason = LIT("Connection lost");
|
cmd->disconnect_reason = LIT("Connection lost");
|
||||||
|
if (cmds_out->last) {
|
||||||
|
cmds_out->last->next = cmd;
|
||||||
|
} else {
|
||||||
|
cmds_out->first = cmd;
|
||||||
|
}
|
||||||
|
cmds_out->last = cmd;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case HOST_EVENT_KIND_MSG:
|
case HOST_EVENT_KIND_MSG:
|
||||||
{
|
{
|
||||||
struct byte_reader br = br_from_buffer(host_event.msg);
|
struct byte_reader br = br_from_buffer(host_event.msg);
|
||||||
while (br_bytes_left(&br) > 0) {
|
while (br_bytes_left(&br) > 0) {
|
||||||
|
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
||||||
u64 cmd_size = br_read_u64(&br);
|
u64 cmd_size = br_read_u64(&br);
|
||||||
u64 cmd_pos_end = br_pos(&br) + cmd_size;
|
u64 cmd_pos_end = br_pos(&br) + cmd_size;
|
||||||
|
|
||||||
cmd->kind = br_read_i8(&br);
|
cmd->kind = br_read_i8(&br);
|
||||||
cmd->state = br_read_i8(&br);
|
cmd->state = br_read_i8(&br);
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
cmd->collider_gjk_steps = br_read_u32(&br);
|
cmd->collider_gjk_steps = br_read_u32(&br);
|
||||||
#endif
|
#endif
|
||||||
@ -1435,11 +1449,6 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
|
|
||||||
ASSERT(br_pos(&br) == cmd_pos_end);
|
ASSERT(br_pos(&br) == cmd_pos_end);
|
||||||
br_seek_to(&br, cmd_pos_end);
|
br_seek_to(&br, cmd_pos_end);
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmds_out->last) {
|
if (cmds_out->last) {
|
||||||
cmds_out->last->next = cmd;
|
cmds_out->last->next = cmd;
|
||||||
@ -1448,6 +1457,11 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
}
|
}
|
||||||
cmds_out->last = cmd;
|
cmds_out->last = cmd;
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -1456,6 +1470,7 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
|
|
||||||
struct string game_string_from_events(struct arena *arena, struct game_event_list events)
|
struct string game_string_from_events(struct arena *arena, struct game_event_list events)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
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));
|
||||||
@ -1479,6 +1494,7 @@ struct string game_string_from_events(struct arena *arena, struct game_event_lis
|
|||||||
|
|
||||||
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out)
|
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
for (u64 i = 0; i < host_events.count; ++i) {
|
for (u64 i = 0; i < host_events.count; ++i) {
|
||||||
struct game_event *game_event = arena_push_zero(arena, struct game_event);
|
struct game_event *game_event = arena_push_zero(arena, struct game_event);
|
||||||
struct host_event host_event = host_events.events[i];
|
struct host_event host_event = host_events.events[i];
|
||||||
@ -1536,6 +1552,7 @@ 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)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
|
|
||||||
bw_write_var_uint(&bw, tick->continuity_gen);
|
bw_write_var_uint(&bw, tick->continuity_gen);
|
||||||
@ -1559,6 +1576,7 @@ struct string game_string_from_tick(struct arena *arena, struct world *tick)
|
|||||||
|
|
||||||
void game_tick_from_string(struct string str, struct world *tick_out)
|
void game_tick_from_string(struct string str, struct world *tick_out)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct byte_reader br = br_from_buffer(str);
|
struct byte_reader br = br_from_buffer(str);
|
||||||
|
|
||||||
tick_out->continuity_gen = br_read_var_uint(&br);
|
tick_out->continuity_gen = br_read_var_uint(&br);
|
||||||
@ -1579,11 +1597,8 @@ void game_tick_from_string(struct string str, struct world *tick_out)
|
|||||||
struct entity *src = &entities_src[i];
|
struct entity *src = &entities_src[i];
|
||||||
struct entity *dst = &tick_out->entity_store->entities[i];
|
struct entity *dst = &tick_out->entity_store->entities[i];
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
DEBUGBREAKABLE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGBREAKABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
125
src/host.c
125
src/host.c
@ -4,6 +4,7 @@
|
|||||||
#include "byteio.h"
|
#include "byteio.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
//#define HOST_NETWORK_ADDRESS_STRING(str)
|
//#define HOST_NETWORK_ADDRESS_STRING(str)
|
||||||
//#define HOST_NETWORK_ADDRESS_ALL_LOCAL_INTERFACES(port)
|
//#define HOST_NETWORK_ADDRESS_ALL_LOCAL_INTERFACES(port)
|
||||||
@ -58,6 +59,8 @@ struct host_channel {
|
|||||||
struct host_packet *last_reliable_packet;
|
struct host_packet *last_reliable_packet;
|
||||||
struct host_packet *first_unreliable_packet;
|
struct host_packet *first_unreliable_packet;
|
||||||
struct host_packet *last_unreliable_packet;
|
struct host_packet *last_unreliable_packet;
|
||||||
|
u64 num_reliable_packets;
|
||||||
|
u64 num_unreliable_packets;
|
||||||
|
|
||||||
/* NOTE: Msg assemblers are allocated in host's `arena` */
|
/* NOTE: Msg assemblers are allocated in host's `arena` */
|
||||||
struct host_msg_assembler *least_recent_msg_assembler;
|
struct host_msg_assembler *least_recent_msg_assembler;
|
||||||
@ -66,6 +69,7 @@ struct host_channel {
|
|||||||
u64 last_sent_msg_id;
|
u64 last_sent_msg_id;
|
||||||
u64 their_acked_seq;
|
u64 their_acked_seq;
|
||||||
u64 our_acked_seq;
|
u64 our_acked_seq;
|
||||||
|
u64 last_sent_seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct host_channel_node {
|
struct host_channel_node {
|
||||||
@ -92,7 +96,7 @@ struct host_msg_assembler {
|
|||||||
struct host *host;
|
struct host *host;
|
||||||
struct host_channel *channel;
|
struct host_channel *channel;
|
||||||
|
|
||||||
|
b32 is_reliable;
|
||||||
|
|
||||||
/* TODO: Remove this (testing) */
|
/* TODO: Remove this (testing) */
|
||||||
struct arena testarena;
|
struct arena testarena;
|
||||||
@ -350,7 +354,7 @@ INTERNAL struct host_msg_assembler *host_get_msg_assembler(struct host *host, st
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns)
|
INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns, b32 is_reliable)
|
||||||
{
|
{
|
||||||
struct host *host = channel->host;
|
struct host *host = channel->host;
|
||||||
struct host_msg_assembler *ma;
|
struct host_msg_assembler *ma;
|
||||||
@ -361,17 +365,20 @@ INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel
|
|||||||
ma = arena_push(&host->arena, struct host_msg_assembler);
|
ma = arena_push(&host->arena, struct host_msg_assembler);
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(ma);
|
MEMZERO_STRUCT(ma);
|
||||||
|
ma->host = channel->host;
|
||||||
ma->channel = channel;
|
ma->channel = channel;
|
||||||
ma->msg_id = msg_id;
|
ma->msg_id = msg_id;
|
||||||
|
|
||||||
ma->num_chunks_total = chunk_count;
|
ma->num_chunks_total = chunk_count;
|
||||||
|
|
||||||
/* FIXME: Use buddy allocator or something */
|
/* FIXME: Use buddy allocator or something */
|
||||||
u64 buff_size = chunk_count * PACKET_CHUNK_MAX_LEN;
|
u64 data_size = chunk_count * PACKET_CHUNK_MAX_LEN;
|
||||||
ma->testarena = arena_alloc(buff_size);
|
u64 bitmap_size = ((chunk_count - 1) / 8) + 1;
|
||||||
|
ma->testarena = arena_alloc(data_size + bitmap_size);
|
||||||
/* FIXME: Ensure chunk_count > 0 */
|
/* FIXME: Ensure chunk_count > 0 */
|
||||||
ma->chunks_received_bitmap = arena_push_array_zero(&ma->testarena, u8, (((chunk_count - 1) / 8) + 1));
|
ma->chunks_received_bitmap = arena_push_array_zero(&ma->testarena, u8, bitmap_size);
|
||||||
ma->data = arena_push_array(&ma->testarena, u8, buff_size);
|
ma->data = arena_push_array(&ma->testarena, u8, data_size);
|
||||||
|
ma->is_reliable = is_reliable;
|
||||||
|
|
||||||
/* Insert into channel list */
|
/* Insert into channel list */
|
||||||
ma->touched_ns = now_ns;
|
ma->touched_ns = now_ns;
|
||||||
@ -444,6 +451,40 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
|
|||||||
host->first_free_msg_assembler = ma;
|
host->first_free_msg_assembler = ma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL void host_msg_assembler_touch(struct host_msg_assembler *ma, i64 now_ns)
|
||||||
|
{
|
||||||
|
struct host_channel *channel = ma->channel;
|
||||||
|
if (ma != channel->most_recent_msg_assembler) {
|
||||||
|
/* Remove from channel list */
|
||||||
|
{
|
||||||
|
struct host_msg_assembler *prev = ma->less_recent;
|
||||||
|
struct host_msg_assembler *next = ma->more_recent;
|
||||||
|
if (prev) {
|
||||||
|
prev->more_recent = next;
|
||||||
|
} else {
|
||||||
|
channel->least_recent_msg_assembler = next;
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
next->less_recent = prev;
|
||||||
|
} else {
|
||||||
|
channel->most_recent_msg_assembler = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert at end of channel list */
|
||||||
|
{
|
||||||
|
if (channel->most_recent_msg_assembler) {
|
||||||
|
channel->most_recent_msg_assembler->more_recent = ma;
|
||||||
|
ma->less_recent = channel->most_recent_msg_assembler;
|
||||||
|
} else {
|
||||||
|
channel->least_recent_msg_assembler = ma;
|
||||||
|
}
|
||||||
|
channel->most_recent_msg_assembler = ma;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ma->touched_ns = now_ns;
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL b32 host_msg_assembler_is_chunk_filled(struct host_msg_assembler *ma, u64 chunk_id)
|
INTERNAL b32 host_msg_assembler_is_chunk_filled(struct host_msg_assembler *ma, u64 chunk_id)
|
||||||
{
|
{
|
||||||
if (chunk_id < ma->num_chunks_total) {
|
if (chunk_id < ma->num_chunks_total) {
|
||||||
@ -466,31 +507,34 @@ INTERNAL void host_msg_assembler_set_chunk_received(struct host_msg_assembler *m
|
|||||||
INTERNAL struct host_packet *host_channel_packet_alloc(struct host_channel *channel, b32 is_reliable)
|
INTERNAL struct host_packet *host_channel_packet_alloc(struct host_channel *channel, b32 is_reliable)
|
||||||
{
|
{
|
||||||
struct host *host = channel->host;
|
struct host *host = channel->host;
|
||||||
struct host_packet *host_packet = NULL;
|
struct host_packet *packet = NULL;
|
||||||
if (host->first_free_packet) {
|
if (host->first_free_packet) {
|
||||||
host_packet = host->first_free_packet;
|
packet = host->first_free_packet;
|
||||||
host->first_free_packet = host_packet->next;
|
host->first_free_packet = packet->next;
|
||||||
} else {
|
} else {
|
||||||
host_packet = arena_push(&host->channel_arena, struct host_packet);
|
packet = arena_push(&host->arena, struct host_packet);
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(host_packet);
|
MEMZERO_STRUCT(packet);
|
||||||
|
|
||||||
if (is_reliable) {
|
if (is_reliable) {
|
||||||
if (channel->last_reliable_packet) {
|
if (channel->last_reliable_packet) {
|
||||||
channel->last_reliable_packet->next = host_packet;
|
channel->last_reliable_packet->next = packet;
|
||||||
} else {
|
} else {
|
||||||
channel->first_reliable_packet = host_packet;
|
channel->first_reliable_packet = packet;
|
||||||
}
|
}
|
||||||
channel->last_reliable_packet = host_packet;
|
channel->last_reliable_packet = packet;
|
||||||
|
++channel->num_reliable_packets;
|
||||||
|
packet->seq = ++channel->last_sent_seq;
|
||||||
} else {
|
} else {
|
||||||
if (channel->last_unreliable_packet) {
|
if (channel->last_unreliable_packet) {
|
||||||
channel->last_unreliable_packet->next = host_packet;
|
channel->last_unreliable_packet->next = packet;
|
||||||
} else {
|
} else {
|
||||||
channel->first_unreliable_packet = host_packet;
|
channel->first_unreliable_packet = packet;
|
||||||
}
|
}
|
||||||
channel->last_unreliable_packet = host_packet;
|
channel->last_unreliable_packet = packet;
|
||||||
|
++channel->num_unreliable_packets;
|
||||||
}
|
}
|
||||||
return host_packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -551,6 +595,7 @@ INTERNAL struct host_queued_event *host_queued_event_alloc_and_append(struct hos
|
|||||||
|
|
||||||
void host_update(struct host *host)
|
void host_update(struct host *host)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
i64 now_ns = sys_time_ns();
|
i64 now_ns = sys_time_ns();
|
||||||
@ -580,7 +625,8 @@ void host_update(struct host *host)
|
|||||||
}
|
}
|
||||||
|
|
||||||
b32 should_process_packet = false;
|
b32 should_process_packet = false;
|
||||||
if (packet_flags & HOST_PACKET_FLAG_RELIABLE) {
|
b32 is_reliable = packet_flags & HOST_PACKET_FLAG_RELIABLE;
|
||||||
|
if (is_reliable) {
|
||||||
u64 packet_seq = br_read_var_uint(&br);
|
u64 packet_seq = br_read_var_uint(&br);
|
||||||
if (packet_seq == channel->our_acked_seq + 1) {
|
if (packet_seq == channel->our_acked_seq + 1) {
|
||||||
channel->our_acked_seq = packet_seq;
|
channel->our_acked_seq = packet_seq;
|
||||||
@ -596,6 +642,7 @@ void host_update(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("Received conection attempt from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
|
||||||
/* TODO: Verify that some per-host uuid isn't
|
/* TODO: Verify that some per-host uuid isn't
|
||||||
* present in a rolling window to prevent reconnects right after a disconnect? */
|
* present in a rolling window to prevent reconnects right after a disconnect? */
|
||||||
channel = host_channel_alloc(host, address);
|
channel = host_channel_alloc(host, address);
|
||||||
@ -606,6 +653,7 @@ void host_update(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("Received connection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
|
||||||
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);
|
||||||
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_OPENED;
|
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_OPENED;
|
||||||
queued_event->event.channel_id = channel->id;
|
queued_event->event.channel_id = channel->id;
|
||||||
@ -617,6 +665,7 @@ void host_update(struct host *host)
|
|||||||
{
|
{
|
||||||
/* A foreign host disconnected from us */
|
/* A foreign host disconnected from us */
|
||||||
if (channel->valid) {
|
if (channel->valid) {
|
||||||
|
logf_info("Received disconnection from %F", FMT_STR(sock_string_from_address(scratch.arena, address)));
|
||||||
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);
|
||||||
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
|
queued_event->event.kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
|
||||||
queued_event->event.channel_id = channel->id;
|
queued_event->event.channel_id = channel->id;
|
||||||
@ -638,7 +687,7 @@ void host_update(struct host *host)
|
|||||||
|
|
||||||
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, is_reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunk_count == ma->num_chunks_total && chunk_id < chunk_count) {
|
if (chunk_count == ma->num_chunks_total && chunk_id < chunk_count) {
|
||||||
@ -652,7 +701,7 @@ void host_update(struct host *host)
|
|||||||
}
|
}
|
||||||
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;
|
host_msg_assembler_touch(ma, 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 */
|
||||||
@ -664,10 +713,18 @@ void host_update(struct host *host)
|
|||||||
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;
|
||||||
|
if (is_reliable) {
|
||||||
|
/* Release assembler if reliable */
|
||||||
|
host_msg_assembler_release(ma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -702,6 +759,7 @@ void host_update(struct host *host)
|
|||||||
host_packet->next = host->first_free_packet;
|
host_packet->next = host->first_free_packet;
|
||||||
host->first_free_packet = host_packet;
|
host->first_free_packet = host_packet;
|
||||||
channel->first_reliable_packet = next;
|
channel->first_reliable_packet = next;
|
||||||
|
--channel->num_reliable_packets;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -712,6 +770,25 @@ void host_update(struct host *host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO: Release timed out unreliable msg buffers */
|
/* TODO: Release timed out unreliable msg buffers */
|
||||||
|
{
|
||||||
|
/* TODO: Configurable timeout */
|
||||||
|
i64 timeout_ns = NS_FROM_SECONDS(4);
|
||||||
|
struct host_msg_assembler *ma = channel->least_recent_msg_assembler;
|
||||||
|
while (ma) {
|
||||||
|
struct host_msg_assembler *next = ma->more_recent;
|
||||||
|
if ((now_ns - ma->touched_ns) > timeout_ns) {
|
||||||
|
if (!ma->is_reliable) {
|
||||||
|
host_msg_assembler_release(ma);
|
||||||
|
if (ma->num_chunks_received != ma->num_chunks_total) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ma = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,6 +803,8 @@ void host_update(struct host *host)
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case HOST_CMD_KIND_TRY_CONNECT:
|
case HOST_CMD_KIND_TRY_CONNECT:
|
||||||
{
|
{
|
||||||
|
logf_info("TRY CONNECT TO %F family: %F, valid: %F", FMT_STR(sock_string_from_address(scratch.arena, channel->address)), FMT_SINT(channel->address.family), FMT_SINT(channel->address.valid));
|
||||||
|
|
||||||
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));
|
||||||
@ -822,10 +901,11 @@ void host_update(struct host *host)
|
|||||||
}
|
}
|
||||||
/* Release unreliable packets */
|
/* Release unreliable packets */
|
||||||
if (channel->first_unreliable_packet) {
|
if (channel->first_unreliable_packet) {
|
||||||
host->first_free_packet = channel->first_unreliable_packet;
|
|
||||||
channel->last_unreliable_packet->next = host->first_free_packet;
|
channel->last_unreliable_packet->next = host->first_free_packet;
|
||||||
|
host->first_free_packet = channel->first_unreliable_packet;
|
||||||
channel->first_unreliable_packet = NULL;
|
channel->first_unreliable_packet = NULL;
|
||||||
channel->last_unreliable_packet = NULL;
|
channel->last_unreliable_packet = NULL;
|
||||||
|
channel->num_unreliable_packets = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,6 +925,7 @@ void host_update(struct host *host)
|
|||||||
|
|
||||||
struct host_event_array host_pop_events(struct arena *arena, struct host *host)
|
struct host_event_array host_pop_events(struct arena *arena, struct host *host)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct host_event_array res = ZI;
|
struct host_event_array res = ZI;
|
||||||
res.count = host->num_queued_events;
|
res.count = host->num_queued_events;
|
||||||
res.events = arena_push_array(arena, struct host_event, res.count);
|
res.events = arena_push_array(arena, struct host_event, res.count);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ 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_port(u16 port);
|
struct sock_address sock_address_from_port(u16 port);
|
||||||
|
struct string sock_string_from_address(struct arena *arena, struct sock_address address);
|
||||||
|
|
||||||
struct sock sock_alloc(u16 listen_port, u32 flags);
|
struct sock sock_alloc(u16 listen_port, u32 flags);
|
||||||
void sock_release(struct sock *sock);
|
void sock_release(struct sock *sock);
|
||||||
|
|||||||
@ -4,7 +4,11 @@
|
|||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define UNICODE
|
||||||
|
#include <Windows.h>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
|
|
||||||
@ -46,20 +50,22 @@ INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char
|
|||||||
while (ai_res) {
|
while (ai_res) {
|
||||||
if (ai_res->ai_family == AF_INET) {
|
if (ai_res->ai_family == AF_INET) {
|
||||||
struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_res->ai_addr;
|
struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_res->ai_addr;
|
||||||
|
res.valid = true;
|
||||||
res.family = SOCK_ADDRESS_FAMILY_IPV4;
|
res.family = SOCK_ADDRESS_FAMILY_IPV4;
|
||||||
res.portnb = sockaddr->sin_port;
|
res.portnb = sockaddr->sin_port;
|
||||||
CT_ASSERT(sizeof(sockaddr->sin_addr) == 4);
|
CT_ASSERT(sizeof(sockaddr->sin_addr) == 4);
|
||||||
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
|
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (ai_res->ai_family == AF_INET6) {
|
} else if (ai_res->ai_family == AF_INET6) {
|
||||||
/* FIXME: Why must this be disabled to work? */
|
/* FIXME: Why must this be disabled to work? */
|
||||||
#if 0
|
#if 0
|
||||||
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
|
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_res->ai_addr;
|
||||||
|
res.valid = true;
|
||||||
res.family = SOCK_ADDRESS_FAMILY_IPV6;
|
res.family = SOCK_ADDRESS_FAMILY_IPV6;
|
||||||
res.portnb = sockaddr->sin6_port;
|
res.portnb = sockaddr->sin6_port;
|
||||||
CT_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
|
CT_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
|
||||||
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
|
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
ai_res = ai_res->ai_next;
|
ai_res = ai_res->ai_next;
|
||||||
@ -73,7 +79,9 @@ INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char
|
|||||||
struct sock_address sock_address_from_string(struct string str)
|
struct sock_address sock_address_from_string(struct string str)
|
||||||
{
|
{
|
||||||
/* Parse string into ip & port */
|
/* Parse string into ip & port */
|
||||||
char *address_cstr = NULL;
|
u8 ip_buff[1024];
|
||||||
|
u8 port_buff[ARRAY_COUNT(ip_buff)];
|
||||||
|
char *ip_cstr = NULL;
|
||||||
char *port_cstr = NULL;
|
char *port_cstr = NULL;
|
||||||
{
|
{
|
||||||
u64 colon_count = 0;
|
u64 colon_count = 0;
|
||||||
@ -83,11 +91,9 @@ struct sock_address sock_address_from_string(struct string str)
|
|||||||
++colon_count;
|
++colon_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u8 address_buff[1024];
|
u64 ip_len = 0;
|
||||||
u8 port_buff[ARRAY_COUNT(address_buff)];
|
|
||||||
u64 address_len = 0;
|
|
||||||
u64 port_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);
|
u64 parse_len = min_u64(min_u64(str.len, ARRAY_COUNT(ip_buff) - 1), ARRAY_COUNT(port_buff) - 1);
|
||||||
if (colon_count > 1 && str.text[0] == '[') {
|
if (colon_count > 1 && str.text[0] == '[') {
|
||||||
/* Parse ipv6 with port */
|
/* Parse ipv6 with port */
|
||||||
b32 parse_addr = true;
|
b32 parse_addr = true;
|
||||||
@ -97,8 +103,8 @@ struct sock_address sock_address_from_string(struct string str)
|
|||||||
if (c == ']') {
|
if (c == ']') {
|
||||||
parse_addr = false;
|
parse_addr = false;
|
||||||
} else {
|
} else {
|
||||||
address_buff[address_len] = c;
|
ip_buff[ip_len] = c;
|
||||||
++address_len;
|
++ip_len;
|
||||||
}
|
}
|
||||||
} else if (c != ':') {
|
} else if (c != ':') {
|
||||||
port_buff[port_len] = c;
|
port_buff[port_len] = c;
|
||||||
@ -114,8 +120,8 @@ struct sock_address sock_address_from_string(struct string str)
|
|||||||
if (c == ':') {
|
if (c == ':') {
|
||||||
parse_addr = false;
|
parse_addr = false;
|
||||||
} else {
|
} else {
|
||||||
address_buff[address_len] = c;
|
ip_buff[ip_len] = c;
|
||||||
++address_len;
|
++ip_len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
port_buff[port_len] = c;
|
port_buff[port_len] = c;
|
||||||
@ -124,12 +130,12 @@ struct sock_address sock_address_from_string(struct string str)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Copy address without port */
|
/* Copy address without port */
|
||||||
address_len = min_u64(str.len, ARRAY_COUNT(address_buff) - 1);
|
ip_len = min_u64(str.len, ARRAY_COUNT(ip_buff) - 1);
|
||||||
MEMCPY(address_buff, str.text, address_len);
|
MEMCPY(ip_buff, str.text, ip_len);
|
||||||
}
|
}
|
||||||
if (address_len > 0) {
|
if (ip_len > 0) {
|
||||||
address_buff[address_len] = 0;
|
ip_buff[ip_len] = 0;
|
||||||
address_cstr = (char *)address_buff;
|
ip_cstr = (char *)ip_buff;
|
||||||
}
|
}
|
||||||
if (port_len > 0) {
|
if (port_len > 0) {
|
||||||
port_buff[port_len] = 0;
|
port_buff[port_len] = 0;
|
||||||
@ -137,15 +143,16 @@ struct sock_address sock_address_from_string(struct string str)
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct sock_address res = sock_address_from_ip_port_cstr(address_cstr, port_cstr);
|
|
||||||
|
struct sock_address res = sock_address_from_ip_port_cstr(ip_cstr, port_cstr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sock_address sock_address_from_port(u16 port)
|
struct sock_address sock_address_from_port(u16 port)
|
||||||
{
|
{
|
||||||
|
u8 port_buff[128];
|
||||||
char *port_cstr = NULL;
|
char *port_cstr = NULL;
|
||||||
{
|
{
|
||||||
u8 port_buff[128];
|
|
||||||
u8 port_buff_reverse[ARRAY_COUNT(port_buff)];
|
u8 port_buff_reverse[ARRAY_COUNT(port_buff)];
|
||||||
u64 port_len = 0;
|
u64 port_len = 0;
|
||||||
while (port > 0 && port_len < (ARRAY_COUNT(port_buff) - 1)) {
|
while (port > 0 && port_len < (ARRAY_COUNT(port_buff) - 1)) {
|
||||||
@ -169,6 +176,24 @@ struct sock_address sock_address_from_port(u16 port)
|
|||||||
return res;
|
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 winsock_address winsock_address_from_sock_address(struct sock_address addr)
|
INTERNAL struct winsock_address winsock_address_from_sock_address(struct sock_address addr)
|
||||||
{
|
{
|
||||||
struct winsock_address res = ZI;
|
struct winsock_address res = ZI;
|
||||||
@ -211,10 +236,14 @@ struct sock sock_alloc(u16 listen_port, u32 flags)
|
|||||||
struct winsock_address ws_addr = winsock_address_from_sock_address(addr);
|
struct winsock_address ws_addr = winsock_address_from_sock_address(addr);
|
||||||
|
|
||||||
SOCKET ws = socket(ws_addr.family, SOCK_DGRAM, IPPROTO_UDP);
|
SOCKET ws = socket(ws_addr.family, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
#if 0
|
||||||
if (flags & SOCK_FLAG_NON_BLOCKING) {
|
if (flags & SOCK_FLAG_NON_BLOCKING) {
|
||||||
u_long mode = 1;
|
u_long mode = 1;
|
||||||
ioctlsocket(ws, FIONBIO, &mode);
|
ioctlsocket(ws, FIONBIO, &mode);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(UNUSED)flags;
|
||||||
|
#endif
|
||||||
//setsockopt(ws, SOL_SOCKET, SO_REUSEADDR
|
//setsockopt(ws, SOL_SOCKET, SO_REUSEADDR
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -239,10 +268,11 @@ 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)
|
||||||
{
|
{
|
||||||
SOCKET ws = *(SOCKET *)&sock->handle;
|
SOCKET ws = *(SOCKET *)&sock->handle;
|
||||||
|
|
||||||
struct sock_read_result res = ZI;
|
struct sock_read_result res = ZI;
|
||||||
|
|
||||||
struct winsock_address ws_addr = ZI;
|
struct winsock_address ws_addr = ZI;
|
||||||
ws_addr.size = sizeof(ws_addr.sas);
|
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);
|
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;
|
ws_addr.family = ws_addr.sin.sin_family;
|
||||||
|
|
||||||
@ -254,7 +284,7 @@ struct sock_read_result sock_read(struct sock *sock, struct string read_buff)
|
|||||||
} else {
|
} else {
|
||||||
#if RTC
|
#if RTC
|
||||||
i32 err = WSAGetLastError();
|
i32 err = WSAGetLastError();
|
||||||
if (err != WSAEWOULDBLOCK && err != WSAECONNRESET) {
|
if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT) {
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -267,5 +297,12 @@ void sock_write(struct sock *sock, struct sock_address address, struct string da
|
|||||||
{
|
{
|
||||||
SOCKET ws = *(SOCKET *)&sock->handle;
|
SOCKET ws = *(SOCKET *)&sock->handle;
|
||||||
struct winsock_address ws_addr = winsock_address_from_sock_address(address);
|
struct winsock_address ws_addr = winsock_address_from_sock_address(address);
|
||||||
sendto(ws, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
|
i32 size = sendto(ws, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
|
||||||
|
#if RTC
|
||||||
|
if (size != (i32)data.len) {
|
||||||
|
i32 err = WSAGetLastError();
|
||||||
|
(UNUSED)err;
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1864,6 +1864,7 @@ void sys_panic(struct string msg)
|
|||||||
{
|
{
|
||||||
if (atomic_i32_eval_compare_exchange(&G.panicking, 0, 1) == 0) {
|
if (atomic_i32_eval_compare_exchange(&G.panicking, 0, 1) == 0) {
|
||||||
log_panic(msg);
|
log_panic(msg);
|
||||||
|
ASSERT(false);
|
||||||
|
|
||||||
wchar_t *wstr = G.panic_wstr;
|
wchar_t *wstr = G.panic_wstr;
|
||||||
u64 wstr_len = 0;
|
u64 wstr_len = 0;
|
||||||
|
|||||||
@ -612,9 +612,6 @@ INTERNAL void user_update(void)
|
|||||||
* Process game events
|
* Process game events
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
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());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user