# NAME

IO::Framed - Convenience wrapper for frame-based I/O

# SYNOPSIS

Reading:

    #See below about seed bytes.
    my $iof = IO::Framed->new( $fh, 'seed bytes' );

    #This returns undef if the $in_fh doesn���t have at least
    #the given length (5 in this case) of bytes to read.
    $frame = $iof->read(5);

    #Don���t call this after an incomplete read().
    $line_or_undef = $iof->read_until("\x0a");

Writing, unqueued (i.e., for blocking writes):

    #The second parameter (if given) is executed immediately after the final
    #byte of the payload is written. For blocking I/O this happens
    #before the following method returns.
    $iof->write('hoohoo', sub { print 'sent!' } );

Writing, queued (for non-blocking writes):

    $iof->enable_write_queue();

    #This just adds to a memory queue:
    $iof->write('hoohoo', sub { print 'sent!' } );

    #This will be 1, since we have 1 message/frame queued to send.
    $iof->get_write_queue_count();

    #Returns 1 if it empties out the queue; 0 otherwise.
    #Partial frame writes are accommodated; the callback given as 2nd
    #argument to write() only fires when the queue item is sent completely.
    my $empty = $iof->flush_write_queue();

You can also use `IO::Framed::Read` and `IO::Framed::Write`, which
contain just the read and write features. (`IO::Framed` is actually a
subclass of them both.)

# DESCRIPTION

While writing [Net::WAMP](https://metacpan.org/pod/Net::WAMP) I noticed that I was reimplementing some of the
same patterns I���d used in [Net::WebSocket](https://metacpan.org/pod/Net::WebSocket) to parse frames from a stream:

- Only read() entire frames, with a read queue for any partials.
- Continuance when a partial frame is delivered.
- Write queue with callbacks for non-blocking I/O
- Signal resilience: resume read/write after Perl receives a trapped
signal rather than throwing/giving EINTR. (cf. [IO::SigGuard](https://metacpan.org/pod/IO::SigGuard))

These are now made available in this distribution.

# ABOUT READS

The premise here is that you expect a given number of bytes at a given time
and that a partial read should be continued once it is sensible to do so.

As a result, `read()` will throw an exception if the number of bytes given
for a continuance is not the same number as were originally requested.
`read_until()` will throw a similar exception if called between an incomplete
`read()` and its completion.

Example:

    #This reads only 2 bytes, so read() will return undef.
    $iof->read(10);

    #��� wait for readiness if non-blocking ���

    #XXX This die()s because we���re in the middle of trying to read
    #10 bytes, not 4.
    $iof->read(4);

    #If this completes the read (i.e., takes in 8 bytes), then it���ll
    #return the full 10 bytes; otherwise, it���ll return undef again.
    $iof->read(10);

EINTR prompts a redo of the read operation. EAGAIN and EWOULDBLOCK (the same
error generally, but not always) prompt an undef return.
Any other failures prompt an instance of [IO::Framed::X::ReadError](https://metacpan.org/pod/IO::Framed::X::ReadError) to be
thrown.

## End-Match Reads

Reader modules now implement a `read_until()` method, which reads arbitrarily
many bytes until
a given sequence of bytes appears then returns those bytes (plus the looked-for
sequence in the return). An obvious application for this feature
is line-by-line reads, e.g., to implement HTTP or other line-based protocols.

## Empty Reads

This class���s `read()` and `read_until()` methods will, by default, throw
an instance of
[IO::Framed::X::EmptyRead](https://metacpan.org/pod/IO::Framed::X::EmptyRead) on an empty read. This is normal and logical
behavior in contexts (like [Net::WebSocket](https://metacpan.org/pod/Net::WebSocket)) where the data stream itself
indicates when no more data will come across. In such cases an empty read
is genuinely an error condition: it either means you���re reading past when
you should, or the other side prematurely went away.

In some other cases, though, that empty read is the normal and expected way
to know that a filehandle/socket has no more data to read.

If you prefer, then, you can call the `allow_empty_read()` method to switch
to a different behavior, e.g.:

    $framed->allow_empty_read();

    my $frame = $framed->read(10);

    if (length $frame) {
        #yay, we got a frame!
    }
    elsif (defined $frame) {
        #no more data will come in, so let���s close up shop
    }
    else {
        #undef means we just haven���t gotten as much data as we want yet;
        #in this case, that means fewer than 10 bytes are available.
    }

    #----------------------------------------------------------------------
    # The same example as above with line-oriented input ���

    my $line = $framed->read_until("\x0a");

    if (length $line) {
        #yay, we got a line!
    }
    elsif (defined $line) {
        #no more data will come in, so let���s close up shop
    }
    else {
        #undef means we just haven���t gotten a full line yet.
    }

Instead of throwing the aforementioned exception, `read()` now returns
empty-string on an empty read. That means that you now have to distinguish
between multiple ���falsey��� states: undef for when the requested number
of bytes hasn���t yet arrived, and empty string for when no more bytes
will ever arrive. But it is also true now that the only exceptions thrown
are bona fide **errors**, which will suit some applications better than the
default behavior.

NB: If you want to be super-light, you can bring in IO::Framed::Read instead
of the full IO::Framed. (IO::Framed is already pretty lightweight, though.)

# ABOUT WRITES

Writes for blocking I/O are straightforward: the system will always send
the entire buffer. The OS���s `write()` won���t return until everything
meant to be written is written. Life is pleasant; life is simple. :)

Non-blocking I/O is trickier. Not only can the OS���s `write()` write
a subset of the data it���s given, but we also can���t know that the output
filehandle is ready right when we want it. This means that we have to queue up
our writes
then write them once we know (e.g., through `select()`) that the filehandle
is ready. Each `write()` call, then, enqueues one new buffer to write.

Since it���s often useful to know when a payload has been sent,
`write()` accepts an optional callback that will be executed immediately
after the last byte of the payload is written to the output filehandle.

Empty out the write queue by calling `flush_write_queue()` and looking for
a truthy response. (A falsey response means there is still data left in the
queue.) `get_write_queue_count()` gives you the number of queue items left
to write. (A partially-written item is treated the same as a fully-unwritten
one.)

Note that, while it���s acceptable to activate and deactive the write queue,
the write queue must be empty in order to deactivate it. (You���ll get a
nasty, untyped exception otherwise!)

`write()` returns undef on EAGAIN and EWOULDBLOCK. It retries on EINTR,
so you should never actually see this error from this module.
Other errors prompt a thrown exception.

NB: `enable_write_queue()` and `disable_write_queue()` return the object,
so you can instantiate thus:

    my $nb_writer = IO::Framed::Write->new($fh)->enable_write_queue();

NB: If you want to be super-light, you can bring in IO::Framed::Write instead
of the full IO::Framed. (IO::Framed is already pretty lightweight, though.)

# CUSTOM READ & WRITE LOGIC

As of version 0.04, you can override READ and WRITE methods with your
preferred logic. For example, in Linux you might prefer `send()` rather than
`syswrite()` to avoid SIGPIPE, thus:

    package My::Framed;

    use parent qw( IO::Framed::Write );

    #Only these two arguments are given.
    sub WRITE {
        return send( $_[0], $_[1], Socket::MSG_NOSIGNAL );
    }

(NB: In \*BSD OSes you can set SO\_SIGNOPIPE on the filehandle instead.)

You can likewise set `READ()` to achieve the same effect for reads.
(`READ()` receives all four arguments that `sysread()` can consume.)

**IMPORTANT:** Unlike most inherited methods, `READ()` and `WRITE()` do
NOT receive the object instance. They must follow the same semantics as
Perl���s `sysread()` and `syswrite()`: i.e., they must return the number
of bytes read/written, or return undef and set `$!` appropriately on error.

# ERROR RESPONSES

An empty read or any I/O error besides the ones mentioned previously
are indicated via an instance of one of the following exceptions.

All exceptions subclass [IO::Framed::X::Base](https://metacpan.org/pod/IO::Framed::X::Base), which itself
subclasses `X::Tiny::Base`.

- [IO::Framed::X::ReadError](https://metacpan.org/pod/IO::Framed::X::ReadError)
- [IO::Framed::X::WriteError](https://metacpan.org/pod/IO::Framed::X::WriteError)

    These both have an `OS_ERROR` property (cf. [X::Tiny::Base](https://metacpan.org/pod/X::Tiny::Base)���s accessor
    method).

- [IO::Framed::X::EmptyRead](https://metacpan.org/pod/IO::Framed::X::EmptyRead)

    No properties. If this is thrown, your peer has probably closed the connection.
    Unless you have called `allow_empty_read()` to set an alternate behavior,
    you might want to trap this exception if you call `read()`.

**NOTE:** This distribution doesn���t write to `$!`. EAGAIN and EWOULDBLOCK on
`flush_write_queue()` are ignored; all other errors are converted
to thrown exceptions.

# LEGACY CLASSES

This distribution also includes the following **DEPRECATED** legacy classes:

- IO::Framed::Write::Blocking
- IO::Framed::Write::NonBlocking
- IO::Framed::ReadWrite
- IO::Framed::ReadWrite::Blocking
- IO::Framed::ReadWrite::NonBlocking

I���ll keep these in for the time being but eventually **WILL** remove them.
Please adjust any calling code that you might have.

# REPOSITORY

[https://github.com/FGasper/p5-IO-Framed](https://github.com/FGasper/p5-IO-Framed)

# AUTHOR

Felipe Gasper (FELIPE)

# COPYRIGHT

Copyright 2017 by [Gasper Software Consulting, LLC](http://gaspersoftware.com)

# LICENSE

This distribution is released under the same license as Perl.