client connection

This commit is contained in:
jacob 2026-01-17 22:10:25 -06:00
parent cacdf10229
commit 3cdff3c4c5
12 changed files with 437 additions and 230 deletions

View File

@ -16,6 +16,7 @@
#include <uuids.h> #include <uuids.h>
#include <Knownfolders.h> #include <Knownfolders.h>
#include <WinSock2.h> #include <WinSock2.h>
#include <Mswsock.h>
#include <TlHelp32.h> #include <TlHelp32.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include <windowsx.h> #include <windowsx.h>

View File

@ -1,8 +1,4 @@
// NOTE: Burst messages with lengths exceeding packet size will degrade
// into sequenced messages
#define NET_PacketSize 1024 #define NET_PacketSize 1024
#define NET_Ephemeral 0xFFFFFFFFFFFFFFFFull #define NET_Ephemeral 0xFFFFFFFFFFFFFFFFull
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -23,6 +19,17 @@ Struct(NET_Key)
#define NET_NilKey ((NET_Key) { 0 }) #define NET_NilKey ((NET_Key) { 0 })
#define NET_IsKeyNil(k) (MatchStructZero(&k)) #define NET_IsKeyNil(k) (MatchStructZero(&k))
////////////////////////////////////////////////////////////
//~ Send types
Enum(NET_SendFlag)
{
NET_SendFlag_None = 0,
// NOTE: Messages marked "raw" that exceed packet size will drop
NET_SendFlag_Raw = (1 << 0),
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Message types //~ Message types
@ -69,6 +76,6 @@ NET_PipeHandle NET_AcquirePipe(void);
void NET_Bind(NET_PipeHandle pipe_handle, u64 port); void NET_Bind(NET_PipeHandle pipe_handle, u64 port);
NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle); NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle);
void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst); void NET_Send(NET_PipeHandle pipe_handle, NET_Key dst, String data, NET_SendFlag flags);
NET_PipeStatistics NET_StatsFromPipe(NET_PipeHandle pipe_handle); NET_PipeStatistics NET_StatsFromPipe(NET_PipeHandle pipe_handle);

View File

@ -46,8 +46,12 @@ struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key)
void NET_W32_SignalWorker(void) void NET_W32_SignalWorker(void)
{ {
// TODO: Only post if previous signal was seen i64 signal = Atomic64Fetch(&NET_W32.signal);
PostQueuedCompletionStatus(NET_W32.iocp, 0, 0, 0); if (Atomic64Fetch(&NET_W32.seen_signal) == signal)
{
Atomic64FetchAdd(&NET_W32.signal, 1);
PostQueuedCompletionStatus(NET_W32.iocp, 0, 0, 0);
}
} }
NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key) NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key)
@ -122,7 +126,7 @@ void NET_W32_PostRecv(NET_W32_Pipe *pipe)
pipe->iocp_count += 1; pipe->iocp_count += 1;
DWORD flags = 0; DWORD flags = 0;
i32 ret = WSARecvFrom( WSARecvFrom(
pipe->udp, pipe->udp,
&pipe->recv_wsabuff, 1, &pipe->recv_wsabuff, 1,
0, 0,
@ -249,7 +253,11 @@ NET_PipeHandle NET_AcquirePipe(void)
void NET_Bind(NET_PipeHandle pipe_handle, u64 port) void NET_Bind(NET_PipeHandle pipe_handle, u64 port)
{ {
NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle); NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle);
Atomic64Set(&pipe->desired_port, port); u64 prev_desired_port = Atomic64FetchSet(&pipe->desired_port, port);
if (prev_desired_port != port)
{
NET_W32_SignalWorker();
}
} }
NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle) NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle)
@ -270,7 +278,7 @@ NET_MsgList NET_Swap(Arena *arena, NET_PipeHandle pipe_handle)
return msg_buff->msgs; return msg_buff->msgs;
} }
void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst) void NET_Send(NET_PipeHandle pipe_handle, NET_Key dst, String data, NET_SendFlag flags)
{ {
NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle); NET_W32_Pipe *pipe = NET_W32_PipeFromHandle(pipe_handle);
if (Atomic64Fetch(&pipe->desired_port) == 0) if (Atomic64Fetch(&pipe->desired_port) == 0)
@ -283,7 +291,7 @@ void NET_Push(NET_PipeHandle pipe_handle, NET_Key dst, String data, b32 burst)
NET_W32_Cmd *cmd = PushStruct(cmd_buff->arena, NET_W32_Cmd); NET_W32_Cmd *cmd = PushStruct(cmd_buff->arena, NET_W32_Cmd);
cmd->key = dst; cmd->key = dst;
cmd->data = PushString(cmd_buff->arena, data); cmd->data = PushString(cmd_buff->arena, data);
cmd->burst = burst; cmd->send_flags = flags;
SllQueuePush(cmd_buff->cmds.first, cmd_buff->cmds.last, cmd); SllQueuePush(cmd_buff->cmds.first, cmd_buff->cmds.last, cmd);
++cmd_buff->cmds.count; ++cmd_buff->cmds.count;
} }
@ -371,27 +379,25 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
i32 timeout_ms = MsFromNs(passive_run_threshold_ns); i32 timeout_ms = MsFromNs(passive_run_threshold_ns);
if (wake_count > 0) if (wake_count > 0)
{ {
// Keep processing without sleeping if we've already received a completion this frame // Continue processing without sleeping if we've already received a completion this frame
timeout_ms = 0; timeout_ms = 0;
} }
// //
// NOTE: We're really only using IOCP so that we have a way to wake // NOTE: We're really only using IOCP so that we have a way to wake
// the worker mid-wait without having to use WSAPoll + a dummy socket. // the worker mid-wait without having to use WSAPoll + a dummy socket.
// This is because any data sent to that dummy socket will itself be // This is because any data sent to that dummy socket will itself be
// affected by network testing tools such as Clumsy, adding additional // affected by network testing tools such as Clumsy.
// unpredictability. E.g. if Clumsy is set to add 50ms of artificial
// and drop 10% of packets on loopback, attempts to wake the worker
// thread so that it can process queued cmds will be affected as well.
// //
ok = GetQueuedCompletionStatus(NET_W32.iocp, &len, &iocp_key, &ovl, timeout_ms); ok = GetQueuedCompletionStatus(NET_W32.iocp, &len, &iocp_key, &ovl, timeout_ms);
wake_count += 1; wake_count += 1;
if (!ok) Atomic64Set(&NET_W32.seen_signal, Atomic64Fetch(&NET_W32.signal));
}
i32 err = GetLastError();
if (!ok)
{
if (err == WAIT_TIMEOUT)
{ {
i32 err = GetLastError(); done = 1;
if (err == WAIT_TIMEOUT)
{
done = 1;
}
} }
} }
@ -399,6 +405,7 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
{ {
NET_W32_Pipe *pipe = (NET_W32_Pipe *)ovl; NET_W32_Pipe *pipe = (NET_W32_Pipe *)ovl;
pipe->iocp_count -= 1; pipe->iocp_count -= 1;
if (ok) if (ok)
{ {
String recv = STRING(len, (u8 *)pipe->recv_wsabuff.buf); String recv = STRING(len, (u8 *)pipe->recv_wsabuff.buf);
@ -551,8 +558,11 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
} }
} }
} }
}
// Re-post recv // Re-post recv
if (err != ERROR_OPERATION_ABORTED)
{
NET_W32_PostRecv(pipe); NET_W32_PostRecv(pipe);
} }
} }
@ -586,6 +596,8 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
(pipe->last_attempted_bind_ns == 0 || now_ns - pipe->last_attempted_bind_ns > bind_retry_threshold_ns) (pipe->last_attempted_bind_ns == 0 || now_ns - pipe->last_attempted_bind_ns > bind_retry_threshold_ns)
) )
{ {
// LogDebugF("Binding to port \"%F\"", FmtUint(desired_port));
b32 ok = 1; b32 ok = 1;
String port_str = StringF(scratch.arena, "%F", FmtUint(desired_port)); String port_str = StringF(scratch.arena, "%F", FmtUint(desired_port));
char *port_cstr = CstrFromString(scratch.arena, port_str); char *port_cstr = CstrFromString(scratch.arena, port_str);
@ -679,6 +691,32 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
ok = ioctlsocket(sock, FIONBIO, &nonblocking) == 0; ok = ioctlsocket(sock, FIONBIO, &nonblocking) == 0;
} }
//- Disable ICMP reporting
{
DWORD bytes = 0;
b32 report = 0;
int rc = WSAIoctl(
sock,
SIO_UDP_CONNRESET,
&report, sizeof(report),
0, 0,
&bytes,
0, 0
);
}
{
DWORD bytes = 0;
b32 report = 0;
int rc = WSAIoctl(
sock,
SIO_UDP_NETRESET,
&report, sizeof(report),
0, 0,
&bytes,
0, 0
);
}
//- Fetch bound port //- Fetch bound port
u64 bound_port = 0; u64 bound_port = 0;
{ {
@ -715,6 +753,8 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
// Post initial recv // Post initial recv
CreateIoCompletionPort((HANDLE)sock, NET_W32.iocp, 0, 0); CreateIoCompletionPort((HANDLE)sock, NET_W32.iocp, 0, 0);
NET_W32_PostRecv(pipe); NET_W32_PostRecv(pipe);
} }
else else
@ -835,7 +875,7 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
i64 msg_seq = ++peer->msg_seq; i64 msg_seq = ++peer->msg_seq;
// LogDebugF("Queued msg with seq %F", FmtSint(msg_seq)); // LogDebugF("Queued msg with seq %F", FmtSint(msg_seq));
// TODO: Burst packets // TODO: Raw packets
b32 is_msg_end = 0; b32 is_msg_end = 0;
while (!is_msg_end) while (!is_msg_end)

View File

@ -7,7 +7,7 @@ Struct(NET_W32_Cmd)
NET_Key key; NET_Key key;
String data; String data;
b32 burst; NET_SendFlag send_flags;
}; };
Struct(NET_W32_CmdList) Struct(NET_W32_CmdList)
@ -43,7 +43,7 @@ Enum(NET_W32_PacketFlag)
NET_W32_PacketFlag_EndMsg = (1 << 0), NET_W32_PacketFlag_EndMsg = (1 << 0),
NET_W32_PacketFlag_Heartbeat = (1 << 2), NET_W32_PacketFlag_Heartbeat = (1 << 2),
// NET_W32_PacketFlag_Burst = (1 << 3), // NET_W32_PacketFlag_Raw = (1 << 3),
}; };
Struct(NET_W32_PacketHeader) Struct(NET_W32_PacketHeader)
@ -136,7 +136,8 @@ Struct(NET_W32_Pipe)
NET_W32_Pipe *next; NET_W32_Pipe *next;
NET_W32_Pipe *prev; NET_W32_Pipe *prev;
Atomic64 desired_port; // >64k means ephemeral Atomic64 desired_port; // ports >64k become ephemeral
Atomic64 seen_desired_port;
Atomic64 total_bytes_sent; Atomic64 total_bytes_sent;
Atomic64 total_bytes_received; Atomic64 total_bytes_received;
@ -184,6 +185,9 @@ Struct(NET_W32_Ctx)
NET_W32_Packet *first_free_packet; NET_W32_Packet *first_free_packet;
HANDLE iocp; HANDLE iocp;
Atomic64 signal;
Atomic64 seen_signal;
}; };
extern NET_W32_Ctx NET_W32; extern NET_W32_Ctx NET_W32;

View File

@ -1166,6 +1166,49 @@ void P_DebugDrawShape(P_Shape shape, Vec4 srgb)
} }
} }
void P_DebugDrawFrame(P_Frame *frame, Vec4 tint)
{
if (P_tl.debug_draw_enabled)
{
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
P_Shape world_shape = P_WorldShapeFromEnt(ent);
// Draw aabb
{
Vec4 color = VEC4(0.4, 0.2, 0.2, 1);
Rng2 bb = P_BoundingBoxFromShape(world_shape);
P_DebugDrawRect(bb, color);
}
// Draw shape
{
// Vec4 color = Color_Cyan;
// Vec4 color = VEC4(0.2, 0.4, 0.2, 1);
Vec4 color = MulVec4Vec4(VEC4(1, 1, 1, 1), tint);
P_DebugDrawShape(world_shape, color);
}
// Draw rot
{
Vec4 color = VEC4(0.8, 0.8, 0.8, 1);
Vec2 p0 = world_shape.centroid;
Vec2 p1 = P_EdgePointFromShape(world_shape, UpFromXform(ent->xf));
P_DebugDrawLine(p0, p1, color);
}
// Draw look
{
Vec4 color = VEC4(0.4, 0.8, 0.4, 1);
Vec2 p0 = world_shape.centroid;
Vec2 p1 = P_EdgePointFromShape(world_shape, ent->control.look);
P_DebugDrawLine(p0, p1, color);
}
}
}
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Msg //~ Msg
@ -2038,47 +2081,6 @@ void P_StepFrame(P_Frame *frame)
} }
} }
//////////////////////////////
//- Debug draw entities
if (P_tl.debug_draw_enabled)
{
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
P_Shape world_shape = P_WorldShapeFromEnt(ent);
// Draw aabb
{
Vec4 color = VEC4(0.4, 0.2, 0.2, 1);
Rng2 bb = P_BoundingBoxFromShape(world_shape);
P_DebugDrawRect(bb, color);
}
// Draw shape
{
// Vec4 color = Color_Cyan;
Vec4 color = VEC4(0.2, 0.4, 0.2, 1);
P_DebugDrawShape(world_shape, color);
}
// Draw rot
{
Vec4 color = VEC4(0.8, 0.8, 0.8, 1);
Vec2 p0 = world_shape.centroid;
Vec2 p1 = P_EdgePointFromShape(world_shape, UpFromXform(ent->xf));
P_DebugDrawLine(p0, p1, color);
}
// Draw look
{
Vec4 color = VEC4(0.4, 0.8, 0.4, 1);
Vec2 p0 = world_shape.centroid;
Vec2 p1 = P_EdgePointFromShape(world_shape, ent->control.look);
P_DebugDrawLine(p0, p1, color);
}
}
}
////////////////////////////// //////////////////////////////
//- End frame //- End frame

View File

@ -69,6 +69,9 @@ Struct(P_DebugDrawNode)
// TODO: Pack efficiently, deduplicate redundant fields // TODO: Pack efficiently, deduplicate redundant fields
#define P_MinPlayerNameLen 1
#define P_MaxPlayerNameLen 24
Struct(P_Control) Struct(P_Control)
{ {
Vec2 move; Vec2 move;
@ -128,7 +131,7 @@ Struct(P_Ent)
NET_Key net; NET_Key net;
u8 string_len; u8 string_len;
u8 string_text[32]; u8 string_text[P_MaxPlayerNameLen + 8];
//- Solver //- Solver
@ -308,6 +311,7 @@ Enum(P_MsgKind)
// Server <-> Client // Server <-> Client
P_MsgKind_Chat, P_MsgKind_Chat,
P_MsgKind_Connect,
// Client -> Server // Client -> Server
// P_MsgKind_UserSnapshot, // P_MsgKind_UserSnapshot,
@ -324,6 +328,7 @@ Enum(P_MsgKind)
Struct(P_Msg) Struct(P_Msg)
{ {
P_MsgKind kind; P_MsgKind kind;
NET_Key src;
NET_Key dst; NET_Key dst;
// P_UserSnapshot user_snapshot; // P_UserSnapshot user_snapshot;
@ -525,6 +530,7 @@ void P_DebugDrawPoint(Vec2 p, Vec4 srgb);
void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb); void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
void P_DebugDrawRect(Rng2 rect, Vec4 srgb); void P_DebugDrawRect(Rng2 rect, Vec4 srgb);
void P_DebugDrawShape(P_Shape shape, Vec4 srgb); void P_DebugDrawShape(P_Shape shape, Vec4 srgb);
void P_DebugDrawFrame(P_Frame *frame, Vec4 tint);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Msg //~ Msg

View File

@ -157,56 +157,85 @@ void S_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Pop messages //- Pop messages
u64 port = 22121; u64 port = 22121;
NET_Bind(net_pipe, port); NET_Bind(net_pipe, port);
P_MsgList in_msgs = Zi; P_MsgList in_msgs = Zi;
{ {
NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe);
for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next)
{ {
NET_Key net_key = net_msg->sender; NET_Key net_key = net_msg->sender;
String address_str = NET_StringFromKey(frame_arena, net_key); String address_str = NET_StringFromKey(frame_arena, net_key);
LogDebugF("Received message from client \"%F\"", FmtString(address_str)); LogDebugF("Received message from client \"%F\"", FmtString(address_str));
// String test_address_str = NET_StringFromKey(frame_arena, net_key);
// LogDebugF("Sending test msg to client \"%F\"", FmtString(test_address_str));
// Create client // NET_Send(net_pipe, net_key, Lit("HIII"), NET_SendFlag_None);
S_Client *client = S_ClientFromNetKey(net_key);
if (S_IsClientNil(client))
{
u64 hash = NET_HashFromKey(net_key);
S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count];
// FIXME: Freelist client
client = PushStruct(perm, S_Client);
client->hash = hash;
client->net_key = net_key;
DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev);
DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin);
{
}
}
String packed = net_msg->data; String packed = net_msg->data;
P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed, net_key);
P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed); // if (client_msgs.count > 0)
// {
// S_Client *client = S_ClientFromNetKey(net_key);
// FIXME: Set src user here based on net key (or maybe just attach net key to msg instead of user) // // Create client
// if (S_IsClientNil(client))
// {
// P_Msg *msg = &client_msgs.first->msg;
// if (msg->kind == P_MsgKind_Connect)
// {
// u64 hash = NET_HashFromKey(net_key);
// S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count];
// String src_name = msg->data;
// src_name = TrimWhitespace(src_name);
// if (src_name.len < P_MinPlayerNameLen)
// {
// src_name = Lit("Player");
// }
// src_name.len = MinI64(src_name.len, P_MaxPlayerNameLen);
// // FIXME: Freelist client
// client = PushStruct(perm, S_Client);
// client->hash = hash;
// client->net_key = net_key;
// client->name_len = MinI64(countof(client->name_text), src_name.len);
// CopyBytes(client->name_text, src_name.text, client->name_len);
// DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev);
// DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin);
// {
// P_Msg *out_msg = P_PushMsg(P_MsgKind_Connect, Zstr);
// out_msg->dst = net_key;
// }
// {
// String name = STRING(client->name_len, client->name_text);
// if (MatchString(name, src_name))
// {
// LogDebugF("Client \"%F\" connecting with name \"%F\"", FmtString(address_str), FmtString(src_name));
// }
// else
// {
// LogDebugF("Client \"%F\" connecting with name \"%F\" (reassigned to \"%F\")", FmtString(address_str), FmtString(src_name), FmtString(name));
// }
// P_Msg *out_msg = P_PushMsg(
// P_MsgKind_Chat,
// StringF(
// frame_arena,
// "Player %F is connecting",
// FmtString(name)
// ));
// }
// }
// }
// }
if (client_msgs.first) if (client_msgs.first)
{ {
@ -225,49 +254,66 @@ void S_TickForever(WaveLaneCtx *lane)
} }
} }
//////////////////////////////
//- Connect clients
for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next)
{
P_Msg *msg = &msg_node->msg;
NET_Key net_key = msg->src;
S_Client *client = S_ClientFromNetKey(net_key);
if (S_IsClientNil(client))
{
String address_str = NET_StringFromKey(frame_arena, net_key);
u64 hash = NET_HashFromKey(net_key);
S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count];
String src_name = msg->data;
src_name = TrimWhitespace(src_name);
if (src_name.len < P_MinPlayerNameLen)
{
src_name = Lit("Player");
}
src_name.len = MinI64(src_name.len, P_MaxPlayerNameLen);
// FIXME: Freelist client
client = PushStruct(perm, S_Client);
client->hash = hash;
client->net_key = net_key;
client->name_len = MinI64(countof(client->name_text), src_name.len);
CopyBytes(client->name_text, src_name.text, client->name_len);
DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev);
DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin);
// Acknowledge player connection
{
P_Msg *out_msg = P_PushMsg(P_MsgKind_Connect, Zstr);
out_msg->dst = net_key;
}
// Broadcast player connection notification
// P_MsgList in_msgs = Zi; {
// { String name = STRING(client->name_len, client->name_text);
// NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); if (MatchString(name, src_name))
// for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) {
// { LogDebugF("Client \"%F\" connecting with name \"%F\"", FmtString(address_str), FmtString(src_name));
// NET_Key net_key = net_msg->sender; }
// String address_str = NET_StringFromKey(frame_arena, net_key); else
// LogDebugF("Received message from client \"%F\"", FmtString(address_str)); {
LogDebugF("Client \"%F\" connecting with name \"%F\" (reassigned to \"%F\")", FmtString(address_str), FmtString(src_name), FmtString(name));
// NET_Push(net_pipe, net_key, Lit("HIII"), 0); }
P_Msg *out_msg = P_PushMsg(
// String packed = net_msg->data; P_MsgKind_Chat,
// P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); StringF(
// P_Msg *dst_msg = &dst_msg_node->msg; frame_arena,
// *dst_msg = P_UnpackMsg(frame_arena, packed); "\"%F\" connected",
// // FIXME: Set src user here based on net key FmtString(name)
// // dst_msg->src_user = ));
// DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); }
// ++in_msgs.count; }
}
// // {
// // LogDebugF(
// // "Server received msg (%F bytes): \"%F\"",
// // FmtUint(packed.len),
// // FmtString(packed)
// // );
// // }
// }
// }
////////////////////////////// //////////////////////////////
//- Process connection messages //- Process connection messages
@ -292,8 +338,8 @@ void S_TickForever(WaveLaneCtx *lane)
// // FIXME: Set net key here // // FIXME: Set net key here
// i32 min_name_len = 3; // i32 min_name_len = P_MinPlayerNameLen;
// i32 max_name_len = countof(user->string_text) - 8; // i32 max_name_len = P_MaxPlayerNameLen;
// // De-duplicate user name // // De-duplicate user name
// String user_name = msg->data; // String user_name = msg->data;
@ -526,9 +572,10 @@ void S_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Step frame //- Step frame
// { {
// P_StepFrame(world_frame, user_msgs); P_StepFrame(world_frame);
// } P_DebugDrawFrame(world_frame, VEC4(0.2, 0.4, 0.2, 0.75));
}
////////////////////////////// //////////////////////////////
//- Push tile messages //- Push tile messages
@ -560,7 +607,7 @@ void S_TickForever(WaveLaneCtx *lane)
// Arena *msgs_arena = P_tl.out_msgs_arena; // Arena *msgs_arena = P_tl.out_msgs_arena;
// P_Msg *msg = P_PushMsg(P_MsgKind_SimSnapshot, Zstr); // P_Msg *msg = P_PushMsg(P_MsgKind_SimSnapshot, Zstr);
// msg->dst_user = user->key; // msg->dst_user = user->key;
// msg->burst = 1; // NET_SendFlag_None = 1;
// P_SimSnapshot *snapshot = &msg->sim_snapshot; // P_SimSnapshot *snapshot = &msg->sim_snapshot;
// { // {
// snapshot->world_seed = world->seed; // snapshot->world_seed = world->seed;
@ -642,7 +689,12 @@ void S_TickForever(WaveLaneCtx *lane)
if (msgs.count > 0) if (msgs.count > 0)
{ {
String packed = P_PackMessages(&packer_bbw, msgs); String packed = P_PackMessages(&packer_bbw, msgs);
NET_Push(net_pipe, client->net_key, packed, 0);
String address_str = NET_StringFromKey(frame_arena, client->net_key);
LogDebugF("Sending message to client \"%F\"", FmtString(address_str));
NET_Send(net_pipe, client->net_key, packed, NET_SendFlag_None);
ZeroStruct(&client->out_msgs); ZeroStruct(&client->out_msgs);
} }
} }
@ -699,7 +751,7 @@ void S_TickForever(WaveLaneCtx *lane)
// { // {
// if (user->is_user) // if (user->is_user)
// { // {
// NET_Push(net_pipe, user->net, packed, msg->burst); // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None);
// } // }
// } // }
// } // }
@ -709,7 +761,7 @@ void S_TickForever(WaveLaneCtx *lane)
// if (!NET_IsKeyNil(user->net)) // if (!NET_IsKeyNil(user->net))
// { // {
// String packed = P_PackMessage(frame_arena, msg); // String packed = P_PackMessage(frame_arena, msg);
// NET_Push(net_pipe, user->net, packed, msg->burst); // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None);
// } // }
// } // }
// } // }
@ -732,7 +784,7 @@ void S_TickForever(WaveLaneCtx *lane)
// { // {
// if (user->is_user) // if (user->is_user)
// { // {
// NET_Push(net_pipe, user->net, packed, msg->burst); // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None);
// } // }
// } // }
// } // }
@ -742,7 +794,7 @@ void S_TickForever(WaveLaneCtx *lane)
// if (!NET_IsKeyNil(user->net)) // if (!NET_IsKeyNil(user->net))
// { // {
// String packed = P_PackMessage(frame_arena, msg); // String packed = P_PackMessage(frame_arena, msg);
// NET_Push(net_pipe, user->net, packed, msg->burst); // NET_Send(net_pipe, user->net, packed, NET_SendFlag_None);
// } // }
// } // }
// } // }
@ -862,9 +914,28 @@ void S_TickForever(WaveLaneCtx *lane)
P.s2v.arena = old_arena; P.s2v.arena = old_arena;
P.s2v.gen = old_gen; P.s2v.gen = old_gen;
} }
ZeroStruct(P.s2v.arena); ResetArena(P.s2v.arena);
P.s2v.gen += 1; P.s2v.gen += 1;
P.s2v.pipe_stats = NET_StatsFromPipe(net_pipe); P.s2v.pipe_stats = NET_StatsFromPipe(net_pipe);
{
i64 dst_idx = 0;
P.s2v.first_debug_draw_node = 0;
P.s2v.last_debug_draw_node = 0;
P.s2v.debug_draw_nodes_count = P_tl.debug_draw_nodes_count;
P_DebugDrawNode *dst_nodes = PushStructsNoZero(P.s2v.arena, P_DebugDrawNode, P.s2v.debug_draw_nodes_count);
for (P_DebugDrawNode *src = P_tl.first_debug_draw_node; src; src = src->next)
{
P_DebugDrawNode *dst = &dst_nodes[dst_idx];
*dst = *src;
dst_idx += 1;
SllQueuePush(P.s2v.first_debug_draw_node, P.s2v.last_debug_draw_node, dst);
}
ResetArena(P_tl.debug_arena);
P_tl.first_debug_draw_node = 0;
P_tl.last_debug_draw_node = 0;
P_tl.debug_draw_nodes_count = 0;
}
} }
UnlockTicketMutex(&P.s2v_tm); UnlockTicketMutex(&P.s2v_tm);
} }

View File

@ -12,6 +12,9 @@ Struct(S_Client)
NET_Key net_key; NET_Key net_key;
P_MsgList out_msgs; P_MsgList out_msgs;
i32 name_len;
u8 name_text[P_MaxPlayerNameLen];
u64 remote_tiles_hash; u64 remote_tiles_hash;
}; };

View File

@ -217,7 +217,7 @@ String P_PackMessages(BB_Writer *bbw, P_MsgList msgs)
return result; return result;
} }
P_MsgList P_UnpackMessages(Arena *arena, String packed) P_MsgList P_UnpackMessages(Arena *arena, String packed, NET_Key sender)
{ {
P_MsgList result = Zi; P_MsgList result = Zi;
BB_Buff bb = BB_BuffFromString(packed); BB_Buff bb = BB_BuffFromString(packed);
@ -235,6 +235,8 @@ P_MsgList P_UnpackMessages(Arena *arena, String packed)
result.count += 1; result.count += 1;
// Read msg data string // Read msg data string
String data_str = BB_ReadString(arena, &bbr); String data_str = BB_ReadString(arena, &bbr);
dst_msg_node->msg.src = sender;
dst_msg_node->msg.dst = NET_NilKey;
dst_msg_node->msg.data = data_str; dst_msg_node->msg.data = data_str;
} }
else else

View File

@ -33,4 +33,4 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed);
//~ Message //~ Message
String P_PackMessages(BB_Writer *bbw, P_MsgList msgs); String P_PackMessages(BB_Writer *bbw, P_MsgList msgs);
P_MsgList P_UnpackMessages(Arena *arena, String packed); P_MsgList P_UnpackMessages(Arena *arena, String packed, NET_Key sender);

View File

@ -543,6 +543,8 @@ void V_TickForever(WaveLaneCtx *lane)
frame->equipped_tile = prev_frame->equipped_tile; frame->equipped_tile = prev_frame->equipped_tile;
frame->edit_camera_pos = prev_frame->edit_camera_pos; frame->edit_camera_pos = prev_frame->edit_camera_pos;
frame->edit_camera_zoom = prev_frame->edit_camera_zoom; frame->edit_camera_zoom = prev_frame->edit_camera_zoom;
frame->sim_key = prev_frame->sim_key;
frame->desired_sim_key = prev_frame->desired_sim_key;
frame->tick = V.current_frame_tick; frame->tick = V.current_frame_tick;
frame->time_ns = TimeNs(); frame->time_ns = TimeNs();
@ -659,6 +661,23 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
s2v_gen = P.s2v.gen; s2v_gen = P.s2v.gen;
sim_pipe_stats = P.s2v.pipe_stats; sim_pipe_stats = P.s2v.pipe_stats;
{
ResetArena(sim_debug_arena);
first_sim_debug_draw_node = 0;
last_sim_debug_draw_node = 0;
{
i64 dst_idx = 0;
P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, P.s2v.debug_draw_nodes_count);
for (P_DebugDrawNode *src = P.s2v.first_debug_draw_node; src; src = src->next)
{
P_DebugDrawNode *dst = &dst_nodes[dst_idx];
*dst = *src;
dst_idx += 1;
SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst);
}
}
}
} }
} }
UnlockTicketMutex(&P.s2v_tm); UnlockTicketMutex(&P.s2v_tm);
@ -2657,6 +2676,47 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
//////////////////////////////
//- Try to connect to server
frame->desired_sim_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
if (!NET_MatchKey(frame->sim_key, frame->desired_sim_key))
{
i64 now_ns = TimeNs();
// i64 retry_rate_ns = NsFromSeconds(0.100);
i64 retry_rate_ns = NsFromSeconds(0);
b32 should_try = 0;
if (!NET_MatchKey(prev_frame->desired_sim_key, frame->desired_sim_key))
{
should_try = 1;
}
if (V.connect_try_ns == 0 || now_ns - V.connect_try_ns > retry_rate_ns)
{
should_try = 1;
}
// if (should_try && now_ns > NsFromSeconds(1.5))
if (should_try)
{
P_MsgNode tmp_msg_node = Zi;
tmp_msg_node.msg.kind = P_MsgKind_Connect;
tmp_msg_node.msg.data = Lit("Guy");
P_MsgList tmp_msglist = Zi;
tmp_msglist.count = 1;
tmp_msglist.first = &tmp_msg_node;
tmp_msglist.last = &tmp_msg_node;
BB_ResetWriter(&packer_bbw);
String packed = P_PackMessages(&packer_bbw, tmp_msglist);
// FIXME: Real connection packet
NET_Send(net_pipe, frame->desired_sim_key, packed, NET_SendFlag_None);
V.connect_try_ns = now_ns;
}
}
////////////////////////////// //////////////////////////////
//- Pop messages from sim //- Pop messages from sim
@ -2667,35 +2727,42 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Reject messages if not from currently connected sim // FIXME: Reject messages if not from currently connected sim
P_MsgList in_msgs = Zi; P_MsgList in_msgs = Zi;
{ {
NET_MsgList net_msgs = NET_Swap(frame->arena, net_pipe); NET_MsgList net_msgs = NET_Swap(frame->arena, net_pipe);
for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next)
{ {
NET_Key net_key = net_msg->sender; NET_Key net_key = net_msg->sender;
String address_str = NET_StringFromKey(frame->arena, net_key); String address_str = NET_StringFromKey(frame->arena, net_key);
LogDebugF("Received message from server \"%F\"", FmtString(address_str)); LogDebugF("Received message from server \"%F\"", FmtString(address_str));
String packed = net_msg->data; if (NET_MatchKey(net_key, frame->desired_sim_key))
P_MsgList server_msgs = P_UnpackMessages(frame->arena, packed);
if (server_msgs.first)
{ {
if (in_msgs.last) frame->sim_key = net_key;
// String address_str = NET_StringFromKey(frame->arena, net_key);
// LogDebugF("Received message from server \"%F\"", FmtString(address_str));
String packed = net_msg->data;
P_MsgList server_msgs = P_UnpackMessages(frame->arena, packed, net_key);
if (server_msgs.first)
{ {
in_msgs.last->next = server_msgs.first; if (in_msgs.last)
{
in_msgs.last->next = server_msgs.first;
}
else
{
in_msgs.first = server_msgs.first;
}
server_msgs.first->prev = in_msgs.last;
in_msgs.last = server_msgs.last;
in_msgs.count += server_msgs.count;
} }
else
{
in_msgs.first = server_msgs.first;
}
server_msgs.first->prev = in_msgs.last;
in_msgs.last = server_msgs.last;
in_msgs.count += server_msgs.count;
} }
} }
} }
@ -2979,6 +3046,7 @@ void V_TickForever(WaveLaneCtx *lane)
P_ClearFrames(predict_world, I64Min, I64Max); P_ClearFrames(predict_world, I64Min, I64Max);
predict_frame = P_PushFrame(predict_world, sim_world->last_frame, sim_world->last_frame->tick); predict_frame = P_PushFrame(predict_world, sim_world->last_frame, sim_world->last_frame->tick);
P_DebugDrawFrame(predict_frame, VEC4(0, 0, 1, 0.75));
@ -3458,66 +3526,66 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Debug draw //- Debug draw
// { {
// // Merge vis debug draws with sim debug draws // Merge vis debug draws with sim debug draws
// P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node; P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node;
// P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node; P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node;
// if (P_tl.first_debug_draw_node) if (P_tl.first_debug_draw_node)
// { {
// if (last_debug_draw_node) if (last_debug_draw_node)
// { {
// last_debug_draw_node->next = P_tl.first_debug_draw_node; last_debug_draw_node->next = P_tl.first_debug_draw_node;
// } }
// else else
// { {
// first_debug_draw_node = P_tl.first_debug_draw_node; first_debug_draw_node = P_tl.first_debug_draw_node;
// } }
// last_debug_draw_node = P_tl.last_debug_draw_node; last_debug_draw_node = P_tl.last_debug_draw_node;
// } }
// // Push draws // Push draws
// for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next) for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next)
// { {
// Vec4 color = Vec4FromU32(n->srgb32); Vec4 color = Vec4FromU32(n->srgb32);
// i32 detail = 24; i32 detail = 24;
// f32 radius = 5; f32 radius = 5;
// switch(n->kind) switch(n->kind)
// { {
// case P_DebugDrawKind_Point: case P_DebugDrawKind_Point:
// { {
// Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p); Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p);
// V_DrawPoint(ui_p, color); V_DrawPoint(ui_p, color);
// } break; } break;
// case P_DebugDrawKind_Line: case P_DebugDrawKind_Line:
// { {
// Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0); Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0);
// Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1); Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1);
// V_DrawLine(ui_p0, ui_p1, color); V_DrawLine(ui_p0, ui_p1, color);
// } break; } break;
// case P_DebugDrawKind_Rect: case P_DebugDrawKind_Rect:
// { {
// Rng2 ui_rect = Zi; Rng2 ui_rect = Zi;
// ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0); ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0);
// ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1); ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1);
// V_DrawRect(ui_rect, color, V_DrawFlag_Line); V_DrawRect(ui_rect, color, V_DrawFlag_Line);
// } break; } break;
// case P_DebugDrawKind_Shape: case P_DebugDrawKind_Shape:
// { {
// P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape); P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape);
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line); V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
// } break; } break;
// } }
// } }
// // Reset vis debug draws // Reset vis debug draws
// ResetArena(P_tl.debug_arena); ResetArena(P_tl.debug_arena);
// P_tl.first_debug_draw_node = 0; P_tl.first_debug_draw_node = 0;
// P_tl.last_debug_draw_node = 0; P_tl.last_debug_draw_node = 0;
// P_tl.debug_draw_nodes_count = 0; P_tl.debug_draw_nodes_count = 0;
// } }
////////////////////////////// //////////////////////////////
@ -3843,13 +3911,11 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Remove this (testing) // FIXME: Remove this (testing)
NET_Key server_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
if (frame->held_buttons[Button_R] && !prev_frame->held_buttons[Button_R]) if (frame->held_buttons[Button_R] && !prev_frame->held_buttons[Button_R])
{ {
LogDebugF("Sending test payload"); LogDebugF("Sending test payload");
// NET_Push(net_pipe, server_key, STRING(P_TilesCount, predict_world->tiles), 0); NET_Send(net_pipe, frame->sim_key, STRING(P_TilesCount, predict_world->tiles), NET_SendFlag_None);
NET_Push(net_pipe, server_key, Lit("Hello there!"), 0); // NET_Send(net_pipe, frame->sim_key, Lit("Hello there!"), NET_SendFlag_None);
} }
@ -3859,7 +3925,7 @@ void V_TickForever(WaveLaneCtx *lane)
// { // {
// P_Msg *msg = &msg_node->msg; // P_Msg *msg = &msg_node->msg;
// String packed = P_PackMessage(frame->arena, msg); // String packed = P_PackMessage(frame->arena, msg);
// NET_Push(net_pipe, server_key, packed, msg->burst); // NET_Send(net_pipe, frame->sim_key, packed, NET_SendFlag_None);
// } // }
{ {
@ -3867,7 +3933,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
BB_ResetWriter(&packer_bbw); BB_ResetWriter(&packer_bbw);
String packed = P_PackMessages(&packer_bbw, P_tl.out_msgs); String packed = P_PackMessages(&packer_bbw, P_tl.out_msgs);
NET_Push(net_pipe, server_key, packed, 0); NET_Send(net_pipe, frame->sim_key, packed, NET_SendFlag_None);
} }
} }

View File

@ -235,6 +235,9 @@ Struct(V_Frame)
f64 dt; f64 dt;
RandState rand; RandState rand;
NET_Key sim_key;
NET_Key desired_sim_key;
Button held_buttons[Button_COUNT]; Button held_buttons[Button_COUNT];
V_Palette palette; V_Palette palette;
@ -305,6 +308,8 @@ Struct(V_Ctx)
V_Panel *root_panel; V_Panel *root_panel;
V_Window *dragging_window; V_Window *dragging_window;
i64 connect_try_ns;
// Notifications // Notifications
V_Notif *first_notif; V_Notif *first_notif;
V_Notif *last_notif; V_Notif *last_notif;