File Coverage

lib/Net/FastCGI/IO.pm
Criterion Covered Total %
statement 30 148 20.2
branch 0 84 0.0
condition 0 27 0.0
subroutine 9 16 56.2
pod 7 7 100.0
total 46 282 16.3


line stmt bran cond sub pod time code
1             package Net::FastCGI::IO;
2 1     1   4384 use strict;
  1         3  
  1         41  
3 1     1   4 use warnings;
  1         3  
  1         24  
4 1     1   5 use warnings::register;
  1         2  
  1         130  
5              
6 1     1   6 use Carp qw[];
  1         2  
  1         44  
7 1     1   793 use Errno qw[EBADF EINTR EPIPE];
  1         1435  
  1         103  
8 1     1   5 use Net::FastCGI::Constant qw[FCGI_HEADER_LEN];
  1         1  
  1         48  
9 1         225 use Net::FastCGI::Protocol qw[build_header build_record build_stream
10 1     1   3 parse_header parse_record];
  1         2  
11              
12             BEGIN {
13 1     1   2 our $VERSION = '0.14';
14 1         2 our @EXPORT_OK = qw[ can_read
15             can_write
16             read_header
17             read_record
18             write_header
19             write_record
20             write_stream ];
21              
22 1         3 our %EXPORT_TAGS = ( all => \@EXPORT_OK );
23              
24 1         4 require Exporter;
25 1         3 *import = \&Exporter::import;
26              
27 1     1   44 eval q;
  1         808  
  1         1730  
  1         4  
28             }
29              
30             *throw = \&Carp::croak;
31              
32             sub read_header {
33 0 0   0 1   @_ == 1 || throw(q/Usage: read_header(fh)/);
34 0           my ($fh) = @_;
35              
36 0           my $len = FCGI_HEADER_LEN;
37 0           my $off = 0;
38 0           my $buf;
39              
40 0           while ($len) {
41 0           my $r = sysread($fh, $buf, $len, $off);
42 0 0         if (defined $r) {
    0          
43 0 0         last unless $r;
44 0           $len -= $r;
45 0           $off += $r;
46             }
47             elsif ($! != EINTR) {
48 0 0         warnings::warn(qq)
49             if warnings::enabled;
50 0           return;
51             }
52             }
53 0 0         if ($len) {
54 0 0         $! = $off ? EPIPE : 0;
55 0 0 0       warnings::warn(q)
56             if $off && warnings::enabled;
57 0           return;
58             }
59 0           return parse_header($buf);
60             }
61              
62             sub write_header {
63 0 0   0 1   @_ == 5 || throw(q/Usage: write_header(fh, type, request_id, content_length, padding_length)/);
64 0           my $fh = shift;
65              
66 0           my $buf = &build_header;
67 0           my $len = FCGI_HEADER_LEN;
68 0           my $off = 0;
69              
70 0           while () {
71 0           my $r = syswrite($fh, $buf, $len, $off);
72 0 0         if (defined $r) {
    0          
73 0           $len -= $r;
74 0           $off += $r;
75 0 0         last unless $len;
76             }
77             elsif ($! != EINTR) {
78 0 0         warnings::warn(qq)
79             if warnings::enabled;
80 0           return undef;
81             }
82             }
83 0           return $off;
84             }
85              
86             sub read_record {
87 0 0   0 1   @_ == 1 || throw(q/Usage: read_record(fh)/);
88 0           my ($fh) = @_;
89              
90 0           my $len = FCGI_HEADER_LEN;
91 0           my $off = 0;
92 0           my $buf;
93              
94 0           while ($len) {
95 0           my $r = sysread($fh, $buf, $len, $off);
96 0 0         if (defined $r) {
    0          
97 0 0         last unless $r;
98 0           $len -= $r;
99 0           $off += $r;
100 0 0 0       if (!$len && $off == FCGI_HEADER_LEN) {
101 0           $len = vec($buf, 2, 16) # Content Length
102             + vec($buf, 6, 8); # Padding Length
103             }
104             }
105             elsif ($! != EINTR) {
106 0 0         warnings::warn(qq)
107             if warnings::enabled;
108 0           return;
109             }
110             }
111 0 0         if ($len) {
112 0 0         $! = $off ? EPIPE : 0;
113 0 0 0       warnings::warn(q)
114             if $off && warnings::enabled;
115 0           return;
116             }
117 0           return parse_record($buf);
118             }
119              
120             sub write_record {
121 0 0 0 0 1   @_ == 4 || @_ == 5 || throw(q/Usage: write_record(fh, type, request_id [, content])/);
122 0           my $fh = shift;
123              
124 0           my $buf = &build_record;
125 0           my $len = length $buf;
126 0           my $off = 0;
127              
128 0           while () {
129 0           my $r = syswrite($fh, $buf, $len, $off);
130 0 0         if (defined $r) {
    0          
131 0           $len -= $r;
132 0           $off += $r;
133 0 0         last unless $len;
134             }
135             elsif ($! != EINTR) {
136 0 0         warnings::warn(qq)
137             if warnings::enabled;
138 0           return undef;
139             }
140             }
141 0           return $off;
142             }
143              
144             sub write_stream {
145 0 0 0 0 1   @_ == 4 || @_ == 5 || throw(q/Usage: write_stream(fh, type, request_id, content [, terminate])/);
146 0           my $fh = shift;
147              
148 0           my $buf = &build_stream;
149 0           my $len = length $buf;
150 0           my $off = 0;
151              
152 0           while () {
153 0           my $r = syswrite($fh, $buf, $len, $off);
154 0 0         if (defined $r) {
    0          
155 0           $len -= $r;
156 0           $off += $r;
157 0 0         last unless $len;
158             }
159             elsif ($! != EINTR) {
160 0 0         warnings::warn(qq)
161             if warnings::enabled;
162 0           return undef;
163             }
164             }
165 0           return $off;
166             }
167              
168             sub can_read (*$) {
169 0 0   0 1   @_ == 2 || throw(q/Usage: can_read(fh, timeout)/);
170 0           my ($fh, $timeout) = @_;
171              
172 0           my $fd = fileno($fh);
173 0 0 0       unless (defined $fd && $fd >= 0) {
174 0           $! = EBADF;
175 0           return undef;
176             }
177              
178 0           my $initial = time;
179 0           my $pending = $timeout;
180 0           my $nfound;
181              
182 0           vec(my $fdset = '', $fd, 1) = 1;
183              
184 0           while () {
185 0           $nfound = select($fdset, undef, undef, $pending);
186 0 0         if ($nfound == -1) {
187 0 0         return undef unless $! == EINTR;
188 0 0 0       redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0;
189 0           $nfound = 0;
190             }
191 0           last;
192             }
193 0           $! = 0;
194 0           return $nfound;
195             }
196              
197             sub can_write (*$) {
198 0 0   0 1   @_ == 2 || throw(q/Usage: can_write(fh, timeout)/);
199 0           my ($fh, $timeout) = @_;
200              
201 0           my $fd = fileno($fh);
202 0 0 0       unless (defined $fd && $fd >= 0) {
203 0           $! = EBADF;
204 0           return undef;
205             }
206              
207 0           my $initial = time;
208 0           my $pending = $timeout;
209 0           my $nfound;
210              
211 0           vec(my $fdset = '', $fd, 1) = 1;
212              
213 0           while () {
214 0           $nfound = select(undef, $fdset, undef, $pending);
215 0 0         if ($nfound == -1) {
216 0 0         return undef unless $! == EINTR;
217 0 0 0       redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0;
218 0           $nfound = 0;
219             }
220 0           last;
221             }
222 0           $! = 0;
223 0           return $nfound;
224             }
225              
226             1;
227