Class LengthPrefixedFramingHandler

java.lang.Object
express.mvp.myra.transport.framing.LengthPrefixedFramingHandler
All Implemented Interfaces:
FramingHandler

public final class LengthPrefixedFramingHandler extends Object implements FramingHandler
A framing handler that uses a 4-byte big-endian length prefix.

This implementation frames messages by prepending a 4-byte (32-bit) unsigned integer in network byte order (big-endian) that specifies the payload length. This is one of the most common framing strategies used in network protocols.

Frame Format

┌────────────────────────┬─────────────────────────────────────┐
│  Length (4 bytes, BE)  │           Payload (N bytes)         │
└────────────────────────┴─────────────────────────────────────┘
          ▲                              ▲
          │                              │
    Network byte order            Variable length
    (big-endian)                  (0 to maxPayloadSize)

Configuration

The maximum payload size is configurable at construction time. The default is 16 MB (16777216 bytes), which is suitable for most applications. For protocols with smaller messages, a lower limit reduces memory requirements and provides better protection against malformed length prefixes.

Usage Example

// Create with default max size (16 MB)
FramingHandler framing = new LengthPrefixedFramingHandler();

// Or with custom max size (1 MB)
FramingHandler framing = new LengthPrefixedFramingHandler(1024 * 1024);

// Frame a message
byte[] payload = "Hello, World!".getBytes(StandardCharsets.UTF_8);
MemorySegment source = MemorySegment.ofArray(payload);
MemorySegment frame = Arena.global().allocate(payload.length + framing.getHeaderSize());
int frameLength = framing.frameMessage(source, payload.length, frame);

// Deframe a message
MemorySegment received = ...; // from network
MemorySegment output = Arena.global().allocate(framing.getMaxPayloadSize());
int payloadLength = framing.deframeMessage(received, bytesReceived, output);
if (payloadLength >= 0) {
    // Process complete message
}

Thread Safety

This class is immutable and thread-safe. The same instance can be used concurrently by multiple threads for framing and deframing operations. All configuration is fixed at construction time.

Zero-Copy Operation

This implementation uses MemorySegment.copy(MemorySegment, long, MemorySegment, long, long) for efficient data transfer between segments. No intermediate buffers are allocated during framing or deframing operations.

See Also:
  • Field Details

    • HEADER_SIZE

      public static final int HEADER_SIZE
      The size of the length prefix header in bytes.
      See Also:
    • DEFAULT_MAX_PAYLOAD_SIZE

      public static final int DEFAULT_MAX_PAYLOAD_SIZE
      The default maximum payload size: 16 MB.
      See Also:
  • Constructor Details

    • LengthPrefixedFramingHandler

      public LengthPrefixedFramingHandler()
      Creates a new length-prefixed framing handler with the default maximum payload size.

      The default maximum payload size is 16777216 bytes (16 MB).

    • LengthPrefixedFramingHandler

      public LengthPrefixedFramingHandler(int maxPayloadSize)
      Creates a new length-prefixed framing handler with the specified maximum payload size.
      Parameters:
      maxPayloadSize - the maximum payload size in bytes
      Throws:
      IllegalArgumentException - if maxPayloadSize is not positive or exceeds Integer.MAX_VALUE - HEADER_SIZE
  • Method Details

    • frameMessage

      public int frameMessage(MemorySegment source, int sourceLength, MemorySegment destination)
      Frames a message by adding protocol-specific headers to the payload.

      This method writes the framing header followed by the payload data to the destination segment. The destination must have sufficient capacity to hold the entire frame (header + payload).

      Required destination capacity: sourceLength + getHeaderSize()

      This implementation writes a 4-byte big-endian length prefix followed by the payload. The length prefix contains the payload size (not including the header itself).

      Specified by:
      frameMessage in interface FramingHandler
      Parameters:
      source - the source segment containing the message payload
      sourceLength - the number of bytes to read from the source (payload length)
      destination - the destination segment to write the framed message to
      Returns:
      the total frame length (header + payload), which equals sourceLength + getHeaderSize()
      Throws:
      FramingException - if sourceLength exceeds getMaxPayloadSize()
    • deframeMessage

      public int deframeMessage(MemorySegment source, int sourceLength, MemorySegment destination)
      Deframes a message by extracting the payload from a framed message.

      This method reads the framing header to determine the payload length, validates the frame, and copies the payload to the destination segment. If the source contains an incomplete frame (fewer bytes than indicated by the header), this method returns -1.

      Return Values

      • >= 0: The payload length; the complete payload has been written to destination
      • -1: Incomplete frame; more data is needed to complete deframing

      Note: When returning -1, the destination segment contents are undefined and should not be used.

      This implementation reads the 4-byte big-endian length prefix to determine the payload size, then copies the payload to the destination. Returns -1 if the source doesn't contain enough bytes for the complete frame (header + indicated payload length).

      Specified by:
      deframeMessage in interface FramingHandler
      Parameters:
      source - the source segment containing the framed message (header + payload)
      sourceLength - the number of bytes available in the source
      destination - the destination segment to write the extracted payload to
      Returns:
      the payload length if deframing succeeded, or -1 if the frame is incomplete
      Throws:
      FramingException - if the length prefix indicates a payload larger than getMaxPayloadSize() or is negative
    • getHeaderSize

      public int getHeaderSize()
      Returns the size of the framing header in bytes.

      This is the overhead added to each message by the framing protocol. For length-prefixed framing, this is typically 4 bytes (32-bit length field).

      Specified by:
      getHeaderSize in interface FramingHandler
      Returns:
      4 (the size of the 32-bit length prefix)
    • getMaxPayloadSize

      public int getMaxPayloadSize()
      Returns the maximum payload size that can be framed.

      Attempts to frame messages larger than this size will result in a FramingException. This limit is typically configured at construction time and may be constrained by protocol requirements or memory considerations.

      Specified by:
      getMaxPayloadSize in interface FramingHandler
      Returns:
      the maximum payload size in bytes
    • toString

      public String toString()
      Returns a string representation of this framing handler.
      Overrides:
      toString in class Object
      Returns:
      a string containing the handler type and configuration