group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
MessageStream Class Reference

Length-prefixed framing layer over a TCP stream socket. More...

#include <MessageStream.hpp>

Public Member Functions

 MessageStream ()=default
 PR-5b: default-construct so server Connection (which embeds a MessageStream) can be try_emplace'd into the clients map.
 MessageStream (NET_StreamSocket *sock)
bool send (const void *data, Uint32 size)
 Send a framed message over the socket.
bool poll (const std::function< void(const void *data, Uint32 size)> &callback)
 Read all available bytes from the socket and invoke the callback once per complete message frame.
bool pumpReads ()
 Read-only half of poll(): drain the kernel into recvBuf.
void drainComplete (const std::function< void(const void *data, Uint32 size)> &callback)
 Decode-only half of poll(): invoke the callback for each complete message currently buffered.

Public Attributes

NET_StreamSocket * socket = nullptr
 Underlying SDL_net stream socket.

Private Member Functions

Uint32 recvAvailable () const noexcept
 Bytes available for parsing in recvBuf, starting at recvHead.
const Uint8 * recvFront () const noexcept
 Pointer to the first unconsumed byte.
void recvCompact ()
 Compact recvBuf: shift unconsumed bytes to the front, reset head.

Private Attributes

std::vector< Uint8 > recvBuf
 Accumulates partial data between poll() calls.
Uint32 recvHead = 0
 Offset of next unconsumed byte in recvBuf (avoids O(N) erase).

Detailed Description

Length-prefixed framing layer over a TCP stream socket.

Wraps a raw NET_StreamSocket and handles splitting the byte stream into discrete messages. Each message is sent/received with a 4-byte (host-endian) length header followed by the payload bytes.

Note
Receive draining: poll() loops NET_ReadFromStreamSocket until the kernel buffer is empty (returns 0). This is essential because each call to poll() must drain whatever the OS has queued, otherwise a snapshot stream that produces faster than the consumer reads will accumulate indefinitely in the kernel buffer (head-of-line blocking). See docs/networking.md.
recvBuf uses a head-offset compaction strategy instead of front-erase so draining N queued messages is O(N) total rather than O(N^2). The buffer is compacted (offset reset to 0) only when a threshold is crossed.

Constructor & Destructor Documentation

◆ MessageStream() [1/2]

MessageStream::MessageStream ( )
default

PR-5b: default-construct so server Connection (which embeds a MessageStream) can be try_emplace'd into the clients map.

The actual socket is assigned right after via the MessageStream(NET_StreamSocket*) form.

◆ MessageStream() [2/2]

MessageStream::MessageStream ( NET_StreamSocket * sock)
inline

Member Function Documentation

◆ drainComplete()

void MessageStream::drainComplete ( const std::function< void(const void *data, Uint32 size)> & callback)

Decode-only half of poll(): invoke the callback for each complete message currently buffered.

Stage 3c uses this from the game thread after pumpReads has run on the network thread. Together with pumpReads it does what poll() does in the single-threaded code path, just split across two threads.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ poll()

bool MessageStream::poll ( const std::function< void(const void *data, Uint32 size)> & callback)

Read all available bytes from the socket and invoke the callback once per complete message frame.

Parameters
callbackCalled with a pointer and length for each complete message.
Returns
False if the socket reports an error.
Here is the call graph for this function:

◆ pumpReads()

bool MessageStream::pumpReads ( )

Read-only half of poll(): drain the kernel into recvBuf.

Stage 3c uses this from a dedicated network thread that owns kernel I/O. The corresponding drainComplete runs on the game thread to dispatch fully-received messages — both halves take a mutex around recvBuf so they don't race.

Returns
False on socket error (caller should disconnect).
Here is the caller graph for this function:

◆ recvAvailable()

Uint32 MessageStream::recvAvailable ( ) const
inlinenodiscardprivatenoexcept

Bytes available for parsing in recvBuf, starting at recvHead.

Here is the caller graph for this function:

◆ recvCompact()

void MessageStream::recvCompact ( )
private

Compact recvBuf: shift unconsumed bytes to the front, reset head.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recvFront()

const Uint8 * MessageStream::recvFront ( ) const
inlinenodiscardprivatenoexcept

Pointer to the first unconsumed byte.

Here is the caller graph for this function:

◆ send()

bool MessageStream::send ( const void * data,
Uint32 size )

Send a framed message over the socket.

Parameters
dataPointer to the payload bytes.
sizePayload length in bytes.
Returns
False if the send fails.

Member Data Documentation

◆ recvBuf

std::vector<Uint8> MessageStream::recvBuf
private

Accumulates partial data between poll() calls.

◆ recvHead

Uint32 MessageStream::recvHead = 0
private

Offset of next unconsumed byte in recvBuf (avoids O(N) erase).

◆ socket

NET_StreamSocket* MessageStream::socket = nullptr

Underlying SDL_net stream socket.


The documentation for this class was generated from the following files: