Choosing a Stream framer

TCP and Unix stream sockets deliver bytes, not messages. Choose framing from the protocol's wire format, then declare that framing once in the Stream subclass.

Quick selection table

| Wire pattern | Declaration name | Typical use | |---|---|---| | payload followed by a marker | Delimiter | lines, CRLF records, sentinel protocols | | every message is exactly N bytes | Fixed | fixed binary records | | 1/2/4-byte unsigned payload length | LengthPrefix | configurable binary protocols | | 4-byte network-order payload length | U32BE | common binary message convention | | length:payload, | Netstring | canonical self-delimiting records | | unsigned LEB128 length plus payload | Varint | compact binary protocols | | ASCII digits, separator, payload | DecimalLength | RFC 6587 octet-counted syslog | | none of these | no framer; use on_data | application-specific parsing |

Names are case-sensitive and are the exact final package components under Linux::Event::Framer.

A connection whose wire format changes after a handshake or upgrade may use different Stream subclasses at different stages. Use transition_to() rather than forcing every stage into one parser; unread native bytes are preserved, and a raw stage can pass its unconsumed chunk suffix with input => $bytes.

Delimiter

Use this when a non-empty byte sequence ends each message:

package CRLFStream;
use parent 'Linux::Event::Stream';
use Linux::Event::Framer 'Delimiter', "\r\n",
    max_frame => 1_048_576;

sub on_message ($stream, $message) { $stream->send($message) }

The delimiter may contain arbitrary bytes and may cross socket reads. include_delimiter => 1 includes it in inbound messages. send($payload) appends it.

There is deliberately no separate line alias. A line protocol states its actual wire delimiter directly, such as "\n" or "\r\n".

Fixed

Use this only when every message has exactly the same byte length:

use Linux::Event::Framer 'Fixed', size => 32;

send() rejects payloads that are not exactly size bytes.

LengthPrefix

Use this for a one-, two-, or four-byte unsigned payload length:

use Linux::Event::Framer 'LengthPrefix',
    bytes          => 2,
    endian         => 'big',
    include_prefix => 0,
    max_frame      => 1_048_576;

bytes defaults to 4 and endian defaults to big. The encoded value is the payload length, not the prefix-plus-payload length.

U32BE

Use this convenience family for an unsigned four-byte network-order payload length:

use Linux::Event::Framer 'U32BE',
    max_frame => 16 * 1024 * 1024;

It has the same wire form as LengthPrefix with bytes => 4 and endian => 'big'.

Netstring

Use this for canonical netstrings:

use Linux::Event::Framer 'Netstring',
    max_frame => 1_048_576;

send('hello') emits 5:hello,. The parser rejects malformed decimal lengths, leading zeroes other than the canonical zero, and a missing trailing comma.

Varint

Use this when the payload length is an unsigned LEB128 integer:

use Linux::Event::Framer 'Varint',
    include_prefix => 0,
    max_frame      => 1_048_576;

Small messages use fewer prefix bytes. The parser rejects non-canonical, overlong, or overflowing prefixes.

DecimalLength

Use this when ASCII decimal digits state the payload length:

use Linux::Event::Framer 'DecimalLength',
    separator      => ' ',
    include_prefix => 0,
    max_frame      => 1_048_576;

The separator must be one non-digit byte. The default wire form for HELLO is 5 HELLO, which matches RFC 6587 octet-counted syslog.

If no built-in matches

Do not force a protocol into the wrong framing family. Define a raw Stream and buffer or parse in on_data:

package ProprietaryStream;
use parent 'Linux::Event::Stream';

sub on_data ($stream, $bytes) {
    my $state = $stream->data;
    $state->{buffer} .= $bytes;
    # Parse as many complete application records as are available.
}

This keeps application-specific state and policy in Perl without requiring a per-connection framer-object protocol. If a framing rule is broadly useful and profiling justifies it, add it to Linux::Event as a native built-in.

Safety limits

Set max_frame for untrusted framed input. Stream also has a class-level max_buffer transport limit, defaulting to 8 MiB. The parser reports violations as Linux::Event::Error objects with type framing, invokes on_error when defined, and closes the Stream.

See FRAMING.md for the complete declaration and extension contract.