Compare commits

...

4 Commits

Author SHA1 Message Date
Adam Shiervani
ad118205ce
chore: update .gitignore and enhance WebSocket connection handling (#35)
* Add .env.development to .gitignore
* Improve handling of existing WebSocket connections by waiting for closure before terminating
2025-04-09 17:10:45 +02:00
Adam Shiervani
efce3ebe7b
Fix/more logging (#34)
* A tiny bit clearer logging

* Enhance WebSocket close event logging to include closure code and reason
2025-04-09 17:00:44 +02:00
Adam Shiervani
710c4d73b4
A tiny bit clearer logging (#33) 2025-04-09 12:48:16 +02:00
Adam Shiervani
dc5aed27e8
Add more logging (#32)
* Add more logging

* Refactor logging in WebRTC signaling to remove "WS" prefix for consistency
2025-04-09 11:33:27 +02:00
3 changed files with 36 additions and 17 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules
.idea
.env
.env
.env.development

View File

@ -75,7 +75,7 @@ async function handleDeviceSocketRequest(
// Inflight means that the device has connected, a client has connected to that device via HTTP, and they're now doing the signaling dance
if (inFlight.has(device.id)) {
console.log(
`[Device WS] Device ${device.id} already has an inflight client connection.`,
`[Device] Device ${device.id} already has an inflight client connection.`,
);
return socket.destroy();
}
@ -83,12 +83,22 @@ async function handleDeviceSocketRequest(
// Handle existing connections for this device
if (activeConnections.has(device.id)) {
console.log(
`[Device WS] Device ${device.id} already connected. Terminating existing connection.`,
`[Device] Device ${device.id} already connected. Terminating existing connection.`,
);
activeConnections.get(device.id)?.[0]?.terminate();
activeConnections.delete(device.id);
// We don't return here, we just delete the existing connection and let it continue and create a new one.
// Why multiple connections are needed, i don't know, but let's cover it.
const [existingDeviceWs] = activeConnections.get(device.id)!;
await new Promise(resolve => {
console.log("[Device] Waiting for existing connection to close...");
existingDeviceWs.on("close", () => {
activeConnections.delete(device.id);
console.log("[Device] Existing connection closed.");
// Now we continue with the new connection
resolve(true);
});
existingDeviceWs.terminate();
});
}
// Complete the WebSocket upgrade
@ -107,26 +117,26 @@ async function authenticateDeviceRequest(req: IncomingMessage) {
const secretToken = authHeader?.split(" ")?.[1];
if (!secretToken) {
console.log("[Device WS] No authorization header provided.");
console.log("[Device] No authorization header provided.");
return null;
}
try {
const device = await prisma.device.findFirst({ where: { secretToken } });
if (!device) {
console.log("[Device WS] Invalid secret token provided.");
console.log("[Device] Invalid secret token provided.");
return null;
}
const id = req.headers["x-device-id"] as string;
if (!id || id !== device.id) {
console.log("[Device WS] Invalid device ID or ID/token mismatch.");
console.log("[Device] Invalid device ID or ID/token mismatch.");
return null;
}
return device;
} catch (error) {
console.error("[Device WS] Error authenticating device:", error);
console.error("[Device] Error authenticating device:", error);
return null;
}
}
@ -143,7 +153,7 @@ function setupDeviceWebSocket(deviceWs: WebSocket, device: Device, req: Incoming
// Store the connection
activeConnections.set(id, [deviceWs, `${ip}`, deviceVersion || null]);
console.log(
`[Device WS] New connection for device ${id}, with version ${deviceVersion || "unknown"}`,
`[Device] New connection for device ${id}, with version ${deviceVersion || "unknown"}`,
);
// Setup ping/pong for connection health checks
@ -157,7 +167,7 @@ function setupDeviceWebSocket(deviceWs: WebSocket, device: Device, req: Incoming
const checkAliveInterval = setInterval(function checkAlive() {
// @ts-ignore
if (deviceWs.isAlive === false) {
console.log("[Device WS] WS is not alive. Terminating connection.");
console.log(`[Device] ${id} is not alive. Terminating connection.`);
return deviceWs.terminate();
}
// @ts-ignore
@ -172,16 +182,18 @@ function setupDeviceWebSocket(deviceWs: WebSocket, device: Device, req: Incoming
await cleanup();
});
deviceWs.on("close", async () => {
console.log(`[Device] Connection closed for ${id}`);
deviceWs.on("close", async (code, reason) => {
console.log(
`[Device] Connection closed for ${id} with code ${code} and reason ${reason}`,
);
await cleanup();
});
// Cleanup function
async function cleanup() {
console.log(`[Device] Cleanup for ${id}`);
activeConnections.delete(id);
clearInterval(checkAliveInterval);
console.log(`[Device] Cleanup for ${id}`);
await updateDeviceLastSeen(id);
}
}
@ -285,7 +297,12 @@ function setupClientWebSocket(clientWs: WebSocket, deviceId: string, token: stri
return clientWs.close();
}
console.log("[Client] Sending client connected message to device", version);
console.log(
"[Client] Sending client device-metadata, version:",
version,
" - ",
deviceId,
);
clientWs.send(
JSON.stringify({

View File

@ -71,6 +71,7 @@ export const CreateSession = async (req: express.Request, res: express.Response)
);
});
console.log("[CreateSession] got response from device", id);
return res.json(JSON.parse(resp.data));
} catch (e) {
console.log(`Error sending data to kvm with ${id}`, e);