Fugu

Fugu::Imsg(3p) Perl Library Manual Fugu::Imsg(3p)

Fugu::Imsg - imsg messages over a connected stream socket

    use Fugu::Imsg;
    my $imsg = Fugu::Imsg->new(fh => $socket);
    $imsg->send(type => 8, data => $payload)
        or warn "send failed: $!";
    my $msg = $imsg->recv(timeout => 10)
        or warn "no reply";
    say $msg->{type};
    $imsg->close;

Fugu::Imsg sends and receives messages of the base-system imsg_init(3) facility over a stream socket that is already connected.

The module owns the socket: the write loop, the "SIGPIPE" guard, the poll, and the read loop. It owns no part of the frame. Protocol::Imsg frames and unframes the bytes, and this module holds one such codec. The module never opens or names a socket, and it never logs. Callers decide what a failure means.

This page does not repeat the wire format: the field layout, the length semantics, the size bounds, and the message boundary rules. Protocol::Imsg documents the codec and its three limits, and the protocol reference spec/protocol/MDNS-Imsg.md in this repository gives the full specification. That document is a curated reference, not an installed manual.

"MAX_PAYLOAD" is the largest payload one message can carry, in bytes. The module re-exports the value of the codec. A caller that splits a long reply into messages reads it here.

"new(fh => $fh)" creates a transport over the connected socket $fh. The handle is necessary. A call without the handle is a programming error, and "new" dies.

"send(type => $type, data => $bytes, peerid => $n)" frames and writes one message. "data" defaults to the empty string. "peerid" defaults to 0.

The module treats "peerid" as opaque. A request and response protocol puts its correlation value there and reads it back from "recv". The method returns 1 on success. On failure, the method returns "undef" and sets $!. This occurs when the connection failed earlier ("EPIPE"), when the payload is larger than "MAX_PAYLOAD" ("EMSGSIZE"), or when a write error occurs. The method tests the connection first, so a dead connection always reports "EPIPE": the two failures have different causes, and a caller shows this $! to the operator. If the peer closed the socket, the method reports "EPIPE". The module suppresses "SIGPIPE" during the write. The method refuses a payload that is too large, and it never truncates the payload.

"recv(timeout => $seconds)" returns one whole message as a hash reference with "type", "peerid", "pid" and "data" keys. Short reads accumulate across calls. If several messages arrive in one read, the method returns them one for each call. The method returns "undef" on a timeout, on a clean end-of-file, or on an unrecoverable framing error ("EBADMSG"). After a framing error, the connection is dead, and every later call returns "undef". Without a "timeout" the call blocks until a message or an end-of-file arrives.

"close" closes the socket and marks the connection dead. The method is idempotent and returns 1. A caller that owns the socket closes it here, and never by reaching into the object. The method also empties the decode buffer. Thus a message that arrived before the close never comes out after it.

"is_dead" reports if the connection can no longer carry a message. A "close", an end-of-file, a write error, or a framing error all lead here.

imsg_init(3), Fugu::Mdnsd

Protocol::Imsg documents the frame. It is a sidecar .pod beside the module and not a manual page, so no cross-reference here resolves to it. The protocol reference spec/protocol/MDNS-Imsg.md in this repository gives the wire format.

Dick Olsson <hi@senzilla.io>

2026-10-16 OpenBSD