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,

    on_data_frame => sub {
        my ($frame) = @_;

        #...
    }
);

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 filehandle

  • max_pings (optional) - The maximum # of pings to send before we send a close frame (which ends the session).

  • on_data_frame (optional) - A callback that receives every data frame that get_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_sr => \q<>,
            fin => $_[0]->get_fin(),
        );
    },

OBJ->get_next_message()

The “workhorse” method. It returns a data message if one is available and is the next frame; otherwise, it returns undef.

This method also handles control frames that arrive before or among message frames:

  • close: Respond with the identical close frame.

  • ping: Send the appropriate pong frame.

  • pong: Set the internal ping counter to zero. If the pong is unrecognized (i.e., we’ve not sent the payload in a ping), then we send a PROTOCOL_ERROR close frame.

This method may not be called after a close frame has been sent (i.e., if the is_closed() method returns true).

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->is_closed()

Return 1 or 0 to indicate whether we have tried to send a close frame.

EXTENSIONS

This module has several controls for supporting WebSocket extensions:

  • get_next_message()’s returned messages will always contain a get_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 type foo.) The parser object that you pass to the constructor has to be aware of such messages; for more details, see the documentation for Net::WebSocket::Parser.