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.
Every built-in framer can use explicit message_batch_size policy with
on_messages when a pipelined workload benefits from fewer Perl callback
crossings. Batching changes delivery shape, not wire framing, and never waits
for future input to fill an array. See FRAMING.md for the exact
flush and transition boundaries.
See FRAMING.md for the complete declaration and extension
contract.