syndicate-js/examples/example-simple-chat/src/wsRelay.ts

74 lines
3.4 KiB
TypeScript

/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { QuasiValue as Q, Ref, Relay, Turn, Supervisor, SupervisorRestartPolicy, Observe, Schemas, assertionFacetObserver, isEmbedded } from "@syndicate-lang/core";
import * as G from "./gen/wsRelay";
export * from "./gen/wsRelay";
export function boot(ds: Ref, debug: boolean = false) {
spawn named 'wsRelay' {
at ds {
during Observe({ "pattern": :pattern G.Resolved({
"addr": \Q.lit($addrValue),
"sturdyref": \Q.lit($sturdyRefValue),
"resolved": \Q.bind(),
}) }) => {
const addr = G.toRelayAddress(addrValue);
const sturdyref = Schemas.sturdy.toSturdyRef(sturdyRefValue);
if (addr && sturdyref) {
assert G.fromViaRelay(G.ViaRelay({
"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,
}));
}
}),
})),
}));
}
}
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) {
stop on message G.ForceRelayDisconnect(addrValue);
const facet = Turn.activeFacet;
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({
debug,
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;
}
}
});
}
});
}
}
}
}