File Coverage

blib/lib/Net/Async/FastCGI/ServerProtocol.pm
Criterion Covered Total %
statement 79 80 98.7
branch 23 26 88.4
condition n/a
subroutine 17 17 100.0
pod 2 4 50.0
total 121 127 95.2


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-2024 -- leonerd@leonerd.org.uk
5              
6             package Net::Async::FastCGI::ServerProtocol 0.26;
7              
8 18     18   244 use v5.14;
  18         65  
9 18     18   107 use warnings;
  18         60  
  18         1460  
10              
11 18     18   210 use base qw( Net::Async::FastCGI::Protocol );
  18         64  
  18         9461  
12 18     18   12909 use IO::Async::Stream 0.33;
  18         700950  
  18         1081  
13              
14 18     18   187 use Net::FastCGI::Constant qw( FCGI_VERSION_1 :type :role :protocol_status );
  18         85  
  18         4853  
15 18         1344 use Net::FastCGI::Protocol qw(
16             build_params parse_params
17             parse_begin_request_body
18             build_end_request_body
19 18     18   163 );
  18         37  
20              
21 18     18   13626 use Net::Async::FastCGI::Request;
  18         87  
  18         16236  
22              
23             sub configure
24             {
25 26     26 1 2003 my $self = shift;
26 26         96 my %params = @_;
27              
28 26         80 foreach (qw( stream_stdin )) {
29             exists $params{$_} and
30 26 100       194 $self->{$_} = delete $params{$_};
31             }
32              
33 26         263 $self->SUPER::configure( %params );
34             }
35              
36             sub _init
37             {
38 17     17   277 my $self = shift;
39 17         47 my ( $params ) = @_;
40              
41 17         126 $self->{fcgi} = delete $params->{fcgi};
42 17         66 $self->{reqs} = {}; # {$reqid} = $req
43             }
44              
45             sub on_closed
46             {
47 9     9 1 12595 my ( $self ) = @_;
48 9         22 $_->_abort for values %{ $self->{reqs} };
  9         84  
49              
50             # TODO: This might want to live in IO::Async::Protocol
51 9 100       44 if( my $parent = $self->parent ) {
52 8         169 $parent->remove_child( $self );
53             }
54             }
55              
56             sub on_mgmt_record
57             {
58 4     4 0 15 my $self = shift;
59 4         10 my ( $type, $rec ) = @_;
60              
61 4 100       19 return $self->_get_values( $rec ) if $type == FCGI_GET_VALUES;
62              
63 1         6 return $self->SUPER::on_mgmt_record( $type, $rec );
64             }
65              
66             sub on_record
67             {
68 98     98 0 223 my $self = shift;
69 98         233 my ( $reqid, $rec ) = @_;
70              
71 98         212 my $type = $rec->{type};
72              
73 98 100       312 if( $type == FCGI_BEGIN_REQUEST ) {
74 25         300 ( my $role, $rec->{flags} ) = parse_begin_request_body( $rec->{content} );
75              
76 25 100       496 if( $role == FCGI_RESPONDER ) {
77             my $req = Net::Async::FastCGI::Request->new(
78             conn => $self,
79             fcgi => $self->{fcgi},
80             rec => $rec,
81             stream_stdin => $self->{stream_stdin},
82 24         489 );
83 24         111 $self->{reqs}->{$reqid} = $req;
84             }
85             else {
86             $self->write_record( { type => FCGI_END_REQUEST, reqid => $rec->{reqid} },
87 1         4 build_end_request_body( 0, FCGI_UNKNOWN_ROLE )
88             );
89             }
90              
91 25         304 return;
92             }
93              
94             # FastCGI spec says we're supposed to ignore any record apart from
95             # FCGI_BEGIN_REQUEST on unrecognised request IDs
96 73 50       279 my $req = $self->{reqs}->{$reqid} or return;
97              
98 73         331 $req->incomingrecord( $rec );
99             }
100              
101             sub _req_needs_flush
102             {
103 51     51   97 my $self = shift;
104              
105             $self->{gensub_queued}++ or $self->write( sub {
106 24     24   25424 my ( $self ) = @_;
107              
108 24         72 undef $self->{gensub_queued};
109              
110 24         45 my $want_more = 0;
111              
112 24         46 foreach my $req ( values %{ $self->{reqs} } ) {
  24         151  
113 16         75 $req->_flush_streams;
114 16 100       58 $want_more = 1 if $req->_needs_flush;
115             }
116              
117 24 100       83 $self->_req_needs_flush if $want_more;
118              
119 24         513 return undef;
120 51 100       656 } );
121             }
122              
123             sub _removereq
124             {
125 21     21   47 my $self = shift;
126 21         75 my ( $reqid ) = @_;
127              
128 21         258 delete $self->{reqs}->{$reqid};
129             }
130              
131             sub _get_values
132             {
133 3     3   6 my $self = shift;
134 3         11 my ( $rec ) = @_;
135              
136 3         50 my $content = $rec->{content};
137              
138 3         7 my $ret = "";
139              
140 3         5 foreach my $name ( keys %{ parse_params( $content ) } ) {
  3         11  
141 3         105 my $value = $self->_get_value( $name );
142 3 50       9 if( defined $value ) {
143 3         12 $ret .= build_params( { $name => $value } );
144             }
145             }
146              
147             $self->write_record(
148             {
149 3         103 type => FCGI_GET_VALUES_RESULT,
150             reqid => 0,
151             },
152             $ret
153             );
154             }
155              
156             # This is a method so subclasses could hook extra values if they want
157             sub _get_value
158             {
159 3     3   6 my $self = shift;
160 3         6 my ( $name ) = @_;
161              
162 3 100       9 return 1 if $name eq "FCGI_MPXS_CONNS";
163              
164 2 100       7 return $Net::Async::FastCGI::MAX_CONNS if $name eq "FCGI_MAX_CONNS";
165 1 50       6 return $Net::Async::FastCGI::MAX_REQS if $name eq "FCGI_MAX_REQS";
166              
167 0           return undef;
168             }
169              
170             0x55AA;