ftown-bridge 0.13.5 → 0.14.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/dist/centrifugo-client.d.ts +5 -1
- package/dist/centrifugo-client.js +21 -1
- package/dist/centrifugo-client.js.map +1 -1
- package/dist/direct-transport/contract.d.ts +84 -0
- package/dist/direct-transport/contract.js +22 -0
- package/dist/direct-transport/contract.js.map +1 -0
- package/dist/direct-transport/peer-manager.d.ts +66 -0
- package/dist/direct-transport/peer-manager.js +364 -0
- package/dist/direct-transport/peer-manager.js.map +1 -0
- package/dist/direct-transport/publish-router.d.ts +37 -0
- package/dist/direct-transport/publish-router.js +63 -0
- package/dist/direct-transport/publish-router.js.map +1 -0
- package/dist/direct-transport/watch-registry.d.ts +38 -0
- package/dist/direct-transport/watch-registry.js +92 -0
- package/dist/direct-transport/watch-registry.js.map +1 -0
- package/dist/index.js +73 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Command, CommandResponse, Loop, Session } from './types.js';
|
|
2
|
+
import { type DirectCommandMessage, type SignalMessage } from './direct-transport/contract.js';
|
|
2
3
|
type TerminalInputHandler = (sessionId: string, data: string) => void;
|
|
3
4
|
type TerminalResizeHandler = (sessionId: string, cols: number, rows: number) => void;
|
|
4
5
|
type TerminalInitHandler = (sessionId: string) => void;
|
|
5
6
|
type CommandHandler = (command: Command) => void;
|
|
7
|
+
type DirectCommandHandler = (msg: DirectCommandMessage) => void;
|
|
6
8
|
export declare class CentrifugoClient {
|
|
7
9
|
private readonly client;
|
|
8
10
|
private readonly subscriptions;
|
|
@@ -21,10 +23,12 @@ export declare class CentrifugoClient {
|
|
|
21
23
|
publishLoopRemoved(userId: string, loopId: string): Promise<void>;
|
|
22
24
|
publishTerminalData(userId: string, sessionId: string, data: string): Promise<void>;
|
|
23
25
|
subscribeToTerminalInput(userId: string, sessionId: string, onInput: TerminalInputHandler, onResize: TerminalResizeHandler, onInit?: TerminalInitHandler): void;
|
|
24
|
-
subscribeToCommands(userId: string, handler: CommandHandler): void;
|
|
26
|
+
subscribeToCommands(userId: string, handler: CommandHandler, onDirectCommand?: DirectCommandHandler): void;
|
|
25
27
|
joinBridgesChannel(userId: string, bridgeId: string): void;
|
|
26
28
|
publishTerminalScreen(userId: string, sessionId: string, raw: string): Promise<void>;
|
|
27
29
|
publishHookEvent(userId: string, sessionId: string, event: Record<string, unknown>): Promise<void>;
|
|
30
|
+
/** Publishes a bridge-originated WebRTC signaling message on the commands channel. */
|
|
31
|
+
publishSignal(userId: string, msg: SignalMessage): Promise<void>;
|
|
28
32
|
publishCommandResponse(userId: string, response: CommandResponse): Promise<void>;
|
|
29
33
|
}
|
|
30
34
|
export {};
|
|
@@ -2,6 +2,7 @@ import { Centrifuge } from 'centrifuge';
|
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
3
|
import { hostname } from 'node:os';
|
|
4
4
|
import { toWireSession } from './session-wire.js';
|
|
5
|
+
import { isSignalMessage, isWatchMessage, } from './direct-transport/contract.js';
|
|
5
6
|
const MAX_PUBLISH_BYTES = 460_000;
|
|
6
7
|
function byteLen(str) {
|
|
7
8
|
return Buffer.byteLength(str, 'utf8');
|
|
@@ -168,7 +169,7 @@ export class CentrifugoClient {
|
|
|
168
169
|
sub.subscribe();
|
|
169
170
|
this.subscriptions.set(channel, sub);
|
|
170
171
|
}
|
|
171
|
-
subscribeToCommands(userId, handler) {
|
|
172
|
+
subscribeToCommands(userId, handler, onDirectCommand) {
|
|
172
173
|
const channel = `commands:rpc#${userId}`;
|
|
173
174
|
const existingSub = this.subscriptions.get(channel);
|
|
174
175
|
if (existingSub) {
|
|
@@ -181,6 +182,15 @@ export class CentrifugoClient {
|
|
|
181
182
|
if (data.type === 'command_response') {
|
|
182
183
|
return;
|
|
183
184
|
}
|
|
185
|
+
if (onDirectCommand && (isSignalMessage(data) || isWatchMessage(data))) {
|
|
186
|
+
try {
|
|
187
|
+
onDirectCommand(data);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
console.error(`[Centrifugo] Direct command handler failed on ${channel}:`, err);
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
184
194
|
const command = data;
|
|
185
195
|
if (!command.type || !command.requestId) {
|
|
186
196
|
return;
|
|
@@ -251,6 +261,16 @@ export class CentrifugoClient {
|
|
|
251
261
|
console.error(`[Centrifugo] Failed to publish hook event to ${channel}:`, err);
|
|
252
262
|
}
|
|
253
263
|
}
|
|
264
|
+
/** Publishes a bridge-originated WebRTC signaling message on the commands channel. */
|
|
265
|
+
async publishSignal(userId, msg) {
|
|
266
|
+
const channel = `commands:rpc#${userId}`;
|
|
267
|
+
try {
|
|
268
|
+
await this.client.publish(channel, msg);
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
console.error(`[Centrifugo] Failed to publish signal to ${channel}:`, err);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
254
274
|
async publishCommandResponse(userId, response) {
|
|
255
275
|
const channel = `commands:rpc#${userId}`;
|
|
256
276
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"centrifugo-client.js","sourceRoot":"","sources":["../src/centrifugo-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"centrifugo-client.js","sourceRoot":"","sources":["../src/centrifugo-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct Transport wire contract — FROZEN.
|
|
3
|
+
* Identical copy lives at ui/src/lib/direct-transport/contract.ts.
|
|
4
|
+
* See docs/plans/direct-transport-contract.md. Do not modify.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DIRECT_PROTOCOL_VERSION = 1;
|
|
7
|
+
export declare const DATA_CHANNEL_LABEL = "ftown";
|
|
8
|
+
export declare const STUN_SERVERS: string[];
|
|
9
|
+
export declare const PAIR_TIMEOUT_MS = 4000;
|
|
10
|
+
export declare const PING_INTERVAL_MS = 15000;
|
|
11
|
+
export declare const WATCH_HEARTBEAT_MS = 20000;
|
|
12
|
+
export declare const WATCH_TTL_MS = 60000;
|
|
13
|
+
/** Signaling + watch messages, published on the commands:rpc#{userId} channel. */
|
|
14
|
+
export type SignalType = 'webrtc_offer' | 'webrtc_answer' | 'webrtc_ice' | 'webrtc_close';
|
|
15
|
+
export interface SignalMessage {
|
|
16
|
+
type: SignalType;
|
|
17
|
+
/** Unique per connection attempt. */
|
|
18
|
+
pairId: string;
|
|
19
|
+
bridgeId: string;
|
|
20
|
+
/** Unique per browser tab (uuid). */
|
|
21
|
+
clientId: string;
|
|
22
|
+
/** SDP (offer/answer) or JSON-serialized ICE candidate; empty for webrtc_close. */
|
|
23
|
+
payload: string;
|
|
24
|
+
}
|
|
25
|
+
export interface WatchMessage {
|
|
26
|
+
type: 'terminal_watch' | 'terminal_unwatch';
|
|
27
|
+
sessionId: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
}
|
|
30
|
+
export type DirectCommandMessage = SignalMessage | WatchMessage;
|
|
31
|
+
export declare function isSignalMessage(msg: {
|
|
32
|
+
type?: string;
|
|
33
|
+
}): msg is SignalMessage;
|
|
34
|
+
export declare function isWatchMessage(msg: {
|
|
35
|
+
type?: string;
|
|
36
|
+
}): msg is WatchMessage;
|
|
37
|
+
/** JSON text frames on the `ftown` DataChannel (ordered, reliable). */
|
|
38
|
+
export type DirectMessage = {
|
|
39
|
+
kind: 'hello';
|
|
40
|
+
clientId: string;
|
|
41
|
+
protocolVersion: number;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'hello_ack';
|
|
44
|
+
bridgeId: string;
|
|
45
|
+
protocolVersion: number;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'attach';
|
|
48
|
+
sessionId: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'detach';
|
|
51
|
+
sessionId: string;
|
|
52
|
+
}
|
|
53
|
+
/** Full serialized screen; resets the output stream for the session. */
|
|
54
|
+
| {
|
|
55
|
+
kind: 'screen';
|
|
56
|
+
sessionId: string;
|
|
57
|
+
data: string;
|
|
58
|
+
seq: number;
|
|
59
|
+
} | {
|
|
60
|
+
kind: 'output';
|
|
61
|
+
sessionId: string;
|
|
62
|
+
data: string;
|
|
63
|
+
seq: number;
|
|
64
|
+
} | {
|
|
65
|
+
kind: 'input';
|
|
66
|
+
sessionId: string;
|
|
67
|
+
data: string;
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'resize';
|
|
70
|
+
sessionId: string;
|
|
71
|
+
cols: number;
|
|
72
|
+
rows: number;
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'ping';
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'pong';
|
|
77
|
+
};
|
|
78
|
+
export type TerminalTransportMode = 'direct' | 'centrifugo' | 'connecting';
|
|
79
|
+
export interface TerminalDataHandlers {
|
|
80
|
+
/** Incremental output chunk. */
|
|
81
|
+
onOutput: (data: string) => void;
|
|
82
|
+
/** Full screen resync; replaces terminal contents. */
|
|
83
|
+
onScreen: (data: string) => void;
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct Transport wire contract — FROZEN.
|
|
3
|
+
* Identical copy lives at ui/src/lib/direct-transport/contract.ts.
|
|
4
|
+
* See docs/plans/direct-transport-contract.md. Do not modify.
|
|
5
|
+
*/
|
|
6
|
+
export const DIRECT_PROTOCOL_VERSION = 1;
|
|
7
|
+
export const DATA_CHANNEL_LABEL = 'ftown';
|
|
8
|
+
export const STUN_SERVERS = ['stun:stun.l.google.com:19302'];
|
|
9
|
+
export const PAIR_TIMEOUT_MS = 4_000;
|
|
10
|
+
export const PING_INTERVAL_MS = 15_000;
|
|
11
|
+
export const WATCH_HEARTBEAT_MS = 20_000;
|
|
12
|
+
export const WATCH_TTL_MS = 60_000;
|
|
13
|
+
export function isSignalMessage(msg) {
|
|
14
|
+
return (msg.type === 'webrtc_offer' ||
|
|
15
|
+
msg.type === 'webrtc_answer' ||
|
|
16
|
+
msg.type === 'webrtc_ice' ||
|
|
17
|
+
msg.type === 'webrtc_close');
|
|
18
|
+
}
|
|
19
|
+
export function isWatchMessage(msg) {
|
|
20
|
+
return msg.type === 'terminal_watch' || msg.type === 'terminal_unwatch';
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/direct-transport/contract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AACrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;AAwBnC,MAAM,UAAU,eAAe,CAAC,GAAsB;IACpD,OAAO,CACL,GAAG,CAAC,IAAI,KAAK,cAAc;QAC3B,GAAG,CAAC,IAAI,KAAK,eAAe;QAC5B,GAAG,CAAC,IAAI,KAAK,YAAY;QACzB,GAAG,CAAC,IAAI,KAAK,cAAc,CAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAsB;IACnD,OAAO,GAAG,CAAC,IAAI,KAAK,gBAAgB,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type SignalMessage } from './contract.js';
|
|
2
|
+
/** Minimal structural view of a node-datachannel DataChannel (injectable for tests). */
|
|
3
|
+
export interface DirectDataChannel {
|
|
4
|
+
sendMessage(msg: string): boolean;
|
|
5
|
+
isOpen(): boolean;
|
|
6
|
+
close(): void;
|
|
7
|
+
onOpen(cb: () => void): void;
|
|
8
|
+
onClosed(cb: () => void): void;
|
|
9
|
+
onError(cb: (err: string) => void): void;
|
|
10
|
+
onMessage(cb: (msg: string | Buffer | ArrayBuffer) => void): void;
|
|
11
|
+
}
|
|
12
|
+
/** Minimal structural view of a node-datachannel PeerConnection (injectable for tests). */
|
|
13
|
+
export interface DirectPeerConnection {
|
|
14
|
+
setRemoteDescription(sdp: string, type: string): void;
|
|
15
|
+
addRemoteCandidate(candidate: string, mid: string): void;
|
|
16
|
+
onLocalDescription(cb: (sdp: string, type: string) => void): void;
|
|
17
|
+
onLocalCandidate(cb: (candidate: string, mid: string) => void): void;
|
|
18
|
+
onStateChange(cb: (state: string) => void): void;
|
|
19
|
+
onDataChannel(cb: (dc: DirectDataChannel) => void): void;
|
|
20
|
+
close(): void;
|
|
21
|
+
}
|
|
22
|
+
export type PeerConnectionFactory = (peerName: string, config: {
|
|
23
|
+
iceServers: string[];
|
|
24
|
+
}) => DirectPeerConnection;
|
|
25
|
+
export interface DirectPeerManagerOptions {
|
|
26
|
+
/** This bridge's identity (as advertised on bridges:presence). */
|
|
27
|
+
bridgeId: string;
|
|
28
|
+
/** Emits bridge-originated answers/ICE over the signaling channel. */
|
|
29
|
+
sendSignal: (msg: SignalMessage) => void;
|
|
30
|
+
/** DataChannel `input` frames feed here (same sink as terminal-input). */
|
|
31
|
+
onInput: (sessionId: string, data: string) => void;
|
|
32
|
+
/** DataChannel `resize` frames feed here (same sink as terminal-input). */
|
|
33
|
+
onResize: (sessionId: string, cols: number, rows: number) => void;
|
|
34
|
+
/** Returns the current full serialized screen for a session on attach. */
|
|
35
|
+
onAttach: (sessionId: string) => string;
|
|
36
|
+
/** node-datachannel PeerConnection factory; defaults to the real module. */
|
|
37
|
+
peerConnectionFactory?: PeerConnectionFactory;
|
|
38
|
+
/** Injectable clock for keepalive/teardown timers (defaults to Date.now). */
|
|
39
|
+
now?: () => number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Manages client-initiated WebRTC peers behind an injectable node-datachannel
|
|
43
|
+
* factory. Answers offers, relays ICE, and fans terminal output/screen to all
|
|
44
|
+
* attached peers over the `ftown` DataChannel.
|
|
45
|
+
*/
|
|
46
|
+
export declare class DirectPeerManager {
|
|
47
|
+
readonly bridgeId: string;
|
|
48
|
+
private readonly sendSignalCb;
|
|
49
|
+
private readonly onInputCb;
|
|
50
|
+
private readonly onResizeCb;
|
|
51
|
+
private readonly onAttachCb;
|
|
52
|
+
private readonly factory;
|
|
53
|
+
private readonly peers;
|
|
54
|
+
constructor(options: DirectPeerManagerOptions);
|
|
55
|
+
/** Never throws — a malformed signal must not propagate into the publication listener. */
|
|
56
|
+
handleSignal(msg: SignalMessage): void;
|
|
57
|
+
sendOutput(sessionId: string, data: string): void;
|
|
58
|
+
sendScreen(sessionId: string, data: string): void;
|
|
59
|
+
hasAttachedPeers(sessionId: string): boolean;
|
|
60
|
+
closeAll(): void;
|
|
61
|
+
teardown(pairId: string): void;
|
|
62
|
+
emitSignal(partial: Omit<SignalMessage, 'bridgeId'>): void;
|
|
63
|
+
getScreen(sessionId: string): string;
|
|
64
|
+
deliverInput(sessionId: string, data: string): void;
|
|
65
|
+
deliverResize(sessionId: string, cols: number, rows: number): void;
|
|
66
|
+
}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { PeerConnection } from 'node-datachannel';
|
|
2
|
+
import { DIRECT_PROTOCOL_VERSION, PING_INTERVAL_MS, STUN_SERVERS, } from './contract.js';
|
|
3
|
+
const ICE_DISCONNECT_GRACE_MS = 10_000;
|
|
4
|
+
const MAX_MISSED_PINGS = 2;
|
|
5
|
+
/** Peers that never reach channel-open within this window are torn down (leak guard). */
|
|
6
|
+
const PAIRING_TIMEOUT_MS = 30_000;
|
|
7
|
+
/**
|
|
8
|
+
* Max chars per DataChannel frame `data` field. Worst-case UTF-8 is 4 bytes per
|
|
9
|
+
* 2 chars, so 32k chars stays under ~128 KiB — safely below the ~256 KiB max
|
|
10
|
+
* message size negotiated by libdatachannel and browsers. Larger payloads are
|
|
11
|
+
* chunked: for screens, one `screen` frame (stream reset) followed by `output`
|
|
12
|
+
* continuation frames — receivers apply them sequentially, reconstructing the
|
|
13
|
+
* full serialized screen without any wire-format change.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_FRAME_DATA_CHARS = 32_000;
|
|
16
|
+
function chunkData(data) {
|
|
17
|
+
if (data.length <= MAX_FRAME_DATA_CHARS)
|
|
18
|
+
return [data];
|
|
19
|
+
const chunks = [];
|
|
20
|
+
for (let i = 0; i < data.length; i += MAX_FRAME_DATA_CHARS) {
|
|
21
|
+
chunks.push(data.slice(i, i + MAX_FRAME_DATA_CHARS));
|
|
22
|
+
}
|
|
23
|
+
return chunks;
|
|
24
|
+
}
|
|
25
|
+
const defaultPeerConnectionFactory = (peerName, config) =>
|
|
26
|
+
// Verified structural match against node-datachannel's PeerConnection surface.
|
|
27
|
+
new PeerConnection(peerName, config);
|
|
28
|
+
/**
|
|
29
|
+
* One WebRTC peer (one connection attempt, keyed by pairId). Owns its
|
|
30
|
+
* PeerConnection + DataChannel, per-session monotonic seq, attach set, and
|
|
31
|
+
* keepalive/teardown timers.
|
|
32
|
+
*/
|
|
33
|
+
class DirectPeer {
|
|
34
|
+
pairId;
|
|
35
|
+
clientId;
|
|
36
|
+
pc;
|
|
37
|
+
manager;
|
|
38
|
+
dc;
|
|
39
|
+
helloOk = false;
|
|
40
|
+
closed = false;
|
|
41
|
+
attached = new Set();
|
|
42
|
+
seq = new Map();
|
|
43
|
+
pingTimer;
|
|
44
|
+
missedPings = 0;
|
|
45
|
+
iceDisconnectTimer;
|
|
46
|
+
pairingTimer;
|
|
47
|
+
constructor(manager, pc, pairId, clientId) {
|
|
48
|
+
this.manager = manager;
|
|
49
|
+
this.pc = pc;
|
|
50
|
+
this.pairId = pairId;
|
|
51
|
+
this.clientId = clientId;
|
|
52
|
+
pc.onLocalDescription((sdp, type) => {
|
|
53
|
+
if (type === 'answer') {
|
|
54
|
+
this.manager.emitSignal({ type: 'webrtc_answer', pairId, clientId, payload: sdp });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
pc.onLocalCandidate((candidate, mid) => {
|
|
58
|
+
const payload = { candidate, mid };
|
|
59
|
+
this.manager.emitSignal({ type: 'webrtc_ice', pairId, clientId, payload: JSON.stringify(payload) });
|
|
60
|
+
});
|
|
61
|
+
pc.onStateChange((state) => this.onStateChange(state));
|
|
62
|
+
pc.onDataChannel((dc) => this.bindDataChannel(dc));
|
|
63
|
+
// Leak guard: tear down attempts that never reach channel-open (client
|
|
64
|
+
// vanished pre-ICE); keepalive only starts once the channel opens.
|
|
65
|
+
this.pairingTimer = setTimeout(() => this.manager.teardown(this.pairId), PAIRING_TIMEOUT_MS);
|
|
66
|
+
this.pairingTimer.unref?.();
|
|
67
|
+
}
|
|
68
|
+
hasAttached(sessionId) {
|
|
69
|
+
return this.attached.has(sessionId);
|
|
70
|
+
}
|
|
71
|
+
/** Throws on native rejection of the SDP; the manager catches and tears down. */
|
|
72
|
+
applyOffer(sdp) {
|
|
73
|
+
this.pc.setRemoteDescription(sdp, 'offer');
|
|
74
|
+
}
|
|
75
|
+
applyIce(payload) {
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = JSON.parse(payload);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (typeof parsed.candidate !== 'string')
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
this.pc.addRemoteCandidate(parsed.candidate, parsed.mid ?? '');
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Malformed candidate ⇒ drop it; ICE can still complete on other candidates.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
sendScreen(sessionId, data) {
|
|
93
|
+
if (!this.attached.has(sessionId))
|
|
94
|
+
return;
|
|
95
|
+
// Large screens are chunked: `screen` resets the stream (seq 0), `output`
|
|
96
|
+
// continuation frames carry the remainder; receivers apply them in order.
|
|
97
|
+
const chunks = chunkData(data);
|
|
98
|
+
this.seq.set(sessionId, chunks.length - 1);
|
|
99
|
+
this.send({ kind: 'screen', sessionId, data: chunks[0], seq: 0 });
|
|
100
|
+
for (let i = 1; i < chunks.length; i++) {
|
|
101
|
+
this.send({ kind: 'output', sessionId, data: chunks[i], seq: i });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
sendOutput(sessionId, data) {
|
|
105
|
+
if (!this.attached.has(sessionId))
|
|
106
|
+
return;
|
|
107
|
+
for (const chunk of chunkData(data)) {
|
|
108
|
+
const next = (this.seq.get(sessionId) ?? 0) + 1;
|
|
109
|
+
this.seq.set(sessionId, next);
|
|
110
|
+
this.send({ kind: 'output', sessionId, data: chunk, seq: next });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
close() {
|
|
114
|
+
if (this.closed)
|
|
115
|
+
return;
|
|
116
|
+
this.closed = true;
|
|
117
|
+
if (this.pingTimer)
|
|
118
|
+
clearInterval(this.pingTimer);
|
|
119
|
+
if (this.iceDisconnectTimer)
|
|
120
|
+
clearTimeout(this.iceDisconnectTimer);
|
|
121
|
+
if (this.pairingTimer)
|
|
122
|
+
clearTimeout(this.pairingTimer);
|
|
123
|
+
this.attached.clear();
|
|
124
|
+
this.seq.clear();
|
|
125
|
+
try {
|
|
126
|
+
this.dc?.close();
|
|
127
|
+
}
|
|
128
|
+
catch { /* already gone */ }
|
|
129
|
+
try {
|
|
130
|
+
this.pc.close();
|
|
131
|
+
}
|
|
132
|
+
catch { /* already gone */ }
|
|
133
|
+
}
|
|
134
|
+
bindDataChannel(dc) {
|
|
135
|
+
this.dc = dc;
|
|
136
|
+
dc.onMessage((msg) => {
|
|
137
|
+
if (typeof msg !== 'string')
|
|
138
|
+
return;
|
|
139
|
+
this.handleFrame(msg);
|
|
140
|
+
});
|
|
141
|
+
dc.onClosed(() => this.manager.teardown(this.pairId));
|
|
142
|
+
dc.onError(() => this.manager.teardown(this.pairId));
|
|
143
|
+
if (dc.isOpen())
|
|
144
|
+
this.startKeepalive();
|
|
145
|
+
else
|
|
146
|
+
dc.onOpen(() => this.startKeepalive());
|
|
147
|
+
}
|
|
148
|
+
startKeepalive() {
|
|
149
|
+
if (this.pairingTimer) {
|
|
150
|
+
clearTimeout(this.pairingTimer);
|
|
151
|
+
this.pairingTimer = undefined;
|
|
152
|
+
}
|
|
153
|
+
if (this.pingTimer)
|
|
154
|
+
return;
|
|
155
|
+
this.missedPings = 0;
|
|
156
|
+
this.pingTimer = setInterval(() => {
|
|
157
|
+
if (this.missedPings >= MAX_MISSED_PINGS) {
|
|
158
|
+
this.manager.teardown(this.pairId);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.missedPings += 1;
|
|
162
|
+
this.send({ kind: 'ping' });
|
|
163
|
+
}, PING_INTERVAL_MS);
|
|
164
|
+
this.pingTimer.unref?.();
|
|
165
|
+
}
|
|
166
|
+
handleFrame(raw) {
|
|
167
|
+
let msg;
|
|
168
|
+
try {
|
|
169
|
+
msg = JSON.parse(raw);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
switch (msg.kind) {
|
|
175
|
+
case 'hello': {
|
|
176
|
+
if (msg.protocolVersion !== DIRECT_PROTOCOL_VERSION) {
|
|
177
|
+
this.manager.teardown(this.pairId);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this.helloOk = true;
|
|
181
|
+
this.send({ kind: 'hello_ack', bridgeId: this.manager.bridgeId, protocolVersion: DIRECT_PROTOCOL_VERSION });
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
case 'attach': {
|
|
185
|
+
if (!this.helloOk)
|
|
186
|
+
return;
|
|
187
|
+
this.attached.add(msg.sessionId);
|
|
188
|
+
const screen = this.manager.getScreen(msg.sessionId);
|
|
189
|
+
this.sendScreen(msg.sessionId, screen);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
case 'detach': {
|
|
193
|
+
this.attached.delete(msg.sessionId);
|
|
194
|
+
this.seq.delete(msg.sessionId);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
case 'input': {
|
|
198
|
+
if (!this.helloOk)
|
|
199
|
+
return;
|
|
200
|
+
this.manager.deliverInput(msg.sessionId, msg.data);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
case 'resize': {
|
|
204
|
+
if (!this.helloOk)
|
|
205
|
+
return;
|
|
206
|
+
this.manager.deliverResize(msg.sessionId, msg.cols, msg.rows);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
case 'ping': {
|
|
210
|
+
this.send({ kind: 'pong' });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
case 'pong': {
|
|
214
|
+
this.missedPings = 0;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
default:
|
|
218
|
+
// Unknown kind ⇒ ignore.
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
onStateChange(state) {
|
|
223
|
+
if (state === 'disconnected') {
|
|
224
|
+
if (this.iceDisconnectTimer)
|
|
225
|
+
return;
|
|
226
|
+
this.iceDisconnectTimer = setTimeout(() => this.manager.teardown(this.pairId), ICE_DISCONNECT_GRACE_MS);
|
|
227
|
+
this.iceDisconnectTimer.unref?.();
|
|
228
|
+
}
|
|
229
|
+
else if (state === 'connected') {
|
|
230
|
+
if (this.iceDisconnectTimer) {
|
|
231
|
+
clearTimeout(this.iceDisconnectTimer);
|
|
232
|
+
this.iceDisconnectTimer = undefined;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else if (state === 'failed' || state === 'closed') {
|
|
236
|
+
this.manager.teardown(this.pairId);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
send(msg) {
|
|
240
|
+
if (this.closed || !this.dc || !this.dc.isOpen())
|
|
241
|
+
return;
|
|
242
|
+
try {
|
|
243
|
+
this.dc.sendMessage(JSON.stringify(msg));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// Drop the frame rather than kill the connection; a genuinely dead
|
|
247
|
+
// channel is detected by onClosed/onError or missed pings.
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Manages client-initiated WebRTC peers behind an injectable node-datachannel
|
|
253
|
+
* factory. Answers offers, relays ICE, and fans terminal output/screen to all
|
|
254
|
+
* attached peers over the `ftown` DataChannel.
|
|
255
|
+
*/
|
|
256
|
+
export class DirectPeerManager {
|
|
257
|
+
bridgeId;
|
|
258
|
+
sendSignalCb;
|
|
259
|
+
onInputCb;
|
|
260
|
+
onResizeCb;
|
|
261
|
+
onAttachCb;
|
|
262
|
+
factory;
|
|
263
|
+
peers = new Map();
|
|
264
|
+
constructor(options) {
|
|
265
|
+
this.bridgeId = options.bridgeId;
|
|
266
|
+
this.sendSignalCb = options.sendSignal;
|
|
267
|
+
this.onInputCb = options.onInput;
|
|
268
|
+
this.onResizeCb = options.onResize;
|
|
269
|
+
this.onAttachCb = options.onAttach;
|
|
270
|
+
this.factory = options.peerConnectionFactory ?? defaultPeerConnectionFactory;
|
|
271
|
+
}
|
|
272
|
+
/** Never throws — a malformed signal must not propagate into the publication listener. */
|
|
273
|
+
handleSignal(msg) {
|
|
274
|
+
if (msg.bridgeId !== this.bridgeId)
|
|
275
|
+
return;
|
|
276
|
+
if (typeof msg.pairId !== 'string' || msg.pairId === '')
|
|
277
|
+
return;
|
|
278
|
+
try {
|
|
279
|
+
switch (msg.type) {
|
|
280
|
+
case 'webrtc_offer': {
|
|
281
|
+
if (typeof msg.payload !== 'string' || msg.payload === '')
|
|
282
|
+
return;
|
|
283
|
+
if (typeof msg.clientId !== 'string' || msg.clientId === '')
|
|
284
|
+
return;
|
|
285
|
+
// Replace any prior pairing for this pairId AND any stale peer of the
|
|
286
|
+
// same client (reconnect) so a session never gets duplicate frames.
|
|
287
|
+
this.teardown(msg.pairId);
|
|
288
|
+
for (const peer of [...this.peers.values()]) {
|
|
289
|
+
if (peer.clientId === msg.clientId)
|
|
290
|
+
this.teardown(peer.pairId);
|
|
291
|
+
}
|
|
292
|
+
const pc = this.factory(`ftown-${msg.pairId}`, { iceServers: [...STUN_SERVERS] });
|
|
293
|
+
const peer = new DirectPeer(this, pc, msg.pairId, msg.clientId);
|
|
294
|
+
this.peers.set(msg.pairId, peer);
|
|
295
|
+
try {
|
|
296
|
+
peer.applyOffer(msg.payload);
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// Malformed SDP: abort just this pairing attempt and tell the client.
|
|
300
|
+
this.teardown(msg.pairId);
|
|
301
|
+
this.emitSignal({ type: 'webrtc_close', pairId: msg.pairId, clientId: msg.clientId, payload: '' });
|
|
302
|
+
}
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
case 'webrtc_ice': {
|
|
306
|
+
if (typeof msg.payload !== 'string')
|
|
307
|
+
return;
|
|
308
|
+
this.peers.get(msg.pairId)?.applyIce(msg.payload);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
case 'webrtc_close': {
|
|
312
|
+
this.teardown(msg.pairId);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
default:
|
|
316
|
+
// webrtc_answer (our own echo) and anything else ⇒ ignore.
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
console.error('[DirectTransport] Failed to handle signal:', err);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
sendOutput(sessionId, data) {
|
|
325
|
+
for (const peer of this.peers.values())
|
|
326
|
+
peer.sendOutput(sessionId, data);
|
|
327
|
+
}
|
|
328
|
+
sendScreen(sessionId, data) {
|
|
329
|
+
for (const peer of this.peers.values())
|
|
330
|
+
peer.sendScreen(sessionId, data);
|
|
331
|
+
}
|
|
332
|
+
hasAttachedPeers(sessionId) {
|
|
333
|
+
for (const peer of this.peers.values()) {
|
|
334
|
+
if (peer.hasAttached(sessionId))
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
closeAll() {
|
|
340
|
+
for (const peer of this.peers.values())
|
|
341
|
+
peer.close();
|
|
342
|
+
this.peers.clear();
|
|
343
|
+
}
|
|
344
|
+
teardown(pairId) {
|
|
345
|
+
const peer = this.peers.get(pairId);
|
|
346
|
+
if (!peer)
|
|
347
|
+
return;
|
|
348
|
+
this.peers.delete(pairId);
|
|
349
|
+
peer.close();
|
|
350
|
+
}
|
|
351
|
+
emitSignal(partial) {
|
|
352
|
+
this.sendSignalCb({ ...partial, bridgeId: this.bridgeId });
|
|
353
|
+
}
|
|
354
|
+
getScreen(sessionId) {
|
|
355
|
+
return this.onAttachCb(sessionId);
|
|
356
|
+
}
|
|
357
|
+
deliverInput(sessionId, data) {
|
|
358
|
+
this.onInputCb(sessionId, data);
|
|
359
|
+
}
|
|
360
|
+
deliverResize(sessionId, cols, rows) {
|
|
361
|
+
this.onResizeCb(sessionId, cols, rows);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=peer-manager.js.map
|