NAME
IO::Handle::Record - IO::Handle extension to pass perl data structures
SYNOPSIS
use IO::Socket::UNIX;
use IO::Handle::Record;
($p, $c)=IO::Socket::UNIX->socketpair( AF_UNIX,
SOCK_STREAM,
PF_UNSPEC );
while( !defined( $pid=fork ) ) {sleep 1}
if( $pid ) {
close $c; undef $c;
$p->fds_to_send=[\*STDIN, \*STDOUT];
$p->record_opts={send_CODE=>1};
$p->write_record( {a=>'b', c=>'d'},
sub { $_[0]+$_[1] },
[qw/this is a test/] );
} else {
close $p; undef $p;
$c->record_opts={receive_CODE=>sub {eval $_[0]}};
($hashref, $coderef, $arrayref)=$c->read_record;
readline $c->received_fds->[0]; # reads from the parent's STDIN
}
INSTALLATION
perl Makefile.PL
make
make test
make install
DEPENDENCIES
* perl 5.8.0
* Storable 2.05
* Class::Member 1.3
DESCRIPTION
"IO::Handle::Record" extends the "IO::Handle" class. Since many classes
derive from "IO::Handle" these extensions can be used with "IO::File",
"IO::Socket", "IO::Pipe", etc.
The methods provided read and write lists of perl data structures. They
can pass anything that can be serialized with "Storable" even
subroutines between processes.
The following methods are added:
$handle->record_opts
This lvalue method expects a hash reference with options as
parameter. The "send_CODE" and "receive_CODE" options correspond to
localized versions of $Storable::Deparse and $Storable::Eval
respectively. Using them Perl code can be passed over a connection.
See the Storable manpage for further information.
Further, setting "forgive_me" sets $Storable::forgive_me before
"freeze()"ing anything. That way GLOB values are stored as strings.
In a few cases IO::Handle::Record passes binary data over the
connection. Normally network byte order is used there. You can save
a few CPU cycles if you set the "local_encoding" option to true. In
this case the byte order of the local machine is used.
Example:
$handle->record_opts={send_CODE=>1, receive_CODE=>1, local_encoding=>1};
$handle->fds_to_send=\@fds
Called before "write_record" sets a list of file handles that are
passed to the other end of a UNIX domain stream socket. The next
"write_record" transfers them as open files. So the other process
can read or write to them.
@fds=@{$handle->received_fds}
This is the counterpart to "fds_to_send". After a successful
"read_record" the receiving process can fetch the transferred
handles from this list. The handles are GLOBs blessed to one of:
* IO::File
* IO::Dir
* IO::Pipe
* IO::Socket::UNIX
* IO::Socket::INET
* IO::Socket::INET6
* IO::Handle
according to their type. "IO::Handle" is used as kind of catchall
type. Open devices are received as such. "IO::Handle::Record" does
not load all of these modules. That's up to you.
$handle->write_record(@data)
writes a list of perl data structures.
"write_record" returns 1 if the record has been transmitted. "undef"
is returned if $handle is non blocking and a EAGAIN condition is
met. In this case reinvoke the operation without parameters (just
"$handle->write_record") when the handle becomes ready. Otherwise it
throws an exception "IO::Handle::Record: syswrite error". Check $!
in this case.
EINTR is handled internally.
Example:
$handle->write_record( [1,2],
sub {$_[0]+$_[1]},
{ list=>[1,2,3],
hash=>{a=>'b'},
code=>sub {print "test\n";} } );
@data=$handle->read_record
reads one record of perl data structures.
On success it returns the record as list. An empty list is returned
if $handle is in non blocking mode and not enough data has been
read. Check $!==EAGAIN to catch this condition. When the handle
becomes ready just repeat the operation to read the next data chunk.
If a complete record has arrived it is returned.
On EOF an empty list is returned. To distinguish this from the non
blocking empty list return check "$handle->end_of_input".
EINTR is handled internally.
Example:
($array, $sub, $hash)=$handle->read_record;
$handle->end_of_input
When an end of file condition is read this is set to true.
($pid, $uid, $gid)=$handle->peercred
ONLY FOR UNIX DOMAIN SOCKETS ON LINUX
Return the PID, eUID and eGID of the peer at the time of the
connect.
$handle->read_buffer
$handle->expected
$handle->expect_fds
$handle->_received_fds
$handle->write_buffer
$handle->written
these methods are used internally to provide a read and write buffer
for non blocking operations.
Exceptions
* "IO::Handle::Record: sysread"
thrown in "read_record". Check $! for more information.
* "IO::Handle::Record: premature end of file"
thrown in "read_record" on end of file if according to the internal
protocol more input is expected.
* "IO::Handle::Record: busy"
thrown in "write_record" if a non-blocking write is not yet
finished. There may be only one write operation at a time. If that
hits you organise a queue.
* "IO::Handle::Record: syswrite"
thrown in "write_record" on an error of the underlying transport
method. Check $! for more information.
* Other exceptions
thrown in "read_record" and "write_record" if something cannot be
encoded or decoded by the "Storable" module. If that hits you the
"Storable" module at one side is probably too old.
EXPORT
None.
Data Transfer Format
The Perl data is serialized using Storable::freeze or Storable::nfreeze.
Storable::freeze is used if the "local_encoding" option is set,
Storable::nfreeze otherwise.
The length in bytes of this data chunk and the number of file handles
that are passed along with the data are then each "pack()"ed as a 4 byte
binary value using the "L" or "N" template. "L" is used of
"local_encoding" is in effect.
If there are file descriptors to be passed they are sent by a separate
sendmsg call along with 2 length fields only.
Both fields is the prepended to the data chunk:
+-----------------+------------------------+
| data length (N) | number of file handles |
| 4 bytes | 4 bytes |
+-----------------+------------------------+
| |
| |
| |
| |
| data |
| |
| N bytes |
| |
| |
| |
| |
| |
+------------------------------------------+
WARNING: The transfer format has changed in version 0.07 (never made it
to CPAN) and again in version 0.08.
TODO
* compression
* credential passing over UNIX domain sockets
SEE ALSO
"IO::Handle"
AUTHOR
Torsten Foertsch,
COPYRIGHT AND LICENSE
Copyright (C) 2005-2009 by Torsten Foertsch
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.