Harden LA publishers and add multi-relay guide
Some checks are pending
ci-gates / checks (push) Waiting to run
deploy-cloudflare / checks (push) Waiting to run
deploy-cloudflare / deploy (push) Blocked by required conditions

This commit is contained in:
Conrad Kramer 2026-06-10 01:28:15 -07:00
parent 5d6f77f868
commit cfc4902016
No known key found for this signature in database
13 changed files with 1430 additions and 402 deletions

View file

@ -212,10 +212,17 @@ type PublicStreamEntry = {
relay_url: string;
broadcast_name: string;
track_name: string;
relays: PublicStreamRelay[];
updated_ms: number;
expires_ms: number;
};
type PublicStreamRelay = {
relay_url: string;
broadcast_name: string;
track_name: string;
};
type PublicStreamList = {
now_ms: number;
entries: PublicStreamEntry[];
@ -323,9 +330,41 @@ type StreamUpsertReq = {
relay_url: string;
broadcast_name: string;
track_name?: string;
relays?: PublicStreamRelay[];
expires_ms?: number;
};
function publicStreamRelayKey(relay: PublicStreamRelay): string {
return `${relay.relay_url}\n${relay.broadcast_name}\n${relay.track_name}`;
}
function normalizePublicStreamRelays(body: StreamUpsertReq): PublicStreamRelay[] {
const relays: PublicStreamRelay[] = [];
const addRelay = (candidate?: Partial<PublicStreamRelay>) => {
if (!candidate?.relay_url || !candidate.broadcast_name) return;
const relay: PublicStreamRelay = {
relay_url: clampStr(candidate.relay_url, 512),
broadcast_name: clampStr(candidate.broadcast_name, 256),
track_name: clampStr(candidate.track_name || "video0.m4s", 256),
};
if (!relays.some((existing) => publicStreamRelayKey(existing) === publicStreamRelayKey(relay))) {
relays.push(relay);
}
};
addRelay({
relay_url: body.relay_url,
broadcast_name: body.broadcast_name,
track_name: body.track_name,
});
if (Array.isArray(body.relays)) {
for (const relay of body.relays) addRelay(relay);
}
return relays.slice(0, 16);
}
function authBearerToken(request: Request): string | null {
const auth = request.headers.get("authorization");
if (!auth) return null;
@ -392,17 +431,20 @@ export class EcApiContainer implements DurableObject {
{ status: 400 },
);
}
const relays = normalizePublicStreamRelays(body);
const requestedExpires = body.expires_ms ?? now + 20_000;
const requestedTtl = Math.max(0, requestedExpires - now);
const ttlMs = Math.min(60_000, Math.max(5_000, requestedTtl));
const primaryRelay = relays[0];
const entry: PublicStreamEntry = {
stream_id: clampStr(body.stream_id, 256),
title: clampStr(body.title, 128),
relay_url: clampStr(body.relay_url, 512),
broadcast_name: clampStr(body.broadcast_name, 256),
track_name: clampStr(body.track_name || "video0.m4s", 256),
relay_url: primaryRelay.relay_url,
broadcast_name: primaryRelay.broadcast_name,
track_name: primaryRelay.track_name,
relays,
updated_ms: now,
expires_ms: now + ttlMs,
};