mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-27 20:39:10 +00:00
152 lines
3.8 KiB
Markdown
152 lines
3.8 KiB
Markdown
# Host Control Mode
|
|
|
|
This document describes the Host Control Mode implementation in the relay and
|
|
extension. It only covers behavior implemented in the current codebase.
|
|
|
|
## Modes
|
|
|
|
### `everyone`
|
|
|
|
- Default room mode.
|
|
- Any peer may send room-moving playback events.
|
|
|
|
### `host-only`
|
|
|
|
- Only controllers may send room-moving playback events.
|
|
- The host is always a controller.
|
|
- The host can promote additional peers to controllers.
|
|
- Guests can keep watching locally in solo/desynced mode, but their local actions
|
|
still do not drive the shared room.
|
|
|
|
Room-moving events are:
|
|
|
|
- `play`
|
|
- `pause`
|
|
- `seek`
|
|
- `force_sync_prepare`
|
|
- `force_sync_execute`
|
|
- `episode_lobby`
|
|
- `episode_lobby_cancel`
|
|
|
|
Heartbeats, force-sync ACKs, episode-ready events, ping/pong, and command ACKs
|
|
remain allowed for guests.
|
|
|
|
## Server State
|
|
|
|
Rooms store Host Control state in memory:
|
|
|
|
```js
|
|
{
|
|
hostPeerId,
|
|
controlMode,
|
|
controllers,
|
|
lastControlModeChangeAt,
|
|
lastRoleChangeAt,
|
|
forceSyncInitiator
|
|
}
|
|
```
|
|
|
|
`controllers` is a `Set` on the server and is serialized as an array in
|
|
`room_data` and `control_mode`.
|
|
|
|
State is not persisted across relay restarts.
|
|
|
|
## Authority Rules
|
|
|
|
### Changing mode
|
|
|
|
Only `hostPeerId` may send `set_control_mode`.
|
|
|
|
Valid values:
|
|
|
|
- `everyone`
|
|
- `host-only`
|
|
|
|
Invalid values are ignored. Non-host attempts are ignored and the sender receives
|
|
the current `control_mode` snapshot so optimistic UI can revert.
|
|
|
|
Mode changes are debounced per room for 500 ms.
|
|
|
|
### Promoting and demoting controllers
|
|
|
|
Only `hostPeerId` may send `set_peer_role`.
|
|
|
|
The host cannot demote themself. No-op role changes are ignored. Role changes are
|
|
debounced per room for 500 ms.
|
|
|
|
### Host leaving
|
|
|
|
When the host leaves and peers remain:
|
|
|
|
- the next peer becomes `hostPeerId`;
|
|
- `controlMode` falls back to `everyone`;
|
|
- `controllers` is reset to the new host;
|
|
- the relay broadcasts `control_mode`.
|
|
|
|
When a non-host controller leaves, the relay removes that peer from
|
|
`controllers` and broadcasts `control_mode`.
|
|
|
|
## Enforcement
|
|
|
|
The implementation has two enforcement points:
|
|
|
|
- The extension background script blocks local guest attempts in `host-only` and
|
|
sends `HOST_BLOCKED` to the content script for local UX.
|
|
- The relay drops room-moving events from non-controllers in `host-only`, so old
|
|
or modified clients cannot drive the room.
|
|
|
|
The relay is the authority for room-wide effects.
|
|
|
|
## Guest UX
|
|
|
|
When a guest action is blocked locally, the content script classifies it:
|
|
|
|
- deliberate user action: show the host-control dialog;
|
|
- likely involuntary player action (buffering, tab refocus, no recent gesture):
|
|
silently snap back when safe;
|
|
- live/DVR stream: degrade without forcing snap-back.
|
|
|
|
The dialog offers:
|
|
|
|
- stay in sync: resync to the host;
|
|
- watch on my own: enter solo/desynced mode.
|
|
|
|
In solo/desynced mode:
|
|
|
|
- the guest can control their local video;
|
|
- host room commands are ignored locally, except force-sync preparation is ACKed
|
|
so the host's flow can continue;
|
|
- the guest can resync to the host.
|
|
|
|
The extension reports `desynced` in peer status so the host UI can show that a
|
|
guest is watching solo.
|
|
|
|
## Force Sync Edge Case
|
|
|
|
The relay tracks `forceSyncInitiator` after a controller sends
|
|
`force_sync_prepare`.
|
|
|
|
This allows that same initiator's `force_sync_execute` through even if their
|
|
controller role changes before execute arrives. Without this, a demotion in the
|
|
middle of a force-sync flow could leave peers waiting after prepare.
|
|
|
|
The relay clears `forceSyncInitiator` after execute or when the initiator leaves.
|
|
|
|
## Capabilities
|
|
|
|
The relay advertises Host Control support in `room_data.capabilities`:
|
|
|
|
- `host-control`
|
|
- `co-host`
|
|
|
|
The extension hides or disables matching UI when capabilities are missing.
|
|
|
|
## Related Events
|
|
|
|
See [PROTOCOL.md](PROTOCOL.md) for payloads and relay behavior for:
|
|
|
|
- `set_control_mode`
|
|
- `control_mode`
|
|
- `set_peer_role`
|
|
- host-only gated relay events
|