X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst%2FEngine%2FHTTP%2FDaemon.pm;h=00daf22454918583ad5f0755ca9ada046e573ca7;hp=7903d3dc8b49981cb699988bb6d8f849a0165a38;hb=21465c884872c1ec8c30acd72796445f9eaacb31;hpb=c7b7c423324f898a2f5b3caa016cc042b89631a6 diff --git a/lib/Catalyst/Engine/HTTP/Daemon.pm b/lib/Catalyst/Engine/HTTP/Daemon.pm index 7903d3d..00daf22 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; @@ -95,9 +123,13 @@ sub run { next if $client->request; next if $client->response; - my $read = $client->sysread( my $buf, 4096 ); + my $nread = $client->sysread( my $buf, 4096 ); - unless ( defined($read) && length($buf) ) { + unless ( $nread ) { + + next if $! == EWOULDBLOCK; + next if $! == EINPROGRESS; + next if $! == EINTR; $select->remove($client); $client->close; @@ -135,20 +167,38 @@ sub run { $class->handler( $client->request, $client->response, $client ); } - for my $client ( $select->can_write(0) ) { + 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; } - my $write = $client->syswrite( $client->response_buffer, - $client->response_length, - $client->response_offset ); + my $nwrite = $client->syswrite( $client->response_buffer, + $client->response_length, + $client->response_offset ); - unless ( defined($write) ) { + unless ( $nwrite ) { + + next if $! == EWOULDBLOCK; + next if $! == EINPROGRESS; + next if $! == EINTR; $select->remove($client); $client->close; @@ -156,13 +206,23 @@ sub run { next; } - $client->response_offset += $write; + $client->response_offset += $nwrite; 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; }