Secure, ephemeral peer-to-peer file sharing. no accounts, no cloud storage, no permanent copies.
A sender uploads a file and gets a port-based invite code plus a one-time PIN. The recipient enters both to download the file. The file is automatically destroyed after 60 seconds or after 2 failed PIN attempts, whichever comes first.
| Feature | Details |
|---|---|
| Drag & drop upload | Click or drop any file to start sharing |
| Invite code | A random ephemeral port (49152β65535) acts as the share link |
| PIN authentication | A random 4-digit PIN is generated per session; recipient needs both code + PIN |
| Session timer | 60-second countdown starts on upload; file auto-deletes at zero |
| Colour-coded timer | Green > 30 s β Amber 10β30 s β Red < 10 s |
| PIN retry limiting | Max 2 wrong attempts before the session is permanently terminated |
| Copy to clipboard | One-click copy for both the invite code and PIN |
| Auto file cleanup | Temp file + TCP socket closed on expiry or lockout |
| Docker support | Single docker-compose up spins up both services |
| One-command startup | start.sh / start.bat builds and launches everything locally |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser :3000 β
β β
β ββββββββββββββββββββ βββββββββββββββββββββ βββββββββββββββββ β
β β FileUpload.tsx β β FileDownload.tsx β βInviteCode.tsx β β
β β (drag & drop) β β (port + PIN form)β β(timer + copy) β β
β ββββββββββ¬ββββββββββ ββββββββββ¬βββββββββββ βββββββββββββββββ β
ββββββββββββββΌββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββ
β POST /api/upload β GET /api/download/:port?pin=
βΌ βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Next.js API Proxy (next.config.js) β
β /api/* βββββββββββββββΊ http://localhost:8080 β
βββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β HTTP :8080
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Java Backend :8080 β
β β
β ββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β UploadHandler β β DownloadHandler β β
β β POST /upload β β GET /download/:port?pin= β β
β βββββββββββ¬βββββββββββ βββββββββββββββββ¬ββββββββββββββββββ β
β β β β
β ββββββββββββββββ¬βββββββββββββββββββ β
β βΌ β
β ββββββββββββββββββββββββββββββββ β
β β FileSharer β β
β β offerFile() validatePin() β β
β β startFileServer() β β
β β terminateSession() β β
β ββββββββββββββββ¬ββββββββββββββββ β
β β β
β βββββββββββββββββββ΄βββββββββββββββββββ β
β βΌ βΌ β
β βββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ β
β β FileSession β β TCP ServerSocket :49152β65535β β
β β fileName β β (one per active session) β β
β β port β β FileSenderHandler (thread) β β
β β pin β βββββββββββββββββββββββββββββββββ β
β β retryCount (max 2) β β
β βββββββββββββββββββββββββ β
β β
β ScheduledExecutorService βββΊ cleanUpSession() @ +60 s β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key design choice: The HTTP server is purely the control plane. Actual file bytes travel over a raw TCP socket on an ephemeral port. The Java backend opens a
Socket("127.0.0.1", port)to its own TCP server and pipes the bytes through the HTTP response and the browser never touches the TCP layer.
User selects / drops a file
β
βΌ
FileUpload.tsx
β
β POST /api/upload (multipart/form-data)
βΌ
Next.js proxy βββββββββββββββββββββββββββΊ Java UploadHandler :8080
β
βββββββββββββΌβββββββββββββ
β Parse multipart body β
β (custom MultiParser) β
βββββββββββββ¬βββββββββββββ
β
βββββββββββββΌβββββββββββββ
β Save to OS temp dir β
β /tmp/echoit-uploads/ β
βββββββββββββ¬βββββββββββββ
β
βββββββββββββΌβββββββββββββ
β FileSharer β
β Β· pick random port β
β (49152β65535) β
β Β· generate 4-digit PINβ
β Β· create FileSession β
βββββββββββββ¬βββββββββββββ
β
ββββββββββββββββ΄βββββββββββββββ
βΌ βΌ
Start TCP ServerSocket Schedule 60 s cleanup
on chosen port (thread) (ScheduledExecutorService)
β
βΌ
Wait for one connection
(ServerSocket.accept())
β
βΌ
JSON { port, pin }
β
βΌ
InviteCode.tsx
Β· Display invite code + PIN
Β· Start 60 s countdown
Β· Copy-to-clipboard buttons
Receiver enters invite code (port) + PIN
β
βΌ
FileDownload.tsx
β
β GET /api/download/:port?pin=XXXX
βΌ
Next.js proxy βββββββββββββββββββββββββββΊ Java DownloadHandler :8080
β
βββββββββββββΌβββββββββββββ
β Parse port from path β
β Parse pin from query β
βββββββββββββ¬βββββββββββββ
β
βββββββββββββΌβββββββββββββ
β FileSharer β
β .validatePin() β
βββββββββββββ¬βββββββββββββ
β
βββββββββββββββββββββββββββββββββββ€
β β
βββββββββββΌβββββββββββ βββββββββββΌβββββββββββββββ
β NOT_FOUND β β WRONG_PIN β
β β 404 β β retryCount-- β
ββββββββββββββββββββββ β β 401 + retriesLeft β
β β
ββββββββββββββββββββββββ€ retryCount == 0? β
β β β terminateSession() β
β β β 403 LOCKED_OUT β
β ββββββββββββββββββββββββββ
β
βββββββββββΌβββββββββββ
β CORRECT β
βββββββββββ¬βββββββββββ
β
β open TCP Socket β 127.0.0.1:<port>
βΌ
FileSenderHandler (Java thread)
Β· write "Filename: <name>\n"
Β· stream file bytes
β
βΌ
DownloadHandler reads TCP stream
Β· parse filename from header line
Β· pipe bytes to HTTP response
Content-Disposition: attachment; filename="<name>"
β
βΌ
Browser saves file to disk
File uploaded
β
βΌ
FileSession created
βββββββββββββββββββββββββββ
β fileName β /tmp/... β
β port β 54321 β
β pin β 7382 β
β retryCount β 2 β
ββββββββββββββ¬βββββββββββββ
β
βββββββββ΄βββββββββββββββββββββββββ
β β
βΌ βΌ
Wrong PIN entered 60 s timer fires
retryCount = 1 ScheduledExecutor
β β
βΌ β
Wrong PIN again β
retryCount = 0 β
β β
βΌ βΌ
terminateSession() ββββββββββ cleanUpSession()
β
βΌ
βββββββββββββββββββββββββββ
β Β· ServerSocket.close() β
β Β· File.delete() β
β Β· Remove from HashMap β
βββββββββββββββββββββββββββ
| Requirement | Version |
|---|---|
| Node.js + npm | 18+ |
| Java JDK | 17+ |
| Maven | 3.6+ |
| Docker + Compose | (optional, for containerised deployment) |
1. git clone https://github.com/manmohak07/echoit.git
2. cd echoit
3. chmod +x vps-setup.sh
4. ./vps-setup.sh The vps-setup.sh script will:
-
Install Java 17, Node.js, Maven, Nginx, and PM2
-
Build both frontend and backend
-
Configure Nginx reverse proxy
-
Start services with PM2
-
Set up auto-restart on boot
1. git clone https://github.com/manmohak07/echoit.git
2. cd echoit
3. mvn clean package
4. java -jar target/echoit-1.0-SNAPSHOT.jar
5. cd ui
6. npm install
7. npm run dev
8. Access the application
9. Frontend: http://localhost:3000
10. Backend: http://localhost:8080docker-compose up --build- Backend on
:8080, frontend on:3000 - The
BACKEND_URLenv var in the compose file routes the Next.js proxy to the backend container automatically.
- Open the Share a File tab.
- Drag & drop a file or click to browse.
- Once the backend responds, you'll see:
- an invite code (the ephemeral port number)
- a 4-digit PIN
- Share both values with your recipient β they need each one to download.
- The session is live for 60 seconds. The file is gone when the timer hits zero.
- Open the Receive a File tab.
- Enter the invite code and the PIN.
- Click Download File β the file arrives in your browser with its original name.
- You get 2 attempts to enter the correct PIN. On the third failure the session is permanently destroyed.
echoit/
βββ src/main/java/echoit/
β βββ App.java β entry point, starts HTTP server on :8080
β βββ controller/
β β βββ FileController.java β HTTP server, UploadHandler, MultiParser, CORS
β β βββ DownloadHandler.java β PIN validation, TCPβHTTP byte bridging
β βββ service/
β β βββ FileSharer.java β session registry, TCP file server, PIN logic
β βββ util/
β βββ FileSession.java β session model (fileName, port, pin, retryCount)
β βββ UploadUtils.java β random port + PIN generators
β
βββ ui/ β Next.js frontend
β βββ src/
β β βββ app/ β App Router pages & global styles
β β βββ components/
β β βββ FileUpload.tsx β drag-and-drop upload zone
β β βββ FileDownload.tsx β invite code + PIN download form
β β βββ InviteCode.tsx β countdown timer, code & PIN display
β βββ next.config.js β API proxy rewrites + BACKEND_URL config
β
βββ Dockerfile.backend
βββ Dockerfile.frontend
βββ docker-compose.yml
βββ start.sh β one-command launcher (Linux/macOS)
βββ start.bat β one-command launcher (Windows)
βββ pom.xml
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, React 18, TypeScript, Tailwind CSS |
| HTTP backend | Java 17, com.sun.net.httpserver.HttpServer |
| File transfer | Raw TCP sockets (java.net.ServerSocket) |
| Build | Maven (backend), npm (frontend) |
| Containerisation | Docker, Docker Compose, Nginx |