package Feersum::Connection::Handle;
use warnings;
use strict;
use Carp ();

sub new {
    Carp::croak "Cannot instantiate Feersum::Connection::Handle directly";
}

package Feersum::Connection::Reader;
use warnings;
use strict;
use base 'Feersum::Connection::Handle';
# <$fh> on psgi.input: shipped code slurps it this way (Plack::App::WrapCGI's
# "local $/; <$fh>"), so the diamond must work, not just ->getline.
# bool is explicit: a reader is always true, and leaving it to be autogenerated
# from <> would consume a line just to test the handle.
use overload '<>' => \&_diamond, 'bool' => sub { 1 }, fallback => 1;

sub write { ## no critic (BuiltinHomonyms)
    Carp::croak "can't call write() on a read-only handle" }
sub write_array {
    Carp::croak "can't call write_array() on a read-only handle" }
sub sendfile {
    Carp::croak "can't call sendfile() on a read-only handle" }

sub getlines {
    my $self = shift;
    Carp::croak "getlines() called in scalar context" unless wantarray;
    my (@lines, $line);
    push @lines, $line while defined($line = $self->getline);
    return @lines;
}

# overloaded <> is invoked once per op, in the op's context - which is the
# whole point, so the context test here is deliberate.
sub _diamond {
    my $self = shift;
    return wantarray ? $self->getlines : $self->getline;
}

package Feersum::Connection::Writer;
use warnings;
use strict;
use base 'Feersum::Connection::Handle';

sub read { ## no critic (BuiltinHomonyms)
    Carp::croak "can't call read() on a write-only handle" }
sub seek { ## no critic (BuiltinHomonyms)
    Carp::croak "can't call seek() on a write-only handle" }
sub getline {
    Carp::croak "can't call getline() on a write-only handle" }
sub getlines {
    Carp::croak "can't call getlines() on a write-only handle" }

package Feersum::Connection::Handle;
1;
__END__

=head1 NAME

Feersum::Connection::Handle - PSGI-style reader/writer objects.

=head1 SYNOPSIS

For read handles:

    my $buf;
    my $r = delete $env->{'psgi.input'};
    $r->read($buf, 1, 1); # read the second byte of input without moving offset
    $r->read($buf, $env->{CONTENT_LENGTH}); # append the whole input
    my $line = $r->getline;  # or <$r>: one record, honouring $/
    $r->close(); # discards any un-read() data

    # assuming the handle is "open":
    $r->seek(2,SEEK_CUR); # returns 1, discards skipped bytes
    $r->seek(-1,SEEK_CUR); # returns 0, can't seek back

    $r->poll_cb(sub { .... });

For write handles:

    $w->write("scalar");
    $w->write(\"scalar ref");
    $w->write_array(\@some_stuff);
    $w->poll_cb(sub {
        # use $_[0] instead of $w to avoid a closure
        $_[0]->write(\"some data");
        # can close() or unregister the poll_cb in here
        $_[0]->close();
    });

For both:

    $h->response_guard(guard { response_is_complete() });

=head1 DESCRIPTION

See the L<PSGI> spec for more information on how read/write handles are used
(The Delayed Response and Streaming Body section has details on the writer).

=head1 METHODS

=head2 Reader methods

The reader is obtained via C<< $env->{'psgi.input'} >>.

=over 4

=item C<< $r->read($buf, $len) >>

Read up to C<$len> more bytes of the request body and B<append> them to
C<$buf>.  Unlike Perl's C<read>/C<sysread>, C<$buf> is B<not> truncated first,
so the usual drain loop must clear it (or use a fresh scalar) each time round:

    my $body = '';
    while ($r->read(my $chunk, 4096)) { $body .= $chunk }   # $chunk is fresh

B<Never read into a buffer that outlives the request> - a closure variable, a
package global, or a lexical hoisted out of the loop.  Because the append is
not reset, such a buffer accumulates: within one request the body is silently
duplicated, and across requests a later handler can see an B<earlier client's>
request body still sitting in front of its own.

An optional third argument is an offset into the B<input> to read from without
advancing the current position.  Returns the number of bytes read, or 0 at end
of input.

The same warning applies to the reader itself, not just the buffer: a handle
wraps the B<connection>, not one request.  A reader kept past the response it
belongs to goes on reading whatever the connection is carrying now, so on a
keep-alive connection it returns the B<next> request's body.  Let it go when
the request is done.

The calls to C<< $r->read() >> will never block: the entire body is buffered
in memory before the Feersum request handler is called (use C<poll_cb> for
incremental delivery).  C<psgix.input.buffered> is still B<not> set in the
PSGI env hash: that flag also promises a rewindable handle, and this one is
forward-only - reads consume the buffer, and C<seek> cannot go back.
Consumers that need re-readable input (L<Plack::Request>, for example) buffer
the body themselves when the flag is absent.

=item C<< $r->getline() >>

Read one record from the input, following C<readline>/C<< <$fh> >> semantics
for C<$/>: the default C<"\n"> and any plain-string separator return one
record I<including> the separator (the final record may lack it),
C<local $/ = undef> slurps all remaining input, C<\$n> reads fixed-size
records, and C<""> reads paragraphs.  Returns C<undef> at end of input.
Like C<read()>, it never blocks, and it stops at the end of the current
request's body.

=item C<< $r->getlines() >>

All remaining records as a list.  Croaks in scalar context, as
L<IO::Handle/getlines> does.

The reader also overloads the diamond operator in both scalar and list
context, so C<< <$fh> >> works - including the slurp idiom shipped Plack code
uses on C<psgi.input> (C<< local $/; <$fh> >> in L<Plack::App::WrapCGI>):

    my $line  = <$r>;            # one record
    my @lines = <$r>;            # all remaining records (perl 5.18+)
    my $body  = do { local $/; <$r> };   # slurp

Perl hands an overloaded C<< <> >> the caller's list context only from 5.18
on; before that C<< my @lines = <$r> >> yields a single record.  Use
C<< $r->getlines >> if you need the list on older perls.  Scalar context,
including the slurp above, behaves the same everywhere.

=item C<< $r->seek(...) >>

Seeking is partially supported.  Feersum discards skipped-over bytes to
conserve memory.  B<Note:> SEEK_SET is treated the same as SEEK_CUR (always
relative to the current position), since the underlying buffer is consumed
as it is read and absolute positioning is not supported.

    $r->seek(0,SEEK_CUR);  # returns 1
    $r->seek(-1,SEEK_CUR); # returns 0
    $r->seek(-1,SEEK_SET); # returns 0
    $r->seek(2,SEEK_CUR);  # returns 1, discards 2 bytes
    $r->seek(42,SEEK_SET); # same as SEEK_CUR: discards 42 bytes
    $r->seek(-8,SEEK_END); # returns 1 if room, discards skipped bytes

=item C<< $r->close() >>

Discards the remainder of the input buffer.  It does not affect connection
reuse: when the request body has already been received in full (the usual
case) the connection stays eligible for keep-alive and an already-pipelined
next request is still served.

=item C<< $r->poll_cb(sub { .... }) >>

Register a callback to be called when more request body data is available.
The callback receives the Reader object as its argument.  On a normal
HTTP/1.x or HTTP/2 request the handler runs only after the whole body has
arrived, so the callback drains an already-complete buffer; it becomes a true
incremental reader only after C<io()>/C<psgix.io> takes over the byte stream.
See L<Feersum/"psgi.input">.

=back

=head2 Writer methods.

The writer is obtained under PSGI by sending a code/headers pair to the
"starter" callback.  Under Feersum, calls to C<< $req->start_streaming >>
return one.

=over 4

=item C<< $w->write("scalar") >>

Send the scalar as a chunk of the streaming response body.  For HTTP/1.1
clients this uses C<Transfer-Encoding: chunked> framing; for HTTP/1.0
(C<Connection: close>) streaming the data is written without chunk framing.

The calls to C<< $w->write() >> will never block and data is buffered until
transmitted.  This behaviour is indicated by C<psgix.output.buffered> in the
PSGI env hash (L<Twiggy> supports this too, for example).

B<Buffering is zero-copy: do not modify a scalar after passing it to
C<write()>.>  Feersum does not copy the bytes.  It keeps a reference to your
scalar and points the pending C<writev()> directly at that scalar's internal
string buffer, and the actual transmission happens I<after> your handler (or
callback) returns.  Modifying the scalar in the meantime changes, or frees,
the memory that is about to be sent:

    # WRONG - all five chunks arrive as "line 5"
    my $line;
    for my $i (1 .. 5) {
        $line = sprintf("line %d\n", $i);
        $w->write($line);
    }

    # WRONG - the reassignment reallocates, and the queued chunk is
    # left pointing at freed memory
    $w->write($buf);
    $buf = "x" x 200_000;

    # RIGHT - a fresh scalar per write; the old ones stay untouched
    for my $i (1 .. 5) {
        $w->write(sprintf("line %d\n", $i));
    }

Passing an expression or a literal is always safe, because the temporary it
produces is private to Feersum and nothing else can reach it.  Only scalars
you still hold a handle on are at risk.  A scalar becomes yours to reuse once
the data has actually gone out - that is, from C<< $w->close() >> onwards, or
inside a C<poll_cb> that fires after the buffer has drained past it.  If in
doubt, build a new scalar instead of reusing one; in Perl that is cheap, and
it is always correct.

The same applies to C<< $r->write(\$scalar) >>, C<< $w->write_array >> and to
scalar-ref bodies passed to C<< $req->send_response >> below.

=item C<< $w->write(\"scalar ref") >>

Works just like C<write("scalar")> above, including the zero-copy contract:
the referenced scalar must not be modified until the response completes.  This
extension is indicated by C<psgix.body.scalar_refs> in the PSGI env hash.

=item C<< $w->write_array(\@array) >>

Pass in an array-ref and it works much like the two C<write()> calls above,
except it's way more efficient than calling C<write()> over and over.
Undefined elements of the array are ignored.  The zero-copy contract applies
to every element: neither the array nor the scalars in it may be modified
until the response completes.

=item C<< $w->close() >>

Close the HTTP response (which triggers the "T-E: chunked" terminating chunk
to be sent).  This method is implicitly called when the last reference to the
writer is dropped.

=item C<< $w->poll_cb(sub { .... }) >>

Register a callback to be called when the write buffer drains to (or below)
the server's C<wbuf_low_water> threshold (default: 0, i.e. empty).  Pass in
C<undef> to unset.  The sub can call C<close()>.

A reference to the writer is passed in as the first and only argument to the
sub.  It's recommended that you use C<$_[0]> rather than closing-over on C<$w>
to prevent a circular reference.

That argument is good for the duration of the call only - it is neutralised
when the callback returns, so keeping it and writing through it later croaks
"Handle is closed".  The writer C<start_streaming> gave you stays valid; use
that one if you need to write from somewhere else.

Each call is an invitation, not a busy-poll.  A callback that has nothing to
say yet can simply return without writing: the response is then parked and
re-invited on a gentle backoff (roughly 1ms doubling to 100ms, reset by any
write), instead of being called in a tight loop.  Writing from any other
event source - a timer, an upstream socket - resumes the stream immediately,
which is the recommended shape for relays and SSE.  A zero-length
C<< $w->write("") >> counts as engagement and requests an immediate
re-invitation; use it only when more data really is imminent, since a
callback that does nothing but empty writes runs at full speed.  These rules
apply identically to HTTP/1.x (plain and TLS) and HTTP/2.  A parked response
has no write deadline - like any quietly waiting stream, ending it is the
application's job - but a client that disconnected is normally noticed at
the next paced retry (on TLS only when the close was abrupt; a graceful
close_notify is only noticed on the next write, as for any quiet stream).

Something else must then keep the writer alive.  Dropping the last reference
calls C<DESTROY>, which closes the writer and so ends the response - and
because that also clears the poll callback, a writer whose only reference was
the lexical in the handler is closed the moment the handler returns, sending
an empty response instead of a streamed one.  Stash it (in a hash keyed by the
connection, say) for as long as the response is meant to last.

=item C<< $w->sendfile($fh [, $offset, $length]) >>

Send file contents using zero-copy sendfile(2) system call. Linux only.
The file handle should be a regular file opened for reading. After calling
sendfile(), call C<close()> on the writer.

The response B<must> carry an explicit C<Content-Length>, and sendfile()
croaks otherwise.  sendfile(2) writes the file verbatim, so it cannot
chunk-frame the data: on an HTTP/1.1 streaming response with no
C<Content-Length> - which is C<Transfer-Encoding: chunked> - the file bytes
would go out unframed and desynchronise the connection.  Setting
C<Content-Length> suppresses chunking, which is what makes sendfile usable.

Optional C<$offset> (bytes to skip from start, default 0) and C<$length>
(bytes to send, default remainder of file) allow sending a portion of
the file.

B<Note:> Not supported for HTTP/2 responses. Use C<write()> instead.

    my $w = $req->start_streaming(200, [
        'Content-Type' => 'application/octet-stream',
        'Content-Length' => -s $filename,
    ]);
    open my $fh, '<', $filename or die $!;
    $w->sendfile($fh);
    close $fh;
    $w->close();

=back

=head2 Common methods.

Methods in common to both types of handles.

=over 4

=item C<< $h->return_from_psgix_io($io) >>

Returns control of the socket back to Feersum after C<psgix.io> was used.
This is the PSGI-handle equivalent of C<< $req->return_from_io($io) >> on
the connection object.  As there, the hand-back takes a private duplicate of
the descriptor, so C<$io> stays usable and is safe to release at any time.
See L<Feersum::Connection/"$req-E<gt>return_from_io($io)">.

=item C<< $h->response_guard($guard) >>

Register a guard to be triggered when the response is completely sent and the
socket is closed.  A "guard" in this context is some object that will do
something interesting in its DESTROY/DEMOLISH method. For example, L<Guard>.

B<On a keepalive connection this is not when the response finishes.>  The guard
is released at whichever comes first: the next C<response_guard()> call on the
same connection, which replaces it, or the connection closing.  So an app that
registers one on every request sees request N's guard fire during request N+1's
handler, and the last one only at close.  Do not use a guard to release a
per-request resource (a database handle, a rate-limit slot) unless keepalive is
off, or it stays held for the life of the connection.

The guard is *not* attached to this handle object; the guard is attached to
the response.

C<psgix.output.guard> is the PSGI-env extension that indicates this method.

=item C<< $h->fileno >>

Returns the file descriptor number for this connection.

=back

=head1 AUTHOR

Jeremy Stashewsky, C<< stash@cpan.org >>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2010 by Jeremy Stashewsky & Socialtext Inc.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.14 or,
at your option, any later version of Perl 5 you may have available.

=cut
