@inkbox/sdk 0.2.16 → 0.3.0
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 +10 -1
- package/dist/_http.d.ts +24 -5
- package/dist/_http.d.ts.map +1 -1
- package/dist/_http.js +21 -11
- package/dist/_http.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/inkbox.d.ts +4 -0
- package/dist/inkbox.d.ts.map +1 -1
- package/dist/inkbox.js +5 -0
- package/dist/inkbox.js.map +1 -1
- package/dist/tunnels/_validation.d.ts +7 -0
- package/dist/tunnels/_validation.d.ts.map +1 -0
- package/dist/tunnels/_validation.js +27 -0
- package/dist/tunnels/_validation.js.map +1 -0
- package/dist/tunnels/client/_bridge.d.ts +35 -0
- package/dist/tunnels/client/_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_bridge.js +52 -0
- package/dist/tunnels/client/_bridge.js.map +1 -0
- package/dist/tunnels/client/_callable_streaming.d.ts +25 -0
- package/dist/tunnels/client/_callable_streaming.d.ts.map +1 -0
- package/dist/tunnels/client/_callable_streaming.js +158 -0
- package/dist/tunnels/client/_callable_streaming.js.map +1 -0
- package/dist/tunnels/client/_cert.d.ts +45 -0
- package/dist/tunnels/client/_cert.d.ts.map +1 -0
- package/dist/tunnels/client/_cert.js +193 -0
- package/dist/tunnels/client/_cert.js.map +1 -0
- package/dist/tunnels/client/_dispatch.d.ts +109 -0
- package/dist/tunnels/client/_dispatch.d.ts.map +1 -0
- package/dist/tunnels/client/_dispatch.js +314 -0
- package/dist/tunnels/client/_dispatch.js.map +1 -0
- package/dist/tunnels/client/_envelope.d.ts +55 -0
- package/dist/tunnels/client/_envelope.d.ts.map +1 -0
- package/dist/tunnels/client/_envelope.js +97 -0
- package/dist/tunnels/client/_envelope.js.map +1 -0
- package/dist/tunnels/client/_h1_server.d.ts +37 -0
- package/dist/tunnels/client/_h1_server.d.ts.map +1 -0
- package/dist/tunnels/client/_h1_server.js +433 -0
- package/dist/tunnels/client/_h1_server.js.map +1 -0
- package/dist/tunnels/client/_h2_transcode.d.ts +43 -0
- package/dist/tunnels/client/_h2_transcode.d.ts.map +1 -0
- package/dist/tunnels/client/_h2_transcode.js +488 -0
- package/dist/tunnels/client/_h2_transcode.js.map +1 -0
- package/dist/tunnels/client/_handler.d.ts +62 -0
- package/dist/tunnels/client/_handler.d.ts.map +1 -0
- package/dist/tunnels/client/_handler.js +121 -0
- package/dist/tunnels/client/_handler.js.map +1 -0
- package/dist/tunnels/client/_listener.d.ts +64 -0
- package/dist/tunnels/client/_listener.d.ts.map +1 -0
- package/dist/tunnels/client/_listener.js +113 -0
- package/dist/tunnels/client/_listener.js.map +1 -0
- package/dist/tunnels/client/_protocol.d.ts +67 -0
- package/dist/tunnels/client/_protocol.d.ts.map +1 -0
- package/dist/tunnels/client/_protocol.js +86 -0
- package/dist/tunnels/client/_protocol.js.map +1 -0
- package/dist/tunnels/client/_runtime.d.ts +143 -0
- package/dist/tunnels/client/_runtime.d.ts.map +1 -0
- package/dist/tunnels/client/_runtime.js +1679 -0
- package/dist/tunnels/client/_runtime.js.map +1 -0
- package/dist/tunnels/client/_state.d.ts +45 -0
- package/dist/tunnels/client/_state.d.ts.map +1 -0
- package/dist/tunnels/client/_state.js +165 -0
- package/dist/tunnels/client/_state.js.map +1 -0
- package/dist/tunnels/client/_tls.d.ts +50 -0
- package/dist/tunnels/client/_tls.d.ts.map +1 -0
- package/dist/tunnels/client/_tls.js +139 -0
- package/dist/tunnels/client/_tls.js.map +1 -0
- package/dist/tunnels/client/_upstream_tls.d.ts +25 -0
- package/dist/tunnels/client/_upstream_tls.d.ts.map +1 -0
- package/dist/tunnels/client/_upstream_tls.js +24 -0
- package/dist/tunnels/client/_upstream_tls.js.map +1 -0
- package/dist/tunnels/client/_url_forward.d.ts +92 -0
- package/dist/tunnels/client/_url_forward.d.ts.map +1 -0
- package/dist/tunnels/client/_url_forward.js +255 -0
- package/dist/tunnels/client/_url_forward.js.map +1 -0
- package/dist/tunnels/client/_validation.d.ts +27 -0
- package/dist/tunnels/client/_validation.d.ts.map +1 -0
- package/dist/tunnels/client/_validation.js +96 -0
- package/dist/tunnels/client/_validation.js.map +1 -0
- package/dist/tunnels/client/_ws.d.ts +149 -0
- package/dist/tunnels/client/_ws.d.ts.map +1 -0
- package/dist/tunnels/client/_ws.js +351 -0
- package/dist/tunnels/client/_ws.js.map +1 -0
- package/dist/tunnels/client/_ws_passthrough.d.ts +129 -0
- package/dist/tunnels/client/_ws_passthrough.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_passthrough.js +432 -0
- package/dist/tunnels/client/_ws_passthrough.js.map +1 -0
- package/dist/tunnels/client/_ws_url_bridge.d.ts +71 -0
- package/dist/tunnels/client/_ws_url_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_url_bridge.js +474 -0
- package/dist/tunnels/client/_ws_url_bridge.js.map +1 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.d.ts +26 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.js +256 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.js.map +1 -0
- package/dist/tunnels/client/_wsframe.d.ts +142 -0
- package/dist/tunnels/client/_wsframe.d.ts.map +1 -0
- package/dist/tunnels/client/_wsframe.js +282 -0
- package/dist/tunnels/client/_wsframe.js.map +1 -0
- package/dist/tunnels/client/index.d.ts +101 -0
- package/dist/tunnels/client/index.d.ts.map +1 -0
- package/dist/tunnels/client/index.js +242 -0
- package/dist/tunnels/client/index.js.map +1 -0
- package/dist/tunnels/exceptions.d.ts +31 -0
- package/dist/tunnels/exceptions.d.ts.map +1 -0
- package/dist/tunnels/exceptions.js +68 -0
- package/dist/tunnels/exceptions.js.map +1 -0
- package/dist/tunnels/resources/tunnels.d.ts +73 -0
- package/dist/tunnels/resources/tunnels.d.ts.map +1 -0
- package/dist/tunnels/resources/tunnels.js +173 -0
- package/dist/tunnels/resources/tunnels.js.map +1 -0
- package/dist/tunnels/types.d.ts +99 -0
- package/dist/tunnels/types.d.ts.map +1 -0
- package/dist/tunnels/types.js +76 -0
- package/dist/tunnels/types.js.map +1 -0
- package/package.json +14 -5
- package/protocol/tunnel_protocol_constants.json +65 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkbox-tunnels/client/_ws_passthrough.ts
|
|
3
|
+
*
|
|
4
|
+
* WebSocket support for passthrough mode.
|
|
5
|
+
*
|
|
6
|
+
* The h1 parser and h2 transcoder hand a {@link WebSocketSink} to the
|
|
7
|
+
* dispatcher when the inbound is a WS upgrade. The dispatcher completes
|
|
8
|
+
* the handshake via `accept` then bridges frames via `sendFrame` /
|
|
9
|
+
* `recvFrame`. The `bridgeWsHandlerOverSink` helper wires an
|
|
10
|
+
* `InkboxWsHandler` to one of those sinks so the same handler shape
|
|
11
|
+
* serves h1 `Upgrade: websocket` and h2 RFC 8441 Extended CONNECT.
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { WS_OPCODE_BINARY, WS_OPCODE_CLOSE, WS_OPCODE_PING, WS_OPCODE_PONG, WS_OPCODE_TEXT, } from "./_wsframe.js";
|
|
15
|
+
const WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
16
|
+
export function computeWsAccept(key) {
|
|
17
|
+
return createHash("sha1")
|
|
18
|
+
.update(key + WS_GUID, "ascii")
|
|
19
|
+
.digest("base64");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Encode an unmasked server-to-client frame. RFC 6455 §5.1 — server
|
|
23
|
+
* frames MUST NOT be masked. The shared `_wsframe.encodeWsFrame`
|
|
24
|
+
* defaults to client semantics (masked); this helper enforces unmasked.
|
|
25
|
+
*/
|
|
26
|
+
export function encodeServerFrame(opcode, payload, fin = true) {
|
|
27
|
+
const out = [];
|
|
28
|
+
out.push((fin ? 0x80 : 0x00) | (opcode & 0x0f));
|
|
29
|
+
const plen = payload.length;
|
|
30
|
+
if (plen < 126) {
|
|
31
|
+
out.push(plen);
|
|
32
|
+
}
|
|
33
|
+
else if (plen < 65536) {
|
|
34
|
+
out.push(126);
|
|
35
|
+
out.push((plen >> 8) & 0xff, plen & 0xff);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
out.push(127);
|
|
39
|
+
// Encode as 8-byte big-endian; payloads > 2^32 not supported here.
|
|
40
|
+
for (let i = 7; i >= 0; i--) {
|
|
41
|
+
out.push((Number(BigInt(plen) >> BigInt(i * 8))) & 0xff);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return Buffer.concat([Buffer.from(out), payload]);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Decode one complete client-to-server frame from `buf`.
|
|
48
|
+
*
|
|
49
|
+
* For h1 WebSockets (RFC 6455 §5.1) client frames MUST be masked;
|
|
50
|
+
* pass `requireMask=true` (default) and the decoder rejects unmasked
|
|
51
|
+
* frames. For h2 WebSockets (RFC 8441 §5.1) frames are NEVER masked —
|
|
52
|
+
* the transcoder passes `requireMask=false` so unmasked payloads are
|
|
53
|
+
* returned verbatim.
|
|
54
|
+
*/
|
|
55
|
+
export function decodeClientFrame(buf, opts) {
|
|
56
|
+
const requireMask = opts?.requireMask ?? true;
|
|
57
|
+
let total = 0;
|
|
58
|
+
for (const c of buf)
|
|
59
|
+
total += c.length;
|
|
60
|
+
if (total < 2)
|
|
61
|
+
return { kind: "need-more" };
|
|
62
|
+
const merged = Buffer.concat(buf, total);
|
|
63
|
+
let offset = 0;
|
|
64
|
+
const b0 = merged[0];
|
|
65
|
+
const b1 = merged[1];
|
|
66
|
+
const fin = (b0 & 0x80) !== 0;
|
|
67
|
+
const opcode = b0 & 0x0f;
|
|
68
|
+
const masked = (b1 & 0x80) !== 0;
|
|
69
|
+
let plen = b1 & 0x7f;
|
|
70
|
+
offset = 2;
|
|
71
|
+
if (plen === 126) {
|
|
72
|
+
if (merged.length < 4) {
|
|
73
|
+
buf.length = 0;
|
|
74
|
+
buf.push(merged);
|
|
75
|
+
return { kind: "need-more" };
|
|
76
|
+
}
|
|
77
|
+
plen = merged.readUInt16BE(2);
|
|
78
|
+
offset = 4;
|
|
79
|
+
}
|
|
80
|
+
else if (plen === 127) {
|
|
81
|
+
if (merged.length < 10) {
|
|
82
|
+
buf.length = 0;
|
|
83
|
+
buf.push(merged);
|
|
84
|
+
return { kind: "need-more" };
|
|
85
|
+
}
|
|
86
|
+
plen = Number(merged.readBigUInt64BE(2));
|
|
87
|
+
offset = 10;
|
|
88
|
+
}
|
|
89
|
+
if (requireMask && !masked)
|
|
90
|
+
return { kind: "rejected" };
|
|
91
|
+
if (!requireMask && masked)
|
|
92
|
+
return { kind: "rejected" };
|
|
93
|
+
let payload;
|
|
94
|
+
if (masked) {
|
|
95
|
+
if (merged.length < offset + 4) {
|
|
96
|
+
buf.length = 0;
|
|
97
|
+
buf.push(merged);
|
|
98
|
+
return { kind: "need-more" };
|
|
99
|
+
}
|
|
100
|
+
const maskKey = merged.subarray(offset, offset + 4);
|
|
101
|
+
offset += 4;
|
|
102
|
+
if (merged.length < offset + plen) {
|
|
103
|
+
buf.length = 0;
|
|
104
|
+
buf.push(merged);
|
|
105
|
+
return { kind: "need-more" };
|
|
106
|
+
}
|
|
107
|
+
const raw = merged.subarray(offset, offset + plen);
|
|
108
|
+
payload = Buffer.alloc(plen);
|
|
109
|
+
for (let i = 0; i < plen; i++) {
|
|
110
|
+
payload[i] = raw[i] ^ maskKey[i % 4];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
if (merged.length < offset + plen) {
|
|
115
|
+
buf.length = 0;
|
|
116
|
+
buf.push(merged);
|
|
117
|
+
return { kind: "need-more" };
|
|
118
|
+
}
|
|
119
|
+
payload = Buffer.from(merged.subarray(offset, offset + plen));
|
|
120
|
+
}
|
|
121
|
+
const remaining = merged.subarray(offset + plen);
|
|
122
|
+
buf.length = 0;
|
|
123
|
+
if (remaining.length > 0)
|
|
124
|
+
buf.push(remaining);
|
|
125
|
+
return { kind: "frame", opcode, payload, fin };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Drive an `InkboxWsHandler` against a `WebSocketSink`. Constructs an
|
|
129
|
+
* `InkboxWebSocket`-shaped object whose lifecycle (`accept`, `send`,
|
|
130
|
+
* `close`, async-iterator) maps onto the sink's frame I/O.
|
|
131
|
+
*/
|
|
132
|
+
export async function bridgeWsHandlerOverSink(opts) {
|
|
133
|
+
const { handler, sink, meta } = opts;
|
|
134
|
+
let accepted = false;
|
|
135
|
+
let closed = false;
|
|
136
|
+
// Inbound message stream — the handler's async-iterator pulls from
|
|
137
|
+
// here. The reader task is started lazily on `accept` so frames
|
|
138
|
+
// received before the user's handler iterates are still buffered.
|
|
139
|
+
const inboundQueue = [];
|
|
140
|
+
const inboundResolvers = [];
|
|
141
|
+
let inboundEnded = false;
|
|
142
|
+
let inboundError = null;
|
|
143
|
+
const pushInbound = (msg) => {
|
|
144
|
+
if (inboundResolvers.length > 0) {
|
|
145
|
+
inboundResolvers.shift()({ value: msg, done: false });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
inboundQueue.push(msg);
|
|
149
|
+
};
|
|
150
|
+
const endInbound = (err) => {
|
|
151
|
+
inboundEnded = true;
|
|
152
|
+
if (err)
|
|
153
|
+
inboundError = err;
|
|
154
|
+
while (inboundResolvers.length > 0) {
|
|
155
|
+
const r = inboundResolvers.shift();
|
|
156
|
+
r({ value: undefined, done: true });
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
let readerTask = null;
|
|
160
|
+
const startReader = () => {
|
|
161
|
+
if (readerTask !== null)
|
|
162
|
+
return;
|
|
163
|
+
readerTask = (async () => {
|
|
164
|
+
let fragments = null;
|
|
165
|
+
let fragmentsText = false;
|
|
166
|
+
while (!closed) {
|
|
167
|
+
let frame;
|
|
168
|
+
try {
|
|
169
|
+
frame = await sink.recvFrame();
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
endInbound(err);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (frame === null) {
|
|
176
|
+
endInbound();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const { opcode, payload, fin } = frame;
|
|
180
|
+
if (opcode === WS_OPCODE_PING) {
|
|
181
|
+
await sink.sendFrame(WS_OPCODE_PONG, payload).catch(() => undefined);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (opcode === WS_OPCODE_PONG)
|
|
185
|
+
continue;
|
|
186
|
+
if (opcode === WS_OPCODE_CLOSE) {
|
|
187
|
+
endInbound();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (opcode === 0x0) {
|
|
191
|
+
if (fragments === null) {
|
|
192
|
+
endInbound(new Error("continuation without start"));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
fragments.push(payload);
|
|
196
|
+
}
|
|
197
|
+
else if (opcode === WS_OPCODE_TEXT) {
|
|
198
|
+
if (fragments !== null) {
|
|
199
|
+
endInbound(new Error("new text frame mid-fragment"));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
fragments = [payload];
|
|
203
|
+
fragmentsText = true;
|
|
204
|
+
}
|
|
205
|
+
else if (opcode === WS_OPCODE_BINARY) {
|
|
206
|
+
if (fragments !== null) {
|
|
207
|
+
endInbound(new Error("new binary frame mid-fragment"));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
fragments = [payload];
|
|
211
|
+
fragmentsText = false;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
endInbound(new Error(`unsupported opcode ${opcode}`));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (!fin)
|
|
218
|
+
continue;
|
|
219
|
+
const merged = fragments.length === 1
|
|
220
|
+
? fragments[0]
|
|
221
|
+
: Buffer.concat(fragments);
|
|
222
|
+
fragments = null;
|
|
223
|
+
if (fragmentsText) {
|
|
224
|
+
try {
|
|
225
|
+
pushInbound(merged.toString("utf-8"));
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
endInbound(new Error("invalid utf-8 in text frame"));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
pushInbound(merged);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})();
|
|
237
|
+
};
|
|
238
|
+
const ws = {
|
|
239
|
+
url: meta.url,
|
|
240
|
+
headers: meta.headers,
|
|
241
|
+
offeredProtocols: meta.offeredSubprotocols,
|
|
242
|
+
async accept(acceptOpts) {
|
|
243
|
+
if (accepted || closed)
|
|
244
|
+
return;
|
|
245
|
+
accepted = true;
|
|
246
|
+
const subprotocol = acceptOpts?.protocol;
|
|
247
|
+
if (subprotocol !== undefined &&
|
|
248
|
+
!meta.offeredSubprotocols.includes(subprotocol)) {
|
|
249
|
+
const { WsProtocolMismatch } = await import("./_ws.js");
|
|
250
|
+
throw new WsProtocolMismatch(subprotocol, meta.offeredSubprotocols);
|
|
251
|
+
}
|
|
252
|
+
await sink.accept({
|
|
253
|
+
subprotocol,
|
|
254
|
+
extraHeaders: acceptOpts?.headers,
|
|
255
|
+
});
|
|
256
|
+
startReader();
|
|
257
|
+
},
|
|
258
|
+
async send(data) {
|
|
259
|
+
if (!accepted || closed) {
|
|
260
|
+
const { WsClosed } = await import("./_ws.js");
|
|
261
|
+
throw new WsClosed();
|
|
262
|
+
}
|
|
263
|
+
if (typeof data === "string") {
|
|
264
|
+
await sink.sendFrame(WS_OPCODE_TEXT, Buffer.from(data, "utf-8"));
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
await sink.sendFrame(WS_OPCODE_BINARY, data);
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
async close(code = 1000, reason = "") {
|
|
271
|
+
if (closed)
|
|
272
|
+
return;
|
|
273
|
+
closed = true;
|
|
274
|
+
if (!accepted) {
|
|
275
|
+
await sink.reject({ status: 403, reason });
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const reasonBuf = Buffer.from(reason, "utf-8");
|
|
279
|
+
const payload = Buffer.alloc(2 + reasonBuf.length);
|
|
280
|
+
payload.writeUInt16BE(code, 0);
|
|
281
|
+
reasonBuf.copy(payload, 2);
|
|
282
|
+
try {
|
|
283
|
+
await sink.sendFrame(WS_OPCODE_CLOSE, payload);
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
/* swallow */
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
[Symbol.asyncIterator]() {
|
|
290
|
+
return {
|
|
291
|
+
async next() {
|
|
292
|
+
if (inboundError !== null)
|
|
293
|
+
throw inboundError;
|
|
294
|
+
if (inboundQueue.length > 0) {
|
|
295
|
+
return { value: inboundQueue.shift(), done: false };
|
|
296
|
+
}
|
|
297
|
+
if (inboundEnded) {
|
|
298
|
+
return { value: undefined, done: true };
|
|
299
|
+
}
|
|
300
|
+
return new Promise((resolve) => inboundResolvers.push(resolve));
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
try {
|
|
306
|
+
await handler(ws);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
if (!accepted) {
|
|
310
|
+
await sink.reject({ status: 500, reason: "handler error" });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
closed = true;
|
|
315
|
+
endInbound();
|
|
316
|
+
if (readerTask !== null) {
|
|
317
|
+
try {
|
|
318
|
+
await readerTask;
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
/* swallow */
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
try {
|
|
325
|
+
await sink.aclose();
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
/* swallow */
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Common `WebSocketSink` impl backed by an inbound byte queue + outbound
|
|
334
|
+
* send callback. The h1 parser drives this from a node:http upgrade
|
|
335
|
+
* socket; the h2 transcoder drives the same shape from Extended-CONNECT
|
|
336
|
+
* stream DATA frames.
|
|
337
|
+
*/
|
|
338
|
+
export class ByteChannelWebSocketSink {
|
|
339
|
+
sendPlaintext;
|
|
340
|
+
buildAccept;
|
|
341
|
+
buildReject;
|
|
342
|
+
onCloseHook;
|
|
343
|
+
requireClientMask;
|
|
344
|
+
inboundChunks = [];
|
|
345
|
+
inboundResolvers = [];
|
|
346
|
+
inboundClosed = false;
|
|
347
|
+
accepted = false;
|
|
348
|
+
closed = false;
|
|
349
|
+
constructor(opts) {
|
|
350
|
+
this.sendPlaintext = opts.sendPlaintext;
|
|
351
|
+
this.buildAccept = opts.buildAcceptResponse;
|
|
352
|
+
this.buildReject = opts.buildRejectResponse;
|
|
353
|
+
this.onCloseHook = opts.onClose;
|
|
354
|
+
this.requireClientMask = opts.requireClientMask ?? true;
|
|
355
|
+
}
|
|
356
|
+
feedInbound(data) {
|
|
357
|
+
if (this.closed)
|
|
358
|
+
return;
|
|
359
|
+
this.inboundChunks.push(data);
|
|
360
|
+
while (this.inboundResolvers.length > 0) {
|
|
361
|
+
this.inboundResolvers.shift()();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
signalInboundEof() {
|
|
365
|
+
this.inboundClosed = true;
|
|
366
|
+
while (this.inboundResolvers.length > 0) {
|
|
367
|
+
this.inboundResolvers.shift()();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
async accept(opts) {
|
|
371
|
+
if (this.accepted || this.closed)
|
|
372
|
+
return;
|
|
373
|
+
this.accepted = true;
|
|
374
|
+
const head = this.buildAccept(opts?.subprotocol ?? null, opts?.extraHeaders ?? null);
|
|
375
|
+
await this.sendPlaintext(head);
|
|
376
|
+
}
|
|
377
|
+
async reject(opts) {
|
|
378
|
+
if (this.accepted || this.closed)
|
|
379
|
+
return;
|
|
380
|
+
this.closed = true;
|
|
381
|
+
const head = this.buildReject(opts?.status ?? 400);
|
|
382
|
+
try {
|
|
383
|
+
await this.sendPlaintext(head);
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
/* swallow */
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
async sendFrame(opcode, payload, opts) {
|
|
390
|
+
if (!this.accepted || this.closed)
|
|
391
|
+
return;
|
|
392
|
+
const fin = opts?.fin ?? true;
|
|
393
|
+
const frame = encodeServerFrame(opcode, payload, fin);
|
|
394
|
+
await this.sendPlaintext(frame);
|
|
395
|
+
}
|
|
396
|
+
async recvFrame() {
|
|
397
|
+
while (true) {
|
|
398
|
+
const decoded = decodeClientFrame(this.inboundChunks, {
|
|
399
|
+
requireMask: this.requireClientMask,
|
|
400
|
+
});
|
|
401
|
+
if (decoded.kind === "frame") {
|
|
402
|
+
return {
|
|
403
|
+
opcode: decoded.opcode,
|
|
404
|
+
payload: decoded.payload,
|
|
405
|
+
fin: decoded.fin,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
if (decoded.kind === "rejected")
|
|
409
|
+
return null;
|
|
410
|
+
// need-more
|
|
411
|
+
if (this.inboundClosed && this.inboundChunks.length === 0) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
await new Promise((r) => this.inboundResolvers.push(r));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
async aclose() {
|
|
418
|
+
if (this.closed)
|
|
419
|
+
return;
|
|
420
|
+
this.closed = true;
|
|
421
|
+
this.signalInboundEof();
|
|
422
|
+
if (this.onCloseHook !== undefined) {
|
|
423
|
+
try {
|
|
424
|
+
await this.onCloseHook();
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
/* swallow */
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
//# sourceMappingURL=_ws_passthrough.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_ws_passthrough.js","sourceRoot":"","sources":["../../../src/tunnels/client/_ws_passthrough.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,MAAM,OAAO,GAAG,sCAAsC,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,UAAU,CAAC,MAAM,CAAC;SACtB,MAAM,CAAC,GAAG,GAAG,OAAO,EAAE,OAAO,CAAC;SAC9B,MAAM,CAAC,QAAQ,CAAC,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,OAAe,EACf,GAAG,GAAG,IAAI;IAEV,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAC5B,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;SAAM,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,mEAAmE;QACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAa,EACb,IAAgC;IAKhC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,IAAI,CAAC;IAC9C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC;IACrB,MAAM,GAAG,CAAC,CAAC;IACX,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,GAAG,CAAC,CAAC;IACb,CAAC;SAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACxB,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACvB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IACD,IAAI,WAAW,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACxD,IAAI,CAAC,WAAW,IAAI,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACxD,IAAI,OAAe,CAAC;IACpB,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC,CAAC;QACZ,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;QACnD,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9B,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,CAAC;QACD,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AACjD,CAAC;AA2BD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAI7C;IACC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACrC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,mEAAmE;IACnE,gEAAgE;IAChE,kEAAkE;IAClE,MAAM,YAAY,GAA2B,EAAE,CAAC;IAChD,MAAM,gBAAgB,GAElB,EAAE,CAAC;IACP,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,YAAY,GAAiB,IAAI,CAAC;IAEtC,MAAM,WAAW,GAAG,CAAC,GAAoB,EAAQ,EAAE;QACjD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,gBAAgB,CAAC,KAAK,EAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,GAAW,EAAQ,EAAE;QACvC,YAAY,GAAG,IAAI,CAAC;QACpB,IAAI,GAAG;YAAE,YAAY,GAAG,GAAG,CAAC;QAC5B,OAAO,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,EAAG,CAAC;YACpC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,UAAU,GAAyB,IAAI,CAAC;IAC5C,MAAM,WAAW,GAAG,GAAS,EAAE;QAC7B,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO;QAChC,UAAU,GAAG,CAAC,KAAK,IAAI,EAAE;YACvB,IAAI,SAAS,GAAoB,IAAI,CAAC;YACtC,IAAI,aAAa,GAAG,KAAK,CAAC;YAC1B,OAAO,CAAC,MAAM,EAAE,CAAC;gBACf,IAAI,KAA+D,CAAC;gBACpE,IAAI,CAAC;oBACH,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,CAAC,GAAY,CAAC,CAAC;oBACzB,OAAO;gBACT,CAAC;gBACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,UAAU,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;gBACvC,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;oBAC9B,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;oBACrE,SAAS;gBACX,CAAC;gBACD,IAAI,MAAM,KAAK,cAAc;oBAAE,SAAS;gBACxC,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;oBAC/B,UAAU,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;gBACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;oBACnB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;wBACvB,UAAU,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;wBACpD,OAAO;oBACT,CAAC;oBACD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,CAAC;qBAAM,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;oBACrC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;wBACvB,UAAU,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;wBACrD,OAAO;oBACT,CAAC;oBACD,SAAS,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtB,aAAa,GAAG,IAAI,CAAC;gBACvB,CAAC;qBAAM,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;oBACvC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;wBACvB,UAAU,CAAC,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;wBACvD,OAAO;oBACT,CAAC;oBACD,SAAS,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtB,aAAa,GAAG,KAAK,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,UAAU,CAAC,IAAI,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAC;oBACtD,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,GAAG;oBAAE,SAAS;gBACnB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC;oBACnC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;oBACd,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAC7B,SAAS,GAAG,IAAI,CAAC;gBACjB,IAAI,aAAa,EAAE,CAAC;oBAClB,IAAI,CAAC;wBACH,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;oBACxC,CAAC;oBAAC,MAAM,CAAC;wBACP,UAAU,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;wBACrD,OAAO;oBACT,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,WAAW,CAAC,MAAM,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,EAAE,GAAoB;QAC1B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,gBAAgB,EAAE,IAAI,CAAC,mBAAmB;QAE1C,KAAK,CAAC,MAAM,CAAC,UAAU;YACrB,IAAI,QAAQ,IAAI,MAAM;gBAAE,OAAO;YAC/B,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,WAAW,GAAG,UAAU,EAAE,QAAQ,CAAC;YACzC,IACE,WAAW,KAAK,SAAS;gBACzB,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAC/C,CAAC;gBACD,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;gBACxD,MAAM,IAAI,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACtE,CAAC;YACD,MAAM,IAAI,CAAC,MAAM,CAAC;gBAChB,WAAW;gBACX,YAAY,EAAE,UAAU,EAAE,OAAO;aAClC,CAAC,CAAC;YACH,WAAW,EAAE,CAAC;QAChB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,IAAI;YACb,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;gBACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;gBAC9C,MAAM,IAAI,QAAQ,EAAE,CAAC;YACvB,CAAC;YACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,GAAG,EAAE;YAClC,IAAI,MAAM;gBAAE,OAAO;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YACnD,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/B,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,aAAa;YACf,CAAC;QACH,CAAC;QAED,CAAC,MAAM,CAAC,aAAa,CAAC;YACpB,OAAO;gBACL,KAAK,CAAC,IAAI;oBACR,IAAI,YAAY,KAAK,IAAI;wBAAE,MAAM,YAAY,CAAC;oBAC9C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC5B,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;oBACvD,CAAC;oBACD,IAAI,YAAY,EAAE,CAAC;wBACjB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;oBAC1C,CAAC;oBACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;gBAClE,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,IAAI,CAAC;QACd,UAAU,EAAE,CAAC;QACb,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC;YACnB,CAAC;YAAC,MAAM,CAAC;gBACP,aAAa;YACf,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,aAAa;QACf,CAAC;IACH,CAAC;AACH,CAAC;AAwBD;;;;;GAKG;AACH,MAAM,OAAO,wBAAwB;IAClB,aAAa,CAAkC;IAC/C,WAAW,CAGhB;IACK,WAAW,CAA6B;IACxC,WAAW,CAAuB;IAClC,iBAAiB,CAAU;IACpC,aAAa,GAAa,EAAE,CAAC;IAC7B,gBAAgB,GAAsB,EAAE,CAAC;IACzC,aAAa,GAAG,KAAK,CAAC;IACtB,QAAQ,GAAG,KAAK,CAAC;IACjB,MAAM,GAAG,KAAK,CAAC;IAEvB,YAAY,IAAyB;QACnC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAC5C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC;QAC5C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAG,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAG,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAGZ;QACC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAC3B,IAAI,EAAE,WAAW,IAAI,IAAI,EACzB,IAAI,EAAE,YAAY,IAAI,IAAI,CAC3B,CAAC;QACF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAA0B;QACrC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,aAAa;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CACb,MAAc,EACd,OAAe,EACf,IAAwB;QAExB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAC1C,MAAM,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC;QAC9B,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,SAAS;QAKb,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,aAAa,EAAE;gBACpD,WAAW,EAAE,IAAI,CAAC,iBAAiB;aACpC,CAAC,CAAC;YACH,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO;oBACL,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,GAAG,EAAE,OAAO,CAAC,GAAG;iBACjB,CAAC;YACJ,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC;YAC7C,YAAY;YACZ,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1D,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,aAAa;YACf,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkbox-tunnels/client/_ws_url_bridge.ts
|
|
3
|
+
*
|
|
4
|
+
* Bridge a WebSocket upgrade between an inbound `WebSocketSink` (h1
|
|
5
|
+
* parser or h2 transcoder) and an `http://` / `https://` URL upstream.
|
|
6
|
+
*
|
|
7
|
+
* Flow per request:
|
|
8
|
+
*
|
|
9
|
+
* 1. Open a TCP / TLS connection to ``forwardTo``.
|
|
10
|
+
* 2. Send a standard h1 ``GET /<path> HTTP/1.1`` upgrade request.
|
|
11
|
+
* 3. Read the upstream's status line + headers; if not 101, reject
|
|
12
|
+
* the inbound sink with the upstream status.
|
|
13
|
+
* 4. Accept on the inbound sink (with the upstream's negotiated
|
|
14
|
+
* subprotocol, when present).
|
|
15
|
+
* 5. Bridge frames: inbound third-party frames re-encoded with the
|
|
16
|
+
* mask bit (we are the h1 client to upstream, RFC 6455 §5.1) and
|
|
17
|
+
* written to the upstream socket; upstream server frames decoded
|
|
18
|
+
* (unmasked) and forwarded back via ``ws.sendFrame``.
|
|
19
|
+
*/
|
|
20
|
+
import * as net from "node:net";
|
|
21
|
+
import * as tls from "node:tls";
|
|
22
|
+
import type { WebSocketSink } from "./_ws_passthrough.js";
|
|
23
|
+
import type { DispatchRequest } from "./_dispatch.js";
|
|
24
|
+
export interface WsUpgradeToUrlOpts {
|
|
25
|
+
forwardTo: URL;
|
|
26
|
+
publicHost: string;
|
|
27
|
+
verifyTls: boolean;
|
|
28
|
+
caBundle: Buffer | string | null;
|
|
29
|
+
request: DispatchRequest;
|
|
30
|
+
ws: WebSocketSink;
|
|
31
|
+
}
|
|
32
|
+
export interface WsUpstreamHandle {
|
|
33
|
+
socket: net.Socket | tls.TLSSocket;
|
|
34
|
+
subprotocol: string | null;
|
|
35
|
+
leftover: Buffer;
|
|
36
|
+
/**
|
|
37
|
+
* All 101 response headers, lowercased keys, in arrival order.
|
|
38
|
+
* Application-defined headers (Set-Cookie, X-Use-Inkbox-*, custom
|
|
39
|
+
* correlation IDs) live here. The runtime filters hop-by-hop +
|
|
40
|
+
* handshake-control headers when reconstructing the third-party
|
|
41
|
+
* 101.
|
|
42
|
+
*/
|
|
43
|
+
headers: Array<[string, string]>;
|
|
44
|
+
}
|
|
45
|
+
export declare class WsUpstreamError extends Error {
|
|
46
|
+
readonly status: number;
|
|
47
|
+
readonly reason: string;
|
|
48
|
+
constructor(status: number, reason: string);
|
|
49
|
+
}
|
|
50
|
+
export interface OpenWsUpstreamOpts {
|
|
51
|
+
forwardTo: URL;
|
|
52
|
+
publicHost: string;
|
|
53
|
+
verifyTls: boolean;
|
|
54
|
+
caBundle: Buffer | string | null;
|
|
55
|
+
requestPath: string;
|
|
56
|
+
requestHeaders: Array<[string, string]>;
|
|
57
|
+
wsSubprotocol: string | null;
|
|
58
|
+
forwardedForIp: string | null;
|
|
59
|
+
/** Bound on connect + h1 head-read. Default 30s. */
|
|
60
|
+
handshakeTimeoutMs?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Open a TCP/TLS connection to ``forwardTo`` and complete an h1
|
|
64
|
+
* ``Upgrade: websocket`` handshake. Verifies the upstream's
|
|
65
|
+
* ``Sec-WebSocket-Accept`` per RFC 6455 §1.3 and returns the connected
|
|
66
|
+
* socket + negotiated subprotocol + any bytes received past the head
|
|
67
|
+
* (typically empty, but possibly the start of an early-pushed frame).
|
|
68
|
+
*/
|
|
69
|
+
export declare function openWsUpstream(opts: OpenWsUpstreamOpts): Promise<WsUpstreamHandle>;
|
|
70
|
+
export declare function bridgeWsUpgradeToUrl(opts: WsUpgradeToUrlOpts): Promise<void>;
|
|
71
|
+
//# sourceMappingURL=_ws_url_bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_ws_url_bridge.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/_ws_url_bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAOhC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAuBtD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,GAAG,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,eAAe,CAAC;IACzB,EAAE,EAAE,aAAa,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC;IACnC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAClC;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,MAAM,EAAE,MAAM;aACd,MAAM,EAAE,MAAM;gBADd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM;CAKjC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,GAAG,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oDAAoD;IACpD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAmP3B;AAgBD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAiLf"}
|