MCPcopy Create free account
hub / github.com/RioArisk/claudecode_api_RemoteControl / setupWebSocketServer

Function setupWebSocketServer

lib/ws-server.js:106–528  ·  view source on GitHub ↗
(server)

Source from the content-addressed store, hash-verified

104}
105
106function setupWebSocketServer(server) {
107 const wss = new WebSocketServer({ server });
108 state.wss = wss;
109
110 wss.on('connection', (ws, req) => {
111 ws._bridgeId = ++state.nextWsId;
112 ws._clientInstanceId = '';
113 ws._authenticated = state.AUTH_DISABLED;
114 ws._approvalMode = 'default';
115 ws._authTimer = null;
116 log(`WS connected: ${wsLabel(ws)} remote=${req.socket.remoteAddress || '?'} ua=${JSON.stringify(req.headers['user-agent'] || '')} authRequired=${!state.AUTH_DISABLED}`);
117
118 if (state.AUTH_DISABLED) {
119 sendAuthOk(ws);
120 sendInitialMessages(ws);
121 } else {
122 ws._authTimer = setTimeout(() => {
123 if (ws.readyState !== WebSocket.OPEN || ws._authenticated) return;
124 log(`Auth timeout for ${wsLabel(ws)}`);
125 ws.close(WS_CLOSE_AUTH_TIMEOUT, WS_CLOSE_REASON_AUTH_TIMEOUT);
126 }, AUTH_HELLO_TIMEOUT_MS);
127 }
128
129 ws._resumeHandled = false;
130 ws._legacyReplayTimer = null;
131 if (state.AUTH_DISABLED) {
132 ws._legacyReplayTimer = setTimeout(() => {
133 if (ws.readyState !== WebSocket.OPEN || ws._resumeHandled) return;
134 ws._resumeHandled = true;
135 sendReplay(ws, null);
136 }, LEGACY_REPLAY_DELAY_MS);
137 }
138
139 ws.on('message', async (raw) => {
140 let msg;
141 try { msg = JSON.parse(raw); } catch { return; }
142
143 // --- Authentication gate ---
144 if (!ws._authenticated) {
145 if (msg.type !== 'hello') return;
146 ws._clientInstanceId = String(msg.clientInstanceId || ws._clientInstanceId || '');
147 log(`WS hello from ${wsLabel(ws)} page=${JSON.stringify(msg.page || '')} ua=${JSON.stringify(msg.userAgent || '')}`);
148
149 const clientToken = String(msg.token || '');
150 if (!state.AUTH_TOKEN || !clientToken) {
151 log(`Auth failed for ${wsLabel(ws)}: missing token`);
152 ws.close(WS_CLOSE_AUTH_FAILED, WS_CLOSE_REASON_AUTH_FAILED);
153 return;
154 }
155 const a = Buffer.from(state.AUTH_TOKEN, 'utf8');
156 const b = Buffer.from(clientToken, 'utf8');
157 if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
158 log(`Auth failed for ${wsLabel(ws)}: invalid token`);
159 ws.close(WS_CLOSE_AUTH_FAILED, WS_CLOSE_REASON_AUTH_FAILED);
160 return;
161 }
162 ws._authenticated = true;
163 if (ws._authTimer) {

Callers 1

server.jsFile · 0.85

Calls 15

logFunction · 0.85
wsLabelFunction · 0.85
sendAuthOkFunction · 0.85
sendInitialMessagesFunction · 0.85
sendReplayFunction · 0.85
sendTurnStateFunction · 0.85
latestEventSeqFunction · 0.85
sendWsFunction · 0.85
executePtyOperationsFunction · 0.85

Tested by

no test coverage detected