Frame Reader and Sender
On this page
Namespaces: Nalix.SDK.Transport.Internal, Nalix.Environment.Sequencing
Assembly: Nalix.SDK
Each concrete session in Nalix.SDK delegates low-level wire I/O, fragmentation, FramePipeline transforms (LZ4 compression and AEAD encryption), and replay window validation to an internal reader/sender pair plus a lock-free SequenceCounter.
Source Mapping
src/Nalix.SDK/Transport/Internal/Tcp/TcpFrameReader.cssrc/Nalix.SDK/Transport/Internal/Tcp/TcpFrameSender.cssrc/Nalix.SDK/Transport/Internal/Udp/UdpFrameReader.cssrc/Nalix.SDK/Transport/Internal/Udp/UdpFrameSender.cssrc/Nalix.SDK/Transport/Internal/Ws/WsFrameReader.cssrc/Nalix.SDK/Transport/Internal/Ws/WsFrameSender.cssrc/Nalix.Environment/Sequencing/SequenceCounter.cs
Transport Framing Comparison
| Transport | Reader / Sender | Wire Framing | Fragmentation | Replay / Sequence Protection |
|---|---|---|---|---|
TCP (TcpSession) | TcpFrameReader / TcpFrameSender | 2-byte little-endian ushort total frame length prefix (HeaderSize = 2) | Outbound FragmentHeader chunking (>= MaxChunkSize) / Inbound FragmentAssembler | SequenceCounter.IsValid(seq, TcpWindow) (1024-bit sliding window) |
UDP (UdpSession) | UdpFrameReader / UdpFrameSender | [8B SessionToken (outbound)][Payload][4B XxHash32 MAC] (<= MaxUdpDatagramSize) | None (single datagram MTU guard) | SequenceCounter.IsValid(seq, UdpWindow) (512-bit sliding window) |
WebSocket (WebSocketSession) | WsFrameReader / WsFrameSender | WebSocketMessageType.Binary (EndOfMessage frames) | Inbound FragmentAssembler (outbound sends complete binary WebSocket messages directly) | SequenceCounter.IsValid(seq, TcpWindow) (1024-bit sliding window) |
Outbound & Inbound Transform Pipeline
flowchart LR
subgraph Outbound["Outbound (Tcp/Udp/WsFrameSender)"]
P1["Serialized BufferLease"] --> P2["FramePipeline.ProcessOutbound<br/>(LZ4 Compress -> AEAD Encrypt with SequenceCounter.Next())"]
P2 --> P3["FragmentHeader Chunking (TCP if >= MaxChunkSize)<br/>or 8B Token + 4B XxHash32 MAC (UDP)"]
P3 --> P4["Socket / ClientWebSocket Send"]
end
subgraph Inbound["Inbound (Tcp/Udp/WsFrameReader)"]
R1["Socket / ClientWebSocket Receive"] --> R2["FragmentAssembler (TCP/WS)<br/>or 4B XxHash32 MAC Check (UDP)"]
R2 --> R3["FramePipeline.ProcessInbound<br/>(AEAD Decrypt -> LZ4 Decompress)"]
R3 --> R4["SequenceCounter.IsValid(seq, window)"]
R4 --> R5["HandleReceiveMessage(IBufferLease)"]
endKey Internal Invariants
- Serialized Outbound Sends:
TcpFrameSenderandWsFrameSenderguard socket writes with aSemaphoreSlim(1, 1)(_sendLock) so concurrentSendAsynccallers never interleave frames or fragment chunks on the stream. - Symmetric Compress-then-Encrypt: Outbound frames run
FramePipeline.ProcessOutbound(compressing payloads $\ge$CompressionOptions.MinSizeToCompressbefore AEAD encryption whenencrypt == true), while inbound frames runFramePipeline.ProcessInbound(decryptingPacketFlags.ENCRYPTEDbefore decompressingPacketFlags.COMPRESSED). SequenceCounterReplay Window: Tracks the 32-bit transport sequence number embedded in encrypted frames and rejects duplicate or out-of-window packets before they reachOnMessageReceived.