Guide Home
POD Home

Sloop::WebSocket

DESCRIPTION

Implements the websocket protocol (ws://) as defined in RFC 6455. This is not an OO interface. To initialize a socket, use start(); this configures a Sloop::Client and associates it with a handler for incoming data. To reply, use sendFrame(). To close the socket, use close().

REQUIRES

This refers to modules not part of Sloop or the perl core.

MIME::Base64
Digest::SHA

SUBROUTINES

Sloop::WebSocket::start($client, %options)

Opens the websocket. This slightly changes the way the connection is handled. It calls $client->setAfterReplyHandler() and chains any existing handler to fire after the one it sets.

Will return undef if the request is not a valid websocket negotiation; an error will be logged via $client->err_log(). Otherwise returns a true value.

The %options are:

dataIn

Required. A subroutine reference that will be called for incoming messages, except for control/close. Will croak if undefined. See below for the parameters passed in.

onControl

A subroutine reference that will be called for incoming control messages, except for close or ping; by the current protocol this just leaves pong, which should be returned if you manually send a ping frame first.

If undefined, the event is simply noted as a request via $client->{logger}; no response is sent and any payload is discarded.

Ping control messages are automatically handled with a pong reply. Close control messages are handled by onClose, if defined.

onClose

A subroutine reference that will be called for incoming close messages. If undefined, $client is sent a close frame in response and any payload is discarded. If defined, it is your responsibility to make sure a close frame is sent in response as the protocol requires this (see section 5.5.1 in RFC 6455, and sendFrame() below).

maxFrameSz

The maximum length of a frame payload in bytes. The default is 4194304 (4 MiB). Frames larger than this will be discarded, an error will be logged, and $client->cancel() called.

All the above callbacks (dataIn, onControl, onClose) receive three arguments:

1) A Sloop::Client object associated with the websocket. This is the same object as passed in to start(). Never use a capture for this or you will end up with a circular reference.

2) A reference to a scalar containing the payload of the message.

3) A hash reference with the following fields (generally these aren't of much interest):

opcode

An opcode corresponding to one of the following constants (see section 11.8 of RFC 6455):

 Sloop::WebSocket::WS_CONTINUATION
 Sloop::WebSocket::WS_TEXT
 Sloop::WebSocket::WS_BINARY
 Sloop::WebSocket::WS_CLOSE
 Sloop::WebSocket::WS_PONG

Ping frames are dealt with automatically according to the protocol and will not fire a callback. Fragmented messages are assembled before any callback is fired, and 'opcode' is set to what it was in the initial frame (so WS_CONTINUATION should not happen).

length

This is the length of the payload in bytes.

FIN

The value of the FIN bit (see section 5.4 of RFC 6455), either 0 or 1. Sloop::WebSocket assembles fragmented messages and delivers them via callback when complete, so this should always be 1.

RSV1
RSV2
RSV3

Values for the RSV1, 2, and 3 bits, either 0 or 1. Technically these must "be 0 unless an extension is negotiated that defines meanings for non-zero values" and if "a nonzero value is received and none of the negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_" (section 5.2 of RFC 6455). However, Sloop::WebSocket itself does not interpret these one way or the other.

closeStatus

This will only be present for close frames that include a status code and possibly a further payload. It's the integer status code (see 7.4 of RFC 6455).

Sloop::WebSocket::sendFrame($client, $dataref, $frameOpts)

Method for transmitting a frame to $client

Sloop::WebSocket does not automatically fragment messages, so this is always really a single frame. The protocol does not stipulate a limit on frame length beyond a value that can fit into a 64-bit number.

$client

Must have previously passed through start() -- i.e., it should generally be the object provided via one of the callbacks registered there. If not, it will be cancelled and an error logged.

$dataref

A reference to a scalar containing the message payload. This must be a reference or the call is fatal. If it is not a scalar reference, the behaviour is undefined. It may be a reference to an empty string (\"") if there is no payload.

$frameOpts is a optional hash ref containing one or more keys:

opcode

A value to use in the opcode field of the websocket frame header. In addition to the constants listed under 'opcode' in the SYNOPSIS above, you can use Sloop::WebSocket::WS_PING.

RSV1

A value to use in the RSV1 field of the websocket frame header.

RSV2

A value to use in the RSV2 field of the websocket frame header.

RSV3

A value to use in the RSV3 field of the websocket frame header.

If $frameOpts is not given, the frame header will use 0 for RSV fields and Sloop::WebSocket::WS_TEXT for the opcode (see SYNOPSIS).

Sloop::WebSocket::close($client)

Convenience method for sending a close frame with no payload.

$client

See sendFrame().