(rfc websocket) - WebSocket

Library (rfc websocket)

This library provides WebSocket APIs defined by RFC 6455.

Following is a simple example to use user level APIs.

(import (rnrs) (rfc websocket))

;; Creates an WebSocket object
(define websocket (make-websocket "wss://echo.websocket.org"))

;; Sets text message event handler
(websocket-on-text-message websocket
  (lambda (ws text) (display text) (newline)))

;; Opens the WebSocket
(websocket-open websocket)

;; Sends a message to endpoint
(websocket-send websocket "Hello")

;; Closes the WebSocket
(websocket-close websocket)

User level APIs

Creates an WebSocket object which communicate to given uri.

The URI reprented by uri must be a valid WebSocket URI. If it's not a valid URI, then &websocket-engine or its sub condition shall be raised.

The keyword argument protocols are a list of sub protocols of the creating WebSocket. If this is set, then handshake will send it with Sec-WebSocket-Protocol header or equivalent.

The keyword argument extensions are a list of extensions of the creating WebSocket. If this is set, then handshake will send it with Sec-WebSocket-Extensions header or equivalent.

The keyword argument engine is a type of handshake engine and must be a symbol. This determines which handshake protocol it should use. The default value is http which uses HTTP/1.1.

Returns #t if given obj is an WebSocket object otherwise #f.

Operating handshake on given WebSocket object websocket if it's not opened, yet. And returns websocket.

If handshake failed, then &websocket-engine or its sub condition shall be raised.

After successfull call of this procedure, the websocket has a message dispatcher thread.

Closes the given websocket if it's open and returns the websocket. This procedure also finishes the underlying thread created by websocket-open.

The keyword argument status is specified, it must be a non negative integer which has less then or equal to 16 bits length, then the procedure sends it as a connection close code.

The keyword argument message is specified, must be a string, then the procedure sends it as a connection close message. This is sent only if the status is specified otherwise ignored.

The keyword argument timeout is used as a timeout period for waiting underlying dispatcher thread. If the thread didn't finish in the specified period, then it'd be terminated and &websocket-close-timeout is raised.

If the underlying thread raised an &uncaught-exception, then the procedure raises its reason.

Sends given data to the websocket and returns websocket. This procedure runs in atomic so the data is sent in one fragmentation sequence.

The optional arguments are passed to underlying data transport procedures. If the data is a string, then websocket-send-text is used. If the data is a bytevector, then websocket-send-binary is used. If the data is not one of the aboves, then &assertion is raised.

Send ping control frame whose data is data to _websocket_and returns websocket.

The procedure waits until the endpoint returns pong control frame. If the pong frame doesn't contain the same data in its payload, then &websocket-pong is raised.

The optional argument timeout specifies how long the procedure waits the pong response.

The optional argument timeout-value is an alternative value when the endpoint didn't return pong in time.

CAUTION: this procedure depends on the endpoint's behaviour.

Event handling

The user level APIs are event driven like JavaScript's WebSocket API. Whenever an event is occured, then the configured event handler is invoked.

There are 2 types of error handler invocations. One is calling active procedures such as websocket-send. The other one is passive situation such as receiving frame from endpoint. The first case, all active procedures would catch &websocket and its sub conditions. If the condition is &websocket-engine or its sub condition, then the condition is re-raised. Other &websocket conditions are not re-raised by the APIs. Other conditions are simply re-raised without invcating event handler. On the second case, it's mostly the same, but when &websocket-closed is raised, then event handler won't be invoked.

Sets event-handler for receiving text message and binary message to websocket, respectively.

The event-handler must be a procedure which accepts 2 arguments, WebSocket object and response data, string or bytevector.

If the event-handler raises an error, and it's not a &websocket, then the dispatcher thread opened by websocket-open stops running.

The procedure returns websocket.

Sets event-handler for open and close event to websocket, respectively.

The event-handler must be a procedure which accepts 1 argument, WebSocket object.

The procedure returns websocket.

Sets event-handler for error situation to websocket.

The event-handler must be a procedure which accepts 2 arguments, WebSocket object and a captured error.

If the event-handler raises an error, then it would be propagated caller of the user level APIs.

The procedure returns websocket.

Low level APIs

The low level APIs can be used when users want to implement WebSocket process in programatic way. The user level APIs are implemented on this APIs.

WebSocket Connection

Creates WebSocket connection object. uri and engine are the same as make-websocket.

Returns #t if given obj is WebSocket connection object otherwise #f.

Processes handshake on given connection. All the optional arguments are passed to underlying handshake engine.

Closes given connection. This procedure simply closes socket connection.

Returns #t if the connection is not connected otherwise #f.

Returns a shared queue which stores pong data from the endpoint of the connection.

WebSocket Messages

Sends text or binary frame of data to given connection.

If the first procedure is called, then data must be a string.

If the second procedure is called, then data must be a bytevector.

The optional argument start specifies from which point of data to send.

The optional argument split is specified, it must be an non negative integer or procedure which accepts 2 arguments, data and start, then the data is sent fragmented.

Sends close control frame to given connection.

If the optional argument data is specified, it must be a properly coded connection close status, the it's sent as a payload of close frame.

If the optional argument wait? is true value, then the procedure waits until the endpoint sends close frame back.

If wait? is #f, then it is users responsibility to receive the response close frame and closes the connection.

Sends ping and pong frame to given connection respectively.

The optional argument data is sent as its payload.

NB: the payload must be less than 125 bytes.

Receives a data frame and return 2 values, opcode and payload.

If the frame is text, then returning value is a string. Otherwise returning value is a bytevector.

If the keyword argument push-pong? is true value, then payload of pong control frame will be pushed in to the pong-queueof the connection.

This procedure doesn't return ping and pong control frame.

Receives a data fragments until its end and return the result of the last call of proc.

The proc must accept 3 values, finished?, opcode and data.

This procedure is useful to receive a huge frame without concising.

The websocket-receive is implemented on top of this procedure like this:

(define (websocket-receive conn :key (push-pong? #f))
  (define (convert opcode data)
    (if (eqv? opcode +websocket-text-frame+)
	(values opcode (utf8->string data))
	(values opcode data)))
  (let-values (((out extract) (open-bytevector-output-port)))
    (websocket-receive-fragments conn
     (lambda (fin? opcode data)
       (put-bytevector out data)
       (if fin? (convert opcode (extract)) (values opcode #f)))
     :push-pong? push-pong?)))

status must be an non negative integer whose bit length must be less than or equal to 16 bits.

If optional argument message is specified, then it must be a string.

Composes a payload of close frame.

data must be a payload of close frame.

Returns 2 values, status and mesasge of the close frame payload.

WebSocket frame type constants. It represents text frame and binary frame, respectively.

WebSocket control frame type constants. It represents cloe frame, ping frame, and pong frame, respectively.

Conditions

&websocket is a base condition of the WebSocket library's condition. The hierarchy is the following:

+ &error
  + &websocket
    + &websocket-engine
      + &websocket-engine-not-found
         - engine
	 - reason
      + &websocket-engine-scheme
         - scheme
      + &websocket-engine-connection
         - host
	 - port
    + &websocket-closed
       - status
       - message
    + &websocket-pong
       - pong-data
    + &websocket-close-timeout

The condition types are not exported by the library.