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.
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, andsendFrame()
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()
.