torrent 0.1.6

High-level async BitTorrent library — session management, HTTP/UDP tracker communication, DHT networking, peer connections, and file storage. Built on torrent-core with tokio.
Documentation
//! Perform a real tracker announce and print the peer list.
//!
//! Uses the bundled Ubuntu 26.04 torrent's built-in tracker list.
//! Demonstrates single and multi-tracker announce via the unified [`Tracker`] API.
//!
//! Run with: `cargo run -p torrent --example tracker_announce`

use torrent::metainfo::Metainfo;
use torrent::peer::PeerId;
use torrent::tracker::{AnnounceEvent, AnnounceRequest, Tracker};
use tracing_subscriber::EnvFilter;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    tracing_subscriber::fmt()
        .with_env_filter(EnvFilter::from_default_env())
        .init();

    // Parse the real torrent to get info_hash and tracker URLs
    let data = include_bytes!("data/ubuntu-26.04-live-server-amd64.iso.torrent");
    let meta = Metainfo::try_from(data)?;
    let info_hash = meta.info_hash();

    println!("Torrent:  ubuntu-26.04-live-server-amd64.iso.torrent");
    println!("Info hash: {:02x?}", info_hash);

    // Build an announce request
    let mut req = AnnounceRequest::new(info_hash, PeerId::random(), 6881);
    req.event = AnnounceEvent::Started;

    // --- Tracker from TorrentSpec (collects announce + announce_list URLs) ---
    let Some(tracker) = Tracker::from_torrent(meta) else {
        eprintln!("no valid trackers found in torrent spec");
        return Ok(());
    };
    println!("\n=== Built-in Trackers (Tracker::from_torrent) ===");
    match tracker.announce(&req).await {
        Ok(resp) => print_response(&resp),
        Err(e) => eprintln!("Tracker failed: {}", e),
    }

    Ok(())
}

fn print_response(resp: &torrent::tracker::AnnounceResponse) {
    println!("Interval:     {}s", resp.interval);
    if let Some(min) = resp.min_interval {
        println!("Min interval: {}s", min);
    }
    println!("Seeders:      {}", resp.complete);
    println!("Leechers:     {}", resp.incomplete);
    println!("Peers found:  {}", resp.peers.len());

    if let Some(ref warning) = resp.warning_message {
        println!("Warning:      {}", warning);
    }

    for (i, peer) in resp.peers.iter().take(10).enumerate() {
        println!("  peer {}: {}", i + 1, peer);
    }
    if resp.peers.len() > 10 {
        println!("  ... and {} more", resp.peers.len() - 10);
    }
}