line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::WebSocket::PMCE::deflate::Data::Streamer; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
23
|
use strict; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
99
|
|
4
|
3
|
|
|
3
|
|
16
|
use warnings; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
104
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=encoding utf-8 |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Net::WebSocket::PMCE::deflate::Data::Streamer |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $streamer = $deflate_data->create_streamer( $frame_class ); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#These frames form a single compressed message in three |
17
|
|
|
|
|
|
|
#fragments whose content is “onetwothree”. |
18
|
|
|
|
|
|
|
my @frames = ( |
19
|
|
|
|
|
|
|
$streamer->create_chunk('one'), |
20
|
|
|
|
|
|
|
$streamer->create_chunk('two'), |
21
|
|
|
|
|
|
|
$streamer->create_final('three'), |
22
|
|
|
|
|
|
|
); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 DESCRIPTION |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
This class implements fragmentation for the permessage-deflate WebSocket |
27
|
|
|
|
|
|
|
extension. It allows you to send a single message in arbitrarily many |
28
|
|
|
|
|
|
|
parts. The class is not instantiated directly, but instances are returned |
29
|
|
|
|
|
|
|
as the result of L’s |
30
|
|
|
|
|
|
|
C method. |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Strictly speaking, this is a base class; the C<::Client> and C<::Server> |
33
|
|
|
|
|
|
|
subclasses implement a bit of logic specific to either endpoint type. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
The C and C methods follow the same |
36
|
|
|
|
|
|
|
pattern as L. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=cut |
39
|
|
|
|
|
|
|
|
40
|
3
|
|
|
3
|
|
1033
|
use Module::Runtime (); |
|
3
|
|
|
|
|
3737
|
|
|
3
|
|
|
|
|
123
|
|
41
|
|
|
|
|
|
|
|
42
|
3
|
|
|
3
|
|
1330
|
use Net::WebSocket::Frame::continuation (); |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
747
|
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 METHODS |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=cut |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub new { |
49
|
5
|
|
|
5
|
0
|
13
|
my ($class, $data_obj, $frame_class) = @_; |
50
|
|
|
|
|
|
|
|
51
|
5
|
100
|
|
|
|
56
|
Module::Runtime::require_module($frame_class) if !$frame_class->can('new'); |
52
|
|
|
|
|
|
|
|
53
|
5
|
|
|
|
|
21
|
my $self = { |
54
|
|
|
|
|
|
|
_data_obj => $data_obj, |
55
|
|
|
|
|
|
|
_frame_class => $frame_class, |
56
|
|
|
|
|
|
|
}; |
57
|
|
|
|
|
|
|
|
58
|
5
|
|
|
|
|
28
|
return bless $self, $class; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
my ($_COMPRESS_FUNC, $_FIN); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head2 I->create_chunk( OCTET_STRING ) |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Compresses OCTET_STRING. The compressor doesn’t necessarily produce output |
66
|
|
|
|
|
|
|
from this, however. If the compressor does produce output, then this |
67
|
|
|
|
|
|
|
method returns a frame object (an instance of either the streamer’s |
68
|
|
|
|
|
|
|
assigned frame class or L); otherwise, |
69
|
|
|
|
|
|
|
undef is returned. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=cut |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub create_chunk { |
74
|
41
|
|
|
41
|
1
|
487814
|
$_COMPRESS_FUNC = '_compress_non_final_fragment'; |
75
|
41
|
|
|
|
|
88
|
$_FIN = 0; |
76
|
|
|
|
|
|
|
|
77
|
41
|
|
|
|
|
158
|
goto &_create; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 I->create_final( OCTET_STRING ) |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Compresses OCTET_STRING and flushes the compressor. The output matches |
83
|
|
|
|
|
|
|
that of C except that the output is always a frame object. |
84
|
|
|
|
|
|
|
The output of this method will complete the message. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub create_final { |
89
|
5
|
|
|
5
|
1
|
13225
|
$_COMPRESS_FUNC = $_[0]->{'_data_obj'}{'final_frame_compress_func'}; |
90
|
5
|
|
|
|
|
10
|
$_FIN = 1; |
91
|
|
|
|
|
|
|
|
92
|
5
|
|
|
|
|
13
|
goto &_create; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub _create { |
96
|
46
|
|
|
46
|
|
110
|
my ($self) = @_; |
97
|
|
|
|
|
|
|
|
98
|
46
|
|
|
|
|
110
|
my $data_obj = $self->{'_data_obj'}; |
99
|
|
|
|
|
|
|
|
100
|
46
|
|
|
|
|
196
|
my $payload_sr = \($data_obj->$_COMPRESS_FUNC( $_[1] )); |
101
|
|
|
|
|
|
|
|
102
|
46
|
100
|
|
|
|
208
|
return undef if !length $$payload_sr; |
103
|
|
|
|
|
|
|
|
104
|
6
|
100
|
|
|
|
23
|
my $class = $self->{'_frames_count'} ? 'Net::WebSocket::Frame::continuation' : $self->{'_frame_class'}; |
105
|
6
|
100
|
|
|
|
55
|
my $rsv = $self->{'_frames_count'} ? 0 : $data_obj->INITIAL_FRAME_RSV(); |
106
|
|
|
|
|
|
|
|
107
|
6
|
|
|
|
|
35
|
$self->{'_frames_count'}++; |
108
|
|
|
|
|
|
|
|
109
|
6
|
|
|
|
|
92
|
return $class->new( |
110
|
|
|
|
|
|
|
payload => $payload_sr, |
111
|
|
|
|
|
|
|
rsv => $rsv, |
112
|
|
|
|
|
|
|
$data_obj->FRAME_MASK_ARGS(), |
113
|
|
|
|
|
|
|
); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
1; |