harden: relay timeouts, DNS resolver reuse, cache hygiene + frontend polish
Server (relay/SSRF): - Bound connect+TLS+request under CONNECT_TIMEOUT and body download under BODY_TIMEOUT so a stalling upstream can't pin a relay permit indefinitely - Add inbound header_read_timeout to defeat slow-loris connections - Allowlist relayed Content-Type (fall back to octet-stream) to block content-confusion from attacker-controlled stream origins - Reuse one DNS resolver process-wide instead of rebuilding it per request (restores hickory's DNS cache; drops per-segment resolver setup) - Probe cache: random per-process hash seed (DefaultHasher was deterministic) + bounded growth with expired-entry eviction - Real Ctrl-C handler for a clean shutdown (honours the banner) - Collapse the wrap_raw no-op alias into wrap Frontend: - Guide: visible focus ring tracking arrow-key navigation - Player: buffering/tuning indicator while <video> is stalled - prefers-contrast: more pass (lifts --ink-dim to meet WCAG AA) - Service worker: date-stamped cache names so shell updates propagate Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+21
-1
@@ -27,6 +27,7 @@ export class Player {
|
||||
this._fallbackIdx = 0;
|
||||
this._wireControls();
|
||||
this._wireActivity();
|
||||
this._wireBuffering();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,12 +94,31 @@ export class Player {
|
||||
if (this.hls) { try { this.hls.destroy(); } catch {} this.hls = null; }
|
||||
this.video.removeAttribute('src');
|
||||
try { this.video.load(); } catch {}
|
||||
this._setBuffering(false); // never leave the indicator stuck across a zap
|
||||
}
|
||||
|
||||
destroy() { this._teardown(); }
|
||||
|
||||
// ---------- buffering / stall indicator ----------
|
||||
// Bridge the gap between the scrying static clearing and the first frame:
|
||||
// without a hint, a slow-loading stream is indistinguishable from a dead one.
|
||||
_wireBuffering() {
|
||||
const v = this.video;
|
||||
const on = () => this._setBuffering(true);
|
||||
const off = () => this._setBuffering(false);
|
||||
v.addEventListener('waiting', on);
|
||||
v.addEventListener('stalled', on);
|
||||
v.addEventListener('playing', off);
|
||||
v.addEventListener('canplay', off);
|
||||
v.addEventListener('pause', off);
|
||||
v.addEventListener('emptied', off);
|
||||
}
|
||||
_setBuffering(on) {
|
||||
if (this.els.screen) this.els.screen.classList.toggle('buffering', on);
|
||||
}
|
||||
|
||||
// ---------- dead-stream "the orb clouds over" ----------
|
||||
_showNoSignal() { this.els.nosignal.hidden = false; }
|
||||
_showNoSignal() { this.els.nosignal.hidden = false; this._setBuffering(false); }
|
||||
_hideNoSignal() { this.els.nosignal.hidden = true; }
|
||||
|
||||
// ---------- live-aware chrome ----------
|
||||
|
||||
Reference in New Issue
Block a user