MCPcopy
hub / github.com/coder/mux / DesktopBridgeServer

Class DesktopBridgeServer

src/node/services/desktop/DesktopBridgeServer.ts:94–402  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

92}
93
94export class DesktopBridgeServer {
95 private readonly desktopSessionManager: Pick<DesktopSessionManager, "getLiveSessionConnection">;
96 private readonly desktopTokenManager: Pick<DesktopTokenManager, "validate">;
97 private readonly wss: WebSocketServer;
98 private readonly activePairs = new Set<BridgePair>();
99 // Keep upgrade rejection aligned with stop() so httpServer.close() cannot hang on sockets
100 // that reconnect after shutdown snapshots the current bridge clients.
101 private isStopping = false;
102 private stopPromise: Promise<void> | null = null;
103
104 constructor(options: DesktopBridgeServerOptions) {
105 assert(options.desktopSessionManager, "DesktopBridgeServer requires a DesktopSessionManager");
106 assert(options.desktopTokenManager, "DesktopBridgeServer requires a DesktopTokenManager");
107
108 this.desktopSessionManager = options.desktopSessionManager;
109 this.desktopTokenManager = options.desktopTokenManager;
110 this.wss = new WebSocketServer({ noServer: true });
111 }
112
113 public ensureReady(): void {
114 assert(this.wss, "DesktopBridgeServer WebSocketServer must be initialized");
115 }
116
117 public handleUpgrade(request: IncomingMessage, socket: Duplex, head: Buffer): void {
118 this.ensureReady();
119 if (this.isStopping) {
120 log.debug("DesktopBridgeServer: rejecting upgrade while stopping", { url: request.url });
121 rejectUpgrade(socket);
122 return;
123 }
124
125 this.wss.handleUpgrade(request, socket, head, (ws) => {
126 void this.handleUpgradedConnection(ws, request);
127 });
128 }
129
130 async stop(): Promise<void> {
131 if (this.stopPromise) {
132 await this.stopPromise;
133 return;
134 }
135
136 this.isStopping = true;
137 const stopPromise = (async () => {
138 const activePairs = Array.from(this.activePairs);
139 const trackedWebSockets = new Set(activePairs.map((pair) => pair.ws));
140 const activePairClosePromises = activePairs.map((pair) => waitForWebSocketClose(pair.ws));
141
142 for (const pair of activePairs) {
143 this.cleanupPair(pair, {
144 closeCode: SERVER_STOPPING_CLOSE_CODE,
145 closeReason: "server stopping",
146 });
147 }
148 await Promise.allSettled(activePairClosePromises);
149
150 const orphanClientClosePromises: Array<Promise<void>> = [];
151 for (const ws of this.wss.clients) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected