NAME

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

SYNOPSIS

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;

DESCRIPTION

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/MDNS-Imsg.md in this repository gives the full specification. That document is a curated reference, not an installed manual.

MAX_PAYLOAD

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

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

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

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

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

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.

SEE ALSO

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/MDNS-Imsg.md in this repository gives the wire format.

AUTHORS

Dick Olsson <hi@senzilla.io>