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 MessageFramerInheritance
Section titled “Inheritance”Inherited Members
Section titled “Inherited Members”object.Equals(object), object.Equals(object, object), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object, object), object.ToString()
Fields
Section titled “Fields”EnvelopeLengthSize
Section titled “ EnvelopeLengthSize”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 = 4Field Value
Section titled “Field Value”HeaderSize
Section titled “ HeaderSize”Header size: 4 (length) + 4 (messageId) + 1 (type) = 9 bytes
public const int HeaderSize = 9Field Value
Section titled “Field Value”MaxMessageSize
Section titled “ MaxMessageSize”Maximum message size (16 MB).
public const int MaxMessageSize = 16777216Field Value
Section titled “Field Value”Methods
Section titled “Methods”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)Parameters
Section titled “Parameters”serializer ISerializer
messageId int
type MessageType
envelope T
payload ReadOnlySpan<byte>
Returns
Section titled “Returns”Type Parameters
Section titled “Type Parameters”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)Parameters
Section titled “Parameters”serializer ISerializer
messageId int
type MessageType
envelope TEnvelope
argument TArgument
Returns
Section titled “Returns”Type Parameters
Section titled “Type Parameters”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)Parameters
Section titled “Parameters”messageId int
type MessageType
payload ReadOnlySpan<byte>
Returns
Section titled “Returns”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)Parameters
Section titled “Parameters”stream Stream
Returns
Section titled “Returns”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)Parameters
Section titled “Parameters”stream Stream
frameReadIdleTimeout TimeSpan
Returns
Section titled “Returns”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)Parameters
Section titled “Parameters”source ReadOnlyMemory<byte>
messageId int
type MessageType
envelope ReadOnlyMemory<byte>
payload ReadOnlyMemory<byte>
Returns
Section titled “Returns”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)Parameters
Section titled “Parameters”source ReadOnlyMemory<byte>
messageId int
type MessageType
Returns
Section titled “Returns”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)Parameters
Section titled “Parameters”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)Parameters
Section titled “Parameters”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)Parameters
Section titled “Parameters”stream Stream
messageId int
type MessageType
payload ReadOnlyMemory<byte>