Initial commit
This commit is contained in:
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