read_download_stream broke out of its read loop on peer EOF (Ok(0)) without checking whether the promised number of bytes had actually arrived, then saved the partial buffer and the caller reported DownloadStatus::Completed. A peer that aborts mid-transfer thus produced a truncated file marked complete. The buffer was also never trimmed, so trailing coalesced bytes were written past the file's real size. finalize_download_buffer now errors with IncompleteDownload when fewer bytes than expected arrived (caller maps this to Failed) and trims any overshoot to the exact expected size. The listener's incoming-file path now also marks the download Failed on error rather than only logging, so it can no longer stay stuck Queued/InProgress forever.
Soulseek-rs 🦀
⚠️WARNING THIS IS UNDER DEVELOPMENT AND NOT READY FOR USE ⚠️
Souleek-rs is an experimental Soulseek library and client built in Rust. It's under development and not yet ready for use. Soulseek is a closed-source P2P file-sharing network from the 2000s. It's still used by music enthusiasts around the world to share niche music.
🎥 Demo
Project Goals
This project is a learning exercise to explore Rust. I've been using Soulseek since the early 2000s, so it's close to my heart, and the Soulseek protocol is a closed-source network protocol that provides a great opportunity to learn about asynchronous and concurrent network programming and reverse engineering
It's not intended to be a production-ready client (yet).
Since it's a learning project, I have a self-imposed restriction not to use external dependencies in the library. This means I can't use any external crates that are not part of the Rust standard library. This is a good challenge to learn how to build complex systems with only the standard library.
In the client crate, external dependencies are allowed for building a rich experience. For me, this is a good balance between learning and practicality.
Planned Features
- Search for files
- Download files
- Configure credentials
- TUI for searching and downloading files
- Configure download & upload directories
- Share files
- Browse user(s) files
- Chat in chatrooms
- Private messaging
- Headless mode daemon mode with remote control
Project Structure
This project is organized as a Cargo workspace with two crates:
- soulseek-rs-lib - The core library implementing the Soulseek protocol
- soulseek-rs - A CLI client built on top of the library
This structure allows:
- Other developers to build custom Soulseek clients using
soulseek-rs-lib - Users to install the ready-made client via
cargo install soulseek-rs - Clean separation of concerns between protocol implementation and user interface
Installation
For Users
cargo install soulseek-rs
For Developers
Clone and build from source:
git clone git@github.com:michel/soulseek-rs.git
cd soulseek-rs
cargo build --release
The binary will be available at target/release/soulseek-rs.
For Library Users
To build your own Soulseek client, add to your Cargo.toml:
[dependencies]
soulseek-rs-lib = "0.1.0"
Usage
./target/release/soulseek-rs "the weeknd Blinding Lights"
Development
To run the project in development mode with debug output and trace output:
RUST_LOG=trace cargo run
Development
To run the tests:
cargo test
To run the linter:
cargo clippy
To run the formatter:
cargo fmt
License
This project is licensed under the MIT License — see the LICENSE file for details.
