Websocket server
Example
import locks import guildenstern/[dispatcher, websocketserver] var lock: Lock initLock(lock) var sockets = newSeq[SocketHandle]() proc onUpgrade(): bool = {.gcsafe.}: withLock(lock): sockets.add(ws.socketdata.socket) true proc afterUpgrade() = wsserver.send(ws.socketdata.socket, "websocket connected!") proc onMessage() = {.gcsafe.}: withLock(lock): let reply = getMessage() discard wsserver.send(sockets, reply) proc onClose(socketdata: ptr SocketData, cause: SocketCloseCause, msg: string) = {.gcsafe.}: withLock(lock): let index = sockets.find(socketdata.socket) sockets.del(index) proc onRequest() = let html = """<!doctype html><title>Web socket chat</title> <script> let websocket = new WebSocket("ws://" + location.host.slice(0, -1) + '1') websocket.onmessage = function(evt) { document.getElementById("ul").appendChild(document.createElement("li")).innerHTML = evt.data } </script> <body><form action="" onsubmit="return false"><input id="input"> <button type=submit onclick="websocket.send(getElementById('input').value+'.')">Send</button> </form><ul id="ul"></ul></body>""" reply(Http200, html) let server = newWebsocketServer(onUpgrade, afterUpgrade, onMessage, onClose) server.start(5051) let httpserver = newHttpServer(onRequest) httpserver.start(5050) joinThreads(server.thread, httpserver.thread) deinitLock(lock)
Types
Opcode = enum Cont = 0, ## continuation frame Text = 1, ## text frame Binary = 2, ## binary frame Close = 8, ## connection close Ping = 9, ## ping Pong = 10, ## pong WsFail = 14 ## protocol failure / connection lost in flight
WebsocketContext = ref object of HttpContext opcode*: Opcode
WebsocketServer = ref object of HttpServer upgradeCallback*: WsUpgradeCallback afterUpgradeCallback*: WsAfterUpgradeCallback messageCallback*: WsMessageCallback
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
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: [].}
proc isMessage(message: string): bool {....raises: [], tags: [], forbids: [].}
proc isWebsocketContext(): bool {....raises: [], tags: [], forbids: [].}
proc newWebsocketServer(upgradecallback: WsUpgradeCallback; afterupgradecallback: WsAfterUpgradeCallback; onwsmessagecallback: WsMessageCallback; onclosesocketcallback: OnCloseSocketCallback; loglevel = LogLevel.WARN): WebsocketServer {....raises: [], tags: [], forbids: [].}
proc send(server: GuildenServer; delivery: ptr WsDelivery; timeoutsecs = 20; sleepmillisecs = 100): int {.discardable, ...raises: [], tags: [], forbids: [].}
-
Sends 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 amount of websockets that had to be closed
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 sleep for (sleepmillisecs * current thread load) milliseconds proc send(server: GuildenServer; socket: posix.SocketHandle; message: string; timeoutsecs = 20; sleepmillisecs = 100): bool {.discardable, ...raises: [], tags: [], forbids: [].}
proc send(server: GuildenServer; sockets: seq[posix.SocketHandle]; message: string; timeoutsecs = 20; sleepmillisecs = 100): bool {. discardable, ...raises: [], tags: [], forbids: [].}
proc sendPong(server: GuildenServer; socket: posix.SocketHandle) {....raises: [], tags: [], forbids: [].}
Exports
-
closeSocket, reply, shutdown, reply, server, isUri, http, replyStart, parseAllHeaders, SocketCloseCause, newHttpServer, reply, isHttpContext, reply, getRequest, LogLevel, GuildenSternVersion, SocketState, replyFinish, getMethod, log, OnCloseSocketCallback, replyMore, startsUri, replyStart, reply, parseHeaders, socketcontext, reply, reply, LogCallback, HttpServer, SocketContext, reply, SocketData, getUri, replyMore, getBody, suspend, isMethod, HttpContext, closeOtherSocket, GuildenServer, getBodylen, isBody, shuttingdown