line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package IO::BindHandles; |
2
|
|
|
|
|
|
|
# ABSTRACT: Bind a set of handles for buffered tunneling |
3
|
|
|
|
|
|
|
|
4
|
5
|
|
|
5
|
|
3174
|
use strict; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
155
|
|
5
|
5
|
|
|
5
|
|
25
|
use warnings; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
121
|
|
6
|
5
|
|
|
5
|
|
5255
|
use IO::Handle; |
|
5
|
|
|
|
|
39697
|
|
|
5
|
|
|
|
|
264
|
|
7
|
5
|
|
|
5
|
|
7370
|
use IO::Select; |
|
5
|
|
|
|
|
21273
|
|
|
5
|
|
|
|
|
2251
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub new { |
10
|
3
|
|
|
3
|
1
|
1004708
|
my $class = shift; |
11
|
3
|
|
33
|
|
|
58
|
$class = ref $class || $class; |
12
|
3
|
|
|
|
|
27
|
my %options = @_; |
13
|
|
|
|
|
|
|
|
14
|
3
|
|
|
|
|
7
|
my $timeout = 0.5; |
15
|
3
|
50
|
|
|
|
39
|
$timeout = $options{timeout} if exists $options{timeout}; |
16
|
3
|
50
|
|
|
|
67
|
$timeout += 0 if defined $timeout; |
17
|
|
|
|
|
|
|
|
18
|
3
|
|
|
|
|
9
|
my $handles = $options{handles}; |
19
|
3
|
50
|
|
|
|
26
|
die "handles must be an ARRAY ref" if ref $handles ne 'ARRAY'; |
20
|
3
|
50
|
|
|
|
11
|
warn "odd number of handles in BindHandles" if scalar(@$handles) & 1; |
21
|
|
|
|
|
|
|
|
22
|
3
|
|
|
|
|
16
|
my @all_handles; |
23
|
3
|
|
|
|
|
15
|
for (my $i = 0; $i < scalar @$handles; $i += 2) { |
24
|
4
|
|
|
|
|
14
|
my $read = $handles->[$i]; |
25
|
4
|
|
|
|
|
12
|
my $write = $handles->[$i+1]; |
26
|
4
|
|
|
|
|
18
|
$read->autoflush(1); |
27
|
4
|
|
|
|
|
116
|
$write->autoflush(1); |
28
|
4
|
|
|
|
|
111
|
my $buffer = ''; |
29
|
4
|
|
|
|
|
18
|
push @all_handles, [ $read, $write, $buffer ]; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
3
|
|
|
|
|
21
|
my $self = { |
33
|
|
|
|
|
|
|
timeout => $timeout, |
34
|
|
|
|
|
|
|
handles => \@all_handles, |
35
|
|
|
|
|
|
|
}; |
36
|
|
|
|
|
|
|
|
37
|
3
|
|
|
|
|
13
|
bless $self, $class; |
38
|
3
|
|
|
|
|
11
|
return $self; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub loop { |
43
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
44
|
0
|
0
|
0
|
|
|
0
|
$self->timeout(0.1) if defined $self->timeout && $self->timeout == 0; |
45
|
|
|
|
|
|
|
#warn "In loop..."; |
46
|
0
|
|
|
|
|
0
|
while ($self->bound()) { |
47
|
|
|
|
|
|
|
#warn "rwcycle..."; |
48
|
0
|
|
|
|
|
0
|
$self->rwcycle(); |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
#warn "Out loop..."; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub bound { |
55
|
9
|
|
|
9
|
1
|
1495
|
my $self = shift; |
56
|
|
|
|
|
|
|
#warn "in bound..."; |
57
|
14
|
100
|
33
|
|
|
287
|
my @list = |
|
|
|
33
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
58
|
|
|
|
|
|
|
grep { |
59
|
9
|
|
|
|
|
188
|
( |
60
|
|
|
|
|
|
|
$_->[0]->opened && $_->[1]->opened && |
61
|
|
|
|
|
|
|
!$_->[0]->error && !$_->[1]->error |
62
|
|
|
|
|
|
|
) |
63
|
|
|
|
|
|
|
|| |
64
|
|
|
|
|
|
|
( $_->[2] && $_->[1]->opened && !$_->[1]->error ) |
65
|
9
|
|
|
|
|
45
|
} @{$self->{handles}}; |
66
|
|
|
|
|
|
|
#warn "out bound..."; |
67
|
|
|
|
|
|
|
return |
68
|
9
|
|
|
|
|
622
|
scalar @list; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub rwcycle { |
73
|
7
|
|
|
7
|
1
|
32
|
my $self = shift; |
74
|
5
|
|
|
5
|
|
5558
|
use bytes; |
|
5
|
|
|
|
|
55
|
|
|
5
|
|
|
|
|
28
|
|
75
|
|
|
|
|
|
|
#warn "in rwcycle..."; |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# we listen on all handles all the time for reading... |
78
|
11
|
50
|
|
|
|
119
|
my @read_handles = grep { $_->opened && !$_->error } |
|
11
|
|
|
|
|
240
|
|
79
|
11
|
50
|
|
|
|
91
|
map { $_->[0] } |
80
|
7
|
|
|
|
|
29
|
grep { $_->[1]->opened && !$_->[1]->error } |
81
|
7
|
|
|
|
|
21
|
@{$self->{handles}}; |
82
|
|
|
|
|
|
|
#warn "Selecting read on ".join ', ', @read_handles; |
83
|
7
|
|
|
|
|
323
|
my $read_select = IO::Select->new(@read_handles); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# but we only listen for writing on those that we have |
87
|
|
|
|
|
|
|
# something to write to. |
88
|
3
|
50
|
|
|
|
14
|
my @write_handles = grep { $_->opened && !$_->error } |
|
3
|
|
|
|
|
8
|
|
89
|
11
|
|
|
|
|
47
|
map { $_->[1] } |
90
|
7
|
|
|
|
|
762
|
grep { $_->[2] } @{$self->{handles}}; |
|
7
|
|
|
|
|
30
|
|
91
|
|
|
|
|
|
|
#warn "Selecting write on ".join ', ', @write_handles; |
92
|
7
|
|
|
|
|
75
|
my $write_select = IO::Select->new(@write_handles); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# we check for exception in all handles; |
96
|
7
|
|
|
|
|
162
|
my @except_handles = (@read_handles, @write_handles); |
97
|
|
|
|
|
|
|
#warn "Selecting exception on ".join ', ', @except_handles; |
98
|
7
|
|
|
|
|
24
|
my $except_select = IO::Select->new(@except_handles); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# now let's see if there's something to be read or written |
102
|
|
|
|
|
|
|
#warn "Select..."; |
103
|
7
|
|
|
|
|
390
|
my ($r_r, $r_w, $e) = IO::Select::select($read_select, $write_select, $except_select, $self->timeout); |
104
|
|
|
|
|
|
|
#warn "done..."; |
105
|
|
|
|
|
|
|
|
106
|
7
|
100
|
50
|
|
|
74395
|
if ($r_r && scalar @$r_r) { |
107
|
5
|
|
|
|
|
21
|
foreach my $h (@$r_r) { |
108
|
5
|
|
|
|
|
16
|
my ($h_desc) = grep { $_->[0] eq $h } @{$self->{handles}}; |
|
8
|
|
|
|
|
51
|
|
|
5
|
|
|
|
|
22
|
|
109
|
5
|
|
|
|
|
12
|
my $handle = $h_desc->[0]; |
110
|
5
|
|
|
|
|
9
|
my $temp_buf; |
111
|
|
|
|
|
|
|
#warn "Reading from $handle."; |
112
|
5
|
|
|
|
|
71
|
my $num_read = $handle->sysread($temp_buf, 1024); |
113
|
5
|
100
|
66
|
|
|
200
|
if (defined $num_read && $num_read > 0) { |
114
|
|
|
|
|
|
|
#warn "Read $num_read"; |
115
|
3
|
|
|
|
|
25
|
$h_desc->[2] .= substr($temp_buf, 0, $num_read); |
116
|
|
|
|
|
|
|
} else { |
117
|
|
|
|
|
|
|
#warn "Error..."; |
118
|
2
|
|
|
|
|
47
|
$handle->close; |
119
|
2
|
|
|
|
|
115
|
$h_desc->[3] = 1; |
120
|
2
|
100
|
|
|
|
15
|
$h_desc->[1]->close unless $h_desc->[2]; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
7
|
100
|
50
|
|
|
72
|
if ($r_w && scalar @$r_w) { |
126
|
3
|
|
|
|
|
9
|
foreach my $h (@$r_w) { |
127
|
3
|
|
|
|
|
6
|
my ($h_desc) = grep { $_->[1] eq $h } @{$self->{handles}}; |
|
5
|
|
|
|
|
18
|
|
|
3
|
|
|
|
|
9
|
|
128
|
3
|
|
|
|
|
12
|
my $handle = $h_desc->[1]; |
129
|
|
|
|
|
|
|
#warn "Writing on $handle."; |
130
|
3
|
|
|
|
|
42
|
my $num_write = $handle->syswrite($h_desc->[2], length($h_desc->[2])); |
131
|
3
|
50
|
33
|
|
|
114
|
if (defined $num_write && $num_write >= 0) { |
132
|
|
|
|
|
|
|
#warn "Wrote $num_write."; |
133
|
3
|
|
|
|
|
17
|
substr($h_desc->[2],0,$num_write,''); |
134
|
|
|
|
|
|
|
} else { |
135
|
|
|
|
|
|
|
#warn "Error."; |
136
|
0
|
|
|
|
|
0
|
$handle->close; |
137
|
0
|
|
|
|
|
0
|
$h_desc->[0]->close; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
7
|
50
|
50
|
|
|
96
|
if ($e && scalar @$e) { |
142
|
0
|
|
|
|
|
0
|
foreach my $h (@$r_w) { |
143
|
|
|
|
|
|
|
#warn "Exception in $h"; |
144
|
0
|
0
|
|
|
|
0
|
my ($h_desc) = grep { $_->[1] eq $h || $_->[0] eq $h } @{$self->{handles}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
145
|
|
|
|
|
|
|
# we close the writing handles unless the |
146
|
|
|
|
|
|
|
# exception was in the reading handle and there |
147
|
|
|
|
|
|
|
# is still buffered content to be sent. |
148
|
0
|
0
|
0
|
|
|
0
|
unless ($h eq $h_desc->[0] && $h_desc->[2]) { |
149
|
0
|
|
|
|
|
0
|
$h_desc->[1]->close; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
# in any case we won't read anymore |
152
|
0
|
|
|
|
|
0
|
$h_desc->[0]->close; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
7
|
|
|
|
|
13
|
foreach my $h (@{$self->{handles}}) { |
|
7
|
|
|
|
|
42
|
|
157
|
11
|
50
|
66
|
|
|
253
|
if (exists $h->[3] && $h->[3] && !$h->[2]) { |
|
|
|
66
|
|
|
|
|
158
|
3
|
|
|
|
|
23
|
$h->[1]->close() |
159
|
2
|
50
|
|
|
|
11
|
unless grep { $_->[0] eq $h->[1] } @{$self->{handles}} |
|
2
|
|
|
|
|
6
|
|
160
|
|
|
|
|
|
|
; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub timeout { |
168
|
7
|
|
|
7
|
1
|
10
|
my $self = shift; |
169
|
7
|
|
|
|
|
35
|
my $ret = $self->{timeout}; |
170
|
7
|
50
|
|
|
|
50
|
$self->{timeout} = shift if @_; |
171
|
7
|
|
|
|
|
68
|
return $ret; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
1; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
__END__ |