diff --git a/src/native/skate3_native_ghost_proto.h b/src/native/skate3_native_ghost_proto.h index c63bad0..b9f61b8 100644 --- a/src/native/skate3_native_ghost_proto.h +++ b/src/native/skate3_native_ghost_proto.h @@ -35,8 +35,10 @@ constexpr uint32_t kGhostMaxRoomMembers = 4; // member names shown per room // captured count are identity-padded so every mesh's referenced bones stay // in range on the receiving side. constexpr uint32_t kGhostMaxBones = 64; -// Placeholder default public relay: replace in ONE place (skate3_native_ghost.cpp). -constexpr const char* kGhostDefaultServer = "ghost.skate3.example"; +// Default public relay (the production beta relay on the OVH VPS). Clients +// connect OUTBOUND to this; no port forwarding on any client. Override at +// runtime with skate3_ghost_server. +constexpr const char* kGhostDefaultServer = "relay.mithraic.lol"; constexpr uint16_t kGhostDefaultServerPort = 40001; // A LAN host with no room advertised is implicitly in this room. constexpr const char* kGhostLobbyRoom = "LOBBY"; @@ -53,7 +55,15 @@ enum PacketType : uint8_t { kTypeRooms = 9, // relay -> client: { RoomsPayload } (the lobby browser) }; -struct alignas(1) PacketHeader { +// True byte-packing: the struct layouts below must match the wire format +// exactly (the receiver bounds-checks every packet against these sizes, and +// the relay rejects undersized datagrams with `n < sizeof(PacketHeader)`). +// alignas(1) alone is NOT enough - it sets the struct alignment but the +// compiler still pads MEMBERS to their natural alignment (a uint16_t lands +// on an even offset, inflating PacketHeader to 8 bytes and dropping every +// real 7-byte packet). +#pragma pack(push, 1) +struct PacketHeader { uint32_t magic; uint8_t type; uint16_t payload_size; // bytes following this header @@ -201,10 +211,11 @@ struct GhostPoseReassembler { // Largest payload: PoseChunkPayload (1214 bytes). constexpr uint16_t kGhostMaxPayload = 3200; -struct alignas(1) PacketBuf { +struct PacketBuf { PacketHeader h; uint8_t payload[kGhostMaxPayload]; }; +#pragma pack(pop) inline uint16_t PacketSize(const PacketBuf& p) { return uint16_t(sizeof(PacketHeader) + p.h.payload_size);