Skip to content

Class MessageFramer

Namespace: DotBoxD.Services.Protocol
Assembly: DotBoxD.Services.dll

Handles message framing for the DotBoxD protocol. Stream frame: [4 bytes: Total Length][4 bytes: MessageId][1 byte: MessageType][N bytes: Body]. For RPC messages the body is un-nested as [4 bytes: Envelope Length][E bytes: Envelope][P bytes: Payload], so the trailing payload can be handed to callers as a zero-copy slice of the frame buffer.

public static class MessageFramer

objectMessageFramer

object.Equals(object), object.Equals(object, object), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object, object), object.ToString()

Length prefix written before the serialized envelope so the trailing payload can be located without the serializer reporting how many bytes it consumed.

public const int EnvelopeLengthSize = 4

int

Header size: 4 (length) + 4 (messageId) + 1 (type) = 9 bytes

public const int HeaderSize = 9

int

Maximum message size (16 MB).

public const int MaxMessageSize = 16777216

int

FrameMessage<T>(ISerializer, int, MessageType, T, ReadOnlySpan<byte>)

Section titled “ FrameMessage<T>(ISerializer, int, MessageType, T, ReadOnlySpan<byte>)”

Serializes envelope and appends the raw payload bytes behind a frame header into a single pooled buffer, then patches the total length and the envelope length. The caller owns the returned DotBoxD.Services.Buffers.Payload.

public static Payload FrameMessage<T>(ISerializer serializer, int messageId, MessageType type, T envelope, ReadOnlySpan<byte> payload)

serializer ISerializer

messageId int

type MessageType

envelope T

payload ReadOnlySpan<byte>

Payload

T

FrameRequest<TEnvelope, TArgument>(ISerializer, int, MessageType, TEnvelope, TArgument)

Section titled “ FrameRequest<TEnvelope, TArgument>(ISerializer, int, MessageType, TEnvelope, TArgument)”

Serializes envelope followed immediately by argument behind a frame header into a single pooled buffer. Unlike DotBoxD.Services.Protocol.MessageFramer.FrameMessage(DotBoxD.Services.Serialization.ISerializer,System.Int32,DotBoxD.Services.Protocol.MessageType,,System.ReadOnlySpan{System.Byte}) this serializes the argument straight into the frame writer, avoiding the intermediate payload buffer and the copy. The caller owns the returned DotBoxD.Services.Buffers.Payload.

public static Payload FrameRequest<TEnvelope, TArgument>(ISerializer serializer, int messageId, MessageType type, TEnvelope envelope, TArgument argument)

serializer ISerializer

messageId int

type MessageType

envelope TEnvelope

argument TArgument

Payload

TEnvelope

TArgument

FrameToPayload(int, MessageType, ReadOnlySpan<byte>)

Section titled “ FrameToPayload(int, MessageType, ReadOnlySpan<byte>)”

Frames a message into an exact-size rented DotBoxD.Services.Buffers.Payload. The caller owns the result.

public static Payload FrameToPayload(int messageId, MessageType type, ReadOnlySpan<byte> payload)

messageId int

type MessageType

payload ReadOnlySpan<byte>

Payload

ReadMessageAsync(Stream, CancellationToken)

Section titled “ ReadMessageAsync(Stream, CancellationToken)”

Reads a framed message using the default finite idle timeout.

public static Task<MessageFramer.FramedMessage?> ReadMessageAsync(Stream stream, CancellationToken ct = default)

stream Stream

ct CancellationToken

Task<MessageFramer.FramedMessage?>

ReadMessageAsync(Stream, TimeSpan, CancellationToken)

Section titled “ ReadMessageAsync(Stream, TimeSpan, CancellationToken)”

Reads a framed message with an explicit frame-read idle timeout.

public static Task<MessageFramer.FramedMessage?> ReadMessageAsync(Stream stream, TimeSpan frameReadIdleTimeout, CancellationToken ct = default)

stream Stream

frameReadIdleTimeout TimeSpan

ct CancellationToken

Task<MessageFramer.FramedMessage?>

TryReadFrame(ReadOnlyMemory<byte>, out int, out MessageType, out ReadOnlyMemory<byte>, out ReadOnlyMemory<byte>)

Section titled “ TryReadFrame(ReadOnlyMemory<byte>, out int, out MessageType, out ReadOnlyMemory<byte>, out ReadOnlyMemory<byte>)”

Parses an un-nested RPC frame out of an in-memory buffer without copying. Both envelope and payload are slices of source and share its lifetime.

public static bool TryReadFrame(ReadOnlyMemory<byte> source, out int messageId, out MessageType type, out ReadOnlyMemory<byte> envelope, out ReadOnlyMemory<byte> payload)

source ReadOnlyMemory<byte>

messageId int

type MessageType

envelope ReadOnlyMemory<byte>

payload ReadOnlyMemory<byte>

bool

TryReadFrameHeader(ReadOnlyMemory<byte>, out int, out MessageType)

Section titled “ TryReadFrameHeader(ReadOnlyMemory<byte>, out int, out MessageType)”

Parses just the DotBoxD frame header. This supports envelope-less control frames such as request cancellation without requiring an RPC envelope prefix.

public static bool TryReadFrameHeader(ReadOnlyMemory<byte> source, out int messageId, out MessageType type)

source ReadOnlyMemory<byte>

messageId int

type MessageType

bool

ValidateOutgoingFrame(ReadOnlySpan<byte>, int)

Section titled “ ValidateOutgoingFrame(ReadOnlySpan<byte>, int)”

Validates that frame is a well-formed outgoing wire frame: at least a full header, a length prefix that exactly matches the buffer length, and within maxMessageSize. Shared by every transport’s send path so a malformed frame is rejected locally instead of being shipped to the peer (where behaviour would otherwise differ by transport). Throws System.IO.InvalidDataException on a bad frame.

public static void ValidateOutgoingFrame(ReadOnlySpan<byte> frame, int maxMessageSize = 16777216)

frame ReadOnlySpan<byte>

maxMessageSize int

WriteFrame(IBufferWriter<byte>, int, MessageType, ReadOnlySpan<byte>)

Section titled “ WriteFrame(IBufferWriter<byte>, int, MessageType, ReadOnlySpan<byte>)”

Writes a complete frame (header + payload) into the supplied buffer writer.

public static void WriteFrame(IBufferWriter<byte> writer, int messageId, MessageType type, ReadOnlySpan<byte> payload)

writer IBufferWriter<byte>

messageId int

type MessageType

payload ReadOnlySpan<byte>

WriteMessageAsync(Stream, int, MessageType, ReadOnlyMemory<byte>, CancellationToken)

Section titled “ WriteMessageAsync(Stream, int, MessageType, ReadOnlyMemory<byte>, CancellationToken)”

Writes a framed message to a stream.

public static Task WriteMessageAsync(Stream stream, int messageId, MessageType type, ReadOnlyMemory<byte> payload, CancellationToken ct = default)

stream Stream

messageId int

type MessageType

payload ReadOnlyMemory<byte>

ct CancellationToken

Task