File Coverage

blib/lib/POEx/HTTP/Server.pm
Criterion Covered Total %
statement 586 736 79.6
branch 118 206 57.2
condition 49 89 55.0
subroutine 111 136 81.6
pod 8 28 28.5
total 872 1195 72.9


line stmt bran cond sub pod time code
1             package POEx::HTTP::Server;
2              
3 13     13   1947953 use strict;
  13         35  
  13         910  
4 13     13   77 use warnings;
  13         20  
  13         560  
5              
6 13     13   70 use Carp qw( carp croak confess cluck );
  13         24  
  13         1266  
7              
8 13     13   5659 use POE;
  13         227024  
  13         96  
9 13     13   829825 use POE::Wheel::SocketFactory;
  13         160479  
  13         515  
10 13     13   15351 use POE::Session::PlainCall;
  13         49238  
  13         2305  
11 13     13   19759 use POE::Session::Multiplex qw( ev evo evos ), 0.0500;
  13         51884  
  13         2975  
12 13     13   8899 use POEx::HTTP::Server::Error;
  13         48  
  13         428  
13 13     13   14278 use POEx::URI;
  13         171771  
  13         543  
14 13     13   2281 use Data::Dump qw( pp );
  13         6597  
  13         1001  
15 13     13   83 use Scalar::Util qw( blessed );
  13         33  
  13         767  
16 13     13   82 use Storable qw( dclone );
  13         24  
  13         1912  
17              
18             our $VERSION = '0.0902';
19              
20             sub DEBUG () { 0 and not $INC{'Test/More.pm'} }
21              
22              
23             ##############################################################################
24             # Methods common to both the Server and the Client
25             package POEx::HTTP::Server::Base;
26              
27 13     13   85 use strict;
  13         25  
  13         491  
28 13     13   74 use warnings;
  13         25  
  13         450  
29              
30 13     13   99 use POE;
  13         23  
  13         113  
31 13     13   4633 use POE::Session::PlainCall;
  13         23  
  13         1643  
32 13     13   73 use HTTP::Status;
  13         27  
  13         5004  
33 13     13   78 use Carp;
  13         27  
  13         996  
34 13     13   14004 use Carp::Heavy;
  13         1894  
  13         383  
35              
36 13     13   72 use Data::Dump qw( pp );
  13         20  
  13         710  
37              
38 13     13   8781 BEGIN { *DEBUG = \&POEx::HTTP::Server::DEBUG }
39              
40             # Virtual methods
41 0     0   0 sub _psm_begin { die "OVERLOAD ME" }
42 0     0   0 sub _psm_end { return }
43 5     5   889 sub _stop { return }
44 0     0   0 sub error { return }
45 0     0   0 sub shutdown { return }
46              
47              
48             #######################################
49             # record the current running state
50             sub state
51             {
52 142     142   542 my( $self, $state ) = @_;
53 142         313 my $rv = $self->{state};
54 142 50       427 if( 2==@_ ) {
55 142         326 $self->{state} = $state;
56 142         614 $self->{S} = { $state => 1 };
57             }
58 142         457 return $rv;
59             }
60              
61             #######################################
62             sub D
63             {
64 0     0   0 my $self = shift;
65 0         0 $self->_D( 1, @_ );
66             }
67              
68             sub D1
69             {
70 0     0   0 my $self = shift;
71 0         0 $self->_D(2,@_);
72             }
73              
74             sub _D
75             {
76 0     0   0 my $self = shift;
77 0         0 my $level = shift;
78 0         0 my $prefix = "$$:$self->{name}:";
79 0 0       0 $prefix .= "$self->{state}:" if $self->{state};
80 0         0 my $msg = join '', @_;
81 0         0 $msg =~ s/^/$prefix /m;
82 0         0 $DB::single = 1;
83 0 0       0 unless( $msg =~ /\n$/ ) {
84 0         0 my %i = Carp::caller_info($level);
85 0         0 $msg .= " at $i{file} line $i{line}\n";
86             }
87 0         0 print STDERR $msg;
88             }
89              
90             #######################################
91             # Dispatch a call to a special handler
92             sub special_dispatch
93             {
94 80     80   279 my( $self, $why, @args ) = @_;
95              
96 80         206 my $handler = $self->{specials}{$why};
97 80 100       400 return unless $handler;
98 20         4720 $self->invoke( $why, $handler, @args );
99             }
100              
101             #######################################
102             # Invoke an HTTP or special handler
103             sub invoke
104             {
105 36     36   134 my( $self, $why, $handler, @args ) = @_;
106 36         126 DEBUG and $self->D( "Invoke handler for '$why' ($handler)" );
107 36         60 eval { $poe_kernel->call( @$handler, @args ) };
  36         232  
108 36 50       9601 if( $@ ) {
109 0         0 warn $@;
110 0 0       0 if( $self->{resp} ) {
111 0         0 $self->{resp}->error( RC_INTERNAL_SERVER_ERROR, $@ );
112             }
113             }
114             }
115              
116             #######################################
117             sub net_error
118             {
119 0     0   0 my( $self, $op, $errnum, $errstr ) = @_;
120 0 0       0 unless( $self->{specials}{on_error} ) {
121             # skip out early
122 0         0 $self->D( "$op error ($errnum) $errstr" );
123 0 0 0     0 die "$$: Failed to bind\n" if $op eq 'bind' and $errnum == 98;
124 0         0 return;
125             }
126              
127 0         0 DEBUG and $self->D( "$op error ($errnum) $errstr" );
128              
129 0         0 my $err = POEx::HTTP::Server->build_error;
130 0         0 $err->details( $op, $errnum, $errstr );
131 0         0 $self->special_dispatch( on_error => $err );
132             }
133              
134              
135              
136              
137              
138              
139              
140              
141              
142              
143              
144              
145             ##############################################################################
146             package POEx::HTTP::Server;
147              
148 13     13   75 use base qw( POEx::HTTP::Server::Base );
  13         25  
  13         52094  
149              
150              
151             #######################################
152             sub spawn
153             {
154 5     5 1 590297 my( $package, %options ) = @_;
155 5         130 my $self = $package->new( %options );
156 5         34 my $session = $self->build_session;
157 5         886 return $self->{alias};
158             }
159              
160             #######################################
161             sub new
162             {
163 6     6 0 139 my( $package, %options ) = @_;
164 6         73 my $self = bless {}, $package;
165 6         127 $self->__init( \%options );
166 6         244 $self->state( 'new' );
167 6         20 return $self;
168             }
169              
170             #######################################
171             sub __init
172             {
173 6     6   49 my( $self, $opt ) = @_;
174 6         179 $self->{N} = 1;
175 6         85 $self->{C} = 0;
176              
177 6         48 $self->{options} = delete $opt->{options};
178 6   50     322 $self->{options} ||= {};
179              
180 6         29 $self->{headers} = delete $opt->{headers};
181 6   100     96 $self->{headers} ||= { Server => join '/', ref( $self ), $VERSION };
182              
183 6         55 $self->{retry} = delete $opt->{retry};
184 6 50       44 $self->{retry} = 60 unless defined $self->{retry};
185              
186 6         42 $self->{concurrency} = delete $opt->{concurrency};
187 6 50       37 $self->{concurrency} = -1 unless defined $self->{concurrency};
188              
189 6         430 $self->{prefork} = delete $opt->{prefork};
190              
191 6         50 $self->{inet} = delete $opt->{inet};
192 6   50     90 my $I = $self->{inet} || {};
193 6   50     159 $I->{Listen} ||= 1;
194 6 50       81 $I->{Reuse} = 1 unless defined $I->{Reuse};
195 6 100       73 $I->{LocalPort} = 80 unless defined $I->{LocalPort};
196 6 50 33     38 $I->{BindAddr} = delete $I->{LocalAddr}
197             if $I->{LocalAddr} and not defined $I->{BindAddr};
198 6 100 66     113 $I->{BindPort} = delete $I->{LocalPort}
199             if $I->{LocalPort} and not defined $I->{BindPort};
200              
201 6         18 $self->{alias} = delete $opt->{alias};
202 6   100     78 $self->{alias} ||= 'HTTPd';
203 6         55 $self->{name} = $self->{alias};
204              
205 6 50       42 if( $opt->{error} ) {
206 0         0 $self->{error} = POEx::URI->new( delete $opt->{error} );
207             }
208              
209 6         29 $self->{blocksize} = delete $opt->{blocksize};
210 6   50     75 $self->{blocksize} ||= 5*1500; # 10 ethernet frames
211              
212 6         17 $self->{keepalive} = delete $opt->{keepalive};
213 6 50 100     157 if( defined $self->{keepalive} and $self->{keepalive} and
      33        
      66        
214             ( $self->{keepalive} !~ /^\d+$/ or $self->{keepalive} == 1) ) {
215             # Apache 1 default
216             #$self->{keepalive} = 15;
217             # Apache 2 default
218 0         0 $self->{keepalive} = 100;
219             }
220 6   100     100 $self->{keepalive} ||= 0;
221             # warn "keepalive=$self->{keepalive}";
222              
223 6         67 $self->{timeout} = delete $opt->{timeout};
224 6 50       38 if( not defined $self->{timeout} ) {
225             # Apache 1 default
226             #$self->{timeout} = 1200;
227             # Apache 2 default
228 6         26 $self->{timeout} = 300;
229             }
230              
231 6         41 $self->{keepalivetimeout} = delete $opt->{keepalivetimeout};
232 6 100 66     121 if( not defined $self->{keepalivetimeout} and $self->{keepalive} ) {
233             # Apache 1 default
234             #$self->{keepalivetimeout} = 15;
235             # Apache 2 default
236 1         9 $self->{keepalivetimeout} = 5;
237             }
238              
239             # if( $self->{concurrency} > 0 and $self->{prefork} ) {
240             # croak "Concurrency and prefork are incompatible. Choose one or the other";
241             # }
242              
243 6         51 $self->__init_handlers( $opt );
244             }
245              
246             #######################################
247             sub __is_special
248             {
249 60     60   341 $_[0] =~ /^(on_error|on_connect|on_disconnect|pre_request|stream_request|post_request)$/;
250             }
251             sub __init_handlers
252             {
253 12     12   1272 my( $self, $opt ) = @_;
254 12         46 $self->{handlers} = delete $opt->{handlers};
255              
256             # handler => URI
257 12 50       77 unless( $self->{handlers} ) {
258 0 0       0 croak "Missing required handler or handlers param"
259             unless $self->{handler};
260 0         0 $self->{handlers} = { '' => delete $self->{handler} };
261             }
262 12         119 $self->{todo} = [];
263             # handlers => URI
264 12 100       694 unless( ref $self->{handlers} ) {
    100          
265 2         7 $self->{todo} = [ '' ];
266 2         9 $self->{handlers} = { '' => $self->{handlers} };
267             }
268             # handlers => { match => URI, ... }
269             elsif( 'HASH' eq ref $self->{handlers} ) {
270 2         4 $self->{todo} = [ keys %{ $self->{handlers} } ];
  2         11  
271             }
272             # handlers => [ match => URI, ... }
273             else {
274 8         17 my %h;
275 8         21 while( @{ $self->{handlers} } ) {
  33         108  
276 25         36 my $re = shift @{ $self->{handlers} };
  25         64  
277 25 100       57 push @{ $self->{todo} }, $re unless __is_special( $re );
  16         33  
278 25         37 $h{$re} = shift @{ $self->{handlers} };
  25         152  
279             }
280 8         63 $self->{handlers} = \%h;
281             }
282              
283             # Get a list of special handlers
284 12         28 my $H = $self->{handlers};
285 12         181 my $S = $self->{specials} = {};
286              
287 12         49 foreach my $re ( keys %$H ) {
288 30 50       592 $H->{$re} = POEx::URI->new( $H->{$re}, 'poe' ) unless blessed $H->{$re};
289 30 100       29128 next unless __is_special( $re );
290 9         33 $S->{$re} = delete $H->{$re};
291             }
292 12         74 return;
293             }
294              
295             #######################################
296             sub build_session
297             {
298 5     5 0 11 my( $self ) = @_;
299              
300 5         11 my $package = __PACKAGE__;
301 5         561 return POEx::HTTP::Server::Session->create(
302             options => $self->{options},
303             package_states => [
304             'POEx::HTTP::Server::Base' =>
305             [ qw( _psm_begin _stop
306             error shutdown ) ],
307             $package => [
308             qw( _start build_server
309             accept retry do_retry close
310             handlers_get handlers_add handlers_remove
311             prefork_child prefork_accept error
312             prefork_parent prefork_shutdown
313             ) ],
314             'POEx::HTTP::Server::Client' => [
315             qw( input timeout
316             respond send
317             sendfile_start
318             flushed done error
319             ) ]
320             ],
321             args => [ $self ],
322             heap => { O=>$self }
323             );
324             }
325              
326             #######################################
327             sub build_handle
328             {
329 5     5 0 24 my( $self ) = @_;
330 5         19 return %{ $self->{inet} };
  5         45  
331             }
332              
333             #######################################
334             sub build_error
335             {
336 0     0 0 0 my( $package, $uri ) = @_;
337 0   0     0 $uri ||= '/';
338 0         0 return POEx::HTTP::Server::Error->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR() );
339             }
340              
341             #######################################
342             sub build_server
343             {
344 5     5 0 17 my( $self ) = @_;
345 5         7 DEBUG and $self->D( "build_server" );
346 5         22 my %invoke = $self->build_handle;
347 5         14 DEBUG and $self->D( pp \%invoke );
348 5         38 $self->{server} = POE::Wheel::SocketFactory->new(
349             %invoke,
350             SuccessEvent => ev 'accept',
351             FailureEvent => ev 'error'
352             );
353 5         8899 return;
354             }
355              
356             sub drop
357             {
358 5     5 0 16 my( $self ) = @_;
359 5         24 DEBUG and $self->D( "drop" );
360 5         91 delete $self->{server};
361 5         1904 return;
362             }
363              
364              
365             #######################################
366             sub _start
367             {
368 5     5   6494 my( $package, $self ) = @_;
369 5         8 DEBUG and $self->D( "_start" );
370 5         40 $poe_kernel->alias_set( $self->{alias} );
371 5         325 poe->session->object( HTTPd => $self );
372 5         172 return;
373             }
374              
375             sub _psm_begin
376             {
377 5     5   1921 my( $self ) = @_;
378 5         10 DEBUG and $self->D( "setup" );
379 5         26 $self->state( 'listen' );
380 5         27 $poe_kernel->sig( shutdown => ev"shutdown" );
381 5         263 $self->build_server;
382 5 50       191 if( $self->{prefork} ) {
383 0         0 $self->__init_prefork;
384 0         0 $self->{server}->pause_accept;
385             }
386             }
387              
388             sub done
389             {
390 5     5 0 12 my( $self ) = @_;
391 5         7 DEBUG and $self->D( "done" );
392 5         24 poe->session->object_unregister( 'HTTPd' );
393             }
394              
395              
396             #######################################
397             sub _stop
398             {
399 0     0   0 my( $package ) = @_;
400 0         0 my $self = poe->heap->{O};
401 0         0 DEBUG and $self->D( "_stop" );
402             }
403              
404             #######################################
405             sub shutdown
406             {
407 5     5 1 2468 my( $self ) = @_;
408 5         24 $self->state( 'shutdown' );
409 5         8 DEBUG and $self->D( "Shutdown" );
410 5 50       67 $poe_kernel->alias_remove( delete $self->{alias} ) if $self->{alias};
411 5 50       185 foreach my $name ( keys %{ $self->{clients}||{} } ) {
  5         86  
412 7         150 DEBUG and $self->D( "shutdown client=$name" );
413 7         30 $poe_kernel->yield( evo $name => 'shutdown' );
414             }
415 5         401 $self->drop;
416             }
417              
418             #######################################
419             sub accept
420             {
421 17     17 0 8670535 my( $self, $socket, $peer ) = @_;
422            
423             # T->start( 'connection' );
424 17         41 DEBUG and $self->D( "accept" );
425 17         90 $self->state( 'accept' );
426              
427 17         183 my $obj = $self->build_client( $self->{N}++, $socket );
428 17         107 poe->session->object( $obj->name, $obj );
429 17         289 $obj->build_wheel( $socket );
430             # Starting the timeout here prevents the client from keeping a connection
431             # open by never sending a request
432 17         508808 $obj->timeout_start;
433              
434 17         85 $self->concurrency_up;
435 17         94 $self->{clients}{$obj->name} = 1;
436 17         36 DEBUG and $self->D( "accept ".$obj->name." socket=".$socket );
437 17         75 $self->prefork_accepted;
438              
439 17         70 $self->state( 'listen' );
440             }
441              
442             sub close
443             {
444 17     17 0 4380 my( $self, $name ) = @_;
445 17         27 DEBUG and
446             $self->D( "close $name" );
447              
448 17         69 $self->concurrency_down;
449 17         58 delete $self->{clients}{$name};
450              
451             # Only close if we really are closed...
452 17 100       59 if( $self->{C} == 0 ) {
453 13         57 $self->prefork_close;
454             }
455              
456 17 100 100     236 unless( $self->{C} > 0 or $self->{server} ) {
457 5         25 $self->done;
458             }
459             }
460              
461             sub concurrency_up
462             {
463 17     17 0 35 my( $self ) = @_;
464 17         46 $self->{C}++;
465 17 50       85 return unless $self->{concurrency} > 0;
466 0 0       0 if( $self->{C} >= $self->{concurrency} ) {
467 0         0 DEBUG and
468             $self->D( "pause_accept C=$self->{C}" );
469 0         0 $self->{server}->pause_accept;
470 0         0 $self->{paused} = 1;
471             }
472             }
473              
474             sub concurrency_down
475             {
476 17     17 0 39 my( $self ) = @_;
477 17         45 $self->{C}--;
478 17 50       76 return unless $self->{concurrency} > 0;
479 0 0 0     0 unless( $self->{C} >= $self->{concurrency} and $self->{paused} ) {
480 0 0       0 if( $self->{server} ) {
481 0         0 DEBUG and
482             $self->D( "resume_accept C=$self->{C}" );
483 0         0 $self->{server}->resume_accept;
484             }
485 0         0 $self->{paused} = 0;
486             }
487             }
488              
489             #######################################
490             sub error
491             {
492 0     0 0 0 my( $self, $op, $errnum, $errstr, $id ) = @_;
493            
494 0         0 $self->net_error( $op, $errnum, $errstr );
495 0         0 delete $self->{server};
496              
497 0         0 $self->retry;
498             }
499              
500             #######################################
501             sub retry
502             {
503 0     0 1 0 my( $self ) = @_;
504 0 0       0 return unless $self->{retry};
505 0         0 my $tid = $poe_kernel->delay_set( ev"do_retry" => $self->{retry} );
506 0         0 DEBUG and $self->D( "Retry in $self->{retry} seconds. tid=$tid." );
507 0         0 return $tid;
508             }
509              
510             #######################################
511             sub do_retry
512             {
513 0     0 0 0 my( $self ) = @_;
514 0         0 DEBUG and $self->D( "do_retry" );
515 0         0 $self->build_server;
516             }
517              
518              
519              
520              
521             #######################################
522             sub handlers_get
523             {
524 0     0 1 0 my( $self ) = @_;
525 0         0 my $ret = dclone $self->{handlers};
526 0         0 my $S = dclone $self->{specials};
527 0         0 @{ $ret }{ keys %$S } = values %$S;
  0         0  
528 0         0 return $ret;
529             }
530              
531             #######################################
532             sub handlers_set
533             {
534 0     0 1 0 my( $self, $H ) = @_;
535 0         0 $self->__init_handlers( { handlers=>$H } );
536 0         0 return 1;
537             }
538              
539             #######################################
540             sub handlers_add
541             {
542 3     3 1 13849 my( $self, $new ) = @_;
543 3 50       14 return unless defined $new;
544 3         8 my $H = $self->{handlers};
545 3         6 my $S = $self->{specials};
546 3         8 my $T = $self->{todo};
547 3         16 $self->__init_handlers( {handlers=>$new} );
548 3         8 delete @{ $S }{ keys %{ $self->{specials} } };
  3         8  
  3         9  
549 3         10 @{ $self->{specials} }{ keys %$S } = values %$S;
  3         15  
550              
551 3         7 delete @{ $H }{ keys %{ $self->{handlers} } };
  3         7  
  3         7  
552 3         4 my @todo;
553 3         6 foreach my $re ( @$T ) {
554 12 50       30 next if $self->{handlers}{$re};
555 12         21 push @todo, $re;
556             }
557 3         7 push @todo, @{ $self->{todo} };
  3         8  
558 3         5 $self->{todo} = \@todo;
559 3         12 @{ $self->{handlers} }{ keys %$H } = values %$H;
  3         29  
560              
561 3         16 return 1;
562             }
563              
564             #######################################
565             sub handlers_remove
566             {
567 3     3 1 9209 my( $self, $del ) = @_;
568 3         5 my @list;
569             my %R;
570 3 100       13 unless( ref $del ) {
    100          
571 1         4 @list = $del;
572             }
573             elsif( 'HASH' eq ref $del ) {
574 1         6 @list = keys %$del;
575             }
576             else {
577 1         5 @list = @$del;
578             }
579 3         7 foreach my $re ( @list ) {
580 5 50       12 if( __is_special( $re ) ) {
581 0         0 delete $self->{specials}{ $re };
582             }
583             else {
584 5         9 $R{$re} = 1;
585 5         37 delete $self->{handlers}{ $re };
586             }
587             }
588              
589 3         6 my @todo;
590 3         12 foreach my $re ( @{ $self->{todo} } ) {
  3         7  
591 14 100       102 next if $R{$re};
592 9         17 push @todo, $re;
593             }
594 3         15 $self->{todo} = \@todo;
595             }
596              
597              
598             #######################################
599             sub __init_prefork
600             {
601 0     0   0 my( $self ) = @_;
602 0 0       0 return unless $self->{prefork};
603 0         0 DEBUG and $self->D( "__init_prefork" );
604              
605 0         0 $self->{parent} = 1;
606 0         0 $poe_kernel->sig( daemon_child => ev 'prefork_child' );
607 0         0 $poe_kernel->sig( daemon_parent => ev 'prefork_parent' );
608 0         0 $poe_kernel->sig( daemon_accept => ev 'prefork_accept' );
609 0         0 $poe_kernel->sig( daemon_shutdown => ev 'prefork_shutdown' );
610             }
611              
612             #######################################
613             sub prefork
614             {
615 0     0 1 0 my( $package, $status ) = @_;
616 0         0 $poe_kernel->call( Daemon => update_status => $status );
617             }
618              
619             #######################################
620             # Called to tell us we are the child
621             sub prefork_child
622             {
623 0     0 0 0 my( $self ) = @_;
624 0         0 DEBUG and
625             $self->D( "prefork_child" );
626 0         0 delete $self->{parent};
627 0         0 $self->prefork( 'wait' );
628             }
629              
630             #######################################
631             # Called when we are the child, and we move to wait state
632             sub prefork_accept
633             {
634 0     0 0 0 my( $self ) = @_;
635 0         0 DEBUG and
636             $self->D( "prefork_accept resume_once=".($self->{resume_once}||'') );
637 0 0       0 if( $self->{resume_once} ) {
638             # Daemon->peek( 1 );
639             }
640             else {
641 0         0 $self->{resume_once} = 1;
642 0         0 $self->{server}->resume_accept;
643             }
644             }
645              
646             #######################################
647             # Called when a new connection opens
648             sub prefork_accepted
649             {
650 17     17 0 35 my( $self ) = @_;
651 17         752 DEBUG and $self->D( "prefork_accepted" );
652 17 50       70 return unless $self->{prefork};
653 0         0 $self->prefork( 'req' );
654             # 2012/07 - server handles the pause_accept() etc in concurrency_down
655             #$self->{server}->pause_accept unless $self->{concurrency} > 1;
656             }
657              
658             #######################################
659             # Called when a connection is closed
660             sub prefork_close
661             {
662 13     13 0 30 my( $self ) = @_;
663 13         388 DEBUG and
664             $self->D( "prefork_close" );
665 13 50       71 return unless $self->{prefork};
666 0         0 $self->prefork( 'done' );
667             }
668              
669             #######################################
670             # Called when it is clear we are the parent
671             sub prefork_parent
672             {
673 0     0 0 0 my( $self ) = @_;
674 0         0 DEBUG and
675             $self->D( "prefork_parent" );
676 0         0 $self->{parent} = $$;
677             }
678              
679             #######################################
680             sub prefork_shutdown
681             {
682 0     0 0 0 my( $self ) = @_;
683 0         0 DEBUG and
684             $self->D( "prefork_shutdown" );
685 0         0 $self->shutdown;
686             }
687              
688             #######################################
689             sub build_client
690             {
691 17     17 0 42 my( $self, $N, $socket ) = @_;
692 17         98 my $name = join '-', $self->{alias}, $N;
693 17         94 return POEx::HTTP::Server::Client->new(
694             socket => $socket,
695             __close => ev"close",
696             alias => $self->{alias},
697             name => $name,
698             todo => $self->{todo},
699             handlers => dclone $self->{handlers},
700             specials => dclone $self->{specials},
701             headers => $self->{headers},
702             error => $self->{error},
703             blocksize => $self->{blocksize},
704             timeout => $self->{timeout},
705             keepalive => $self->{keepalive},
706             keepalivetimeout => $self->{keepalivetimeout},
707             );
708             }
709              
710             ##############################################################################
711             package POEx::HTTP::Server::Client;
712              
713 13     13   115 use strict;
  13         24  
  13         477  
714 13     13   77 use warnings;
  13         30  
  13         440  
715              
716 13     13   69 use Carp;
  13         22  
  13         898  
717 13     13   74 use HTTP::Status;
  13         34  
  13         4905  
718 13     13   85 use POE;
  13         23  
  13         106  
719 13     13   35917 use POE::Wheel::ReadWrite;
  13         160807  
  13         446  
720 13     13   24938 use POE::Filter::HTTPD;
  13         109365  
  13         457  
721 13     13   8154 use POEx::HTTP::Server::Request;
  13         35  
  13         314  
722 13     13   78 use POEx::HTTP::Server::Response;
  13         30  
  13         395  
723 13     13   6225 use POEx::HTTP::Server::Connection;
  13         39  
  13         385  
724 13     13   87 use POEx::HTTP::Server::Error;
  13         28  
  13         313  
725 13     13   71 use POE::Session::PlainCall;
  13         25  
  13         2041  
726 13     13   79 use POE::Session::Multiplex qw( ev evo rsvp );
  13         23  
  13         830  
727 13     13   23325 use POE::Filter::Stream;
  13         4838  
  13         384  
728              
729 13     13   79 use base qw( POEx::HTTP::Server::Base );
  13         28  
  13         7741  
730              
731 13     13   86 use Data::Dump qw( pp );
  13         26  
  13         834  
732              
733 13     13   906 BEGIN { *DEBUG = \&POEx::HTTP::Server::DEBUG }
734             # sub DEBUG () { 1 }
735              
736             our $HAVE_SENDFILE;
737             BEGIN {
738 13 100   13   5516 unless( defined $HAVE_SENDFILE ) {
739 11         25 $HAVE_SENDFILE = 0;
740 11     11   723 eval "
  11         4507  
  0         0  
  0         0  
741             use Sys::Sendfile 0.11;
742             ";
743             # warn $@ if $@;
744 11 50       30401 $HAVE_SENDFILE = 1 unless $@;
745             }
746             }
747              
748             #######################################
749             sub new
750             {
751 17     17   164571 my( $package, %param ) = @_;
752              
753 17         246 my $self = bless { %param }, $package;
754 17         115 $self->state( 'waiting' );
755 17         524 $self->build_connect( delete $self->{socket} );
756 17         94 return $self;
757              
758             }
759              
760 95     95   1084 sub name () { $_[0]->{name} }
761              
762             #######################################
763             sub build_wheel
764             {
765 17     17   44 my( $self, $socket ) = @_;
766              
767 17         57 my $filter = $self->build_filter;
768 17         1089 $self->{wheel} = POE::Wheel::ReadWrite->new(
769             Handle => $socket,
770             InputEvent => evo( $self->{name}, 'input' ),
771             ErrorEvent => evo( $self->{name}, 'error' ),
772             FlushedEvent => evo( $self->{name}, 'flushed' ),
773             Filter => $filter
774             );
775             }
776              
777             sub build_filter
778             {
779 17     17   473 return POE::Filter::HTTPD->new;
780             }
781              
782             sub build_stream_filter
783             {
784 2     2   47 return POE::Filter::Stream->new;
785             }
786              
787             sub build_connect
788             {
789 17     17   51 my( $self, $socket ) = @_;
790 17         331 $self->{connection} =
791             POEx::HTTP::Server::Connection->new( $self->{name}, $socket );
792             }
793              
794              
795             sub build_response
796             {
797 16     16   40 my( $self ) = @_;
798 16         342 my $resp = POEx::HTTP::Server::Response->new(RC_OK);
799 16         1602 $resp->header( 'X-PID' => $$ );
800 16 50       1996 $resp->request( $self->{req} ) if $self->{req};
801 16         231 $resp->{__respond} = rsvp"respond";
802 16         566 $resp->{__send} = rsvp"send";
803 16         481 $resp->{__sendfile} = rsvp"sendfile_start";
804 16         576 $resp->{__done} = rsvp"done";
805 16         423 return $resp;
806             }
807              
808             #######################################
809             sub _psm_begin
810             {
811 17     17   4260 my( $self ) = @_;
812 17         68 $self->on_connect;
813             }
814              
815             #######################################
816             sub on_connect
817             {
818 17     17   36 my( $self ) = @_;
819 17         124 $self->special_dispatch( on_connect => $self->{connection} );
820             }
821              
822             sub on_disconnect
823             {
824 17     17   30 my( $self ) = @_;
825 17         73 $self->special_dispatch( on_disconnect => $self->{connection} );
826             }
827              
828             #######################################
829             sub error
830             {
831 3     3   4958 my( $self, $op, $errnum, $errstr, $id ) = @_;
832              
833 3 50 33     51 if( $op eq 'read' and $errnum == 0 ) {
834             # this is a normal error
835 3         6 DEBUG and
836             $self->D( "$op error ($errnum) $errstr" );
837             }
838             else {
839 0         0 $self->net_error( $op, $errnum, $errstr );
840             }
841              
842             # 2013-04 - We use ->yield and not ->close so that POE can empty the
843             # queue of all events provoked by the last select(). This way the
844             # explicit socket->close will not cause problems.
845 3         15 $poe_kernel->yield( ev "close" );
846             }
847              
848             #######################################
849             sub close
850             {
851 17     17   29 my( $self ) = @_;
852 17         56 $self->state( 'closing' );
853 17         23 DEBUG and
854             $self->D( "Close" );
855 17         69 $poe_kernel->yield( $self->{__close}, $self->name );
856 17         1383 poe->session->object_unregister( $self->{name} );
857 17         674 $self->on_disconnect;
858 17         58 $self->close_connection;
859 17         370 $self->keepalive_stop;
860 17         159 $self->timeout_stop;
861             # use POE::Component::Daemon;
862             # Daemon->peek( 1 );
863             }
864              
865             sub close_connection
866             {
867 17     17   31 my( $self ) = @_;
868 17         30 DEBUG and $self->D( "close_connection" );
869 17         37 my $C = delete $self->{connection};
870 17         115 $C->{aborted} = 1;
871 17         37 my $W = delete $self->{wheel};
872 17 50       70 if( $W ) {
873 17         133 my $socket = $W->get_input_handle;
874 17         180 $W->DESTROY;
875 17 50       4475 if( $socket ) {
876 17         30 DEBUG and $self->D( "Shutdown socket=$socket" );
877             # Do an explicit shutdown, for Windows problems
878 17         775 shutdown( $socket, 2 );
879 17         219 $socket->close;
880             }
881             }
882             # T->end( 'connection' );
883 17         523 return;
884             }
885              
886             sub drop
887             {
888 18     18   30 my( $self ) = @_;
889 18         100 delete $self->{req};
890 18         461 delete $self->{resp};
891             }
892              
893              
894             #######################################
895             sub input
896             {
897 18     18   3373039 my( $self, $req ) = @_;
898             # T->start( 'REQ' );
899 18         41 DEBUG and $self->D( "input" );
900              
901 18         74 $self->state( 'handling' );
902              
903             # stop the timer that was started on accept
904 18         76 $self->timeout_stop;
905             # stop any keepalive timer we might have
906 18         2416 $self->keepalive_stop;
907              
908 18 50       200 if( $self->{req} ) {
909 0         0 warn "New request while we still have a request";
910 0         0 $self->pending_push( $req );
911 0         0 return;
912             }
913              
914 18 100       264 if ( $req->isa("HTTP::Response") ) {
915 2         13 $self->input_error( $req );
916 2         16 return;
917             }
918              
919             # Rebless to our package
920 16         135 $self->{req} = bless $req, 'POEx::HTTP::Server::Request';
921 16         142 $req->connection( $self->{connection} );
922              
923             # Tell the user code
924 16         63 $self->special_dispatch( 'pre_request', $req );
925              
926             # Build response
927 16         70 $self->{resp} = $self->build_response;
928 16         77 $self->reset_req;
929              
930 16         92 $self->dispatch;
931             }
932              
933             sub input_error
934             {
935 2     2   4 my( $self, $resp ) = @_;
936 2         3 DEBUG and $self->D( "ERROR ", $resp->status_line );
937 2         5 bless $resp, 'POEx::HTTP::Server::Error';
938 2         9 $self->special_dispatch( on_error => $resp );
939 2         81 $self->{req} = POEx::HTTP::Server::Request->new( ERROR => '/' );
940 2         393 $self->{req}->connection( $self->{connection} );
941 2         22 $self->{req}->protocol( "HTTP/1.1" );
942 2         45 $self->{resp} = $resp;
943 2         10 $self->reset_req;
944 2         5 $self->{shutdown} = 1;
945              
946 2         7 $self->respond;
947             }
948              
949             sub reset_req
950             {
951 18     18   69 my( $self ) = @_;
952            
953 18 50       78 if( delete $self->{stream_wheel} ) {
954             # Second request on a keep-alive wheel. Switch back to Filter::HTTPD
955 0         0 $self->{wheel}->set_output_filter( $self->build_filter );
956             }
957 18         92 $self->{will_close} = 0;
958 18         66 $self->{once} = 0;
959 18         60 $self->{flushing} = 0;
960             }
961              
962             #######################################
963             sub output
964             {
965 29     29   189 my( $self, $something ) = @_;
966              
967 29         54 $self->{flushing} = 1;
968             # T->point( REQ => 'output' );
969 29         248 $self->{wheel}->put( $something );
970             }
971              
972             #######################################
973             ## POE::Wheel::ReadWrite is telling us that what we wrote has been written
974             sub flushed
975             {
976 29     29   36780 my( $self ) = @_;
977              
978 29         64 $self->{flushing} = 0;
979 29         41 DEBUG and $self->D( "Flushed" );
980            
981             # wrote a bit of a file
982 29 100       109 if( $self->{sendfile} ) {
983 1         6 return $self->sendfile_next; # send some more
984             }
985              
986             # Request has finished
987 28 100 66     461 if( not $self->{resp} or $self->{S}{done} or $self->{resp}->finished ) {
    50 100        
988 18         78 return $self->finish_request;
989             }
990              
991             # streaming?
992             elsif( $self->{resp}->streaming ) {
993 10         22 return $self->send_more; # send some more
994             }
995              
996             # The last possiblity is that calls to ->send have filled up the Wheel's
997             # or the driver's buffer and it was flushed.
998             }
999              
1000              
1001              
1002              
1003             #######################################
1004             # Clean up after a request
1005             sub finish_request
1006             {
1007 18     18   94 my( $self ) = @_;
1008 18         59 $self->state( 'done' );
1009 18         22 DEBUG and $self->D( 'finish_request' );
1010              
1011 18 100       71 if( $self->keepalive_start ) {
1012             # if we have keepalive set, then we don't need the TCP timeout
1013 4         10 $self->timeout_stop;
1014             }
1015             # If we don't have a keepalive, {will_close} will be true and that will
1016             # force a socket close
1017              
1018             # next 3 MUST be in this order if we want post_request to always come
1019             # before on_disconnect (which is posted from ->close())
1020 18         376 $self->special_dispatch( 'post_request', $self->{req}, $self->{resp} );
1021 18 100       94 $self->close if $self->{will_close};
1022 18         1230 $self->drop;
1023 18         77 $self->pending_next;
1024             # T->end( 'REQ' );
1025             }
1026              
1027              
1028              
1029              
1030              
1031             #######################################
1032             sub dispatch
1033             {
1034 16     16   40 my( $self ) = @_;
1035 16 50 33     817 my $path = $self->{req} && $self->{req}->uri ?
1036             $self->{req}->uri->path : '/';
1037              
1038 16         1087 my( $why, $handler ) = $self->find_handler( $path );
1039 16 50       75 if( $handler ) {
1040             # T->point( REQ => "handler $re" );
1041 16         280 $self->invoke( $why, $handler, $self->{req}, $self->{resp} );
1042             }
1043             else {
1044 0         0 $self->{resp}->error( RC_NOT_FOUND, "No handler for path $path.\n" );
1045             }
1046             }
1047            
1048             #######################################
1049             sub find_handler
1050             {
1051 20     20   9696 my( $self, $path ) = @_;
1052 20         33 DEBUG and $self->D( "Request for $path" );
1053 20         38 foreach my $re ( @{ $self->{todo} } ) {
  20         92  
1054 39 100 100     627 next unless $re eq '' or $path =~ /$re/;
1055 19         199 return( $re, $self->{handlers}{$re} );
1056             }
1057 1         4 return;
1058             }
1059              
1060             #######################################
1061             sub respond
1062             {
1063 16     16   3140 my( $self ) = @_;
1064              
1065 16         35 DEBUG and $self->D( "respond" );
1066             # XXX - make this next bit a POE-croak
1067 16 50       67 confess "Responding more then once to a request" if $self->{once}++;
1068              
1069 16 50       105 unless( $self->{resp}->headers_sent ) {
1070 16         79 $self->should_close;
1071 16         58 $self->send_headers;
1072             }
1073              
1074 16         62 $self->{resp}->content( undef() );
1075 16         300 $self->timeout_start();
1076 16         92 return;
1077             }
1078              
1079             sub send_headers
1080             {
1081 18     18   32 my( $self ) = @_;
1082              
1083 18         28 DEBUG and $self->D( "Response: ".$self->{resp}->status_line );
1084 18         62 $self->__fix_headers;
1085 18         644 $self->output( $self->{resp} );
1086 18         8324 $self->{resp}->headers_sent( 1 );
1087             }
1088              
1089              
1090              
1091             #######################################
1092             sub __fix_headers
1093             {
1094 18     18   37 my( $self ) = @_;
1095 18         31 while( my( $h, $v ) = each %{$self->{headers}} ) {
  36         1304  
1096 18 50       72 next if $self->{resp}->header( $h );
1097 18         721 $self->{resp}->header( $h => $v);
1098             }
1099              
1100             # Tell the browser the connection should close
1101 18 50 66     1340 if( $self->{will_close} and $self->{req} and $self->{req}->protocol eq 'HTTP/1.1' ) {
      66        
1102 14         194 my $c = $self->{resp}->header( 'Connection' );
1103 14 50       518 if( $c ) { $c .= ",close" }
  0         0  
1104 14         35 else { $c = 'close' }
1105 14         62 $self->{resp}->header( 'Connection', $c );
1106             }
1107             }
1108              
1109             #######################################
1110             sub should_close
1111             {
1112 18     18   146 my( $self ) = @_;
1113 18         43 $self->{will_close} = 1;
1114 18 50 33     611 if ( $self->{req} and $self->{req}->protocol eq 'HTTP/1.1' ) {
1115 18         223 $self->{will_close} = 0; # keepalive
1116             # It turns out the connection field can contain multiple
1117             # comma separated values
1118 18   100     115 my $conn = $self->{req}->header('Connection')||'';
1119 18 100       1249 $self->{will_close} = 1 if qq(,$conn,) =~ /,\s*close\s*,/i;
1120             #warn "$$:conn=$conn will_close=$self->{will_close}";
1121             # Allow handler code to control the connection
1122 18   50     93 $conn = $self->{resp}->header('Connection')||'';
1123 18 50       803 $self->{will_close} = 1 if qq(,$conn,) =~ /,\s*close\s*,/i;
1124             #warn "$$:conn=$conn will_close=$self->{will_close}";
1125             }
1126             else {
1127             # HTTP/1.0-style keep-alives fail
1128             #my $conn = $self->{req}->header('Connection')||'';
1129             #$self->{will_close} = 0 if qq(,$conn,) =~ /,\s*keep-alive\s*,/i;
1130             #warn "$$:conn=$conn will_close=$self->{will_close}";
1131             }
1132              
1133 18 100       106 $self->{will_close} = 1 if $self->{resp}->streaming;
1134             #warn "$$:post streaming will_close=$self->{will_close}";
1135 18 100       67 $self->{will_close} = 1 unless $self->{keepalive} > 1;
1136             #warn "$$:post keepalive will_close=$self->{will_close}";
1137 18 100       57 $self->{will_close} = 1 if $self->{shutdown};
1138 18         25 DEBUG and
1139             $self->D( "will_close=$self->{will_close}" );
1140 18         35 return $self->{will_close};
1141             }
1142              
1143             #######################################
1144             sub send
1145             {
1146 13     13   1909 my( $self, $something ) = @_;
1147 13         17 DEBUG and $self->D("send");
1148 13 50       44 confess "Responding more then once to a request" unless $self->{resp};
1149 13 100       54 unless( $self->{resp}->headers_sent ) {
1150 2         9 $self->should_close;
1151 2         17 $self->send_headers;
1152 2         20 $self->{stream_wheel} = 1;
1153 2         11 $self->{wheel}->set_output_filter( $self->build_stream_filter );
1154 2 100       75 if( $self->{resp}->streaming ) {
1155 1         2 eval {
1156 1         4 $SIG{__DIE__} = 'DEFAULT';
1157 1         4 $self->__tcp_hot;
1158             };
1159 1 50       9 warn $@ if $@;
1160             }
1161             }
1162              
1163 13 100       77 $self->output( $something ) if defined $something;
1164 13 100 66     1595 if( $self->{resp}->streaming and $self->{wheel} ) {
1165 11         37 $self->{wheel}->flush;
1166             }
1167 13         253 $self->timeout_start();
1168 13         411 return;
1169             }
1170              
1171             # We are in streaming mode. The last chunk has flushed. Send a new one
1172             sub send_more
1173             {
1174 10     10   14 my( $self ) = @_;
1175 10         19 $self->timeout_stop();
1176 10         677 $self->special_dispatch( 'stream_request', $self->{req}, $self->{resp} );
1177             }
1178              
1179              
1180             # We are in streaming mode. Turn off Nagle's algorithm
1181             # This isn't as effective as you might think
1182             sub __tcp_hot
1183             {
1184 1     1   3 my( $self ) = @_;
1185 1         1 DEBUG and
1186             $self->D( "TCP_NODELAY" );
1187 1         11 my $h = $self->{wheel}->get_output_handle;
1188 1 50       15 setsockopt($h, Socket::IPPROTO_TCP(), Socket::TCP_NODELAY(), 1)
1189             or die "setsockopt TCP_NODELAY: $!";
1190            
1191             # Note: On linux, even if we set the buffer size to 576, the minimum
1192             # is 2048. However, this still allows us to by-pass Nagle's algorithm.
1193 1 50       8 setsockopt($h, Socket::SOL_SOCKET(), Socket::SO_SNDBUF(), 576)
1194             or die "setsockopt SO_SNDBUF: $!";
1195            
1196 1         3 DEBUG and $self->D( "SO_SNDBUF=", unpack "i",
1197             getsockopt($h, Socket::SOL_SOCKET(), Socket::SO_SNDBUF()));
1198            
1199             }
1200              
1201             sub __tcp_sndbuf
1202             {
1203 0     0   0 my( $self ) = @_;
1204 0         0 my $h = $self->{wheel}->get_output_handle;
1205 0         0 my $bs = eval {
1206 0         0 $SIG{__DIE__} = 'DEFAULT';
1207 0         0 return unpack "i", getsockopt($h, Socket::SOL_SOCKET(), Socket::SO_SNDBUF());
1208             };
1209 0         0 return $bs;
1210             }
1211              
1212             #######################################
1213             # Send an entire file
1214             # This is a callback from Response
1215             # $path is what should be reported in errors
1216             # $file is the full path to a readable file
1217             # $size is the amount of the file to send. Should be entire file.
1218             sub sendfile_start
1219             {
1220 1     1   171 my( $self, $path, $file, $size ) = @_;
1221              
1222 1 50       5 die "Already sending a file" if $self->{sendfile};
1223              
1224 1         2 DEBUG and $self->D( "sendfile path=$path size=$size" );
1225              
1226             # Open the file
1227 1         24 my $fh = IO::File->new;
1228 1 50       64 unless( $fh->open($file) ) {
1229 0         0 $self->{resp}->error(RC_INTERNAL_SERVER_ERROR, "Unable to open $path: $!" );
1230 0         0 return;
1231             }
1232              
1233 1         94 $self->{sendfile} = { offset=>0, size=>$size, fh=>$fh,
1234             path=>$path, bs=>$self->{blocksize} };
1235 1         8 $self->send;
1236             # we wait for the 'flush' event to invoke sendfile.
1237 1         4 $self->timeout_start();
1238             }
1239              
1240             sub sendfile_next
1241             {
1242 1     1   3 my( $self ) = @_;
1243              
1244 1         3 my $S = $self->{sendfile};
1245 13     13   174 use bytes;
  13         31  
  13         116  
1246              
1247 1         2 my $len;
1248 1 50       8 if( $HAVE_SENDFILE ) {
1249 0         0 DEBUG and $self->D( "sendfile path=$S->{path} offset=$S->{offset}" );
1250 0         0 my $socket = $self->{wheel}->get_output_handle;
1251 0         0 $len = sendfile( $socket, $S->{fh}, 0, $S->{offset} );
1252 0 0       0 unless( defined $len ) {
1253 0         0 $self->net_error( 'sendfile', 0+$!, "$!" );
1254 0         0 return;
1255             }
1256 0         0 $poe_kernel->select_resume_write( $socket );
1257             }
1258             else {
1259 1         1 DEBUG and $self->D( "sysread path=$S->{path} offset=$S->{offset}" );
1260 1         4 my $c = '';
1261 1         1998 $len = sysread( $S->{fh}, $c, $S->{bs} );
1262 1 50       9 if( $len > 0 ) {
1263 1         3 DEBUG and $self->D( "send bytes=".length $c );
1264 1         8 $self->send( $c );
1265             }
1266             }
1267 1         5 $S->{offset} += $len;
1268 1 50       7 if( $S->{offset} >= $S->{size} ) {
1269 1         1 DEBUG and $self->D( "sendfile done" );
1270 1 50       6 $self->D( "Sendfile sent to many bytes!" ) if $S->{offset} > $S->{size};
1271 1         5 $self->done;
1272 1         4 delete $self->{sendfile};
1273             }
1274 1         4 $self->timeout_start();
1275 1         102 return $len;
1276             }
1277              
1278              
1279             #######################################
1280             sub done
1281             {
1282 15     15   1760 my( $self ) = @_;
1283 15         54 $self->state( 'done' );
1284 15         27 DEBUG and $self->D( "Done" );
1285             # If we don't have a {req}, then the request has already finished
1286             # But wait until request is flushed to finish it.
1287 15 50 33     127 if( not $self->{flushing} and $self->{req} ) {
1288 0         0 $self->finish_request;
1289             }
1290             }
1291              
1292             #######################################
1293             sub keepalive_start
1294             {
1295 18     18   36 my( $self ) = @_;
1296             # $self->D( "will_close=$self->{will_close} keepalive=$self->{keepalive}" );
1297 18 100       90 return if $self->{will_close};
1298 4         8 $self->{keepalive}--;
1299 4 50       12 return unless $self->{keepalive} > 0;
1300 4         5 DEBUG and
1301             $self->D( "keep-alive=$self->{keepalive}" );
1302 4         4 DEBUG and $self->D( "keep-alive timeout=$self->{keepalivetimeout}" );
1303 4         12 $self->{KAID} = $poe_kernel->delay_set( ev"timeout",
1304             $self->{keepalivetimeout}
1305             );
1306 4         276 DEBUG and $self->D1( "keep-alive start tid=$self->{KAID}" );
1307 4         13 $self->state( 'waiting' );
1308 4         10 return 1;
1309             }
1310              
1311             #######################################
1312             sub timeout
1313             {
1314 0     0   0 my( $self ) = @_;
1315 0         0 $self->keepalive_stop;
1316 0         0 $self->timeout_stop;
1317 0         0 $self->close;
1318             }
1319              
1320             #######################################
1321             sub keepalive_stop
1322             {
1323 38     38   79 my( $self ) = @_;
1324 38 100       209 return unless $self->{KAID};
1325 4         3 DEBUG and $self->D1( "keep-alive stop tid=$self->{KAID}" );
1326 4         16 $poe_kernel->alarm_remove( delete $self->{KAID} );
1327             }
1328              
1329              
1330              
1331             #######################################
1332             sub timeout_start
1333             {
1334 48     48   132 my( $self ) = @_;
1335 48 100 66     396 return unless $self->{timeout} and $self->{connection};
1336 47 100       148 if( $self->{TID} ) {
1337 3         3 DEBUG and
1338             $self->D1( "timeout restart tid=$self->{TID}" );
1339 3         17 $poe_kernel->delay_adjust( $self->{TID}, $self->{timeout} );
1340             }
1341             else {
1342 44         58 DEBUG and $self->D( "timeout timeout=$self->{timeout}" );
1343 44         138 $self->{TID} = $poe_kernel->delay_set( evo( $self->name, "timeout" ),
1344             $self->{timeout}
1345             );
1346 44         5492 DEBUG and
1347             $self->D1( "timeout start tid=$self->{TID}" );
1348             }
1349             }
1350              
1351              
1352             #######################################
1353             sub timeout_stop
1354             {
1355 49     49   110 my( $self ) = @_;
1356 49 100       160 return unless $self->{TID};
1357 44         60 DEBUG and
1358             $self->D1( "timeout stop tid=$self->{TID}" );
1359 44         260 $poe_kernel->alarm_remove( delete $self->{TID} );
1360             }
1361              
1362              
1363             #######################################
1364             sub shutdown
1365             {
1366 3     3   484 my( $self ) = @_;
1367 3         9 my $state = $self->state( 'shutdown' );
1368 3         5 DEBUG and $self->D( "shutdown flushing=$self->{flushing} state=$state" );
1369 3         9 $self->{shutdown} = 1;
1370 3         5 $self->{will_close} = 1;
1371             # If we are handling a request or flushing it's output, we wait
1372             # until that's completed
1373 3 50 33     33 $self->close unless $self->{flushing} or $state eq 'handling';
1374 3         69 $self->keepalive_stop;
1375             }
1376              
1377              
1378             #######################################
1379             sub pending_push
1380             {
1381 0     0   0 my( $self, $req ) = @_;
1382 0         0 push @{ $self->{pending} }, $req;
  0         0  
1383             }
1384              
1385              
1386             #######################################
1387             sub pending_next
1388             {
1389 18     18   37 my( $self ) = @_;
1390 18 50 33     498 return unless $self->{pending} and @{ $self->{pending} };
  0            
1391 0 0 0       if( $self->{S}{shutdown} or $self->{S}{closing} ) {
1392 0           $self->D( "We are closing down with pending requests" );
1393 0           $self->pending_no_reply;
1394 0           return;
1395             }
1396 0           my $next = shift @{ $self->{pending} };
  0            
1397 0 0         return unless $next;
1398              
1399 0           $self->input( $next );
1400             }
1401              
1402             #######################################
1403             sub pending_no_reply
1404             {
1405 0     0     my( $self ) = @_;
1406 0 0         return unless $self->{wheel};
1407 0           foreach my $req ( @{ $self->{pending} } ) {
  0            
1408 0           my $resp = $self->build_error_response( RC_SERVICE_UNAVAILABLE,
1409             "This request could not be handled." );
1410 0           $self->{wheel}->put( $resp );
1411 0 0         last unless $self->{wheel}
1412             }
1413 0 0         $self->{wheel}->flush() if $self->{wheel};
1414             }
1415              
1416              
1417             ##############################################################################
1418             package POEx::HTTP::Server::Session;
1419              
1420 13     13   15845 use strict;
  13         25  
  13         433  
1421 13     13   78 use warnings;
  13         26  
  13         431  
1422              
1423 13     13   71 use POE::Session::PlainCall;
  13         26  
  13         1523  
1424 13     13   70 use POE::Session::Multiplex;
  13         25  
  13         882  
1425              
1426 13     13   74 use base qw( POE::Session::Multiplex POE::Session::PlainCall );
  13         26  
  13         1878  
1427              
1428              
1429              
1430             1;
1431              
1432             __END__