Skip to content

fix: support large addon chunk payloads and prevent packet truncation#78

Open
Liparakis wants to merge 3 commits into
Extremelyd1:mainfrom
Liparakis:PacketTruncationFix
Open

fix: support large addon chunk payloads and prevent packet truncation#78
Liparakis wants to merge 3 commits into
Extremelyd1:mainfrom
Liparakis:PacketTruncationFix

Conversation

@Liparakis
Copy link
Copy Markdown
Contributor

Main changes

1. Fail fast on oversized normal packets

  • SSMP/Networking/Packet/Packet.cs
  • SSMP/Networking/Packet/LengthCountingPacket.cs
  • SSMP/Networking/UpdateManager.cs

Added size validation before normal addon packet data is stored/sent.

Key effects:

  • Packet.WriteLength() now throws if serialized size exceeds ushort.MaxValue
  • Packet.ValidateSize(...) measures packet-data size without allocating a full packet
  • normal addon data collection paths now validate aggregate size and roll back mutations if validation fails

This is the core truncation fix: oversized normal packets stop early and explicitly.

2. Add explicit chunk transport for large addon payloads

  • SSMP/Api/Client/Networking/IClientAddonNetworkSender.cs
  • SSMP/Api/Server/Networking/IServerAddonNetworkSender.cs
  • SSMP/Api/Client/Networking/ClientAddonNetworkSender.cs
  • SSMP/Api/Server/Networking/ServerAddonNetworkSender.cs
  • SSMP/Networking/Packet/ChunkAddonPacketBuilder.cs
  • SSMP/Networking/Packet/Data/ChunkAddonData.cs

Added new addon sender APIs for large payloads:

  • client: SendChunkData(...)
  • server: SendChunkData(...) and BroadcastChunkData(...)

Large addon payloads are now:

  1. serialized as addon-local payload bytes
  2. wrapped in a ChunkAddonData envelope containing AddonId, PacketId, and raw payload bytes
  3. queued through the chunk sender instead of the normal update packet path

ChunkAddonPacketBuilder centralizes that flow and enforces both bounds:

  • reject payloads that are too small to need chunk transport
  • reject payloads that exceed ConnectionManager.MaxChunkSize

3. Register and dispatch chunked addon payloads through connection packets

  • SSMP/Networking/Packet/Connection/ClientConnectionPacket.cs
  • SSMP/Networking/Packet/Connection/ServerConnectionPacket.cs
  • SSMP/Networking/Packet/Connection/ClientConnectionPacketId.cs
  • SSMP/Networking/Packet/Connection/ServerConnectionPacketId.cs
  • SSMP/Networking/Packet/PacketManager.cs
  • SSMP/Api/Client/Networking/ClientAddonNetworkReceiver.cs
  • SSMP/Networking/Server/NetServer.cs

Chunked addon payloads are transported as connection-packet envelopes rather than through the normal addon framing.

4. Gate large chunked addon traffic until connection setup is complete

  • SSMP/Networking/Client/ClientConnectionManager.cs
  • SSMP/Networking/Server/ServerConnectionManager.cs
  • SSMP/Networking/Client/NetClient.cs
  • SSMP/Networking/Server/NetServer.cs
  • SSMP/Networking/ConnectionManager.cs

Added explicit pre-auth vs post-auth chunk behavior.

Key changes:

  • new AllowAddonChunks gate in both connection managers
  • new MaxPreAuthChunkSize cap before registration/auth completes
  • client starts in pre-auth chunk mode and switches to full chunk mode only after successful connection setup
  • server keeps clients in pre-auth chunk mode until registration succeeds

This prevents large addon chunk traffic from becoming available too early in the connection lifecycle.

5. Rewrite chunk sender/receiver internals to support the new flow safely

  • SSMP/Networking/Chunk/ChunkSender.cs
  • SSMP/Networking/Chunk/ChunkReceiver.cs
  • SSMP/Networking/Packet/Data/SliceData.cs
  • SSMP/Networking/Packet/Data/SliceAckData.cs
  • SSMP/Networking/Client/ClientUpdateManager.cs
  • SSMP/Networking/Server/ServerUpdateManager.cs
  • SSMP/Networking/UpdateManager.cs

The chunk path needed more than just a new API. This PR also hardens the transport machinery it relies on.

Notable changes:

  • Slice IDs and slice counts now use ushort instead of the old byte-based encoding.
  • Slice packets are sent immediately instead of waiting for the normal update tick.
  • The chunk sender now uses a fixed in-flight window plus resend pacing based on ACKs.
  • Pooled arrays replace large fixed sender allocations to reduce GC pressure.
  • The receiver now validates slice counts, slice bounds, chunk size, and stale partial chunks.
  • The receiver stores per-slice segments and assembles the payload only after the full chunk arrives.
  • Transport writes are serialized behind a dedicated send lock.

6. Tighten lifecycle and disposal behavior

  • SSMP/Api/Client/Networking/INetClient.cs
  • SSMP/Networking/Client/NetClient.cs
  • SSMP/Networking/Server/NetServerClient.cs
  • SSMP/Networking/Server/NetServer.cs
  • SSMP/Networking/UpdateManager.cs

Chunk sending now owns background resources, so teardown had to be made explicit.

Key changes:

  • INetClient now extends IDisposable
  • NetClient disposes its ChunkSender
  • NetServerClient now implements IDisposable
  • server cleanup paths now dispose clients instead of only disconnecting them
  • update-manager stop paths and chunk sender lifecycle paths were tightened to reduce join/deadlock/race issues

This is supporting work, but it is necessary. Large-payload transport is not safe if disconnect/shutdown can leave sender threads or shared state behind. This branch is bigger than the title alone suggests. It is not only a packet-size check. It also changes chunk protocol encoding, chunk sender/receiver concurrency, connection-manager dispatch behavior, client/server lifecycle and disposal.

Note

XML comments / wording (i suck at those) by AI & the 2 boilerplate Packet classes
Rest by me. Please review thoroughly as this is critical concurrent code :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant