use std::time::Duration;
use anyhow::Context;
use librqbit_core::magnet::Magnet;
use librqbit_dht::DhtBuilder;
use tokio_stream::StreamExt;
use tracing::info;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let magnet = std::env::args()
.nth(1)
.expect("first argument should be a magnet link");
let magnet = Magnet::parse(&magnet).unwrap();
let info_hash = magnet
.as_id20()
.context("Supplied magnet link didn't contain a BTv1 infohash")?;
tracing_subscriber::fmt::init();
let dht = DhtBuilder::new().await.context("error initializing DHT")?;
let mut stream = dht.get_peers(info_hash, None);
let stats_printer = async {
loop {
tokio::time::sleep(Duration::from_secs(5)).await;
info!("DHT stats: {:?}", dht.stats());
}
#[allow(unreachable_code)]
Ok::<_, anyhow::Error>(())
};
let routing_table_dumper = async {
loop {
tokio::time::sleep(Duration::from_secs(15)).await;
dht.with_routing_table(|r| {
let filename = "/tmp/routing-table.json";
let mut f = std::fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(filename)
.unwrap();
serde_json::to_writer_pretty(&mut f, r).unwrap();
info!("Dumped DHT routing table to {}", filename);
});
}
#[allow(unreachable_code)]
Ok::<_, anyhow::Error>(())
};
let peer_printer = async {
while let Some(peer) = stream.next().await {
info!("peer found: {}", peer)
}
Ok(())
};
let res = tokio::select! {
res = stats_printer => res,
res = peer_printer => res,
res = routing_table_dumper => res,
};
res
}