Server Security (S-1 through S-8): - S-1: Type-check and clamp peerId, protocolVersion, password - S-2: Validate numeric/boolean/enum fields in relay peerData - S-3: Construct explicit relay payload (stop spreading raw data) - S-4: Type-check targetId and actionTimestamp in EVENT_ACK - S-5: Restrict room IDs to [a-zA-Z0-9-] only - S-7: Add eventCounts periodic cleanup alongside connectionCounts - S-8: Guard version parsing against NaN bypass Documentation (P-1, R-1 through R-6): - P-1: Fix PRIVACY.md typo, document all in-memory data maps - R-1/R-5: Fix stale sync-constants.bat references in shared/ - R-2: Fix stale lastTargetState ref in ARCHITECTURE.md - R-3: Extension README title reflects cross-browser support - R-6: Document content injection markers in scripts/README.md
5.6 KiB
KoalaSync Architecture
This document describes the communication flows and internal logic of the KoalaSync system.
1. Extension Startup & Connection
- Initialization: On startup,
background.jsreads settings (Server URL, Username, Last Room) fromchrome.storage.sync. - WebSocket Handshake:
- Background creates a
new WebSocketto/socket.io/?EIO=4&transport=websocket&version=1.0.0. - Server performs security checks:
- IP Rate Limit: Checks if the IP has exceeded connection limits.
- Protocol Version: Client must match the server's protocol (currently
1.0.0).
- Server responds with Engine.IO handshake (
0) and the client joins the namespace (40).
- Background creates a
- Room Join: Background emits
JOIN_ROOMcontainingroomId,password,peerId, andusername. - Deduplication: If a user joins with a
peerIdthat already has an active socket, the server kills the old socket to prevent "Ghost Peers".
2. Media Event Synchronization
When a user interacts with a video:
- Detection:
content.jslistens to native events (play,pause,seeked) on the<video>element. - Prevention of Loops: Uses an
expectedEventsSet to distinguish between user actions and programmatic actions. Expected events are consumed on match and expire via timeout. - Reporting:
content.jssends aCONTENT_EVENTtobackground.js. - Relay: The Server forwards the event to all other peers in the room.
- Execution: Remote peers receive the command and call
video.play(),video.pause(), orvideo.currentTime = targetTime.
3. Two-Phase Force Sync
Ensures all peers are frame-perfect and buffered before resuming:
- Prepare: Initiator sends
FORCE_SYNC_PREPAREwith the target timestamp. - Buffer: Peers seek and pause. Once buffered (
readyState >= 3), they send aFORCE_SYNC_ACK. (Note:content.jslimits polling to 8000ms). - Execute: Once the Initiator collects ACKs (or after an 8.5s timeout), they send
FORCE_SYNC_EXECUTE.Important
Network Transit Buffer Rule: The orchestrator (
background.js) must always use a timeout at least 500ms longer than the worker (content.js) to account for IPC and network transit time. Never align them exactly 1:1, as this will introduce a race condition on slow connections. - Resume: All peers call
play()simultaneously.
4. Episode Auto-Sync
Maintains continuous synchronized viewing when watching series:
- Detection:
content.jsmonitors the Media Session API for title changes. - Lobby Creation: When a new title is detected, the peer initiates an
EPISODE_LOBBYand broadcasts the new title. - Wait State: All peers freeze their video until they have also loaded the exact same title.
- Mid-Lobby Joins: If a new user joins the room during an active lobby, the lobby initiator broadcasts the active lobby state so the newcomer can sync up.
- Resume: Once all peers report
EPISODE_READY, the lobby is resolved and playback resumes perfectly.
5. Peer Lifecycle & Dual Heartbeat
To maintain a clean room state and eliminate "Ghost Peers":
- Session Heartbeat (Background): Every 30 seconds,
background.jssends an "I'm alive" signal to the server. This keeps you in the room even if no video is playing. - Video Heartbeat (Content): Every 15 seconds,
content.jssends current playback metadata (time, title, state) if a video is found. - Server Pruning: The server runs a "Reaper" every 2 minutes. If a peer has sent zero activity (no events and no heartbeats) for 5 minutes, they are forcefully disconnected.
- Immediate Cleanup: Rooms are deleted instantly when the last peer leaves or disconnects.
Caution
Identity Rule: Differentiate between
peerIdandsocket.id. Usesocket.idexclusively for ephemeral transport routing on the server. UsepeerIdexclusively for identity, state management, and room tracking across the stack.
6. Broadcast Protocol & Routing
KoalaSync uses a megaphone routing approach to minimize server logic:
emit()Broadcast Behavior: Anyemit()from the extension client is unconditionally broadcast to all other peers in the room. It is not a direct message.- Storm Prevention: When dispatching state updates in response to a new user joining (e.g., an active lobby state), ensure ONLY the initiator (or a designated leader) calls
emit()to preventO(N)broadcast storms.
7. Security & Stability
- Service Worker Lifecycle: Uses
chrome.alarmsto prevent the Manifest V3 service worker from suspending while in an active room. - Rate Limiting: Server-side per-socket and per-IP rate limits to prevent sync-spamming or DoS.
- Noise Filtering: Uses a curated blacklist of domains (Search Engines, Social Media) to declutter the "Target Tab" selector in the popup.
- Diagnostics: A "Dev" tab provides real-time access to the underlying
<video>state (readyState,paused,currentTime) for easier troubleshooting.
8. Constant Synchronization & Consistency
To maintain a "Single Source of Truth" across the server and extension without using a bundler:
- Relay Server & Extension Modules:
background.jsandpopup.jsimport constants directly fromshared/constants.js. - Content Scripts: To ensure zero-latency execution,
content.jsuses a synchronized copy ofEVENTSand constants. - Automation: The
node scripts/build-extension.jsscript automatically injects these constants intocontent.jsduring the build process, eliminating the risk of manual mirror mismatch. - Verification: Any protocol change is automatically propagated across the stack by running the build script.