Transfer multi-gigabyte files directly between browsers using WebRTC, without uploading them to a central server.
Traditional file-sharing services require uploading files to a server before a recipient can download them. This adds transfer delay, wastes server storage, and increases bandwidth costs.
Ronin P2P removes the server from the transfer path by connecting two browsers directly using WebRTC. Files stream straight from sender to receiver, making transfers faster and more privacy-focused.
To handle multi-gigabyte files (such as video masters, database dumps, and zip archives) without crashing the browser, incoming data streams directly to the receiver's disk. Writing data straight to storage instead of keeping it in memory prevents out-of-memory errors during large transfers.
%%{init: {'theme': 'dark', 'themeVariables': { 'fontSize': '16px'}, 'flowchart': {'useMaxWidth': false, 'htmlLabels': true}} }%%
graph TD
%% Node Stylings
classDef client fill:#18181b,stroke:#818cf8,stroke-width:2px,color:#fff;
classDef server fill:#09090b,stroke:#27272a,stroke-width:2px,color:#a1a1aa;
classDef pipe fill:#1e1b4b,stroke:#6366f1,stroke-width:2px,color:#e0e7ff;
%% Elements
Sender["Sender Client (Browser A)"]:::client
Signaling["Node.js Signaling Server"]:::server
Receiver["Receiver Client (Browser B)"]:::client
DataPipe{"Open WebRTC Data Channel"}:::pipe
%% Step 1: Meeting at the Server
Sender -->|1. Create Room| Signaling
Receiver -->|2. Join Room via Link| Signaling
%% Step 2: Trading Connection Details
Signaling -->|3. Pass Connection Details| Receiver
Receiver -->|4. Return Acceptance Details| Signaling
Signaling -.->|Broker Complete| Sender
%% Step 3: Going Direct (Cutting out the Middleman)
Sender ===>|5. Establish Direct P2P Line| DataPipe
Receiver ===>|5. Establish Direct P2P Line| DataPipe
%%{init: {'theme': 'dark', 'themeVariables': { 'fontSize': '16px'}, 'flowchart': {'useMaxWidth': false, 'htmlLabels': true}} }%%
graph TD
%% Node Stylings
classDef client fill:#18181b,stroke:#818cf8,stroke-width:2px,color:#fff;
classDef server fill:#09090b,stroke:#27272a,stroke-width:2px,color:#a1a1aa;
classDef pipe fill:#1e1b4b,stroke:#6366f1,stroke-width:2px,color:#e0e7ff;
classDef loop fill:#27272a,stroke:#4b5563,stroke-width:1px,color:#e0e7ff;
%% Elements
Sender["Sender Workspace"]:::client
DataPipe{"Established WebRTC Data Channel"}:::pipe
Receiver["Receiver Workspace"]:::client
Disk[(Physical Storage Drive)]:::server
%% Step 1: File Transfer Handshake
Sender -->|1. Metadata Header: FILE_REQUEST| DataPipe
DataPipe -->|2. User Grants Storage Handle: FILE_ACCEPTED| Receiver
%% Step 2: The Core Backpressure Streaming Engine
subgraph FlowControl ["Memory Guard: Asynchronous Flow Control Loop"]
A1[Slice File into 16KB ArrayBuffer Chunks] --> A2{Is dataChannel.bufferedAmount > 2MB?}
%% Congestion Path
A2 -- YES: Buffer Saturated --> A3[Pause Chunk Reading Loop Thread]
A3 --> A4[Bind One-Time Hook to onbufferedamountlow]
A4 --> A5{Has Buffer Dropped Below 1MB?}
A5 -- YES: Queue Clear --> A6[Wake Thread & Resume Ingestion]
A6 --> A1
%% Safe Path
A2 -- NO: Buffer Safe --> A7[dataChannel.send Chunk]
end
%% Step 3: Network Transmission & Disk Commits
Sender -.->|Orchestrates| FlowControl
A7 -->|3. Push Network Chunks| DataPipe
DataPipe -->|4. Native FileSystemAccessAPI Stream Write| Receiver
Receiver -->|5. Zero-Copy Flush| Disk
During large file transfers, the sender can produce data faster than the network is able to transmit it. If chunks are sent continuously, the WebRTC data channel's internal buffer keeps growing, which increases memory usage and can eventually lead to performance issues or channel errors.
To prevent this, Ronin P2P implements a high and low watermark backpressure mechanism.
| Parameter | Value | Purpose |
|---|---|---|
| Chunk Size | 16 KB | Splits files into manageable chunks for transmission. |
| High Watermark | 2 MB | Pause sending when the buffered data exceeds this limit. |
| Low Watermark | 1 MB | Resume sending once the buffer drops below this limit. |
The sender continuously monitors the data channel's bufferedAmount. When the buffered data exceeds 2 MB, file reading is paused to prevent the buffer from growing further. The application then waits for the onbufferedamountlow event, which is triggered after the buffer falls below 1 MB. Once this event fires, file reading resumes automatically.
This mechanism keeps memory usage stable, prevents buffer overflow, and enables reliable multi-gigabyte file transfers without overwhelming the browser.
Traditional web applications typically store incoming file data in memory before creating a downloadable file. While this approach works well for smaller files, it becomes inefficient for multi-gigabyte transfers because memory usage continues to grow and may eventually cause the browser tab to crash.
Ronin P2P avoids this by streaming incoming data directly to disk using the File System Access API.
-
Chromium Support: On Chromium-based browsers (Chrome, Edge, Brave), the application requests a writable file handle using
window.showSaveFilePicker()before the transfer begins. -
Direct Disk Writes: Each incoming 16 KB
ArrayBufferchunk is written immediately to aFileSystemWritableFileStreaminstead of being accumulated in memory. Since data is streamed directly to disk, memory usage remains low regardless of file size.
This allows Ronin P2P to reliably transfer multi-gigabyte files without exhausting the browser's available memory.
To keep file transfers responsive and reliable, Ronin P2P includes several runtime optimizations.
-
Updating React state for every received chunk causes unnecessary re-renders, especially during large file transfers. Instead, Ronin P2P updates the UI only when the transfer percentage changes.
-
This reduces thousands of React renders to at most 100 UI updates per transfer, allowing the browser to spend more time handling network operations instead of rendering the interface.
-
Long file transfers can be interrupted if the operating system puts the device to sleep. On supported browsers, Ronin P2P uses the Screen Wake Lock API (
navigator.wakeLock) to keep the screen awake while a transfer is in progress. -
The wake lock is automatically released when the transfer completes or is cancelled.
-
The application continuously monitors both the WebRTC peer connection and the data channel during a transfer.
-
If the peer connection enters the
failedstate or the data channel is no longeropen, the transfer is stopped immediately. Active file streams are closed, wake locks are released, and application resources are cleaned up to prevent memory leaks.
Ronin P2P uses the File System Access API for direct-to-disk streaming. Since this API is currently supported only by Chromium-based browsers, some features vary by browser.
-
Chromium Browsers (Chrome, Edge, Brave): Full support for direct-to-disk streaming using the File System Access API. Large files can be transferred without consuming significant browser memory.
-
Firefox: Firefox does not currently support the File System Access API. As a fallback, incoming data is temporarily buffered in memory. To avoid excessive memory usage, transfers larger than 200 MB display a recommendation to use a Chromium-based browser for the best experience.
- React – User interface
- Vite – Development and build tool
- Tailwind CSS – Styling
- Three.js / React Three Fiber – 3D globe visualization
- Node.js
- Socket.io – WebRTC signaling server
- WebRTC – Peer-to-peer file transfer
- STUN / ICE – Peer connection establishment
- File System Access API – Direct-to-disk streaming
- Screen Wake Lock API – Prevents the device from sleeping during transfers
Follow these commands to deploy the project architecture locally:
Ensure you have Node.js installed on your machine.
# 1. Clone the repository structure
git clone [https://github.com/yourusername/roninp2p.git](https://github.com/yourusername/roninp2p.git)
# 2. Access the project root folder
cd roninp2p
# 3. Install core dependencies
npm install
# 4. Initiate the localized dev workspace
npm run dev
---
## Developed ByBuilt by [vasanth642]
🔗 GitHub: @vasanth642
If this project helped you understand peer-to-peer streaming or accelerated your development workflow, please consider giving it a star! It helps others discover the repository.
⭐ Star this repository