Plapper
This was our project for the Distributed Systems module. The task was to build a chat system that works without a central server, supports group channels and file sharing, and can be extended through plugins that load at runtime.
Visual Overview
From the start we committed to full decentralisation, which meant every design decision had to work without a coordinator, a shared clock or any global authority. That's harder than it sounds when you start thinking through the edge cases. What happens when two separate networks merge and their message histories need to be combined? How do you distribute files reliably when any peer might go offline at any point? How do you let people install plugins from the network without just blindly executing foreign code?
We worked through each of these one by one. For message propagation we built a flooding model on top of TCP with a custom protocol, where every message carries a global ID that peers use to drop duplicates. It's not the most bandwidth-efficient approach but it's robust, and for a project at this scale it was the right call. For network partitions we went with a pragmatic merge strategy which meant appending incoming history and deduplicating by message ID rather than trying to reconstruct causal order.
We decided to built the file transfer system similarly to BitTorrent: piece-based, parallel downloads from multiple sources, SHA-256 integrity checks, and any peer that holds a complete file automatically becomes a source.
Plugins load at runtime without restarting the app, and if one peer starts a plugin-based feature the other side doesn't have, an installation offer gets broadcast through the network automatically. Packages are verified for integrity and authenticity before activation, and there's a trust store of allowed signers that acts as the root of trust. For the app we implemented two plugins that can be added: a poll feature and a whiteboard where peers can sketch and write together.