This is a starting point for Rust solutions to the "Build Your Own BitTorrent" Challenge.
In this challenge, you’ll build a BitTorrent client that's capable of parsing a .torrent file and downloading a file from a peer. Along the way, we’ll learn about how torrent files are structured, HTTP trackers, BitTorrent’s Peer Protocol, pipelining and more.
Note: If you're viewing this repo on GitHub, head over to codecrafters.io to try the challenge.
The entry point for your BitTorrent implementation is in src/main.rs
. Study
and uncomment the relevant code, and push your changes to pass the first stage:
git commit -am "pass 1st stage" # any msg
git push origin master
Time to move on to the next stage!
Note: This section is for stages 2 and beyond.
- Ensure you have
cargo (1.70)
installed locally - Run
./your_bittorrent.sh
to run your program, which is implemented insrc/main.rs
. This command compiles your Rust project, so it might be slow the first time you run it. Subsequent runs will be fast. - Commit your changes and run
git push origin master
to submit your solution to CodeCrafters. Test output will be streamed to your terminal.
Torrent files and magnet links are supported for downloading a single file.
./your_bittorrent.sh decode <encoded_value>
./your_bittorrent.sh info <path_to_torrent_file>
./your_bittorrent.sh peers <path_to_torrent_file>
./your_bittorrent.sh handshake <path_to_torrent_file> <peer_ip>:<peer_port>
- Peer's IP address and port can be obtained by running the
peers
command and picking any peer from the list.
- Peer's IP address and port can be obtained by running the
./your_bittorrent.sh download_piece -o <path_to_output_file> <path_to_torrent_file> <piece_index>
./your_bittorrent.sh download -o <path_to_output_file> <path_to_torrent_file>
./your_bittorrent.sh magnet_parse "<magnet-link>"
./your_bittorrent.sh magnet_handshake "<magnet-link>"
./your_bittorrent.sh magnet_info "<magnet-link>"
./your_bittorrent.sh magnet_download_piece -o <path_to_output_file> "<magnet-link>" <piece_index>
./your_bittorrent.sh magnet_download -o <path_to_output_file> "<magnet-link>"
We can alternatively run it by cargo run --release
, instead of ./your_bittorrent.sh
.
To enable the provided logging facility, first set the logging level by setting the RUST_LOG
environment variable.
To set it for the entire terminal session, execute export RUST_LOG=debug
, for example, first.
Or, prepend the run command with a desired log level; for example:
RUST_LOG=debug ./your_bittorrent.sh download -o <path_to_output_file> <path_to_torrent_file>
Choose between:
RUST_LOG=[trace | debug | info | warn]
Note: Logging is fully enabled only for the download_piece
and download
commands. Some commands
don't have any log output.
Sample torrent files are provided in the root of the repository, as well as in the test_samples subdirectory.
Note: The sample torrent files can be used for testing the code, and in this case they work, but these are NOT real-world torrent files!
This challenge is NOT production-ready!
First, it only supports single-file torrents, but even they are not fully, i.e., properly supported, so even they don't work.
Secondly, multi-file torrents are not supported at all. This solution has placeholders to support the functionality, but it hasn't been implemented.
We only support compact mode, but that is the recommended mode in practice anyway, so it should be enough.
https://www.bittorrent.org/beps/bep_0023.html
The assignment itself only supports the compact mode.
- Optional application configuration, through the optional config.json file.
- Logging.
- Timing of the whole-file download.
- We check the Bitfield message payload to see whether a peer has the piece that we need.
The challenge doesn't require this as all their peers have all the required pieces during testing, but in real life this is practically required. - We pipeline requests to a single peer for increased download speed.
This was suggested as optional but is practically required because of the test timeout.
This increases the download speed from a single peer significantly. - We also added working with multiple peers at once, on top of pipelining requests to a single peer.
This was also suggested as optional, but not required.
Still, this is something that is required in case of real-life torrents. Namely, we cannot rely on a single peer having all pieces in real life. In the challenge's test suite, they do.
We try to find a peer that has a piece, for every piece.
- Make the application work for real-life single-file torrents.
- Make the application work for real-life multiple-file torrents.
- Send keep-alive messages to connected peers.
- Discover new peers at regular time intervals, but this is not required in the challenge.
- Whenever a piece is successfully downloaded and written to file, store the necessary information (work parameters) in a file that can be used to resume download of the file when the application is restarted, if the file hasn't been downloaded fully.
- The BitTorrent Economics Paper (PDF) has more ideas, but none of them are required in this challenge.