| Fugu::JSONSocket(3p) | Perl Library Manual | Fugu::JSONSocket(3p) |
NAME
Fugu::JSONSocket - newline-delimited JSON over a UNIX socket
SYNOPSIS
use Fugu::JSONSocket;
my $client = Fugu::JSONSocket->new(
path => '/tmp/qmp.sock',
timeout => 10,
greeting => 1,
);
$client->connect or die $client->error . "\n";
my $reply = $client->request({ execute => 'query-status' });
$client->disconnect;
DESCRIPTION
Fugu::JSONSocket is a client for a protocol of one JSON object for each line, in both directions. qemu(1) speaks this on its machine-protocol and guest-agent sockets, and so does every other program that wanted a protocol without inventing a framing.
The codec is JSON::PP, which is core Perl. Thus a program that only talks to a local socket needs nothing installed.
Every read has a wall-clock deadline. The "Timeout" of IO::Socket governs its own connect and accept only, so a bare "readline" blocks for ever against a peer that stopped answering on an open socket.
Bytes after a newline stay buffered. Thus a reply that shares a segment with the one after it is not lost.
new
new(%args) creates a client. The method does not open the socket. Call "connect".
These are the arguments:
- "path"
- The UNIX socket. This argument is necessary.
- "timeout"
- The deadline for one read, in seconds. The default is 10.
- "greeting"
- Read one line at connect. A protocol that announces itself before it takes a command sets this. Then "connect" reads that line and "greeting" returns it. The default is off.
connect
"connect" opens the socket, and reads the greeting when the caller asked for one. A second call on an open connection is a success that does nothing.
disconnect
"disconnect" closes the socket and drops the buffer. The method is idempotent.
request
request($hashref) encodes, sends, and reads one reply.
send_message
send_message($hashref) encodes and writes one message with its newline. Use this, and then "read_message", for a protocol whose replies do not pair one to one with its requests.
read_message
"read_message" reads one line and decodes it.
read_line
"read_line" reads one line without its terminator, and does not decode it.
is_connected
"is_connected" reports if the socket is open.
exists
"exists" reports if the socket file is there. A peer that has not started is not an error, so a caller can test before it connects.
greeting
"greeting" returns the decoded greeting, for a connection that asked for one. It is "undef" otherwise.
path
"path" returns the socket path.
error
"error" returns the most recent failure.
RETURN VALUES
"connect" and "send_message" return 1 on success and "undef" on failure.
"request" and "read_message" return the decoded value, or "undef". "read_line" returns a string, or "undef". Every failure puts its reason in "error".
"disconnect" returns the object. "is_connected" and "exists" return 1 or 0.
EXAMPLES
This example builds a command set over the client:
sub query_status ($self)
{
my $reply = $self->{socket}->request({ execute => 'query-status' });
return if !defined $reply || exists $reply->{error};
return $reply->{return};
}
ERRORS
"new" dies when "path" is absent or empty. That is a programming error.
No other method dies. A missing socket, a peer that closed the connection, a timeout, and a line that is not JSON all report through the return value and "error".
A write error and an end of file both close the connection. A later call reports "not connected" until the caller connects again.
SEE ALSO
Fugu::Imsg, IO::Socket::UNIX, JSON::PP
AUTHORS
Dick Olsson <hi@senzilla.io>
CAVEATS
The module is a client. It does not listen and does not accept.
A reply must be one line. A peer that pretty-prints its JSON across several lines does not work with this module, and no such peer exists among the protocols it was written for.
The timeout bounds one read. A reply that arrives in pieces resets nothing: the deadline covers the whole line.
| 2026-10-16 | OpenBSD |