LAN-native messaging and file sharing β zero configuration, single binary, no cloud.
MeshWave is a zero-configuration communication tool for local area networks. It compiles into a single binary that auto-discovers peers on the LAN, serves a browser-based dashboard, and enables real-time chat and file transfer β all without internet, cloud accounts, or external dependencies.
Launch the binary on any machine in the network. Pick Server or Client mode from the browser UI. Multiple servers can coexist; clients discover them automatically via UDP broadcast and switch freely.
- Zero-config discovery β servers announce via UDP broadcast; clients find them instantly
- Real-time chat β named peers exchange messages routed through a central server
- Chunked file transfer β 64 KB chunks with ACK/NACK, automatic retry (3 attempts), pause/resume
- Embedded web dashboard β WhatsApp Web-inspired UI served directly from the binary
- Single binary β no runtime dependencies, no config files, no installation
$ ./meshwave
[10:32:01.204] meshwave: starting on port 5558
[10:32:01.205] meshwave: opening browser to http://localhost:5558
The browser opens to a mode selection screen. Choose Server to host or Client to join. The sidebar shows discovered servers (client) or connected peers (server). Chat messages appear as bubbles; file transfers show real-time progress bars.
| Tool | Version |
|---|---|
| C/C++ compiler | GCC 11+ or Clang 14+ |
| CMake | 3.20 or newer |
| Python 3 | For HTML embedding at build time |
| A modern browser | Chrome, Firefox, Safari, Edge |
git clone https://github.com/mathewthomas/meshwave.git
cd meshwave
mkdir build && cd build
cmake ..
make -j$(nproc)
./meshwaveThe binary opens http://localhost:5558 in your default browser.
| Flag | Description |
|---|---|
| (no flags) | Interactive β browser opens, user picks mode |
--server |
Start directly as server (skip mode selection) |
--client <IP> |
Start as client, connect to server at <IP> |
- Run
./meshwave --serveron Machine A - Run
./meshwaveon Machine B (same LAN) - Machine B's dashboard auto-discovers Machine A in the sidebar
- Click the server name β enter a username β start chatting
MeshWave follows a modular C architecture with a thin C++ layer for HTTP serving:
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Browser ββββββΊβ http.cpp ββββββΊβ client.c β
β (index.html)β HTTPβ REST + SSE βEventβ TCP connect β
ββββββββββββββββ ββββββββββββββββQueueββββββββ¬ββββββββ
β TCP
ββββββββββββββββ ββββββββΌββββββββ
β discovery.c β UDP β server.c β
β broadcast ββββββΊβ accept loop β
ββββββββββββββββ ββββββββ¬ββββββββ
β
ββββββββββββββββ β
β transfer.c βββββββββββββββ
β chunk engine β File I/O
ββββββββββββββββ
| Module | Language | Purpose |
|---|---|---|
protocol.h |
C | Wire format, enums, constants β the shared vocabulary |
discovery.c |
C | UDP broadcast announce (server) and scan (client) |
server.c |
C | TCP accept loop, peer table, message/file routing |
client.c |
C | TCP connection, send/receive, event queue for UI |
transfer.c |
C | Chunked file I/O with ACK/NACK, pause/resume, retry |
http.cpp |
C++ | Embedded HTTP/1.1 server, REST API, SSE streaming |
main.cpp |
C++ | Entry point, argument parsing, thread orchestration |
util.c |
C | Logging (util_log) and time helpers |
For a deeper dive, see docs/ARCHITECTURE.md.
All communication uses a compact binary protocol over TCP with a 7-byte packed header:
ββββββββ¬βββββββ¬ββββββββββββββ
β type β seq β payload_len β
β 1B β 4B β 2B β
ββββββββ΄βββββββ΄ββββββββββββββ
Nine message types cover the full lifecycle:
| Type | Code | Description |
|---|---|---|
MSG_HELLO |
0x01 |
Peer handshake with username |
MSG_CHAT |
0x02 |
Text message to a named peer |
MSG_FILE_META |
0x03 |
File transfer initiation (name, size, chunks) |
MSG_FILE_CHUNK |
0x04 |
64 KB data chunk |
MSG_FILE_ACK |
0x05 |
Chunk received successfully |
MSG_FILE_NACK |
0x06 |
Chunk error β request retransmit |
MSG_PAUSE |
0x07 |
Pause active transfer |
MSG_RESUME |
0x08 |
Resume paused transfer |
MSG_BYE |
0x09 |
Graceful disconnect |
See docs/PROTOCOL.md for the full wire specification.
meshwave/
βββ CMakeLists.txt # Build configuration
βββ README.md # This file
βββ projectdocument.md # Original project specification
βββ docs/
β βββ ARCHITECTURE.md # System design and module details
β βββ BUILDING.md # Detailed build instructions
β βββ PROTOCOL.md # Wire protocol specification
βββ src/
β βββ protocol.h # Shared types and constants
β βββ util.c / util.h # Logging and helpers
β βββ discovery.c / .h # UDP peer discovery
β βββ server.c / .h # TCP server and routing
β βββ client.c / .h # TCP client and event queue
β βββ transfer.c / .h # Chunked file transfer engine
β βββ http.cpp / http.h # Embedded HTTP server
β βββ main.cpp # Entry point
βββ web/
β βββ index.html # Frontend dashboard (embedded at build time)
βββ scripts/
βββ embed_html.py # HTML β C string converter
Total: ~3,300 lines across 17 source files.
The embedded HTTP server exposes these endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Serve the dashboard UI |
GET |
/api/status |
Server/client mode and connection state |
POST |
/api/mode |
Set mode ({"mode":"server"} or {"mode":"client","ip":"..."}) |
GET |
/api/servers |
Discovered servers (client mode) |
POST |
/api/connect |
Connect to a server {"ip":"...","name":"..."} |
GET |
/api/peers |
Connected peers list |
POST |
/api/chat |
Send message {"to":"peer","text":"hello"} |
GET |
/api/events |
SSE stream β real-time chat and file events |
POST |
/api/file/send |
Start file transfer {"path":"/file","to":"peer"} |
POST |
/api/file/pause |
Pause transfer {"id":1} |
POST |
/api/file/resume |
Resume transfer {"id":1} |
GET |
/api/transfers |
Status of all active transfers |
| Port | Protocol | Purpose |
|---|---|---|
| 5556 | UDP | Discovery broadcast |
| 5557 | TCP | Data (chat messages + file chunks) |
| 5558 | TCP | HTTP dashboard |
| Decision | Rationale |
|---|---|
| C for networking core | Direct socket API access, minimal overhead, educational value |
| C++ only for HTTP | String handling and std::thread simplify HTTP parsing |
| No third-party libraries | Self-contained binary; demonstrates socket programming fundamentals |
| Embedded HTML | Single binary deployment; no filesystem dependency at runtime |
| SSE over WebSocket | Simpler implementation; sufficient for serverβclient push |
| 64 KB chunks | Balances throughput with memory use; fits in a single TCP segment |
| Bitmask for chunk tracking | O(1) lookup for received chunks; enables resume from any point |
| Platform | Status | Toolchain |
|---|---|---|
| Linux | β Supported | GCC 11+ |
| macOS | β Supported | Clang 14+ (Xcode) |
| Windows | β Not supported | β |
MeshWave is built on POSIX APIs that are fundamental to Unix systems programming:
- POSIX sockets β
sys/socket.h,arpa/inet.h,netinet/in.h - POSIX threading β
pthread_create,pthread_mutex_t,PTHREAD_MUTEX_INITIALIZER - POSIX I/O β
pwrite(),fcntl(),select()with file descriptors - Network interfaces β
ifaddrs.h,getifaddrs()for local IP detection - Packed structs β
__attribute__((packed))(GCC/Clang extension)
Windows does not provide these headers or APIs natively. A port would require replacing the entire networking and threading layer with Winsock2 (ws2_32), Win32 threads or C11 threads, and MSVC-compatible struct packing (#pragma pack). This is a deliberate design choice β the project serves as a systems programming exercise focused on Unix socket programming fundamentals.
For Windows users, running MeshWave inside WSL2 (Windows Subsystem for Linux) works seamlessly with no code changes.
- Unix/macOS only β requires POSIX APIs; see Platform Support above
- Single subnet only β discovery uses broadcast, which doesn't cross routers
- No encryption β all traffic is plaintext (LAN-only use case)
- No persistent history β messages and transfers exist only during the session
- Sequential chunk ACK β throughput could improve with sliding window ACK
- Browser file API β drag-and-drop passes filename only; full path requires manual input
This section outlines planned and proposed features for future versions of MeshWave, grouped by category.
MeshWave already has the two core primitives a game lobby needs: peer discovery and real-time messaging. The natural extension is a lightweight session-brokering layer on top.
How it would work:
- Servers advertise open game sessions via a new
MSG_GAME_ANNOUNCEmessage type alongside the existing UDP broadcast - Clients see available game sessions in a dedicated lobby panel in the dashboard
- A join handshake (
MSG_GAME_JOIN/MSG_GAME_START) coordinates readiness before the session begins - Game state is exchanged as JSON payloads over the existing TCP channel β no separate game server needed
Games that fit naturally within the current architecture:
| Game | Notes |
|---|---|
| Battleship | Turn-based, low message frequency |
| Tic-Tac-Toe | Minimal state, good proof-of-concept |
| Uno / Card games | State machine maps cleanly to message types |
| Trivia / Quiz | Server acts as quiz master; broadcast to all peers |
No changes to the wire protocol header format are required β new message type codes can be added within the existing type byte.
A persistent, shared clipboard pool visible to all connected peers.
- Any peer can push text snippets, URLs, or small code blocks to the pool via
POST /api/clipboard - All peers receive the new entry via the existing SSE event stream
- Entries are timestamped, tagged with the sender's username, and displayed in a dedicated sidebar panel
- One-click copy to local clipboard from the dashboard
This addresses the common workflow of moving a URL or snippet between machines on the same desk without reaching for a cloud tool.
A pinned message board that survives the ephemeral chat session.
- Peers can post announcements that are pinned to the top of the dashboard for all connected users
- Posts are stored in a local flat file (e.g.,
meshwave_board.json) and loaded on startup - Supports basic formatting: title, body, author, and timestamp
- Complements the existing chat by providing a place for standing information (meeting times, shared credentials, build status)
This directly addresses the no persistent history limitation listed in the current README.
All traffic is currently plaintext, which is acceptable for trusted LANs but limits deployment in shared environments like dorms, open offices, or conference networks.
- Encrypt all TCP payloads with ChaCha20-Poly1305 using a pre-shared key exchanged at connect time via a simple Diffie-Hellman handshake
- Implemented as a single vendored
.cfile with no OpenSSL or external dependency β keeps the single-binary promise intact - Opt-in via a
--encryptflag; unencrypted peers can still connect and are shown asβ οΈ in the dashboard - Adds a new
MSG_KEY_EXCHANGEhandshake type to the protocol
Current UDP broadcast discovery is limited to a single subnet. This is a real constraint on managed networks with multiple VLANs (offices, universities, co-working spaces).
- Replace or supplement UDP broadcast with mDNS (RFC 6762) and DNS-SD (RFC 6763) service records
- Servers register as
_meshwave._tcp.localso any mDNS-capable resolver on the network can find them - Falls back to manual IP entry (already supported via
--client <IP>) when mDNS is unavailable - No router or infrastructure changes required β mDNS is link-local but works across many managed switch configurations
The current sequential chunk ACK model (MSG_FILE_ACK per chunk before sending the next) is the primary throughput bottleneck for file transfers, especially on links with non-trivial round-trip times.
- Implement a sliding window of configurable size (default: 8 outstanding chunks, ~512 KB in flight)
- Sender tracks a window of unacknowledged chunks using the existing bitmask in
transfer.c - On
MSG_FILE_NACK, only the missing chunk is retransmitted β window slides forward for all others - Window size negotiated at
MSG_FILE_METAtime so both sides agree before transfer starts - Backward-compatible: peers that do not advertise window support fall back to sequential ACK
Expected throughput improvement on a typical gigabit LAN: 5β10Γ for large files.
Make the peer list feel like a real communication tool rather than a static list.
- Peers broadcast a heartbeat (
MSG_PING) every 10 seconds; the server marks peers as away after two missed beats and offline after five - Peers can set a status string (Available, Busy, In a meeting, etc.) via
POST /api/status - Status and presence shown as colour-coded indicators in the peer sidebar
- Dashboard updates in real time via the existing SSE stream β no polling required
An ncurses-based or ANSI escape code UI that runs entirely in the terminal, skipping the browser dashboard.
- Enables MeshWave over SSH sessions where opening a browser is impractical
- Split-pane layout: peer list on the left, chat on the right, status bar at the bottom
- File transfer progress displayed as ASCII progress bars
- Activated via a
--tuiflag; the HTTP server is not started in this mode - Fully in the spirit of the single-binary, no-dependencies philosophy
| Feature | Complexity | Impact | Dependencies |
|---|---|---|---|
| Shared Clipboard | Low | High | None |
| Peer Presence & Status | Low | Medium | None |
| Persistent Announcement Board | Low | Medium | Flat file I/O |
| Sliding Window ACK | Medium | High | Protocol version bump |
| LAN Game Lobby | Medium | High | New message types |
| Optional Encryption | High | Medium | Vendored crypto |
| Multi-Subnet Discovery (mDNS) | High | Medium | mDNS library or custom impl |
| Terminal / CLI Mode | High | Medium | ncurses or raw ANSI |
Features are ordered within each tier by estimated implementation effort. All proposed additions preserve the zero-configuration, single-binary, no-cloud design principles of MeshWave.
This is a graduate coursework project. If you'd like to extend it:
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Commit your changes (
git commit -m "feat: add your feature") - Push to the branch (
git push origin feature/your-feature) - Open a pull request
Please follow the existing code style: snake_case functions with module prefixes, PascalCase types, UPPER_SNAKE constants.
This project is released under the MIT License.
Mathew Thomas
Graduate Student β Computer Science
Built as a systems programming project demonstrating socket programming, protocol design, and embedded web serving in C/C++.