commit
3b3b7b8f8f
@ -0,0 +1 @@
|
||||
An example of communicating with the Yggdrasil control socket over Syndicate.
|
@ -0,0 +1,69 @@
|
||||
# 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()
|
@ -0,0 +1,13 @@
|
||||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Emery Hemingway"
|
||||
description = "An example of communicating with the Yggdrasil control socket over Syndicate"
|
||||
license = "Unlicense"
|
||||
srcDir = "src"
|
||||
bin = @["yggdrasilctl"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.4"
|
Loading…
Reference in new issue