---
title: "Learning Rust the Hard Way"
date: "2025-12-04"
---
# Learning Rust the hard way: reverse engineering a 2000s P2P protocol
Update, September 2026: soulseek-rs has matured a lot since I wrote this. It shares files now, browses other people's collections, resumes dead transfers, and does chat rooms and private messages. There is a TUI, a CLI built for scripts and agents, a daemon mode, and a Homebrew tap. Check it out at re-invention.nl/soulseek-rs.
// soulseek-rs demo
On a flight to Costa Rica, 12 hours offline with my laptop and a folder of Wireshark captures.
After months of staring at hex dumps, something clicked. I finally got file transfers working.
It was an off-by-one bit error.
## What was I even doing?
I wanted to really learn Rust. I needed a challenge after so many years of building systems for the web. I wanted real systems programming, not another tutorial.
So I picked something close to my heart: Soulseek, the underground music sharing network that's been running since the early 2000s, and I've been using it to pirate music for my DJ sets.
// Old Soulseek Windows client
## The rules I set myself:
• No external dependencies (just Rust's standard library)
• Reverse engineer the binary protocol (no peeking at existing implementations)
• No AI assistance - just me, the compiler, and documentation
• Keep going till it works
## The struggle
I got stuck on the protocol for months, testing against the real server instead of a stable simulation, because I didn't want to cheat by peeking at existing implementations.
Many sleepless nights staring at hex dumps, trying to figure out why my downloads wouldn't start transferring.
// tcpdump and hexyl packet analysis
That flight with zero distractions finally broke through what months of fragmented debugging couldn't.
// Rust code for message decoding
## What I ended up building from scratch
My goal was learning Rust the hard way. In my marathon training, I learned you just have to keep running kilometres for your body to adapt to the load. Programming is the same, just start building and actually doing things. Even better if you reinvent the wheel a few times. So instead of using libraries or reference implementations, I went and implemented things you'd normally take off the shelf:
• Binary protocol parsing (managing bits and bytes)
• Async-free networking
• Zlib decompression (following the official RFC)
• Custom logger/log levels & buffering
• Speed-ran through trying and building different concurrency models: naive threads per peer, to thread pools, to a homegrown actor system and making steps to migrate to a reactor event loop (epoll/kqueue)
## The verdict on Rust
The compiler is brutal until you stop fighting it. Once it compiles, it usually works. But productivity-wise? I wouldn't build an information system in it; the kind that captures domain and business logic. Those systems are prone to change and require flexibility. In Rust, once you define an abstraction or structure, it takes work to change it. You become careful upfront because the cost of redesign is high. During this project, I changed my design and abstractions many times. Each time was painful.
I'm nowhere near done. My code is riddled with .clone() calls. The multi-threading is naive. The design doesn't gracefully handle tens of thousands of peer connections yet, and you can't even share files, making it a very incomplete client.
But searching and downloading works, and that's a milestone!
// Hacking in the Costa Rica jungle
Find the project on: https://re-invention.nl/soulseek-rs/ or GitHub
#rust #systemsprogramming #learning #soulseek #rustlang #softwareengineering