2021-12-12 22:59:49 +00:00
|
|
|
/// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
|
|
|
|
2021-12-13 11:21:29 +00:00
|
|
|
import { QuasiValue as Q, Ref, Relay, Turn, Supervisor, SupervisorRestartPolicy, Observe, Schemas, assertionFacetObserver, isEmbedded } from "@syndicate-lang/core";
|
2021-12-13 12:34:26 +00:00
|
|
|
import * as G from "./gen/ws";
|
|
|
|
export * from "./gen/ws";
|
2021-12-12 22:59:49 +00:00
|
|
|
|
2021-12-13 11:21:29 +00:00
|
|
|
export function boot(ds: Ref, debug: boolean = false) {
|
2021-12-12 22:59:49 +00:00
|
|
|
spawn named 'wsRelay' {
|
|
|
|
at ds {
|
2021-12-13 11:21:29 +00:00
|
|
|
during Observe({ "pattern": :pattern G.Resolved({
|
2021-12-13 19:20:31 +00:00
|
|
|
"addr": \$addrPatValue,
|
|
|
|
"sturdyref": \$sturdyRefPatValue,
|
2021-12-13 11:21:29 +00:00
|
|
|
"resolved": \Q.bind(),
|
|
|
|
}) }) => {
|
2021-12-13 19:20:31 +00:00
|
|
|
const addr = Q.drop_lit(addrPatValue, G.toRelayAddress);
|
|
|
|
const sturdyref = Q.drop_lit(sturdyRefPatValue, Schemas.sturdy.toSturdyRef);
|
2021-12-13 11:21:29 +00:00
|
|
|
if (addr && sturdyref) {
|
2022-01-24 13:11:41 +00:00
|
|
|
assert G.ViaRelay({
|
2021-12-13 11:21:29 +00:00
|
|
|
"addr": addr,
|
|
|
|
"assertion": Schemas.gatekeeper.fromResolve(Schemas.gatekeeper.Resolve({
|
|
|
|
"sturdyref": sturdyref,
|
|
|
|
"observer": create assertionFacetObserver(e => {
|
|
|
|
if (isEmbedded(e)) {
|
|
|
|
assert G.fromResolved(G.Resolved({
|
|
|
|
"addr": addr,
|
|
|
|
"sturdyref": sturdyref,
|
|
|
|
"resolved": e.embeddedValue,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
})),
|
2022-01-24 13:11:41 +00:00
|
|
|
});
|
2021-12-13 11:21:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-12 22:59:49 +00:00
|
|
|
during G.ViaRelay({ "addr": $addrValue }) => spawn named ['wsRelay', addrValue] {
|
|
|
|
let counter = 0;
|
|
|
|
new Supervisor({
|
|
|
|
restartPolicy: SupervisorRestartPolicy.ALWAYS,
|
|
|
|
}, () => ['wsRelay', addrValue, counter++], () => {
|
|
|
|
const addr = G.toRelayAddress(addrValue);
|
|
|
|
if (addr !== void 0) {
|
2021-12-13 11:21:29 +00:00
|
|
|
stop on message G.ForceRelayDisconnect(addrValue);
|
|
|
|
const facet = Turn.activeFacet;
|
2021-12-12 22:59:49 +00:00
|
|
|
const ws = new WebSocket(addr.url);
|
|
|
|
ws.binaryType = 'arraybuffer';
|
|
|
|
ws.onclose = () => facet.turn(() => { stop {} });
|
|
|
|
ws.onerror = () => facet.turn(() =>
|
|
|
|
Turn.active.crash(new Error("WebSocket error")));
|
|
|
|
ws.onopen = () => facet.turn(() => {
|
|
|
|
const relay = new Relay.Relay({
|
2021-12-13 11:21:29 +00:00
|
|
|
debug,
|
2021-12-12 22:59:49 +00:00
|
|
|
trustPeer: true,
|
|
|
|
packetWriter: bs => ws.send(bs),
|
|
|
|
setup(r: Relay.Relay) {
|
|
|
|
ws.onmessage = e => facet.turn(() =>
|
|
|
|
r.accept(new Uint8Array(e.data)));
|
|
|
|
},
|
|
|
|
initialOid: 0,
|
|
|
|
});
|
|
|
|
during G.ViaRelay({ "addr": addrValue, "assertion": $a }) => {
|
|
|
|
at relay.peer! {
|
|
|
|
assert a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|