# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[asyncdispatch, json] import preserves import syndicate, syndicate/relays import ws import ../schema/config, ../json_messages type WebSocket = ws.WebSocket # not the object from the transportAddress schema proc spawnWebsocketActor*(turn: var Turn; root: Cap): Actor = spawn("websocket-actor", turn) do (turn: var Turn): during(turn, root, ?:WebsocketArguments) 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 connectedHandle = publish(turn, ds, initRecord("connected", url.toPreserves)) 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).toPreserves)) 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) when isMainModule: runActor("main") do (turn: var Turn; root: Cap): connectStdio(turn, root) discard spawnWebsocketActor(turn, root)