NAME
    IO::BindHandles - Bind a set of handles for buffered tunneling

VERSION
    version 0.006

SYNOPSIS
    Simple usage:

      use IO::BindHandles;
      # connect $r1 to $w1 and $r2 to $w2
      my $bh = IO::BindHandles->new(
        handles => [
          $r1, $w1, # read from $r1, write to $w1
          $r2, $w2, # read from $r2, write to $r2
        ]
      );
  
      # block until the handles close themselves
      $bh->loop;

    More complex scenario with non-blocking calls

      # connect STDIN and STDOUT to a socket in non-blocking way
      $socket->blocking(0);
      STDIN->blocking(0);
      STDOUT->blocking(0);
      my $bh = IO::BindHandles->new(
        timeout => 0, # non-blocking
        handles => [
          *STDIN, $socket,  # read from STDIN, write to socket
          $socket, *STDOUT, # read from socket, write to STDOUT
        ]
      );
  
      # do it in an explicit unblocking loop
      while (1) {
        $bh->rwcycle;
        # do something else that takes some time
        my $cond = do_something_else();
        # you can check if the bind is still valid
        last if $cond && $bh->bound;
      }

DESCRIPTION
    This module implements a buffered tunneling between a set of arbitrary
    IO handles. It basically implements a select loop on a set of handles,
    reading and writing from them using an internal buffer.

    This replicates what a dup or fdopen call would do when you can't
    actually do it, i.e.: attach STDIN/STDOUT to a socket or attach two
    different sockets toguether.

    This module doesn't perform any low-level operation on the handles, so
    it should support any IO::Handle that is supported by IO::Select.

METHODS
  new(timeout => $val, handles => [ $h1, $h2 ])
    Initializes a new BindHandles instance. The timeout value defaults to
    0.5. The handles argument receives an arrayref with pairs of handles.
    Each pair represents a binding between a read and a write handle.

    You can pass as many handle pairs as you want, and you can even use the
    same handle for a read and a write role. But you should not use the same
    handle for more then one read or one write operation.

    Future versions of this module might support "read one write many",
    "read many write one" or even "read many write many". Contact me if you
    think this features are important and I might even implement it.

    This method will call autoflush(1) on all handles.

  loop()
    Blocking loop to consume all read handles and write the data to their
    bound handles until they are no longer bound, i.e.: when the remote
    socket is closed.

    In order to avoid consuming all the CPU, this method will override the
    timeout configuration to 0.1 if it is set to 0.

  bound()
    Checks if there are still bound handles. It will return false when no
    more write handles are open or when read handles close without any write
    buffer left. This can be used as a "while" condition.

    It returns the number of valid bindings.

  rwcycle()
    Selects handles ready to read, write or with exceptions and act
    accordingly. The select might block according to the configured timeout
    value.

    This method will close handles in the following situations:

    *   When a read operation returns undef or 0 it will close the read
        handle. It will also close the write handle if there are no contents
        in the related write buffer.

    *   When a write operation returns undef or 0 it will close both the
        read and write handle.

    *   When an exception is detected in one handle, it will close it. It
        will also close the bound handle unless the exception hapenned in
        the read handle and there are contents in the write buffer.

  timeout
    Accessor for the timeout value.

BUGS
    Please submit all bugs regarding IO::BindHandles to
    bug-io-bindhandles@rt.cpan.org

AUTHOR
    Daniel Ruoso <daniel@ruoso.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2011 by Daniel Ruoso.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

