# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[asyncdispatch, asyncnet, json, streams, tables] from std/nativesockets import AF_UNIX, SOCK_STREAM, Protocol import preserves, preserves/jsonhooks import syndicate, syndicate/capabilities type Controller = ref object ds: Ref facet: Facet handles: Table[JsonNode, Handle] sock: AsyncSocket Yggdrasilctl {.preservesRecord: "yggdrasilctl".} = object label: string payload: JsonNode proc dispatchReplies(ctl: Controller) = if not ctl.sock.isClosed: ctl.sock.recv(4096).addCallback do (fut: Future[string]): if fut.failed: close(ctl.sock) raise fut.error var str = newStringStream(fut.read) for js in parseJsonFragments(str): if js["status"].getStr == "success": run(ctl.facet) do (turn: var Turn): var req = js["request"] for label, val in js["response"].pairs: var resp = Yggdrasilctl(label: label, payload: val) ctl.handles[req] = replace(turn, ctl.ds, ctl.handles.getOrDefault(req), resp) callSoon: dispatchReplies(ctl) proc connectController(facet: Facet; ds: Ref; socketPath: string): Future[Controller] {.async.} = var sock = newAsyncSocket( domain = AF_UNIX, sockType = SOCK_STREAM, protocol = cast[Protocol](0), buffered = false) await connectUnix(sock, socketPath) let ctl = Controller(ds: ds, facet: facet, sock: sock) dispatchReplies(ctl) return ctl proc request(ctl: Controller; req: string; fields: JsonNode): Future[void] = var js = %* { "keepalive": true, "request": req, "fields": fields } ctl.sock.send($js) proc mint(): SturdyRef = var key: array[16, byte] mint(key, "syndicate") bootDataspace("main") do (ds: Ref; turn: var Turn): let ctl = waitFor connectController(turn.facet, ds, "/run/yggdrasil/yggdrasil.sock") onMessage(turn, ds, ?Yggdrasilctl) do (label: string, fields: JsonNode): asyncCheck ctl.request(label, fields) onPublish(turn, ds, ?Yggdrasilctl) do (label: string, resp: JsonNode): stderr.writeLine label, ": ", resp.pretty # yggdrasil response test message(turn, ds, Yggdrasilctl(label: "getself", payload: newJObject())) # yggdrasil request test for _ in 0..7: poll()