@threadedstack/wmd-web 0.0.0-stage → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2601 -2
- package/RELEASE.json +123 -0
- package/export-page/coi-sw.js +20 -0
- package/export-page/index.html +17 -0
- package/export-page/run.css +10 -0
- package/export-page/run.js +236 -0
- package/guest/arm64/Image +4 -0
- package/guest/arm64/Image-4k +4 -0
- package/guest/arm64/initramfs.cpio.gz +0 -0
- package/guest/arm64/vm.wasm +0 -0
- package/package.json +36 -4
- package/page/sw.js +381 -0
- package/relay/control.ts +139 -0
- package/relay/engine.ts +787 -0
- package/relay/hosted.ts +660 -0
- package/relay/keys.ts +53 -0
- package/relay/local-tls.ts +121 -0
- package/relay/lock.ts +81 -0
- package/relay/logfile.ts +138 -0
- package/relay/main.ts +642 -0
- package/relay/policy.ts +241 -0
- package/relay/relay.ts +266 -0
- package/relay/token.ts +116 -0
- package/relay/v1.ts +107 -0
- package/relay/wisp.ts +615 -0
- package/src/base.js +325 -0
- package/src/boot.js +2037 -0
- package/src/calib-worker.js +40 -0
- package/src/fs/9p/codec.js +303 -0
- package/src/fs/9p/server.js +521 -0
- package/src/fs/errno.js +43 -0
- package/src/fs/graph.js +380 -0
- package/src/fs/overlay.js +1018 -0
- package/src/fs/pack-write.js +165 -0
- package/src/fs/pack.js +427 -0
- package/src/fs/seed.js +22 -0
- package/src/fs/svc-snapshot.js +65 -0
- package/src/fs/upper-pack.js +112 -0
- package/src/host/base-cache.js +195 -0
- package/src/host/base-file.js +328 -0
- package/src/host/base-io.js +93 -0
- package/src/host/boot-events.js +209 -0
- package/src/host/chan-service.js +300 -0
- package/src/host/chan-services.js +689 -0
- package/src/host/chan.js +655 -0
- package/src/host/ckpt-file.js +395 -0
- package/src/host/ckpt-io.js +207 -0
- package/src/host/ckpt-point.js +160 -0
- package/src/host/ckpt-save.js +64 -0
- package/src/host/ckpt.js +434 -0
- package/src/host/clock.js +111 -0
- package/src/host/ctl.js +778 -0
- package/src/host/errno.js +18 -0
- package/src/host/fs.js +167 -0
- package/src/host/gcnudge.js +83 -0
- package/src/host/i64shim.js +81 -0
- package/src/host/jit-cache.js +341 -0
- package/src/host/jit-hub-core.js +208 -0
- package/src/host/jit-hub.js +93 -0
- package/src/host/jit-snap.js +226 -0
- package/src/host/jit.js +1903 -0
- package/src/host/layout.js +100 -0
- package/src/host/monitor.js +110 -0
- package/src/host/p9mount.js +27 -0
- package/src/host/ram-mem.js +125 -0
- package/src/host/stdio.js +143 -0
- package/src/host/threads.js +109 -0
- package/src/host/wasi.js +335 -0
- package/src/host/wmd-imports.js +71 -0
- package/src/host/yamux.js +387 -0
- package/src/image-files.js +154 -0
- package/src/net/dhcp-dns.js +126 -0
- package/src/net/net-worker.js +172 -0
- package/src/net/packet.js +227 -0
- package/src/net/peer.js +230 -0
- package/src/net/proto.js +189 -0
- package/src/net/relay-client.js +226 -0
- package/src/net/stack.js +867 -0
- package/src/net/switch.js +160 -0
- package/src/net/wisp-client.js +570 -0
- package/src/net/wisp-transport.js +196 -0
- package/src/net/wisp.js +511 -0
- package/src/registry/client.js +176 -0
- package/src/registry/converter.js +68 -0
- package/src/registry/hub.js +221 -0
- package/src/registry/oci.js +76 -0
- package/src/registry/pack-worker.js +70 -0
- package/src/registry/pull.js +258 -0
- package/src/registry/ref.js +110 -0
- package/src/registry/wasi-mem.js +355 -0
- package/src/worker.js +315 -0
- package/wmdpack.wasm +0 -0
package/relay/v1.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// W59: the wmd-relay.v1 adapter (src/net/proto.js) over the relay engine (engine.ts).
|
|
2
|
+
// Its bytes, close codes, HTTP refusals and log lines are pinned by test/unit/relay-v1-golden.test.js.
|
|
3
|
+
|
|
4
|
+
import { E, MAX_DATA, PROTOCOL, T, WINDOW, abortMsg, connectedMsg, dnsReplyMsg, msg, parse, u32Msg } from '../src/net/proto.js'
|
|
5
|
+
import type { Engine, Principal, Session, Wire } from './engine.ts'
|
|
6
|
+
import { verifyToken } from './token.ts'
|
|
7
|
+
|
|
8
|
+
function send(s: Session, m: Uint8Array) {
|
|
9
|
+
if (s.closed) return
|
|
10
|
+
s.ws.send(m)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const wire: Wire = {
|
|
14
|
+
connected(s, st, detail) {
|
|
15
|
+
// the first window is upload credit too: it comes out of the bucket (the rest is owed)
|
|
16
|
+
const g = s.p.up.take(WINDOW)
|
|
17
|
+
st.ourGrant = g
|
|
18
|
+
send(s, connectedMsg(st.id, E.OK, g, detail))
|
|
19
|
+
if (g < WINDOW) s.w.engine.owe(s, st.id, WINDOW - g)
|
|
20
|
+
},
|
|
21
|
+
refused: (s, id, code, why) => send(s, connectedMsg(id, code, 0, why)),
|
|
22
|
+
data: (s, st, bytes) => send(s, msg(T.RDATA, st.id, bytes)),
|
|
23
|
+
end: (s, st) => send(s, msg(T.REND, st.id)),
|
|
24
|
+
abort: (s, st, code, why) => send(s, abortMsg(st.id, code, why)),
|
|
25
|
+
grant(s, st, n) {
|
|
26
|
+
st.ourGrant += n
|
|
27
|
+
send(s, u32Msg(T.RCREDIT, st.id, n))
|
|
28
|
+
},
|
|
29
|
+
dnsReply: (s, id, rcode, ttl, addrs, why) => send(s, dnsReplyMsg(id, rcode, ttl, addrs, why)),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createV1(engine: Engine, o: { secret: string; origins?: string[] }) {
|
|
33
|
+
const stats = engine.stats
|
|
34
|
+
|
|
35
|
+
/** The HTTP upgrade at /relay: origin, subprotocol, token, then the engine's admission. */
|
|
36
|
+
function fetch(req: Request, srv: any): Response | undefined {
|
|
37
|
+
const origin = req.headers.get('origin') || ''
|
|
38
|
+
if (o.origins?.length && !o.origins.includes(origin)) {
|
|
39
|
+
stats.refusedSessions++
|
|
40
|
+
return new Response('origin not allowed\n', { status: 403 })
|
|
41
|
+
}
|
|
42
|
+
const protos = (req.headers.get('sec-websocket-protocol') || '').split(',').map(x => x.trim())
|
|
43
|
+
if (!protos.includes(PROTOCOL)) return new Response(`subprotocol ${PROTOCOL} required\n`, { status: 400 })
|
|
44
|
+
const tok = protos.find(p => p.startsWith('t.'))
|
|
45
|
+
const info = tok ? verifyToken(o.secret, tok.slice(2)) : 'no token'
|
|
46
|
+
if (typeof info === 'string') {
|
|
47
|
+
engine.refusedSession(info, { origin })
|
|
48
|
+
return new Response(`${info}\n`, { status: 401 })
|
|
49
|
+
}
|
|
50
|
+
if (engine.hasSession(info.sid)) {
|
|
51
|
+
stats.refusedSessions++
|
|
52
|
+
return new Response('session already connected\n', { status: 409 })
|
|
53
|
+
}
|
|
54
|
+
const uid = info.uid || info.sid
|
|
55
|
+
const a = engine.admit(uid, info.grp || uid, info.exp)
|
|
56
|
+
if (!a.ok) return new Response(a.body, { status: a.status })
|
|
57
|
+
const ok = srv.upgrade(req, { data: { kind: 'v1', sid: info.sid, exp: info.exp, p: a.p }, headers: { 'Sec-WebSocket-Protocol': PROTOCOL } })
|
|
58
|
+
return ok ? undefined : new Response('upgrade failed\n', { status: 400 })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function open(ws: any) {
|
|
62
|
+
const { sid, exp, p } = ws.data as { sid: string; exp: number; p: Principal }
|
|
63
|
+
const s = engine.open(ws, sid, p, exp, wire, WINDOW)
|
|
64
|
+
if (!s) return
|
|
65
|
+
s.w = { engine }
|
|
66
|
+
ws.data.session = s
|
|
67
|
+
ws.send(JSON.stringify({ t: 'hello', protocol: PROTOCOL, limits: engine.limits(p) }))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function message(ws: any, raw: ArrayBuffer | Uint8Array | string) {
|
|
71
|
+
const s = ws.data.session as Session
|
|
72
|
+
if (!s || typeof raw === 'string') return
|
|
73
|
+
const u8 = raw instanceof Uint8Array ? raw : new Uint8Array(raw)
|
|
74
|
+
if (u8.length > MAX_DATA + 1024) return s.ws.close(1009, 'message too large') // the server's frame limit may be higher for Wisp
|
|
75
|
+
const m: any = parse(u8)
|
|
76
|
+
if (!m) return s.ws.close(4002, 'malformed message')
|
|
77
|
+
switch (m.type) {
|
|
78
|
+
case T.CONNECT:
|
|
79
|
+
engine.connectSafe(s, m.id, m.host, m.port)
|
|
80
|
+
break
|
|
81
|
+
case T.DATA: {
|
|
82
|
+
const st = s.streams.get(m.id)
|
|
83
|
+
if (!st || !st.connected || !st.sock || st.clientEnded) return // a stream that just failed: its ABORT is on the way
|
|
84
|
+
if (m.payload.length > st.ourGrant) return engine.fail(s, st, E.BAD, 'data over the granted credit')
|
|
85
|
+
st.ourGrant -= m.payload.length
|
|
86
|
+
engine.write(s, st, m.payload)
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
case T.END:
|
|
90
|
+
engine.clientEnd(s, m.id)
|
|
91
|
+
break
|
|
92
|
+
case T.ABORT:
|
|
93
|
+
engine.clientAbort(s, m.id)
|
|
94
|
+
break
|
|
95
|
+
case T.CREDIT:
|
|
96
|
+
engine.credit(s, m.id, m.n)
|
|
97
|
+
break
|
|
98
|
+
case T.DNS:
|
|
99
|
+
engine.dns(s, m.id, m.name, m.qtype).catch(e => engine.log({ ev: 'error', sid: s.sid, error: String(e) }))
|
|
100
|
+
break
|
|
101
|
+
default:
|
|
102
|
+
s.ws.close(4002, 'unknown message type')
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { fetch, open, message }
|
|
107
|
+
}
|