### Rust Torrent Download Example Source: https://github.com/vimpunk/cratetorrent/blob/master/cratetorrent/README.md This example shows how to initialize the CrateTorrent engine, create a torrent from a metainfo file, and listen for download progress and completion alerts. Ensure you have a valid .torrent file and a download directory configured. ```rust use cratetorrent::prelude::*; #[tokio::main] async fn main() -> Result<(), Box> { // spawn the engine with a default config let conf = Conf::new("/tmp/downloads"); let (engine, mut alert_rx) = engine::spawn(conf)?; // parse torrent metainfo and start the download let metainfo = tokio::fs::read("/tmp/imaginary.torrent").await?; let metainfo = Metainfo::from_bytes(&metainfo)?; let torrent_id = engine.create_torrent(TorrentParams { metainfo, // tell the engine to assign a randomly chosen free port listen_addr: None, // here we could specify peers we knew of that we'd want // to connect to mode: Mode::Download { seeds: Vec::new() }, conf: None, })?; // listen to alerts from the engine while let Some(alert) = alert_rx.next().await { match alert { Alert::TorrentStats { id, stats } => { println!("{}: {:#?}", id, stats); } Alert::TorrentComplete(id) => { println!("{} complete, shutting down", id); break; } Alert::Error(e) => { // this is where you'd handle recoverable errors println!("Engine error: {}", e); } _ => (), } } // Don't forget to call shutdown on the engine to gracefully stop all // entities in the engine. This will wait for announcing the client's // leave to all trackers of torrent, finish pending disk and network IO, // as well as wait for peer connections to cleanly shut down. engine.shutdown().await?; Ok(()) } ``` -------------------------------- ### Conceptual Example: Piece to File Mapping Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md Illustrates how a piece (piece 1) maps to multiple files (b, c, d) based on byte offsets within the torrent. This example helps visualize the partitioning logic. ```text -------------------------------------------------------------- |0:0 |1:16 |2:32 | -------------------------------------------------------------- |a:0,8 |b:9,19 |c:20,26 |d:27,36 |e:37,50 | -------------------------------------------------------------- ``` -------------------------------- ### Conceptual Example: Piece Spanning Multiple Files Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md Demonstrates another scenario where a piece (piece 1) intersects with files 'b' and 'c', highlighting how pieces can be split across files with different offset ranges. ```text ------------------------------------------------------- |0:0 |1:16 |2:32 | ------------------------------------------------------- |a:0,15 |b:16,19 |c:20,23 |d:32,44 | ------------------------------------------------------- ``` -------------------------------- ### Add .torrent Suffix to Start Seeding Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Renames the torrent metainfo file by adding the .torrent suffix. This action triggers the Transmission daemon to automatically begin seeding the associated torrent. ```bash mv transmission/watch/1mb-test.txt{,.torrent} ``` -------------------------------- ### Piece Write Workflow Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md Outlines the steps involved in writing a complete piece to disk, including hashing, iovec allocation, and file boundary management. ```text 1. Create in-progress piece entry and map files. 2. Buffer downloaded blocks. 3. Remove piece entry, spawn blocking task for hashing and write. 4. Hash piece; alert on failure. 5. Allocate iovecs for blocks. 6. Create and adjust iovec slice for writes. 7. For each file the piece spans: 8. Get file slice for writing. 9. Bound iovecs by file slice length, reallocate if necessary. 10. Write to file. 11. Trim iovec slice by bytes written. 12. Repeat steps 10-11 if not all bytes were written. ``` -------------------------------- ### Build CrateTorrent CLI and Docker Image Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Build the cratetorrent-cli binary and its corresponding Docker image. This is a prerequisite for running tests. ```bash (cd cli && cargo build --release && docker build --tag cratetorrent-test-cli .) ``` -------------------------------- ### Generate Documentation with Private Items Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md This command generates inline documentation for all items, including private ones, for the cratetorrent workspace, excluding the CLI binary. It then opens the documentation in a web browser. ```bash cargo doc --document-private-items --workspace --exclude cratetorrent-cli --open ``` -------------------------------- ### Run CrateTorrent CLI for Downloads Source: https://github.com/vimpunk/cratetorrent/blob/master/cratetorrent/README.md Execute the CrateTorrent CLI to download torrents. This command requires specifying seed addresses, the metainfo file path, and the download directory. Ensure you are running this from the repository root. ```bash cargo run --release -p cratetorrent-cli -- \ --seeds 192.168.0.10:50051,192.168.0.172:49985 \ --metainfo path/to/mytorrent.torrent \ --download-dir ~/Downloads ``` -------------------------------- ### Successful CrateTorrent Integration Test Output Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md This log output represents a successful integration test run for CrateTorrent. It shows the sequence of events from torrent download completion to disk I/O operations and validation, concluding with a confirmation that the downloaded file matches the source. ```log [2020-07-19T11:59:22Z INFO cratetorrent::torrent] Finished torrent download, exiting [2020-07-19T11:59:22Z TRACE cratetorrent::storage_info] Returning files intersecting piece 31 [2020-07-19T11:59:22Z TRACE cratetorrent::disk] Shutting down disk IO task [2020-07-19T11:59:22Z DEBUG cratetorrent::disk::io] Piece 31 intersects files: 0..1 [2020-07-19T11:59:22Z INFO cratetorrent::peer] Shutting down peer 172.17.0.2:51413 session [2020-07-19T11:59:22Z DEBUG cratetorrent::disk::io] Disk received command [2020-07-19T11:59:22Z TRACE cratetorrent::disk::io] Saving torrent 0 block BlockInfo { piece_index: 31, offset: 16384, len: 16384 } to disk [2020-07-19T11:59:22Z TRACE cratetorrent::disk::io] Saving block BlockInfo { piece_index: 31, offset: 16384, len: 16384 } to disk [2020-07-19T11:59:22Z DEBUG cratetorrent::disk::io] Piece hash: 8048e7746ba19b1e52ea6396bfcc8d5240b021f3 [2020-07-19T11:59:22Z INFO cratetorrent::disk::io] Piece 31 is valid [2020-07-19T11:59:22Z DEBUG cratetorrent::disk::io] Disk received command [2020-07-19T11:59:22Z INFO cratetorrent::disk::io] Shutting down disk event loop real 0m14,614s user 0m0,036s sys 0m0,029s Comparing downloaded file /tmp/cratetorrent/1mb-test.txt to source file ~/code/cratetorrent/tests/assets/1mb-test.txt SUCCESS: downloaded file matches source file ``` -------------------------------- ### Create Torrent Metainfo File Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Generates a torrent metainfo file for the test file using the transmission-create command. The .torrent suffix is omitted initially to manage file permissions before the Transmission daemon picks it up. ```bash transmission-create -o /watch/1mb-test.txt /downloads/complete/1mb-test.txt ``` -------------------------------- ### Create Symbolic Link for Test File Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Creates a symbolic link to the test file within the assets directory. This is a convenience for the test runner, avoiding hardcoding paths to the Transmission directory structure. ```bash ln -s transmission/downloads/complete/1mb-test.txt 1mb-test.txt ``` -------------------------------- ### Generate 1MB Test File Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Creates a 1MB test file filled with random characters. This is useful for testing torrent creation and seeding functionalities. ```bash truncate -s 1M 1mb-test.txt ``` ```bash head -c 1048576 < /dev/urandom > 1mb-test.txt ``` -------------------------------- ### Handling Blocks Spanning Multiple Files Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md Illustrates the scenario where a block spans across two files, requiring careful handling of iovecs to avoid writing beyond file boundaries. ```text ------------------ | file1 | file 2 | --------.--------- | block . | --------.--------- ^ file boundary ``` -------------------------------- ### Calculate Optimal Request Queue Size Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md Formula to calculate the optimal number of outstanding block requests (Q) based on download rate (B) and link latency (D). Assumes a standard block size of 16 KiB and a latency of 1 second. ```text Q = B * D / 16 KiB ``` -------------------------------- ### Vectored IO System Call Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md The `pwritev` syscall is used for concrete IO operations, allowing writes to a specified file position without a separate seek syscall. ```rust use nix::sys::uio::pwritev; use std::os::unix::io::RawFd; // Example usage (simplified): pwritev(fd, &iov, offset) ``` -------------------------------- ### Move Test File to Transmission Downloads Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Moves the generated test file into the Transmission container's downloads directory. This makes the file accessible to the Transmission daemon for torrent creation. ```bash mv 1mb-test.txt transmission/downloads/complete ``` -------------------------------- ### Spawn Transmission Docker Container Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Launches a Transmission Docker container, mapping ports and mounting volumes for downloads, watch, and config directories. Ensure the PUID and PGID environment variables are set to your user's ID. ```bash docker run --rm \ --name transmission \ -p 9091:9091 \ -e PUID=$UID \ -e PGID=$UID \ --mount type=bind,src=$(pwd)/transmission/downloads,dst=/downloads \ --mount type=bind,src=$(pwd)/transmission/watch,dst=/watch \ --mount type=bind,src=$(pwd)/transmission/config,dst=/config \ linuxserver/transmission ``` -------------------------------- ### Handle Block Write Command in Disk Task Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md This code snippet shows how the disk task processes a BlockWrite command. It uses the `?` operator for error propagation, assuming `write_block` returns a `Result` type. Non-fatal errors are handled via alert channels, while fatal errors (like channel failure) will abort the loop. ```rust while let Some(cmd) = self.cmd_rx.recv().await { match cmd { Command::BlockWrite(block) => { self.write_block(block)?; } } } ``` -------------------------------- ### Restoring Trimmed IOVEC Data Source: https://github.com/vimpunk/cratetorrent/blob/master/DESIGN.md An alternative approach to managing trimmed iovecs, where metadata about the trimmed portion is kept and restored after IO. ```cpp #include "file.h" // ... inside tide's file.cpp ... // L403: Restore trimmed part of iovec ``` -------------------------------- ### Have Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The have message is sent when a peer announces that it has downloaded a new piece, provided the piece's hash verification was successful. ```plaintext <4: len=5> <1: id=6> <4: piece index> ``` -------------------------------- ### BitTorrent Request Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md Sent by a downloader to request a specific chunk of a file piece from a peer. Assumes a standard block length of 16 KiB. ```plaintext <4: len=13> <1: id=6> <4: piece index> <4: offset> <4: length=16384> ``` -------------------------------- ### BitTorrent Piece (Block) Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md Sent in response to a request message, containing the actual data block. The term 'block' is used for messages, while 'piece' refers to file segments. ```plaintext <4: len=9+X> <1: id=7> <4: piece index> <4: offset> ``` -------------------------------- ### Handshake Message Format Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md Defines the structure of the initial handshake message, including protocol length, protocol string, reserved bytes, info hash, and peer ID. Used for the very first message exchange. ```text <1: prot len=19> <19: prot="BitTorrent protocol"> <8: reserved> <20: info hash> <20: peer id> ``` -------------------------------- ### Change Torrent File Ownership Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Changes the ownership of the generated torrent file to match the user and group ID provided to the Transmission container. This resolves potential permission denied errors. ```bash sudo chown $USER:$USER transmission/watch/1mb-test.txt ``` -------------------------------- ### Access Transmission Container Shell Source: https://github.com/vimpunk/cratetorrent/blob/master/tests/README.md Opens an interactive bash shell session inside the running Transmission Docker container. This allows for executing commands within the container's environment. ```bash docker exec -ti transmission bash ``` -------------------------------- ### Unchoke Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The unchoke message signals that a peer may download pieces. This message is not currently used as seeding functionality is not implemented. ```plaintext <4: len=1> <1: id=1> ``` -------------------------------- ### Interested Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The interested message informs a peer that we are interested in the pieces it has available. ```plaintext <4: len=1> <1: id=2> ``` -------------------------------- ### BitTorrent Cancel Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md Used to cancel an outstanding download request, typically in 'endgame mode' to optimize the retrieval of the final pieces of a download. ```plaintext <4: len=13> <1: id=8> <4: piece index> <4: offset> <4: length=16384> ``` -------------------------------- ### Bitfield Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The bitfield message indicates which pieces of the torrent a peer has. It's sent after the handshake and its payload is a bitfield where each bit represents a piece. Byte 0 corresponds to indices 0-7, byte 1 to indices 8-15, and so on. If a peer has no pieces, this message is not sent. ```plaintext <4: len=1+X> <1: id=5> ``` -------------------------------- ### Choke Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The choke message signals that a peer may not download any pieces. This message is not currently used as seeding functionality is not implemented. ```plaintext <4: len=1> <1: id=0> ``` -------------------------------- ### Not Interested Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The not interested message informs a peer that we are not interested in its available pieces because we already possess them. ```plaintext <4: len=1> <1: id=3> ``` -------------------------------- ### Keep Alive Message Structure Source: https://github.com/vimpunk/cratetorrent/blob/master/PEER_MESSAGES.md The keep alive message has a length of 0 and no ID. ```plaintext <4: len=0> ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.