hopefully fix

This commit is contained in:
KingKDot
2026-06-16 17:51:41 -05:00
parent a6d6b4d31b
commit 932b7cbc33
6 changed files with 36 additions and 12 deletions
+2 -2
View File
@@ -547,7 +547,7 @@ func runSession(ctx context.Context, cancel context.CancelFunc, conn *websocket.
sendCtx, sendCancel := context.WithTimeout(context.Background(), 2*time.Second) sendCtx, sendCancel := context.WithTimeout(context.Background(), 2*time.Second)
defer sendCancel() defer sendCancel()
_ = wire.WriteMsg(sendCtx, conn, di) _ = wire.WriteMsg(sendCtx, conn, di)
conn.Close(websocket.StatusNormalClosure, "bye") conn.CloseNow()
}() }()
identity := config.DeriveIdentity() identity := config.DeriveIdentity()
@@ -747,8 +747,8 @@ func runSession(ctx context.Context, cancel context.CancelFunc, conn *websocket.
last := env.LastPong() last := env.LastPong()
if !last.IsZero() && time.Since(last) > grace { if !last.IsZero() && time.Since(last) > grace {
log.Printf("ping: no pong for %s, forcing reconnect", time.Since(last)) log.Printf("ping: no pong for %s, forcing reconnect", time.Since(last))
conn.Close(websocket.StatusGoingAway, "pong timeout")
cancel() cancel()
conn.CloseNow()
return return
} }
} }
@@ -857,6 +857,20 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
setStreamState("connecting", "Connecting"); setStreamState("connecting", "Connecting");
return; return;
} }
if (msg.status === "starting") {
clearOfflineTimer();
if (desiredStreaming && streamState !== "streaming") {
setStreamState("starting", "Starting stream");
}
return;
}
if (msg.status === "stopped") {
clearOfflineTimer();
desiredStreaming = false;
lastFrameAt = 0;
setStreamState("idle", "Stopped");
return;
}
if (msg.status === "online") { if (msg.status === "online") {
clearOfflineTimer(); clearOfflineTimer();
if (elevationPending) { if (elevationPending) {
@@ -1348,10 +1362,12 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
stopBtn.addEventListener("click", function () { stopBtn.addEventListener("click", function () {
if (isRecording()) stopRecording(); if (isRecording()) stopRecording();
desiredStreaming = false; desiredStreaming = false;
lastFrameAt = 0;
setStreamState("stopping", "Stopping stream"); setStreamState("stopping", "Stopping stream");
sendCmd("desktop_stop", {}); sendCmd("desktop_stop", {});
disconnectAudio(); disconnectAudio();
stopAllWebrtc(); stopAllWebrtc();
setStreamState("idle", "Stopped");
}); });
if (recordBtn) { if (recordBtn) {
recordBtn.addEventListener("click", function () { recordBtn.addEventListener("click", function () {
+10 -8
View File
@@ -566,7 +566,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
hasRenderedFrame = true; hasRenderedFrame = true;
bitmap.close(); bitmap.close();
updateViewerFps(); updateViewerFps();
setStreamState("streaming", "Streaming"); if (desiredStreaming) setStreamState("streaming", "Streaming");
} finally { } finally {
drawPending = false; drawPending = false;
} }
@@ -600,7 +600,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
h264TimestampUs += 66_666; h264TimestampUs += 66_666;
videoDecoder.decode(chunk); videoDecoder.decode(chunk);
updateViewerFps(); updateViewerFps();
setStreamState("streaming", "Streaming"); if (desiredStreaming) setStreamState("streaming", "Streaming");
} catch (err) { } catch (err) {
console.warn("webcam h264 decode failed", err, "payloadBytes=", payload.length); console.warn("webcam h264 decode failed", err, "payloadBytes=", payload.length);
} }
@@ -698,6 +698,13 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
if (msg.status === "offline") { if (msg.status === "offline") {
desiredStreaming = false; desiredStreaming = false;
setStreamState("offline", msg.reason || "Client offline"); setStreamState("offline", msg.reason || "Client offline");
} else if (msg.status === "starting") {
if (desiredStreaming && streamState !== "streaming") {
setStreamState("starting", "Starting");
}
} else if (msg.status === "stopped") {
desiredStreaming = false;
setStreamState("idle", "Stopped");
} else if (msg.status === "connecting") { } else if (msg.status === "connecting") {
setStreamState("idle", "Ready"); setStreamState("idle", "Ready");
} else if (msg.status === "online") { } else if (msg.status === "online") {
@@ -790,12 +797,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
send("webcam_stop"); send("webcam_stop");
stopAllWebrtc(); stopAllWebrtc();
disconnectAudio(); disconnectAudio();
setStreamState("stopping", "Stopping"); setStreamState("idle", "Stopped");
setTimeout(() => {
if (streamState === "stopping") {
setStreamState("idle", "Stopped");
}
}, 300);
}); });
function stopOnExit() { function stopOnExit() {
@@ -36,7 +36,7 @@ describe("pruneStaleClients", () => {
expect(deleted).toEqual([]); expect(deleted).toEqual([]);
}); });
test("closes and marks offline stale role=client entries without deleting", () => { test("closes, marks offline, and deletes stale role=client entries", () => {
const clients = new Map<string, ClientInfo>(); const clients = new Map<string, ClientInfo>();
const staleClient = makeClient("stale-c", Date.now() - 120_000, "client"); const staleClient = makeClient("stale-c", Date.now() - 120_000, "client");
clients.set("stale-c", staleClient); clients.set("stale-c", staleClient);
@@ -53,7 +53,7 @@ describe("pruneStaleClients", () => {
}); });
expect(offlined).toContain("stale-c"); expect(offlined).toContain("stale-c");
expect(deleted).not.toContain("stale-c"); expect(deleted).toContain("stale-c");
expect((staleClient.ws as any)._calls[0]).toStartWith("close:"); expect((staleClient.ws as any)._calls[0]).toStartWith("close:");
}); });
@@ -20,6 +20,7 @@ export function pruneStaleClients(params: PruneStaleClientsParams): void {
if (info.role === "client") { if (info.role === "client") {
info.ws.close(4000, "stale"); info.ws.close(4000, "stale");
params.setOnlineState(id, false); params.setOnlineState(id, false);
params.deleteClient(id);
processed += 1; processed += 1;
continue; continue;
} }
@@ -390,6 +390,7 @@ export function handleRemoteDesktopViewerMessage(ws: ServerWebSocket<SocketData>
whepPath: `/api/webrtc/${streamPath}/whep`, whepPath: `/api/webrtc/${streamPath}/whep`,
}); });
} }
safeSendViewer(ws, { type: "status", status: "starting" });
sendDesktopCommand(target, "desktop_set_fps", { fps: clampDesktopFps(state.maxFps) }); sendDesktopCommand(target, "desktop_set_fps", { fps: clampDesktopFps(state.maxFps) });
sendDesktopCommand(target, "desktop_start", {}); sendDesktopCommand(target, "desktop_start", {});
state.isStreaming = true; state.isStreaming = true;
@@ -403,6 +404,7 @@ export function handleRemoteDesktopViewerMessage(ws: ServerWebSocket<SocketData>
logger.info(`[rd-debug] desktop_start reasserting stale stream client=${clientId} lastFrameAgeMs=${Number.isFinite(lastFrameAgeMs) ? lastFrameAgeMs : -1} state=${JSON.stringify(state)} viewers=${sessionManager.getRdSessionsForClient(clientId).length}`); logger.info(`[rd-debug] desktop_start reasserting stale stream client=${clientId} lastFrameAgeMs=${Number.isFinite(lastFrameAgeMs) ? lastFrameAgeMs : -1} state=${JSON.stringify(state)} viewers=${sessionManager.getRdSessionsForClient(clientId).length}`);
sendDesktopCommand(target, "desktop_set_fps", { fps: clampDesktopFps(state.maxFps) }); sendDesktopCommand(target, "desktop_set_fps", { fps: clampDesktopFps(state.maxFps) });
sendDesktopCommand(target, "desktop_start", {}); sendDesktopCommand(target, "desktop_start", {});
safeSendViewer(ws, { type: "status", status: "starting" });
state.isStreaming = true; state.isStreaming = true;
state.startedAt = Date.now(); state.startedAt = Date.now();
rdStreamingState.set(clientId, state); rdStreamingState.set(clientId, state);
@@ -437,6 +439,7 @@ export function handleRemoteDesktopViewerMessage(ws: ServerWebSocket<SocketData>
} else { } else {
logger.debug(`[rd] ignoring desktop_stop for client ${clientId} - ${otherViewers.length} other viewer(s) still active`); logger.debug(`[rd] ignoring desktop_stop for client ${clientId} - ${otherViewers.length} other viewer(s) still active`);
} }
safeSendViewer(ws, { type: "status", status: "stopped" });
break; break;
} }
case "desktop_record_start": { case "desktop_record_start": {
@@ -994,6 +997,7 @@ export function handleWebcamViewerMessage(ws: ServerWebSocket<SocketData>, raw:
whepPath: `/api/webrtc/${streamPath}/whep`, whepPath: `/api/webrtc/${streamPath}/whep`,
}); });
} }
safeSendViewer(ws, { type: "status", status: "starting" });
sendDesktopCommand(target, "webcam_start", {}); sendDesktopCommand(target, "webcam_start", {});
state.isStreaming = true; state.isStreaming = true;
webcamStreamingState.set(clientId, state); webcamStreamingState.set(clientId, state);
@@ -1019,6 +1023,7 @@ export function handleWebcamViewerMessage(ws: ServerWebSocket<SocketData>, raw:
} else { } else {
logger.debug(`[webcam] ignoring webcam_stop for client ${clientId} - ${otherWebcamViewers.length} other viewer(s) still active`); logger.debug(`[webcam] ignoring webcam_stop for client ${clientId} - ${otherWebcamViewers.length} other viewer(s) still active`);
} }
safeSendViewer(ws, { type: "status", status: "stopped" });
break; break;
} }
case "webrtc_p2p_offer": { case "webrtc_p2p_offer": {