json_socket_translator: convert to gatekeeper protocol

This commit is contained in:
Emery Hemingway 2024-06-04 10:54:21 +03:00
parent 1fd920f1c8
commit a40cdbce2c
4 changed files with 43 additions and 53 deletions

View File

@ -88,8 +88,7 @@ $http [
### JSON Socket Translator ### JSON Socket Translator
Communicate with sockets that send and receive lines of JSON using `<send …>` and `<recv …>` messages. Communicate with sockets that send and receive lines of JSON using `<send …>` and `<recv …>` messages.
Responds to the gatekeeper step `<json-socket-translator { socket: <unix "…"> / <tcp "…" … }> $resolver>`.
Do not send messages into the dataspace configure with `<json-socket-translator …>` until `<connected @socketPath string>` is asserted.
``` ```
# MPV configuration example # MPV configuration example
@ -107,25 +106,11 @@ Do not send messages into the dataspace configure with `<json-socket-translator
protocol: none protocol: none
}> }>
let ?mpvSpace = dataspace let ?resolver = dataspace
$resolver ? <accepted ?mpvSpace> $mpvSpace [
? <service-state <daemon mpv-server> ready> [
<require-service <daemon syndesizer>>
? <service-object <daemon syndesizer> ?cap> [
$cap <json-socket-translator {
dataspace: $mpvSpace
socket: <unix "/run/user/1000/mpv.sock">
}>
]
]
$mpvSpace [
# announce the dataspace when the translator is connected # announce the dataspace when the translator is connected
? <connected $socketPath> [ $config <mpv $mpvSpace>
$config <mpv $mpvSpace> $config <bind <ref { oid: "mpv" key: #x"" }> $mpvSpace #f>
$config <bind <ref { oid: "mpv" key: #x"" }> $mpvSpace #f>
]
# translate <play-file > to an MPV command # translate <play-file > to an MPV command
?? <play-file ?file> [ ?? <play-file ?file> [
@ -137,6 +122,15 @@ $mpvSpace [
! <send { "command": ["playlist-clear"] }> ! <send { "command": ["playlist-clear"] }>
] ]
] ]
? <service-state <daemon mpv-server> ready> [
<require-service <daemon syndesizer>>
? <service-object <daemon syndesizer> ?cap> [
$cap <resolve <json-socket-translator {
socket: <unix "/run/user/1000/mpv.sock">
}> $resolver>
]
]
``` ```
### JSON Stdio Translator ### JSON Stdio Translator

View File

@ -19,8 +19,6 @@ JsonTranslatorArguments = <json-stdio-translator {
dataspace: #:any dataspace: #:any
}>. }>.
JsonTranslatorConnected = <connected @address SocketAddress>.
TcpAddress = <tcp @host string @port int>. TcpAddress = <tcp @host string @port int>.
UnixAddress = <unix @path string>. UnixAddress = <unix @path string>.
@ -34,8 +32,7 @@ HttpDriverArguments = <http-driver {
dataspace: #:any dataspace: #:any
}>. }>.
JsonSocketTranslatorArguments = <json-socket-translator { JsonSocketTranslatorStep = <json-socket-translator {
dataspace: #:any
socket: SocketAddress socket: SocketAddress
}>. }>.

View File

@ -40,16 +40,6 @@ type
Base64DecoderArguments* {.preservesRecord: "base64-decoder".} = object Base64DecoderArguments* {.preservesRecord: "base64-decoder".} = object
`field0`*: Base64DecoderArgumentsField0 `field0`*: Base64DecoderArgumentsField0
JsonTranslatorConnected* {.preservesRecord: "connected".} = object
`address`*: SocketAddress
JsonSocketTranslatorArgumentsField0* {.preservesDictionary.} = object
`dataspace`* {.preservesEmbedded.}: EmbeddedRef
`socket`*: SocketAddress
JsonSocketTranslatorArguments* {.preservesRecord: "json-socket-translator".} = object
`field0`*: JsonSocketTranslatorArgumentsField0
XsltArgumentsField0* {.preservesDictionary.} = object XsltArgumentsField0* {.preservesDictionary.} = object
`dataspace`* {.preservesEmbedded.}: EmbeddedRef `dataspace`* {.preservesEmbedded.}: EmbeddedRef
@ -62,6 +52,12 @@ type
HttpDriverArguments* {.preservesRecord: "http-driver".} = object HttpDriverArguments* {.preservesRecord: "http-driver".} = object
`field0`*: HttpDriverArgumentsField0 `field0`*: HttpDriverArgumentsField0
JsonSocketTranslatorStepField0* {.preservesDictionary.} = object
`socket`*: SocketAddress
JsonSocketTranslatorStep* {.preservesRecord: "json-socket-translator".} = object
`field0`*: JsonSocketTranslatorStepField0
WebhooksArgumentsField0* {.preservesDictionary.} = object WebhooksArgumentsField0* {.preservesDictionary.} = object
`endpoints`*: Table[seq[string], EmbeddedRef] `endpoints`*: Table[seq[string], EmbeddedRef]
`listen`*: Tcp `listen`*: Tcp
@ -131,10 +127,9 @@ type
proc `$`*(x: WebsocketArguments | HttpClientArguments | JsonTranslatorArguments | proc `$`*(x: WebsocketArguments | HttpClientArguments | JsonTranslatorArguments |
SocketAddress | SocketAddress |
Base64DecoderArguments | Base64DecoderArguments |
JsonTranslatorConnected |
JsonSocketTranslatorArguments |
XsltArguments | XsltArguments |
HttpDriverArguments | HttpDriverArguments |
JsonSocketTranslatorStep |
WebhooksArguments | WebhooksArguments |
FileSystemUsageArguments | FileSystemUsageArguments |
SqliteArguments | SqliteArguments |
@ -153,10 +148,9 @@ proc encode*(x: WebsocketArguments | HttpClientArguments |
JsonTranslatorArguments | JsonTranslatorArguments |
SocketAddress | SocketAddress |
Base64DecoderArguments | Base64DecoderArguments |
JsonTranslatorConnected |
JsonSocketTranslatorArguments |
XsltArguments | XsltArguments |
HttpDriverArguments | HttpDriverArguments |
JsonSocketTranslatorStep |
WebhooksArguments | WebhooksArguments |
FileSystemUsageArguments | FileSystemUsageArguments |
SqliteArguments | SqliteArguments |

View File

@ -1,11 +1,12 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[json, options] import
import pkg/sys/[ioqueue, sockets] std/[json, options],
import preserves, preserves/jsonhooks, syndicate pkg/sys/[ioqueue, sockets],
pkg/preserves, pkg/preserves/jsonhooks,
import ../schema/[config, json_messages] pkg/syndicate, pkg/syndicate/protocols/[gatekeeper, sturdy],
../schema/[config, json_messages]
template translateSocketBody {.dirty.} = template translateSocketBody {.dirty.} =
# Template workaround for CPS and parameterized types. # Template workaround for CPS and parameterized types.
@ -24,7 +25,8 @@ template translateSocketBody {.dirty.} =
whelp write(socket[], $data & "\n") whelp write(socket[], $data & "\n")
else: else:
stderr.writeLine "dropped send of ", data stderr.writeLine "dropped send of ", data
discard publish(turn, ds, initRecord("connected", sa.toPreserves)) discard publish(turn, observer, ResolvedAccepted(responderSession: ds))
# Resolve the <json-socket-translator { }> step.
onStop(facet, kill) onStop(facet, kill)
run(facet, setup) run(facet, setup)
while alive: while alive:
@ -45,33 +47,36 @@ template translateSocketBody {.dirty.} =
stderr.writeLine "close socket ", sa stderr.writeLine "close socket ", sa
close(socket[]) close(socket[])
proc translateSocket(facet: Facet; ds: Cap; sa: TcpAddress) {.asyncio.} = proc translateSocket(facet: Facet; sa: TcpAddress; ds, observer: Cap) {.asyncio.} =
var var
socket = new AsyncConn[Protocol.Tcp] socket = new AsyncConn[Protocol.Tcp]
conn = connectTcpAsync(sa.host, Port sa.port) conn = connectTcpAsync(sa.host, Port sa.port)
socket[] = conn socket[] = conn
translateSocketBody() translateSocketBody()
proc translateSocket(facet: Facet; ds: Cap; sa: UnixAddress) {.asyncio.} = proc translateSocket(facet: Facet; sa: UnixAddress; ds, observer: Cap) {.asyncio.} =
var var
socket = new AsyncConn[Protocol.Unix] socket = new AsyncConn[Protocol.Unix]
conn = connectUnixAsync(sa.path) conn = connectUnixAsync(sa.path)
socket[] = conn socket[] = conn
translateSocketBody() translateSocketBody()
proc spawnJsonSocketTranslator*(turn: Turn; root: Cap): Actor {.discardable.} = proc spawnJsonSocketTranslator*(turn: Turn; relay: Cap): Actor {.discardable.} =
let pat = Resolve?:{ 0: JsonSocketTranslatorStep.grabTypeFlat, 1: grab() }
spawnActor(turn, "json-socket-translator") do (turn: Turn): spawnActor(turn, "json-socket-translator") do (turn: Turn):
during(turn, root, ?:JsonSocketTranslatorArguments) do (ds: Cap, sa: TcpAddress): during(turn, relay, pat) do (sa: TcpAddress, observer: Cap):
linkActor(turn, "json-socket-translator") do (turn: Turn): linkActor(turn, "json-socket-translator") do (turn: Turn):
let ds = turn.newDataspace()
discard trampoline: discard trampoline:
whelp translateSocket(turn.facet, ds, sa) whelp translateSocket(turn.facet, sa, ds, observer)
during(turn, root, ?:JsonSocketTranslatorArguments) do (ds: Cap, sa: UnixAddress): during(turn, relay, pat) do (sa: UnixAddress, observer: Cap):
linkActor(turn, "json-socket-translator") do (turn: Turn): linkActor(turn, "json-socket-translator") do (turn: Turn):
let ds = turn.newDataspace()
discard trampoline: discard trampoline:
whelp translateSocket(turn.facet, ds, sa) whelp translateSocket(turn.facet, sa, ds, observer)
when isMainModule: when isMainModule:
import syndicate/relays import syndicate/relays
runActor("main") do (turn: Turn): runActor("main") do (turn: Turn):
resolveEnvironment(turn) do (turn: Turn; ds: Cap): resolveEnvironment(turn) do (turn: Turn; relay: Cap):
spawnJsonSocketTranslator(turn, ds) spawnJsonSocketTranslator(turn, relay)