Websocket server
see examples/websockettest.nim for a concrete example.
Types
WebsocketServerObj = object of HttpServerObj isclient* = false ## If a `clientmaskkey` is given in initWebsocketServer, this is set to true upgradeCallback*: WsUpgradeCallback ## Optional, return true to accept, false to decline a websocket upgrade request afterUpgradeCallback*: WsAfterUpgradeCallback ## Optional, good for sending the very first websocket message to client messageCallback*: WsMessageCallback ## Triggered when a message is received. Streaming reads are not supported: message length must be shorter than buffersize.
WsAfterUpgradeCallback = proc () {....gcsafe, nimcall, ...raises: [].}
WsDelivery = tuple[sockets: seq[posix.SocketHandle], message: ptr string, binary: bool, states: seq[State]]
-
send takes pointer to this as parameter.
sockets: the websockets that should receive this message
message: the message to send (empty message sends a Pong)
binary: whether the message contains bytes or chars WsMessageCallback = proc () {....gcsafe, nimcall, ...raises: [].}
WsUpgradeCallback = proc (): bool {....gcsafe, nimcall, ...raises: [].}
Procs
proc getMessage(): string {....raises: [], tags: [], forbids: [].}
- Returns the body as a string copy. See also: getMessageView
proc getMessageview(ws: HttpContext): openArray[char] {....raises: [], tags: [], forbids: [].}
- Returns the message without making an expensive string copy. Requires --experimental:views compiler switch.
proc handleWsRequest() {....gcsafe, nimcall, ...raises: [], tags: [RootEffect], forbids: [].}
proc handleWsThreadInitialization(theserver: GuildenServer) {....raises: [], tags: [RootEffect], forbids: [].}
proc initWebsocketServer(theserver: WebsocketServer; upgradecallback: WsUpgradeCallback; afterupgradecallback: WsAfterUpgradeCallback; onwsmessagecallback: WsMessageCallback; loglevel = LogLevel.WARN; clientmaskkey = "\x00\x00\x00\x00") {....raises: [], tags: [], forbids: [].}
proc isMessage(message: string): bool {....raises: [], tags: [], forbids: [].}
proc newWebsocketServer(upgrade: WsUpgradeCallback = nil; afterupgrade: WsAfterUpgradeCallback = nil; receive: WsMessageCallback; close: OnCloseSocketCallback = nil; loglevel = LogLevel.WARN): WebsocketServer {....raises: [], tags: [], forbids: [].}
proc newWebsocketServer(upgradecallback: WsUpgradeCallback; afterupgradecallback: WsAfterUpgradeCallback; onwsmessagecallback: WsMessageCallback; deprecatedOnclosesocketcallback: DeprecatedOnCloseSocketCallback; loglevel = LogLevel.WARN): WebsocketServer {....raises: [], tags: [], forbids: [].}
- This constructor is going to get deprecated. Please switch to the one that uses the new OnCloseSocketCallback.
proc send(theserver: WebsocketServer; delivery: ptr WsDelivery; failedsockets: var seq[SocketHandle]; timeoutsecs = 10; sleepmillisecs = 10) {....raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
-
Sends a message to multiple websockets at once. Uses non-blocking I/O so that slow receivers do not slow down fast receivers.
Can be called from multiple threads in parallel.
Returns sockets that failed and had to be closed in the failedsockets parameter.
timeoutsecs: a timeout after which sending is given up and all sockets with messages in-flight are closed
sleepmillisecs: if all in-flight receivers are blocking, will suspend for (sleepmillisecs * in-flight receiver count) milliseconds proc send(theserver: WebsocketServer; delivery: ptr WsDelivery; timeoutsecs = 10; sleepmillisecs = 10): int {.discardable, ...raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
proc send(theserver: WebsocketServer; socket: posix.SocketHandle; message: string; binary = false; timeoutsecs = 2; sleepmillisecs = 10): bool {. ...gcsafe, discardable, ...raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
proc send(theserver: WebsocketServer; sockets: seq[posix.SocketHandle]; message: string; binary = false; timeoutsecs = 10; sleepmillisecs = 10): bool {. discardable, ...raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
proc send(theserver: WebsocketServer; sockets: seq[posix.SocketHandle]; message: string; failedsockets: var seq[SocketHandle]; binary = false; timeoutsecs = 10; sleepmillisecs = 10) {....raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
proc sendClose(theserver: WebsocketServer; socket: posix.SocketHandle; statuscode: int16 = 1000.int16; timeoutsecs = 1; sleepmillisecs = 10): bool {.discardable, ...raises: [], tags: [RootEffect, TimeEffect], forbids: [].}
- Sends a close frame to the client, in sync with other possible deliveries going to the same socket from other threads. | statuscode: Available for the client. For semantics, see https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1 Returns whether the sending was succesful (and if not, you may want to just call closeSocket)