# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[asyncdispatch, json] import preserves, preserves/jsonhooks import syndicate import ws type Args* {.preservesDictionary.} = object dataspace: Cap url: string SendJson* {.preservesRecord: "send".} = object data: JsonNode RecvJson* {.preservesRecord: "recv".} = object data: JsonNode runActor("websocket-json-actor") do (root: Cap; turn: var Turn): connectStdio(root, turn) during(turn, root, ?Args) do (ds: Cap, url: string): let facet = turn.facet var ws: WebSocket connectedHandle: Handle newWebSocket(url).addCallback(turn) do (turn: var Turn; sock: WebSocket): ws = sock let connectedHandle = publish(turn, ds, initRecord("connected", url.toPreserve)) var fut: Future[(Opcode, string)] proc recvMessage() {.gcsafe.} = fut = receivePacket ws addCallback(fut, facet) do (turn: var Turn): let (opcode, data) = read fut case opcode of Text: message(turn, ds, RecvJson(data: data.parseJson)) of Binary: message(turn, ds, initRecord("recv", cast[seq[byte]](data).toPreserve)) of Ping: asyncCheck(turn, ws.send(data, Pong)) of Pong, Cont: discard of Close: retract(turn, connectedHandle) stderr.writeLine "closed connection with ", url stop(turn) return recvMessage() recvMessage() onMessage(turn, ds, ?SendJson) do (data: JsonNode): asyncCheck(turn, ws.send($data, Text)) do: close(ws)