Module shared

Types

ProtocolError = object of Exception
Opcode = enum
  Cont = 0x00000000,            ## Continued Frame (when the previous was fin = 0)
  Text = 0x00000001,            ## Text frames need to be valid UTF-8
  Binary = 0x00000002,          ## Binary frames can be anything.
  Close = 0x00000008,           ## Socket is being closed by the remote, or we intend to close it.
  Ping = 0x00000009,            ## Ping
  Pong = 0x0000000A             ## Pong. Needs to echo back the app data in ping.
Frame = tuple[fin: bool,         ## Last frame in current packet.
            rsv1: bool,        ## Extension data: negotiated in http prequel, or 0.
            rsv2: bool,        ## Extension data: negotiated in http prequel, or 0.
            rsv3: bool,        ## Extension data: negotiated in http prequel, or 0.
            masked: bool, ## If the frame was received masked/is supposed to be masked.
                        ## Do not mask data yourself.
            opcode: Opcode,    ## The opcode of this frame.
            data: string]
A frame read off the netlayer.
SocketKind = enum
  Client, Server
AsyncWebSocket = ref AsyncWebSocketObj

Procs

proc makeFrame(f: Frame): string {.
raises: [Exception], tags: [WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Generate valid websocket frame data, ready to be sent over the wire. This is useful for rolling your own impl, for example with AsyncHttpServer
proc makeFrame(opcode: Opcode; data: string; masked: bool): string {.
raises: [Exception], tags: [WriteIOEffect, TimeEffect, ReadIOEffect]
.}
A convenience shorthand.
proc recvFrame(ws: AsyncSocket): Future[Frame] {.
raises: [FutureError], tags: [RootEffect]
.}

Read a full frame off the given socket.

You probably want to use the higher-level variant, readData.

proc readData(ws: AsyncSocket; isClientSocket: bool): Future[
    tuple[opcode: Opcode, data: string]] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}

Reads reassembled data off the websocket and give you joined frame data.

Note: You will still see control frames, but they are all handled for you (Ping/Pong, Cont, Close, and so on).

The only ones you need to care about are Opcode.Text and Opcode.Binary, the so-called application frames.

As per the websocket specifications, all clients need to mask their responses. It is up to you to to set isClientSocket with a proper value, depending on if you are reading from a server or client socket.

Will raise IOError when the socket disconnects and ProtocolError on any websocket-related issues.

proc sendText(ws: AsyncSocket; p: string; masked: bool): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends text data. Will only return after all data has been sent out.
proc sendBinary(ws: AsyncSocket; p: string; masked: bool): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends binary data. Will only return after all data has been sent out.
proc sendPing(ws: AsyncSocket; masked: bool; token: string = ""): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends a WS ping message. Will generate a suitable token if you do not provide one.
proc readData(ws: AsyncWebSocket): Future[tuple[opcode: Opcode, data: string]] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}

Reads reassembled data off the websocket and give you joined frame data.

Note: You will still see control frames, but they are all handled for you (Ping/Pong, Cont, Close, and so on).

The only ones you need to care about are Opcode.Text and Opcode.Binary, the so-called application frames.

Will raise IOError when the socket disconnects and ProtocolError on any websocket-related issues.

proc sendText(ws: AsyncWebSocket; p: string; masked: bool): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends text data. Will only return after all data has been sent out.
proc sendBinary(ws: AsyncWebSocket; p: string; masked: bool): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends binary data. Will only return after all data has been sent out.
proc sendPing(ws: AsyncWebSocket; masked: bool; token: string = ""): Future[void] {.
raises: [FutureError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect]
.}
Sends a WS ping message. Will generate a suitable token if you do not provide one.
proc closeWebsocket(ws: AsyncSocket; code = 0; reason = ""): Future[void] {.
raises: [FutureError], tags: [WriteIOEffect, RootEffect, TimeEffect, ReadIOEffect]
.}
Closes the socket.
proc close(ws: AsyncWebSocket; code = 0; reason = ""): Future[void] {.
raises: [FutureError], tags: [WriteIOEffect, RootEffect, TimeEffect, ReadIOEffect]
.}
Closes the socket.