NAME
Net::WebSocket::Endpoint::Server
SYNOPSIS
my $ept = Net::WebSocket::Endpoint::Server->new(
parser => $parser_obj,
out => $out_fh,
#optional, # of pings to send before we send a close
max_pings => 5,
#optional
on_data_frame => sub {
my ($frame_obj) = @_;
#...
},
);
my $msg_to_send = $ept->create_message('text', 'Hello!');
if ( _we_timed_out_waiting_for_read_readiness() ) {
$ept->check_heartbeat();
}
else {
#This should only be called when reading won’t produce an error.
#For example, in non-blocking I/O you’ll need a select() in front
#of this. (Blocking I/O can just call it and wait!)
$ept->get_next_message();
#Check for this at the end of each cycle.
_custom_logic_to_finish_up() if $ept->is_closed();
}
DESCRIPTION
This module, like its twin, Net::WebSocket::Endpoint::Client, attempts to wrap up “obvious” bits of a WebSocket endpoint’s workflow into a reusable component.
The basic workflow is shown in the SYNOPSIS; descriptions of the individual methods follow:
METHODS
CLASS->new( %OPTS )
Instantiate the class. Nothing is actually done here. Options are:
parser
(required) - An instance of Net::WebSocket::Parser.out
(required) - The endpoint’s output object. An instance of IO::Framed or a compatible class.max_pings
(optional) - The maximum # of pings to send before we send aclose
frame (which ends the session).on_data_frame
(optional) - A callback that receives every data frame thatget_next_message()
receives. Use this to facilitate chunking.If you want to avoid buffering a large message, you can do this:
on_data_frame => sub { #... however you’re going to handle this chunk $_[0] = (ref $_[0])->new( payload => q<>, fin => $_[0]->get_fin(), ); },
OBJ->get_next_message()
The “workhorse” method. It returns one of the following:
a data message if one is available
empty string if the Parser’s
get_next_frame()
indicated end-of-file without an exceptionotherwise, undef
This method also handles control frames that arrive before or among message frames:
close: Respond (immediately) with the identical close frame. See below for more information.
ping: Send the appropriate pong frame.
pong: As per the protocol specification.
This method may not be called after a close frame has been sent (i.e., if the is_closed()
method returns true).
OBJ->create_message( FRAME_TYPE, PAYLOAD )
Creates an unfragmented message with the given PAYLOAD.
FRAME_TYPE can be either text
or binary
(for Net::WebSocket’s default frame classes) or full package names (e.g., to use a custom frame class).
This is a convenience method that takes care of mask creation and module loading for you.
See Net::WebSocket::PMCE::deflate::Data for similar functionality to create a compressed message.
OBJ->check_heartbeat()
Ordinarily, sends a distinct ping frame to the remote server and increments the ping counter. Once a sent ping is received back (i.e., a pong), the ping counter gets reset.
If the internal ping counter has already reached max_pings
, then we send a PROTOCOL_ERROR close frame. Further I/O attempts on this object will prompt an appropriate exception to be thrown.
OBJ->sent_close_frame()
Returns a Net::WebSocket::Frame::close
object or undef to represent the frame that the object has sent, either via the close()
method directly or automatically via the internal handling of control messages.
OBJ->received_close_frame()
Returns a Net::WebSocket::Frame::close
object or undef to represent the frame that the object has received.
OBJ->is_closed()
DEPRECATED: Returns 1 or 0 to indicate whether we have sent a close frame. Note that sent_close_frame()
provides a more useful variant of the same functionality; there is no good reason to use this method anymore.
OBJ->do_not_die_on_close()
Ordinarily, receipt of a close frame prompts an exception after the response close frame is sent. This is, arguably, a suboptimal design choice since receipt of a close frame is a perfectly normal thing to happen; i.e., it’s not “exception-al”. If you want to check for close yourself instead, you can do so by calling this method.
OBJ->die_on_close()
The inverse of do_not_die_on_close()
: restores the default behavior when a close frame is received.
WHEN A CLOSE FRAME IS RECEIVED
get_next_message()
will automatically send a close frame in response when it receives one. The received close frame is not returned to the application but, like ping and pong, is handled transparently.
Rationale: WebSocket is often billed as “TCP for the web”; however, the protocol curiously diverges from TCP in not supporting “half-close”; a WebSocket connection is either fully open (i.e., bidirectional) or fully closed. (There is some leeway given for finishing up an in-progress message, but this is a much more limited concept.)
EXTENSIONS
This module has several controls for supporting WebSocket extensions:
get_next_message()
’s returned messages will always contain aget_frames()
method, which you can use to read the reserved bits of the individual data frames.You can create
on_*
methods on a subclass of this module to handle different types of control frames. (e.g.,on_foo(FRAME)
) to handle frames of typefoo
.) Theparser
object that you pass to the constructor has to be aware of such messages; for more details, see the documentation for Net::WebSocket::Parser.