| Protocol::Imsg(3p) | Perl Library Manual | Protocol::Imsg(3p) |
NAME
Protocol::Imsg - the OpenBSD imsg(3) frame, as bytes
SYNOPSIS
use Protocol::Imsg;
my $codec = Protocol::Imsg->new;
my $bytes = $codec->encode(type => 8, data => $payload);
$codec->append($received_bytes);
while (my $msg = $codec->next_message) {
# $msg->{type}, $msg->{peerid}, $msg->{pid}, $msg->{data}
}
DESCRIPTION
This module frames and unframes messages of the OpenBSD imsg(3) facility. It takes bytes and returns bytes: it performs no system call, it opens no file, and it names no socket. Fugu::Imsg owns the socket and uses this module for the frame.
State three limits before anything else, because each one bounds where this module is usable.
- The header is native-endian, and the format never crosses a host.
- Both ends of an imsg connection are the same machine, so imsg writes the header in the sender's own byte order. There is no byte-order negotiation and no network-order variant. Two hosts that disagree on byte order cannot exchange these frames.
- The module frames without descriptor passing.
- Native imsg can pass a file descriptor as "SCM_RIGHTS" ancillary data, on a message whose "len" carries "IMSG_FD_MARK". This module masks that mark off and never sets it, so it reads such a message as a plain frame and it can never send one. A caller that needs descriptor passing needs "recvmsg" and "sendmsg" as well, which this codec has no way to reach.
- "encode" reads $$ on every call.
- Native imsg seeds the pid once, when the buffer is initialized. This module reads it per call instead. The two agree in one process and diverge in a forked child: the child's frames carry the child's pid where native imsg would still carry the parent's. Pass "pid" explicitly when that matters.
The wire format is in spec/protocol/MDNS-Imsg.md in this repository. That document is a curated reference, not an installed manual.
CONSTANTS
- "HEADER_SIZE"
- 16, the size of "struct imsg_hdr".
- "HEADER_TEMPLATE"
- The "pack" template of the header: "L4", four native "uint32" fields in the order "type", "len", "peerid", "pid".
- "MAX_IMSGSIZE"
- 16384, the bound on the whole message.
- "MAX_PAYLOAD"
- 16368, which is "MAX_IMSGSIZE" less the header.
- "FD_MARK"
- 0x80000000, the reserved high bit of "len".
METHODS
new()
Return a codec with an empty decode buffer.
encode(%args)
Return the framed bytes of one message.
- "type"
- The message type. Required.
- "data"
- The payload. The default is the empty string.
- "peerid"
- A correlation value that is opaque to this module. The default is 0, which is what a protocol that does not correlate sends.
- "pid"
- The sender pid. The default is $$. A "pid" of 0 also gives $$, because imsg substitutes the sender's pid for a 0 the caller passes.
The method returns "undef", with $! set to "EMSGSIZE", for a payload above "MAX_PAYLOAD". An encoder must refuse a larger payload rather than truncate it.
append($bytes)
Add received bytes to the decode buffer and return the object. A partial header, a partial payload, and several whole messages at once are all normal.
next_message()
Pop one whole message off the buffer and return a hash reference with "type", "peerid", "pid", and "data". Return "undef" when more bytes are necessary.
An invalid "len" sets $! to "EBADMSG" and makes the failure permanent: native imsg drops such a connection, and so must every reader. "len" is invalid below "HEADER_SIZE" and above "MAX_IMSGSIZE".
is_failed()
Report the permanent framing failure. Nothing clears it but "reset".
reset()
Empty the buffer, clear the failure, and return the object. A transport calls it when it closes a connection, so that a frame which arrived before the close cannot come out after it.
SEE ALSO
Fugu::Imsg, spec/protocol/MDNS-Imsg.md
| 2026-10-16 | OpenBSD |