POE

 view release on metacpan or  search on metacpan

lib/POE/Component/Server/TCP.pm  view on Meta::CPAN

Filter modules are not automatically loaded.  Be sure that the program
loads the class before using it.

=head4 ClientFlushed

C<ClientFlushed> exposes POE::Wheel::ReadWrite's C<FlushedEvent> as a
callback.  It is called whenever the client's output buffer has been
fully flushed to the client socket.  At this point it's safe to shut
down the socket without losing data.

C<ClientFlushed> is useful for streaming servers, where a "flushed"
event signals the need to send more data.

  ClientFlushed => sub {
    my $data_source = $_[HEAP]{file_handle};
    my $read_count = sysread($data_source, my $buffer = "", 65536);
    if ($read_count) {
      $_[HEAP]{client}->put($buffer);
    }
    else {
      $_[KERNEL]->yield("shutdown");

lib/POE/Driver/SysRW.pm  view on Meta::CPAN

the base interface.

=head2 new [BlockSize => OCTETS]

new() creates a new buffered I/O driver that uses sysread() to read
data from a handle and syswrite() to flush data to that handle.  The
constructor accepts one optional named parameter, C<BlockSize>, which
indicates the maximum number of OCTETS that will be read at one time.

C<BlockSize> is 64 kilobytes (65536 octets) by default.  Higher values
may improve performance in streaming applications, but the trade-off
is a lower event granularity and increased resident memory usage.

Lower C<BlockSize> values reduce memory consumption somewhat with
corresponding throughput penalties.

  my $driver = POE::Driver::SysRW->new;

  my $driver = POE::Driver::SysRW->new( BlockSize => $block_size );

Drivers are commonly instantiated within POE::Wheel constructor calls:

lib/POE/Filter/HTTPD.pm  view on Meta::CPAN


sub DEBUG () { 0 }

sub BUFFER        () { 0 } # raw data buffer to build requests
sub STATE         () { 1 } # built a full request
sub REQUEST       () { 2 } # partial request being built
sub CLIENT_PROTO  () { 3 } # client protocol version requested
sub CONTENT_LEN   () { 4 } # expected content length
sub CONTENT_ADDED () { 5 } # amount of content added to request
sub CONTENT_MAX   () { 6 } # max amount of content
sub STREAMING     () { 7 } # we want to work in streaming mode
sub MAX_BUFFER    () { 8 } # max size of framing buffer
sub FIRST_UNUSED  () { 9 }

sub ST_HEADERS    () { 0x01 } # waiting for complete header block
sub ST_CONTENT    () { 0x02 } # waiting for complete body

use Carp qw(croak cluck carp);
use HTTP::Status qw( status_message RC_BAD_REQUEST RC_OK RC_LENGTH_REQUIRED 
                                    RC_REQUEST_ENTITY_TOO_LARGE );
use HTTP::Request ();

lib/POE/Filter/HTTPD.pm  view on Meta::CPAN


#------------------------------------------------------------------------------

sub new {
  my $type = shift;
  croak "$type requires an even number of parameters" if @_ and @_ & 1;
  my %params = @_;

  my $max_content = $type->__param_max( MaxContent => 1024*1024, \%params );
  my $max_buffer = $type->__param_max( MaxBuffer => 512*1024*1024, \%params );
  my $streaming = $params{Streaming} || 0;

  croak "MaxBuffer is not large enough for MaxContent"
        unless $max_buffer >= $max_content + length( $max_content ) + 1;

  delete @params{qw(MaxContent MaxBuffer Streaming)};
  carp("$type ignores unknown parameters: ", join(', ', sort keys %params))
    if scalar keys %params;

  return bless(
    [
      '',         # BUFFER
      ST_HEADERS, # STATE
      undef,      # REQUEST
      undef,      # CLIENT_PROTO
      0,          # CONTENT_LEN
      0,          # CONTENT_ADDED
      $max_content, # CONTENT_MAX
      $streaming, # STREAMING
      $max_buffer # MAX_BUFFER
    ],
    $type
  );
}

#------------------------------------------------------------------------------

sub get_one_start {
  my ($self, $stream) = @_;

lib/POE/Filter/HTTPD.pm  view on Meta::CPAN

C<MaxBuffer> sets the maximum amount of data the filter will hold in memory. 
Defaults to 512 MB (536870912 octets).  Because POE::Filter::HTTPD copies
all data into memory, setting this number to high would allow a malicious
HTTPD client to fill all server memory and swap.

C<MaxContent> sets the maximum size of the content of an HTTP request. 
Defaults to 1 MB (1038336 octets).  Because POE::Filter::HTTPD copies all
data into memory, setting this number to high would allow a malicious HTTPD
client to fill all server memory and swap.  Ignored if L</Streaming> is set.

C<Streaming> turns on request streaming mode.  Defaults to off.  In
streaming mode this filter will return either an HTTP::Request object or a
block of content.  The HTTP::Request object's content will return empty. 
The blocks of content will be parts of the request's body, up to
Content-Length in size.  You distinguish between request objects and content
blocks using C<Scalar::Util/bless> (See L</Streaming Request> below).  This
option supersedes C<MaxContent>.

=head1 CAVEATS

Some versions of libwww are known to generate invalid HTTP.  For
example, this code (adapted from the HTTP::Request::Common

lib/POE/Filter/HTTPD.pm  view on Meta::CPAN

content-less request and invalid data.  The invalid data may also
appear to be a request!  Hilarity will ensue, possibly repeatedly,
until the filter can find the next valid request.  By shutting down
the connection on the first sign of error, the client can retry its
request with a clean connection and filter.


=head1 Streaming Request

Normally POE::Filter::HTTPD reads the entire request content into memory
before returning the HTTP::Request to your code.  In streaming mode, it will
return the content separately, as unblessed scalars.  The content may be
split up into blocks of varying sizes, depending on OS and transport
constraints.  Your code can distinguish the request object from the content
blocks using L<Scalar::Util/blessed>.

    use Scalar::Util;
    use POE::Wheel::ReadWrite;
    use POE::Filter:HTTPD;

    $heap->{wheel} = POE::Wheel::ReadWrite->new( 

lib/POE/Filter/HTTPD.pm  view on Meta::CPAN

        local $ENV{'QUERY_STRING'} = $heap->{req}->uri->query;

        my $q = CGI->new();

        # now use $q as you would normaly
        # ....
    }

=head1 Streaming Response

It is possible to use POE::Filter::HTTPD for streaming content, but an
application can use it to send headers and then switch to
POE::Filter::Stream.

From the input handler (the InputEvent handler if you're using wheels,
or the ClientInput handler for POE::Component::Server::TCP):

  my $response = HTTP::Response->new(200);
  $response->push_header('Content-type', 'audio/x-mpeg');
  $_[HEAP]{client}->put($response);
  $_[HEAP]{client}->set_output_filter(POE::Filter::Stream->new());

lib/POE/Wheel/ReadWrite.pm  view on Meta::CPAN

    delete $_[HEAP]{wheels}{$id}; # shut down that wheel
  }

=head4 HighEvent

HighEvent and LowEvent are used along with HighMark and LowMark to
control the flow of streamed output.

A HighEvent is sent when the output buffer of a POE::Wheel::ReadWrite
object exceeds a certain size (the "high water" mark, or HighMark).
This advises an application to stop streaming output.  POE and Perl
really don't care if the application continues, but it's possible that
the process may run out of memory if a buffer grows without bounds.

A POE::Wheel::ReadWrite object will continue to flush its buffer even
after an application stops streaming data, until the buffer is empty.
Some streaming applications may require the buffer to always be primed
with data, however.  For example, a media server would encounter
stutters if it waited for a FlushedEvent before sending more data.

LowEvent solves the stutter problem.  A POE::Wheel::ReadWrite object
will send a LowEvent when its output buffer drains below a certain
level (the "low water" mark, or LowMark).  This notifies an
application that the buffer is small enough that it may resume
streaming.

The stutter problem is solved because the output buffer never quite
reaches empty.

HighEvent and LowEvent are edge-triggered, not level-triggered.  This
means they are emitted once whenever a POE::Wheel::ReadWrite object's
output buffer crosses the HighMark or LowMark.  If an application
continues to put() data after the HighMark is reached, it will not
cause another HighEvent to be sent.

t/10_units/05_filters/99_filterchange.t  view on Meta::CPAN

### The object is to figure out how to unglom things.

POE::Session->create(
  inline_states => {
    _start    => \&streamed_start,
    _stop     => sub { }, # placeholder for stricture test
    got_input => \&streamed_input,
  }
);

# Begin the handshaking and streaming tests.  I think this is an
# improvement over forking.

POE::Kernel->run();

### PARTIAL BUFFER TESTS.  (1) Create each test filter; (2) stuff each
### filter with a whole message and a part of one; (3) check that one
### whole message comes out; (4) check that get_pending returns the
### incomplete message; (5) check that get_pending again returns
### undef.



( run in 0.279 second using v1.01-cache-2.11-cpan-4d50c553e7e )