X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine%2FHTTP%2FDaemon.pm;h=aeaeea593ba230c63621955b44e111e7d90e2550;hb=a2f2cde95194a17fe2401ae58c92b5494bac599f;hp=f8f87ede22cd6ce4b7627c96a5c41c3fa35df04f;hpb=ad1fb6807fd7c3ff87da7ad4df9ee4c94507fbd1;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Engine/HTTP/Daemon.pm b/lib/Catalyst/Engine/HTTP/Daemon.pm index f8f87ed..aeaeea5 100644 --- a/lib/Catalyst/Engine/HTTP/Daemon.pm +++ b/lib/Catalyst/Engine/HTTP/Daemon.pm @@ -3,7 +3,32 @@ package Catalyst::Engine::HTTP::Daemon; use strict; use base 'Catalyst::Engine::HTTP::Base'; +use Catalyst::Exception; use IO::Select; +use IO::Socket; + +BEGIN { + + if ( $^O eq 'MSWin32' ) { + + *EINTR = sub { 10004 }; + *EINPROGRESS = sub { 10036 }; + *EWOULDBLOCK = sub { 10035 }; + *F_GETFL = sub { 0 }; + *F_SETFL = sub { 0 }; + + *IO::Socket::blocking = sub { + my ( $self, $blocking ) = @_; + my $nonblocking = $blocking ? 0 : 1; + ioctl( $self, 0x8004667e, \$nonblocking ); + }; + } + + else { + Errno->require; + Errno->import( qw[EWOULDBLOCK EINPROGRESS EINTR] ); + } +} =head1 NAME @@ -64,14 +89,17 @@ sub run { $SIG{'PIPE'} = 'IGNORE'; my $daemon = Catalyst::Engine::HTTP::Daemon::Catalyst->new( - Listen => 1, + Listen => SOMAXCONN, LocalPort => $port, ReuseAddr => 1, Timeout => 5 ); unless ( defined $daemon ) { - die(qq/Failed to create daemon. Reason: '$!'/); + + Catalyst::Exception->throw( + message => qq/Failed to create daemon. Reason: '$!'/ + ); } my $base = URI->new( $daemon->url )->canonical; @@ -82,7 +110,7 @@ sub run { while (1) { - for my $client ( $select->can_read(1) ) { + for my $client ( $select->can_read(0.01) ) { if ( $client == $daemon ) { $client = $daemon->accept; @@ -97,7 +125,11 @@ sub run { my $nread = $client->sysread( my $buf, 4096 ); - unless ( defined($nread) && length($buf) ) { + unless ( $nread ) { + + next if $! == EWOULDBLOCK; + next if $! == EINPROGRESS; + next if $! == EINTR; $select->remove($client); $client->close; @@ -135,12 +167,26 @@ sub run { $class->handler( $client->request, $client->response, $client ); } - for my $client ( $select->can_write(1) ) { + for my $client ( $select->can_write(0.01) ) { next unless $client->response; unless ( $client->response_buffer ) { - $client->response_buffer = $client->response->as_string; + + $client->response->header( Server => $daemon->product_tokens ); + + my $connection = $client->request->header('Connection') || ''; + + if ( $connection =~ /Keep-Alive/i ) { + $client->response->header( 'Connection' => 'Keep-Alive' ); + $client->response->header( 'Keep-Alive' => 'timeout=60, max=100' ); + } + + if ( $connection =~ /close/i ) { + $client->response->header( 'Connection' => 'close' ); + } + + $client->response_buffer = $client->response->as_string("\x0D\x0A"); $client->response_offset = 0; } @@ -148,7 +194,11 @@ sub run { $client->response_length, $client->response_offset ); - unless ( defined($nwrite) ) { + unless ( $nwrite ) { + + next if $! == EWOULDBLOCK; + next if $! == EINPROGRESS; + next if $! == EINTR; $select->remove($client); $client->close; @@ -160,9 +210,19 @@ sub run { if ( $client->response_offset == $client->response_length ) { - my $connection = $client->request->header('Connection'); + my $connection = $client->request->header('Connection') || ''; + my $protocol = $client->request->protocol; + my $persistent = 0; + + if ( $protocol eq 'HTTP/1.1' && $connection !~ /close/i ) { + $persistent++; + } + + if ( $protocol ne 'HTTP/1.1' && $connection =~ /Keep-Alive/i ) { + $persistent++; + } - unless ( $connection && $connection =~ /Keep-Alive/i ) { + unless ( $persistent ) { $select->remove($client); $client->close; }