This document details the technical architecture, protocols and low-level design of the FileShare system.
FileShare uses a hybrid Peer-to-Peer architecture. A centralized signaling server facilitates discovery and connection establishment, while the actual data transfer happens directly between clients using WebRTC.
graph TD
subgraph "Clients"
Sender[Sender Browser]
Receiver[Receiver Browser]
end
subgraph "Signaling Service (AWS Lambda)"
Handler[WebSocket Handler]
Redis[(Redis Session Store)]
end
Sender <--> |WebSocket| Handler
Receiver <--> |WebSocket| Handler
Handler <--> Redis
Sender -.-> |WebRTC DataChannel| Receiver
The backend is a stateless AWS Lambda function that uses Redis for cross-invocation state management.
- Logic: Uses
SecureRandomto generate a 6-character alphanumeric PIN. - Alphabet:
ABCDEFGHJKLMNPQRSTUVWXYZ23456789(excludes confusing characters likeI,O,0,1). - Uniqueness: The generator retries if a PIN collision is detected in Redis.
| Key Pattern | Type | Purpose | TTL |
|---|---|---|---|
pin:{PIN} |
Hash | Stores senderConnId and receiverConnId. |
600s |
connection:{connId} |
String | Maps a connection ID back to its PIN for cleanup. | 600s |
The Transport layer is responsible for breaking files into packets and ensuring they arrive safely without overwhelming the receiver.
Each packet sent over the RTCDataChannel follows this binary format:
[0-3] chunkIndex (uint32, big-endian)
[4-7] payloadLength (uint32, big-endian)
[8-N] payload (raw bytes)
- Chunk Size: Hardcoded to 64KB for maximum compatibility across browser engines.
To prevent the browser's SCTP buffer from overflowing:
- Thresholds:
MAX_BUFFERED_AMOUNT: 4MBLOW_THRESHOLD: 512KB
- Flow: If
bufferedAmount> 4MB, the sender pauses and waits for thebufferedamountlowevent before continuing.
The receiver uses the FileSystem Access API to handle large files (GigaBytes) without crashing the browser tab:
- Upon metadata arrival, the receiver requests a file handle via
showSaveFilePicker. - As chunks arrive, they are written to the
FileSystemWritableFileStreamusing.seek(position). - If the API is unavailable (e.g., Firefox/Safari), it falls back to in-memory
Blobassembly.
stateDiagram-v2
[*] --> IDLE
IDLE --> CONNECTING: click Share/Join
CONNECTING --> WAITING: registered (PIN shown)
WAITING --> HANDSHAKING: peer joined
HANDSHAKING --> TRANSFERRING: DataChannel open
TRANSFERRING --> COMPLETED: all chunks ACKed
TRANSFERRING --> FAILED: connection lost / cancel
COMPLETED --> IDLE: reset
The signaling phase exchanges session descriptions (SDP) and ICE candidates.
sequenceDiagram
participant S as Sender
participant B as Backend
participant R as Receiver
S->>B: {"action": "register"}
B-->>S: {"type": "register", "pin": "X4Y7Z2"}
Note over S, R: Sender shares PIN out-of-band
R->>B: {"action": "join", "pin": "X4Y7Z2"}
B-->>S: {"type": "peer-joined"}
B-->>R: {"type": "joined"}
S->>B: {"action": "offer", "payload": SDP}
B->>R: {"type": "offer", "payload": SDP}
R->>B: {"action": "answer", "payload": SDP}
B->>S: {"type": "answer", "payload": SDP}
Note over S, R: Connection Established
- Encryption: WebRTC provides mandatory DTLS encryption for the DataChannel.
- Speed: Optimized by minimal protocol overhead and binary framing; typically limited only by the user's upload bandwidth.
- Privacy: No file data is ever persisted or transmitted through the signaling server.