File Coverage

blib/lib/Net/Async/FastCGI/ServerProtocol.pm
Criterion Covered Total %
statement 75 76 98.6
branch 21 24 87.5
condition n/a
subroutine 16 16 100.0
pod 1 3 33.3
total 113 119 94.9


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2005-2011 -- leonerd@leonerd.org.uk
5              
6             package Net::Async::FastCGI::ServerProtocol;
7              
8 17     17   115 use strict;
  17         36  
  17         722  
9 17     17   106 use warnings;
  17         34  
  17         613  
10              
11 17     17   84 use base qw( Net::Async::FastCGI::Protocol );
  17         32  
  17         10738  
12 17     17   24834 use IO::Async::Stream 0.33;
  17         363328  
  17         751  
13              
14 17     17   193 use Net::FastCGI::Constant qw( FCGI_VERSION_1 :type :role :protocol_status );
  17         37  
  17         5465  
15 17         1207 use Net::FastCGI::Protocol qw(
16             build_params parse_params
17             parse_begin_request_body
18             build_end_request_body
19 17     17   108 );
  17         33  
20              
21 17     17   13180 use Net::Async::FastCGI::Request;
  17         57  
  17         13185  
22              
23             sub _init
24             {
25 16     16   209 my $self = shift;
26 16         39 my ( $params ) = @_;
27              
28 16         206 $self->{fcgi} = delete $params->{fcgi};
29 16         78 $self->{reqs} = {}; # {$reqid} = $req
30             }
31              
32             sub on_closed
33             {
34 9     9 1 5997 my ( $self ) = @_;
35 9         19 $_->_abort for values %{ $self->{reqs} };
  9         71  
36              
37             # TODO: This might want to live in IO::Async::Protocol
38 9 100       54 if( my $parent = $self->parent ) {
39 8         153 $parent->remove_child( $self );
40             }
41             }
42              
43             sub on_mgmt_record
44             {
45 4     4 0 7 my $self = shift;
46 4         7 my ( $type, $rec ) = @_;
47              
48 4 100       16 return $self->_get_values( $rec ) if $type == FCGI_GET_VALUES;
49              
50 1         8 return $self->SUPER::on_mgmt_record( $type, $rec );
51             }
52              
53             sub on_record
54             {
55 85     85 0 129 my $self = shift;
56 85         175 my ( $reqid, $rec ) = @_;
57              
58 85         144 my $type = $rec->{type};
59              
60 85 100       243 if( $type == FCGI_BEGIN_REQUEST ) {
61 22         118 ( my $role, $rec->{flags} ) = parse_begin_request_body( $rec->{content} );
62              
63 22 100       261 if( $role == FCGI_RESPONDER ) {
64 21         216 my $req = Net::Async::FastCGI::Request->new(
65             conn => $self,
66             fcgi => $self->{fcgi},
67             rec => $rec,
68             );
69 21         82 $self->{reqs}->{$reqid} = $req;
70             }
71             else {
72 1         6 $self->write_record( { type => FCGI_END_REQUEST, reqid => $rec->{reqid} },
73             build_end_request_body( 0, FCGI_UNKNOWN_ROLE )
74             );
75             }
76              
77 22         223 return;
78             }
79              
80             # FastCGI spec says we're supposed to ignore any record apart from
81             # FCGI_BEGIN_REQUEST on unrecognised request IDs
82 63 50       212 my $req = $self->{reqs}->{$reqid} or return;
83              
84 63         213 $req->incomingrecord( $rec );
85             }
86              
87             sub _req_needs_flush
88             {
89 51     51   78 my $self = shift;
90              
91             $self->{gensub_queued}++ or $self->write( sub {
92 24     24   13659 my ( $self ) = @_;
93              
94 24         51 undef $self->{gensub_queued};
95              
96 24         38 my $want_more = 0;
97              
98 24         40 foreach my $req ( values %{ $self->{reqs} } ) {
  24         76  
99 16         64 $req->_flush_streams;
100 16 100       57 $want_more = 1 if $req->_needs_flush;
101             }
102              
103 24 100       86 $self->_req_needs_flush if $want_more;
104              
105 24         225 return undef;
106 51 100       649 } );
107             }
108              
109             sub _removereq
110             {
111 21     21   69 my $self = shift;
112 21         45 my ( $reqid ) = @_;
113              
114 21         184 delete $self->{reqs}->{$reqid};
115             }
116              
117             sub _get_values
118             {
119 3     3   6 my $self = shift;
120 3         6 my ( $rec ) = @_;
121              
122 3         5 my $content = $rec->{content};
123              
124 3         4 my $ret = "";
125              
126 3         5 foreach my $name ( keys %{ parse_params( $content ) } ) {
  3         9  
127 3         99 my $value = $self->_get_value( $name );
128 3 50       7 if( defined $value ) {
129 3         10 $ret .= build_params( { $name => $value } );
130             }
131             }
132              
133             $self->write_record(
134             {
135 3         71 type => FCGI_GET_VALUES_RESULT,
136             reqid => 0,
137             },
138             $ret
139             );
140             }
141              
142             # This is a method so subclasses could hook extra values if they want
143             sub _get_value
144             {
145 3     3   3 my $self = shift;
146 3         4 my ( $name ) = @_;
147              
148 3 100       8 return 1 if $name eq "FCGI_MPXS_CONNS";
149              
150 2 100       16 return $Net::Async::FastCGI::MAX_CONNS if $name eq "FCGI_MAX_CONNS";
151 1 50       4 return $Net::Async::FastCGI::MAX_REQS if $name eq "FCGI_MAX_REQS";
152              
153 0           return undef;
154             }
155              
156             0x55AA;