line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::HTTPS::NB; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
184569
|
use strict; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
177
|
|
4
|
3
|
|
|
3
|
|
4014
|
use Net::HTTP; |
|
3
|
|
|
|
|
386703
|
|
|
3
|
|
|
|
|
48
|
|
5
|
3
|
|
|
3
|
|
7326
|
use IO::Socket::SSL 0.98; |
|
3
|
|
|
|
|
407133
|
|
|
3
|
|
|
|
|
33
|
|
6
|
3
|
|
|
3
|
|
747
|
use Exporter; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
135
|
|
7
|
3
|
|
|
3
|
|
18
|
use vars qw($VERSION @ISA @EXPORT $HTTPS_ERROR); |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
480
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$VERSION = 0.13; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 NAME |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Net::HTTPS::NB - Non-blocking HTTPS client |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 SYNOPSIS |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=over |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=item Example from L |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
use Net::HTTPS::NB; |
22
|
|
|
|
|
|
|
use IO::Select; |
23
|
|
|
|
|
|
|
use strict; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $s = Net::HTTPS::NB->new(Host => "pause.perl.org") || die $@; |
26
|
|
|
|
|
|
|
$s->write_request(GET => "/"); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $sel = IO::Select->new($s); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
READ_HEADER: { |
31
|
|
|
|
|
|
|
die "Header timeout" unless $sel->can_read(10); |
32
|
|
|
|
|
|
|
my($code, $mess, %h) = $s->read_response_headers; |
33
|
|
|
|
|
|
|
redo READ_HEADER unless $code; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
while (1) { |
37
|
|
|
|
|
|
|
die "Body timeout" unless $sel->can_read(10); |
38
|
|
|
|
|
|
|
my $buf; |
39
|
|
|
|
|
|
|
my $n = $s->read_entity_body($buf, 1024); |
40
|
|
|
|
|
|
|
last unless $n; |
41
|
|
|
|
|
|
|
print $buf; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=item Example of non-blocking connect |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
use strict; |
47
|
|
|
|
|
|
|
use Net::HTTPS::NB; |
48
|
|
|
|
|
|
|
use IO::Select; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $sock = Net::HTTPS::NB->new(Host => 'encrypted.google.com', Blocking => 0); |
51
|
|
|
|
|
|
|
my $sele = IO::Select->new($sock); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
until ($sock->connected) { |
54
|
|
|
|
|
|
|
if ($HTTPS_ERROR == HTTPS_WANT_READ) { |
55
|
|
|
|
|
|
|
$sele->can_read(); |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
elsif($HTTPS_ERROR == HTTPS_WANT_WRITE) { |
58
|
|
|
|
|
|
|
$sele->can_write(); |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
else { |
61
|
|
|
|
|
|
|
die 'Unknown error: ', $HTTPS_ERROR; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=back |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
See `examples' subdirectory for more examples. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head1 DESCRIPTION |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Same interface as Net::HTTPS but it will never try multiple reads when the |
72
|
|
|
|
|
|
|
read_response_headers() or read_entity_body() methods are invoked. In addition |
73
|
|
|
|
|
|
|
allows non-blocking connect. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=over |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item If read_response_headers() did not see enough data to complete the headers an empty list is returned. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item If read_entity_body() did not see new entity data in its read the value -1 is returned. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=back |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=cut |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# we only supports IO::Socket::SSL now |
86
|
|
|
|
|
|
|
# use it force |
87
|
|
|
|
|
|
|
$Net::HTTPS::SSL_SOCKET_CLASS = 'IO::Socket::SSL'; |
88
|
|
|
|
|
|
|
require Net::HTTPS; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# make aliases to IO::Socket::SSL variables and constants |
91
|
|
|
|
|
|
|
use constant { |
92
|
3
|
|
|
|
|
4872
|
HTTPS_WANT_READ => SSL_WANT_READ, |
93
|
|
|
|
|
|
|
HTTPS_WANT_WRITE => SSL_WANT_WRITE, |
94
|
3
|
|
|
3
|
|
18
|
}; |
|
3
|
|
|
|
|
6
|
|
95
|
|
|
|
|
|
|
*HTTPS_ERROR = \$SSL_ERROR; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head1 PACKAGE CONSTANTS |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Imported by default |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
HTTPS_WANT_READ |
102
|
|
|
|
|
|
|
HTTPS_WANT_WRITE |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 PACKAGE VARIABLES |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Imported by default |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
$HTTPS_ERROR |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=cut |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# need export some stuff for error handling |
113
|
|
|
|
|
|
|
@EXPORT = qw($HTTPS_ERROR HTTPS_WANT_READ HTTPS_WANT_WRITE); |
114
|
|
|
|
|
|
|
@ISA = qw(Net::HTTPS Exporter); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 METHODS |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head2 new(%cfg) |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Same as Net::HTTPS::new, but in addition allows `Blocking' parameter. By setting |
121
|
|
|
|
|
|
|
this parameter to 0 you can perform non-blocking connect. See connected() to |
122
|
|
|
|
|
|
|
determine when connection completed. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub new { |
127
|
3
|
|
|
3
|
1
|
45323
|
my ($class, %args) = @_; |
128
|
|
|
|
|
|
|
|
129
|
3
|
|
|
|
|
49
|
my %ssl_opts; |
130
|
3
|
|
|
|
|
63
|
while (my $name = each %args) { |
131
|
7
|
50
|
|
|
|
78
|
if (substr($name, 0, 4) eq 'SSL_') { |
132
|
0
|
|
|
|
|
0
|
$ssl_opts{$name} = delete $args{$name}; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
3
|
50
|
|
|
|
49
|
unless (exists $args{PeerPort}) { |
137
|
0
|
|
|
|
|
0
|
$args{PeerPort} = 443; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# create plain socket first |
141
|
3
|
50
|
|
|
|
149
|
my $self = Net::HTTP->new(%args) |
142
|
|
|
|
|
|
|
or return; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# and upgrade it to SSL then |
145
|
3
|
50
|
|
|
|
29795
|
$class->start_SSL($self, %ssl_opts, SSL_startHandshake => 0) |
146
|
|
|
|
|
|
|
or return; |
147
|
|
|
|
|
|
|
|
148
|
3
|
100
|
66
|
|
|
21204
|
if (!exists($args{Blocking}) || $args{Blocking}) { |
149
|
|
|
|
|
|
|
# blocking connect |
150
|
2
|
50
|
|
|
|
28
|
$self->connected() |
151
|
|
|
|
|
|
|
or return; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
# non-blocking handshake will be started after SUPER::connected |
154
|
|
|
|
|
|
|
|
155
|
1
|
|
|
|
|
31
|
return $self; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head2 connected() |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Returns true value when connection completed (https handshake done). Otherwise |
161
|
|
|
|
|
|
|
returns false. In this case you can check $HTTPS_ERROR to determine what handshake |
162
|
|
|
|
|
|
|
need for, read or write. $HTTPS_ERROR could be HTTPS_WANT_READ or HTTPS_WANT_WRITE |
163
|
|
|
|
|
|
|
respectively. See L. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=cut |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub connected { |
168
|
5
|
|
|
5
|
1
|
1361
|
my $self = shift; |
169
|
|
|
|
|
|
|
|
170
|
5
|
50
|
|
|
|
14
|
if (exists ${*$self}{httpsnb_connected}) { |
|
5
|
|
|
|
|
43
|
|
171
|
|
|
|
|
|
|
# already connected or disconnected |
172
|
0
|
|
|
|
|
0
|
return ${*$self}{httpsnb_connected}; |
|
0
|
|
|
|
|
0
|
|
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
5
|
100
|
|
|
|
12
|
if (${*$self}{httpsnb_super_connected}) { |
|
5
|
|
|
|
|
22
|
|
176
|
|
|
|
|
|
|
# SUPER already connected |
177
|
|
|
|
|
|
|
# start/continue SSL handshaking |
178
|
2
|
50
|
|
|
|
50
|
if ( $self->connect_SSL() ) { |
179
|
0
|
|
|
|
|
0
|
return ${*$self}{httpsnb_connected} = 1; |
|
0
|
|
|
|
|
0
|
|
180
|
|
|
|
|
|
|
} |
181
|
2
|
|
|
|
|
798
|
return 0; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
3
|
100
|
|
|
|
58
|
if ($self->SUPER::connected) { |
185
|
|
|
|
|
|
|
# SUPER just connected. Start handshaking |
186
|
2
|
|
|
|
|
112
|
${*$self}{httpsnb_super_connected} = 1; |
|
2
|
|
|
|
|
36
|
|
187
|
2
|
|
|
|
|
26
|
return $self->connected; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# SUPER still not connected |
191
|
1
|
50
|
|
|
|
130
|
if ($! = $self->sockopt(SO_ERROR)) { |
192
|
|
|
|
|
|
|
# some error while connecting |
193
|
0
|
|
|
|
|
0
|
$HTTPS_ERROR = $!; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
else { |
196
|
1
|
|
|
|
|
82
|
$HTTPS_ERROR = HTTPS_WANT_WRITE; |
197
|
|
|
|
|
|
|
} |
198
|
1
|
|
|
|
|
16
|
return 0; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub close { |
202
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
203
|
|
|
|
|
|
|
# need some cleanup |
204
|
0
|
|
|
|
|
0
|
${*$self}{httpsnb_connected} = 0; |
|
0
|
|
|
|
|
0
|
|
205
|
0
|
|
|
|
|
0
|
return $self->SUPER::close(); |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head2 blocking($flag) |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
As opposed to Net::HTTPS where blocking method consciously broken you |
211
|
|
|
|
|
|
|
can set socket blocking. For example you can return socket to blocking state |
212
|
|
|
|
|
|
|
after non-blocking connect. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=cut |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub blocking { |
217
|
|
|
|
|
|
|
# blocking() is breaked in Net::HTTPS |
218
|
|
|
|
|
|
|
# restore it here |
219
|
2
|
|
|
2
|
1
|
5955500
|
my $self = shift; |
220
|
2
|
|
|
|
|
40
|
$self->IO::Socket::blocking(@_); |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# code below copied from Net::HTTP::NB with some modifications |
224
|
|
|
|
|
|
|
# Author: Gisle Aas |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub sysread { |
227
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
228
|
0
|
0
|
|
|
|
|
unless (${*$self}{'httpsnb_reading'}) { |
|
0
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# allow reading without restrictions when called |
230
|
|
|
|
|
|
|
# not from our methods |
231
|
0
|
|
|
|
|
|
return $self->SUPER::sysread(@_); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
0
|
0
|
|
|
|
|
if (${*$self}{'httpsnb_read_count'}++) { |
|
0
|
|
|
|
|
|
|
235
|
0
|
|
|
|
|
|
${*$self}{'http_buf'} = ${*$self}{'httpsnb_save'}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
236
|
0
|
|
|
|
|
|
die "Multi-read\n"; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
0
|
|
0
|
|
|
|
my $offset = $_[2] || 0; |
240
|
0
|
|
|
|
|
|
my $n = $self->SUPER::sysread($_[0], $_[1], $offset); |
241
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_save'} .= substr($_[0], $offset); |
|
0
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
|
return $n; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub read_response_headers { |
246
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
247
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_reading'} = 1; |
|
0
|
|
|
|
|
|
|
248
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_read_count'} = 0; |
|
0
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_save'} = ${*$self}{'http_buf'}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
|
my @h = eval { $self->SUPER::read_response_headers(@_) }; |
|
0
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_reading'} = 0; |
|
0
|
|
|
|
|
|
|
252
|
0
|
0
|
|
|
|
|
if ($@) { |
253
|
0
|
0
|
0
|
|
|
|
return if $@ eq "Multi-read\n" || $HTTPS_ERROR == HTTPS_WANT_READ; |
254
|
0
|
|
|
|
|
|
die; |
255
|
|
|
|
|
|
|
} |
256
|
0
|
|
|
|
|
|
return @h; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub read_entity_body { |
260
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
261
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_reading'} = 1; |
|
0
|
|
|
|
|
|
|
262
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_read_count'} = 0; |
|
0
|
|
|
|
|
|
|
263
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_save'} = ${*$self}{'http_buf'}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# XXX I'm not so sure this does the correct thing in case of |
265
|
|
|
|
|
|
|
# transfer-encoding tranforms |
266
|
0
|
|
|
|
|
|
my $n = eval { $self->SUPER::read_entity_body(@_) }; |
|
0
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
|
${*$self}{'httpsnb_reading'} = 0; |
|
0
|
|
|
|
|
|
|
268
|
0
|
0
|
0
|
|
|
|
if ($@ || (!defined($n) && $HTTPS_ERROR == HTTPS_WANT_READ)) { |
|
|
|
0
|
|
|
|
|
269
|
0
|
|
|
|
|
|
$_[0] = ""; |
270
|
0
|
|
|
|
|
|
return -1; |
271
|
|
|
|
|
|
|
} |
272
|
0
|
|
|
|
|
|
return $n; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
1; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=head1 SEE ALSO |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
L, L |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head1 COPYRIGHT |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Copyright 2011-2013 Oleg G . |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or |
286
|
|
|
|
|
|
|
modify it under the same terms as Perl itself. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=cut |