File Coverage

blib/lib/Net/WebSocket/Endpoint/Server.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Net::WebSocket::Endpoint::Server;
2              
3 9     9   389835 use strict;
  9         50  
  9         270  
4 9     9   47 use warnings;
  9         19  
  9         292  
5              
6 9         57 use parent qw(
7             Net::WebSocket::Endpoint
8             Net::WebSocket::Masker::Server
9 9     9   572 );
  9         381  
10              
11             =encoding utf-8
12              
13             =head1 NAME
14              
15             Net::WebSocket::Endpoint::Server
16              
17             =head1 SYNOPSIS
18              
19             my $ept = Net::WebSocket::Endpoint::Server->new(
20             parser => $parser_obj,
21              
22             out => $out_fh,
23              
24             #optional, # of pings to send before we send a close
25             max_pings => 5,
26              
27             #optional
28             on_data_frame => sub {
29             my ($frame_obj) = @_;
30              
31             #...
32             },
33             );
34              
35             my $msg_to_send = $ept->create_message('text', 'Hello!');
36              
37             if ( _we_timed_out_waiting_for_read_readiness() ) {
38             $ept->check_heartbeat();
39             }
40             else {
41              
42             #This should only be called when reading won’t produce an error.
43             #For example, in non-blocking I/O you’ll need a select() in front
44             #of this. (Blocking I/O can just call it and wait!)
45             $ept->get_next_message();
46              
47             #Check for this at the end of each cycle.
48             _custom_logic_to_finish_up() if $ept->is_closed();
49             }
50              
51             =head1 DESCRIPTION
52              
53             This module, like its twin, L, attempts
54             to wrap up “obvious” bits of a WebSocket endpoint’s workflow into a
55             reusable component.
56              
57             The basic workflow is shown in the SYNOPSIS; descriptions of the individual
58             methods follow:
59              
60             =head1 METHODS
61              
62             =head2 I->new( %OPTS )
63              
64             Instantiate the class. Nothing is actually done here. Options are:
65              
66             =over
67              
68             =item * C (required) - An instance of L.
69              
70             =item * C (required) - The endpoint’s output object. An
71             instance of L or a compatible class.
72              
73             =item * C (optional) - The maximum # of pings to send before
74             we send a C frame (which ends the session).
75              
76             =item * C (optional) - A callback that receives every data
77             frame that C receives. Use this to facilitate chunking.
78              
79             If you want to avoid buffering a large message, you can do this:
80              
81             on_data_frame => sub {
82             #... however you’re going to handle this chunk
83              
84             $_[0] = (ref $_[0])->new(
85             payload => q<>,
86             fin => $_[0]->get_fin(),
87             );
88             },
89              
90             =back
91              
92             =head2 I->get_next_message()
93              
94             The “workhorse” method. It returns one of the following:
95              
96             =over
97              
98             =item * a data message if one is available
99              
100             =item * empty string if the Parser’s C indicated
101             end-of-file without an exception
102              
103             =item * otherwise, undef
104              
105             =back
106              
107             This method also handles control frames that arrive before or among
108             message frames:
109              
110             =over
111              
112             =item * close: Respond (immediately) with the identical close frame.
113             See below for more information.
114              
115             =item * ping: Send the appropriate pong frame.
116              
117             =item * pong: As per the protocol specification.
118              
119             =back
120              
121             This method may not be called after a close frame has been sent (i.e.,
122             if the C method returns true).
123              
124             =head2 I->create_message( FRAME_TYPE, PAYLOAD )
125              
126             Creates an unfragmented message with the given PAYLOAD.
127              
128             FRAME_TYPE can be either C or C (for Net::WebSocket’s
129             default frame classes) or full package names (e.g., to use a custom
130             frame class).
131              
132             This is a convenience method that takes care of mask creation and module
133             loading for you.
134              
135             See L for similar functionality
136             to create a compressed message.
137              
138             =cut
139              
140             =head2 I->check_heartbeat()
141              
142             Ordinarily, sends a distinct ping frame to the remote server
143             and increments the ping counter. Once a sent ping is
144             received back (i.e., a pong), the ping counter gets reset.
145              
146             If the internal ping counter has already reached C, then we
147             send a PROTOCOL_ERROR close frame. Further I/O attempts on this object
148             will prompt an appropriate exception to be thrown.
149              
150             =head2 I->sent_close_frame()
151              
152             Returns a C object or undef to represent the
153             frame that the object has sent, either via the C method directly
154             or automatically via the internal handling of control messages.
155              
156             =head2 I->received_close_frame()
157              
158             Returns a C object or undef to represent the
159             frame that the object has received.
160              
161             =head2 I->is_closed()
162              
163             DEPRECATED: Returns 1 or 0 to indicate whether we have sent a close frame.
164             Note that C provides a more useful variant of the
165             same functionality; there is no good reason to use this method anymore.
166              
167             =head2 I->do_not_die_on_close()
168              
169             Ordinarily, receipt of a close frame prompts an exception after the
170             response close frame is sent. This is, arguably, a suboptimal design
171             choice since receipt of a close frame is a perfectly normal thing to happen;
172             i.e., it’s not “exception-al”. If you want to check for close yourself
173             instead, you can do so by calling this method.
174              
175             =head2 I->die_on_close()
176              
177             The inverse of C: restores
178             the default behavior when a close frame is received.
179              
180             =head1 WHEN A CLOSE FRAME IS RECEIVED
181              
182             C will automatically send a close frame in response
183             when it receives one. The received close frame is not returned to the
184             application but, like ping and pong, is handled transparently.
185              
186             Rationale: WebSocket is often billed as “TCP for the web”; however, the
187             protocol curiously diverges from TCP in not supporting “half-close”; a
188             WebSocket connection is either fully open (i.e., bidirectional) or fully
189             closed. (There is some leeway given for finishing up an in-progress message,
190             but this is a much more limited concept.)
191              
192             =head1 EXTENSIONS
193              
194             This module has several controls for supporting WebSocket extensions:
195              
196             =over
197              
198             =item * C’s returned messages will always contain
199             a C method, which you can use to read the reserved bits
200             of the individual data frames.
201              
202             =item * You can create C methods on a subclass of this module
203             to handle different types of control frames. (e.g., C)
204             to handle frames of type C.) The C object that you pass
205             to the constructor has to be aware of such messages; for more details,
206             see the documentation for L.
207              
208             =back
209              
210             =cut
211              
212             1;