Document device media paths and direct transfer requirements
This commit is contained in:
69
docs/p2p-transfer.md
Normal file
69
docs/p2p-transfer.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Direct device media transfers
|
||||
|
||||
## Existing paths (audit before implementation)
|
||||
|
||||
| Path | Existing media-byte route | Relevant code |
|
||||
| --- | --- | --- |
|
||||
| Paired remote | Controls only; the host plays its own source. No existing file-send action. | `frontend/app.js` Remote; `server/remote.js` |
|
||||
| Presenter and OBS | Lyrics, timing and metadata only; neither currently plays host media. | Presenter and overlay modules; remote relay |
|
||||
| Watch Party playback | Each guest loads independently through normal server/YouTube playback, unless already saved locally. | Party `applyState`, `Player.loadVideo`; `server/party.js` |
|
||||
| Watch Party voice | Direct WebRTC audio; server forwards SDP/ICE only. | Party voice mesh, party `rtc` relay |
|
||||
| On other devices / failed playback | Existing verified-file DataChannel download, 64 KiB frames, SHA-256 validation, worker writes OPFS. Only offered after server failure in playback. | `p2p-transfer.js`, `p2p-recv-worker.js`, `getFromPeers` |
|
||||
| Save / preload | Server download first, then OPFS. | `preload`, `API.cacheDownload`, download endpoints |
|
||||
| Export to Files / Photos | Local OPFS first, server URL next, peer fallback last. Native share is an OS export, not paired-device transfer. | `exportToDevice`, `export.js` |
|
||||
| Profile / playlist share and send | Metadata only. Sending a playlist does not transfer its media files. | Profile/playlist sync APIs |
|
||||
| Verify & share | Explicit device upload to server intake; hash and media validation admit it into the server cache. | `P2PClient.contribute`, `p2p-intake.js` |
|
||||
| Automatic rehydration | Server requests a holder to upload its full file to intake. This is an implicit media-byte server path. | `createRehydrator`, client `upload-request` handler |
|
||||
| Admin uploads / original YouTube downloads | Intentional server ingestion of original media; separate from direct device transfer. | Upload and media-cache endpoints |
|
||||
| VLC / external player URLs | HTTP server media URLs; these players cannot consume this application's DataChannel. | External player actions |
|
||||
|
||||
The current file protocol has no resume: its receiver truncates partial files and
|
||||
removes them on failure. Connection timeout is 20 seconds per holder. Device
|
||||
signalling authenticates a device, but does not constrain its destination to a
|
||||
verified profile or paired room. Profile names supplied at device registration
|
||||
are not proof of profile membership. Existing server-verified holdings also
|
||||
exclude files whose bytes the server has never admitted.
|
||||
|
||||
## Implementation design
|
||||
|
||||
Reuse ordered RTCDataChannel transfers with public STUN only. The WebSocket
|
||||
server carries bounded, validated signalling and metadata, never file chunks.
|
||||
Pair authorization must come from an authenticated remote/party room or a
|
||||
verified profile session, not an arbitrary client-supplied profile name.
|
||||
|
||||
A receiver explicitly accepts an invitation before saving. A cryptographically
|
||||
random, expiring, one-use invitation binds sender, receiver and file identity;
|
||||
subsequent signalling remains bound to that pair. Reject replay, mismatched
|
||||
identities, binary WebSocket messages and unrecognized protocol fields.
|
||||
|
||||
Send 64 KiB chunks with bufferedAmount backpressure. Persist a partial OPFS file
|
||||
and resume at its exact committed byte offset. Rehash the retained prefix before
|
||||
continuing and verify total size and SHA-256 before promoting the file into the
|
||||
saved store; only then record metadata. A changed hash/size cannot reuse a partial.
|
||||
|
||||
Use a 10-second connection deadline and an explicit, clearly labelled server
|
||||
fallback offer. Direct mode must not silently rehydrate server media from a
|
||||
device. Register “Direct device transfer (P2P)” in Settings, default on.
|
||||
|
||||
Party playback should request a host's saved file when announced, then play the
|
||||
receiver's OPFS copy. Remote controls and presenter lyrics retain their existing
|
||||
behaviour; add explicit receive/play actions rather than automatically starting
|
||||
media in a control-only screen. A manual send action targets authenticated peers.
|
||||
|
||||
Ordinary faststart MP4 cannot safely be appended as arbitrary MediaSource chunks.
|
||||
Progressive playback requires supported fragmented media and codec detection;
|
||||
otherwise use the completed, verified file (including iOS). Do not claim that
|
||||
raw MP4 chunks provide progressive playback.
|
||||
|
||||
## Verification required before release
|
||||
|
||||
Pure tests cover protocol parsing, chunk bounds, offsets, invitation replay and
|
||||
pair authorization. A two-page localhost browser test must transfer real bytes
|
||||
into OPFS through WebRTC and assert that server HTTP/WS logs contain only
|
||||
signalling and metadata. Exercise interruption/resume and explicit fallback.
|
||||
Review real iPhone foreground/background behaviour and restrictive NAT failure.
|
||||
|
||||
## Implementation status
|
||||
|
||||
This document records the pre-implementation audit and design. Transport,
|
||||
authorization and UI changes described above are not yet implemented.
|
||||
Reference in New Issue
Block a user