WebSocket for Tcl HTTP client library
- www::websocket - WebSocket add-on for the www Tcl library
SYNOPSIS
-
package require Tcl 8.6
package require www 2.0
package require www::websocket 1.0
www websocket ?option value ...? url ?protocols? ?extensions?
DESCRIPTION
-
The www::websocket package extends the www package with
support for setting up websocket connections.
When the package is loaded, a new subcommand is added to the www
package:
- www websocket ?option value ...? url ?protocols? ?extensions?
-
The url argument specifies the URL to which to connect. This should be a URL handled by a WebSocket server. The URL should employ a ws or wss scheme.
The protocols argument can be used to indicate a list of sub-protocols the client requests to use. The list of protocols should be ordered by preference. See Protocols for details.
The extensions argument may be used to request the use of one or more websocket extensions. The extensions are defined using a dict that is keyed on the extension name and has at least the implementation subkey. Extension parameters may be specified using the parameters subkey. See Extensions for details.
The www websocket subcommand supports the following options: -auth, -digest, -maxredir, and -timeout. See the www manual entry for details on these options.
Upon a successful websocket connection, the command returns a websocket object command. See Object Command below for details. The protocol key in the return options indicates which protocol the server selected to use, if any. See Protocols for details.
OBJECT COMMAND
-
The websocket object command has the following subcommands:
- websocket binary data
- Send binary data over the web socket. The data argument should be a binary data string as created by e.g. the binary format or encoding convertto commands.
- websocket callback types commandPrefix
-
Arrange for commandPrefix to be executed (with additional arguments)
whenever one of the specified message types is received on the websocket.
When the commandPrefix argument is the empty string, the callback for
the specified types is disabled. When the types argument is also
empty, all callbacks are disabled.
The base www::websocket package supports the callback types listed below. Extensions can provide additional callback types.
- commandPrefix binary data
- This handler must be defined for a websocket connection to accept binary messages. In the absence of a binary handler, it is considered an error to receive a binary message. If that happens, the websocket connection is terminated with code 1003 (unacceptable data type).
- commandPrefix close code reason
- If the server closes the connection using a close message without a status code, this callback is invoked with a code of 1005 (no status code). If the websocket connection is terminated without the server sending a close message, this callback is invoked with a code of 1006 (connection closed abnormally).
- commandPrefix ping data
- When a callback has been enabled for the ping message, it becomes the responsibility of the callback handler to send a pong message.
- commandPrefix pong data
- Use when sending a ping message.
- commandPrefix text data
- This handler must be defined for a websocket connection to accept text messages. In the absence of a text handler, it is considered an error to receive a text message. If that happens, the websocket connection is terminated with code 1003 (unacceptable data type).
- websocket close ?code? ?reason?
- Send a close message to the server. The client expects the server to actually drop the TCP connection.
- websocket ping ?data?
- Send a ping message. A pong handler should be defined to be able to verify the response from the server.
- websocket pong ?data?
- Send a pong message. This should normally only be done from within a ping handler.
- websocket text string
- Send a text message to the server. The string will be UTF-8 encoded before sending.
PROTOCOLS
-
The list of protocols specified in the www websocket command is offered to the WebSocket server via the Sec-WebSocket-Protocol header. If the server agrees to using one of the offered protocols, it confirms that by returning the selected protocol in the Sec-WebSocket-Protocol header in the response. This information can be found in the protocol return option.
Here is an example of how to examine the return option:
try { www websocket $url {soap mqtt} } on ok {websock info} { set protocol [dict get $info protocol] if {$protocol eq "mqtt"} { $websock callback {binary close} mqtthandler } elseif {$protocol eq "soap"} { $websock callback {text close} soaphandler } else { $websock callback {text close} texthandler } }
EXTENSIONS
-
The WebSocket specification allows for extending the protocol. The www::websocket package supports this via the extensions argument to the www websocket command. The extensions argument should be a dict consisting of dicts defining the implementation and optional parameters of an extension.
For example, to request the use of the permessage-deflate extension, the following dict may be passed as the extensions argument to the www websocket command:
permessage-deflate { implementation WSDeflate parameters { client_max_window_bits server_max_window_bits=10 } }
The extension implementation must be an TclOO class with the name specified in the implementation subkey of the extension name. When the server accepts the use of the extension, the implementation class is mixed into the websocket object command. The class can define methods that override or augment the default websocket object methods. The class should at least provide a parameters method with a single argument. This method is invoked with the list of parameters the server returned for the extension.
The following private methods are designed for augmenting in an extension:
- Read
- Read raw data from the socket. Returns the data.
- Write data
- Write raw data to the socket.
- Receive opcode data flags
- Process a received websocket message. Fragmented messages have already been reassembled before this method is called. The flags argument is a string of 3 bits representing the RSV1, RSV2, and RSV3 bits.
- Transmit opcode data ?flags?
- Transmit a websocket message. The flags argument is expected to be a string of up to 4 bits representing the FIN, RSV1, RSV2, and RSV3 bits. Unused trailing bits may be omitted. So, to send a fragmented message, the flags argument can be specified as "0" on all but the final frame. The flags argument defaults to "1" (FIN), indicating a complete message.
Below is an (incomplete) outline of how an extension class for the permessage-deflate extension (specified in RFC7692) may be defined:
oo::class create WSDeflate { method parameters {params} { my variable parameters set parameters $params } method Transmit {opcode data {flags 1}} { if {$opcode < 8} { set data [deflate $data] } next $opcode $data $flags } method Receive {opcode data flags} { if {$opcode < 8} { set data [inflate $data] } next $opcode $data $flags } }
SEE ALSO
- www
COPYRIGHT
- Copyright © 2021 Schelte Bron