Relay: a member's media through the server's buffer (proto 8)
ci / core (push) Successful in 28s
ci / updater-windows (push) Successful in 49s
ci / server (push) Successful in 49s

Viewers who cannot reach the media get it through the server: a file on
any member's computer, a link passed on by a member ("Through me") or
fetched by the server ("Server fetches it", password-protected servers
only), and Jellyfin items for guests without an account, sourced by
whoever put them up with their own sign-in (or a pasted link's key),
which never leaves their machine. Fixes guests on a dedicated server
without a Jellyfin login being blocked.

The source dials /r/.../source (works behind NAT) and answers pulls with
an adaptive in-flight window (2 x rate x min RTT, 256 KiB..8 MiB). The
server keeps a memory-only buffer of 1 MiB slices sized like a viewer's
mpv buffer (pinned head/tail, 64 MiB back, 256 MiB ahead), fills it with
one sequential pull at a time (blocked viewers first, newest request
only), fetches nothing while nobody watches through it, and drops it on
the next swap or stop. Measured with mpv through shaped links
(tool/relay_e2e.dart): 400 Mbit/s seeks ~0.03 s; 40 Mbit/s no stalls,
3 viewers cost the source ~1x the bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-08 20:41:01 +03:00
1 parent 9c5733719b
commit e7f33b5dc3
27 files changed
+2438 -116

No files matched your search

@@ -201,7 +201,8 @@ final class OwnPlay extends JellyfinPlan {
bool get jfAccess => true;
}
/// Through the sync server's relay (`/j/...`).
/// Through the server: its own Jellyfin login (`/j/...`) or the member
/// who put it up (`/r/...`).
final class RelayPlay extends JellyfinPlan {
final String url;
const RelayPlay(this.url);
@@ -210,7 +211,7 @@ final class RelayPlay extends JellyfinPlan {
bool get jfAccess => false;
}
/// Neither: no (usable) account here and the server cannot relay.
/// Neither: no (usable) account here and nothing relays it.
final class BlockedPlay extends JellyfinPlan {
final String serverId;
/// Known only when this install has (had) an account there.
@@ -224,20 +225,22 @@ final class BlockedPlay extends JellyfinPlan {
String get message {
final where = serverName == null || serverName!.isEmpty ? 'that Jellyfin server' : serverName!;
final base = 'This needs a Jellyfin account on $where (or the host can relay)';
return problem == null ? base : '$base — $problem';
final base = 'No Jellyfin account here for $where, and nobody is passing it on';
return problem == null ? base : '$base ($problem)';
}
}
/// Picks how to play [ref]: this install's account first (PlaybackInfo
/// with its own user; a 401 marks the account expired), else the relay
/// when the server offers it ([relay] = `state.relay`, [relayUrl] this
/// member's `/j/...` URL), else [BlockedPlay].
/// with its own user; a 401 marks the account expired), else the server's
/// own Jellyfin login ([relay] = `state.relay`, [relayUrl] this member's
/// `/j/...` URL), else the member who put it up ([memberRelayUrl], the
/// `/r/...` URL when `media.relay` is set), else [BlockedPlay].
Future<JellyfinPlan> resolveJellyfinRef(
JellyfinAccounts accounts,
JellyfinRef ref, {
required bool relay,
required String? relayUrl,
String? memberRelayUrl,
Duration timeout = const Duration(seconds: 15),
}) async {
await accounts.ensureLoaded();
@@ -282,6 +285,7 @@ Future<JellyfinPlan> resolveJellyfinRef(
}
}
if (relay && relayUrl != null && relayUrl.isNotEmpty) return RelayPlay(relayUrl);
if (memberRelayUrl != null && memberRelayUrl.isNotEmpty) return RelayPlay(memberRelayUrl);
return BlockedPlay(serverId: ref.serverId, serverName: account?.displayName, problem: problem);
}