File Coverage

blib/lib/Net/SPDY/Session.pm
Criterion Covered Total %
statement 38 52 73.0
branch 8 18 44.4
condition n/a
subroutine 7 8 87.5
pod 3 4 75.0
total 56 82 68.2


line stmt bran cond sub pod time code
1             package Net::SPDY::Session;
2              
3             =head1 NAME
4              
5             Net::SPDY::Session - Handle SPDY protocol connection
6              
7             =head1 ALPHA WARNING
8              
9             B This is an ALPHA stage software.
10             In particular this means that even though it probably won't kill your cat,
11             re-elect George W. Bush nor install Solaris 11 Express edition to your hard
12             drive, it is in active development, functionality is missing and no APIs are
13             stable.
14              
15             See F file in the distribution to learn about missing and planned
16             functionality. You are more than welcome to join the development and submit
17             patches with fixes or enhancements. Bug reports are probably not very useful
18             at this point.
19              
20             =head1 SYNOPSIS
21              
22             use Net::SPDY::Session;
23              
24             my $server = new IO::Socket::SSL (
25             LocalAddr => 'localhost:443',
26             ReuseAddr => 1,
27             SSL_server => 1,
28             SSL_cert_file => $cert,
29             SSL_key_file => $key,
30             SSL_npn_protocols => ['spdy/3'])
31             or die IO::Socket::SSL::errstr;
32              
33             while (my $client = $server->accept) {
34             # Fork a child to handle the connection
35             my $kidpid = fork;
36             die $! unless defined $kidpid;
37             # Proceed with next connection
38             next if $kidpid;
39              
40             my $session = new Net::SPDY::Session ($client);
41             while ($session->process_frame) {
42             ...
43             }
44             }
45              
46             =head1 DESCRIPTION
47              
48             B represents the single stateful SPDY connection along
49             with its state, which in called a session.
50              
51             It provides access to the underlying protocol and convenience functions to
52             access the state and communicate via the protocol.
53              
54             =cut
55              
56 3     3   60586 use strict;
  3         6  
  3         98  
57 3     3   14 use warnings;
  3         4  
  3         79  
58              
59 3     3   1054 use Net::SPDY::Framer;
  3         5  
  3         70  
60 3     3   1275 use Net::SPDY::Compressor;
  3         10  
  3         1658  
61              
62             our $VERSION = '0.1';
63              
64             =head1 PROPERTIES
65              
66             =over 4
67              
68             =item compressor
69              
70             L object representing the Zlib streams (one in each
71             direction) used by the framer. A new one is created upon session construction.
72              
73             =item socket
74              
75             L instance that is used for actual network communication.
76              
77             =item framer
78              
79             L the protocol implementation on top of I and
80             I it is coupled with. A new one is created upon session construction.
81              
82             =back
83              
84             =head1 METHODS
85              
86             =over 4
87              
88             =cut
89              
90             sub got_settings
91             {
92 3     3 0 5 my $self = shift;
93 3         12 my %frame = @_;
94              
95 3 100       8 if ($frame{flags} & Net::SPDY::Framer::FLAG_SETTINGS_CLEAR_SETTINGS) {
96 1         4 $self->{settings} = {};
97             }
98              
99 3         10 my %new_settings;
100 3         4 foreach my $setting (@{$frame{id_values}}) {
  3         10  
101 6 100       25 next if exists $new_settings{$setting->{id}};
102 5         32 $new_settings{$setting->{id}} = [$setting->{value},
103             $setting->{flags}];
104             }
105 3         6 %{$self->{settings}} = (%{$self->{settings}}, %new_settings);
  3         16  
  3         11  
106             }
107              
108             =item new SOCKET
109              
110             Creates a new session instance. First argument is the socket (either server
111             or client, it does not matter) for the network communication.
112              
113             =cut
114              
115             sub new
116             {
117 1     1 1 1444 my $class = shift;
118 1         50 my $self = bless {}, $class;
119              
120             # Couple with framer
121 1         40 $self->{compressor} = new Net::SPDY::Compressor ();
122 1         21 $self->{socket} = shift;
123 1         14 $self->{settings} = {};
124              
125 1         34 $self->{framer} = new Net::SPDY::Framer ({
126             compressor => $self->{compressor},
127             socket => $self->{socket},
128             });
129              
130 1         10 return $self;
131             }
132              
133             =item process_frame
134              
135             Read a single frame from the framer and process it, which may include changing
136             session state and and eventually sending an appropriate response.
137              
138             =cut
139              
140             sub process_frame
141             {
142 3     3 1 28719 my $self = shift;
143              
144 3         22 my %frame = $self->{framer}->read_frame ();
145 3 50       10 return () unless %frame;
146              
147 3 50       12 if (not $frame{control}) {
148 0         0 warn 'Not implemented: Data frame received';
149 0         0 return %frame;
150             }
151              
152 3 50       24 if ($frame{type} == Net::SPDY::Framer::SYN_STREAM) {
    50          
    0          
    0          
    0          
153 0         0 my $body = 'Hello, World!';
154              
155 0         0 $self->{framer}->write_syn_reply (
156             stream_id => $frame{stream_id},
157             flags => 0,
158             headers => [
159             ':status' => '200 Ok',
160             ':version' => 'HTTP/1.1',
161             'content-length' => length($body),
162             ]
163             );
164 0         0 $self->{framer}->write_frame (
165             control => 0,
166             stream_id => $frame{stream_id},
167             flags => Net::SPDY::Framer::FLAG_FIN,
168             data => $body,
169             );
170             } elsif ($frame{type} == Net::SPDY::Framer::SETTINGS) {
171 3         17 $self->got_settings (%frame);
172             } elsif ($frame{type} == Net::SPDY::Framer::PING) {
173 0         0 $self->{framer}->write_ping (
174             flags => 0,
175             id => $frame{id},
176             );
177             } elsif ($frame{type} == Net::SPDY::Framer::GOAWAY) {
178 0         0 $self->close (0);
179             } elsif ($frame{type} == Net::SPDY::Framer::HEADERS) {
180             # We should remember values gotten here for stream
181 0         0 warn 'Not implemented: Got headers frame'
182             } else {
183 0         0 die 'Unknown frame type '.$frame{type};
184             }
185              
186 3         17 return %frame;
187             }
188              
189             =item close
190              
191             Do whatever is needed to terminate a connection.
192             May involve sending a C frame and closing the socket.
193              
194             =cut
195              
196             sub close
197             {
198 0     0 1   my $self = shift;
199 0           my $status = shift;
200              
201 0           $self->{framer}->write_goaway (
202             last_good_stream_id => 0,
203             status => $status,
204             );
205 0           $self->{framer}{socket}->close;
206 0           $self->{framer}{socket} = undef;
207             }
208              
209             =back
210              
211             =head1 SEE ALSO
212              
213             =over
214              
215             =item *
216              
217             L -- SPDY project web site
218              
219             =item *
220              
221             L -- SSL/TLS socket bindings with NPN support
222              
223             =item *
224              
225             L -- SPDY protocol implementation
226              
227             =item *
228              
229             L -- SPDY header compression
230              
231             =back
232              
233             =head1 CONTRIBUTING
234              
235             Source code for I is kept in a public GIT repository.
236             Visit L.
237              
238             Bugs reports and feature enhancement requests are tracked at
239             L.
240              
241             =head1 COPYRIGHT
242              
243             Copyright 2012, Lubomir Rintel
244              
245             This program is free software; you can redistribute it and/or modify it
246             under the same terms as Perl itself.
247              
248             =head1 AUTHOR
249              
250             Lubomir Rintel C
251              
252             =cut
253              
254             1;