diff --git a/src/main.rs b/src/main.rs index e0f3059..f159718 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,15 @@ // who do you think you are? my mom?! #![allow(uncommon_codepoints)] -use std::{env, fs}; - +use crate::bencode::de::from_bytes; +use crate::torrent::{TrackerResponseFailure, TrackerResponseSuccess}; use anyhow::{anyhow, Result}; use rand::prelude::*; use reqwest::blocking::Client; use reqwest::Url; +use std::net::IpAddr; +use std::str::FromStr; +use std::{env, fs}; use torrent::Torrent; mod bencode; @@ -47,7 +50,6 @@ fn main() -> Result<()> { .append_pair("compact", "1") .append_pair("left", &format!("{torrent_length}")); - let mut query = url.query().unwrap().to_string(); query = format!("{query}&peer_id={}&info_hash={}", urlencoding::encode_binary(&peer_id[..]), @@ -56,12 +58,24 @@ fn main() -> Result<()> { println!("url: {}", url); - let client = Client::new(); - let resp = client.get(url).send()?; - let status = resp.status(); + let clientv4 = Client::builder() + .local_address(IpAddr::from_str("0.0.0.0")?) + .build()?; + let resp = clientv4.get(url).send()?; - let _body = resp.text()?; - println!("Response: {status}"); + let status = resp.status(); + println!("Response status: {status}"); + + let resp_bytes = resp.bytes()?; + + if let Ok(failure) = from_bytes::(&resp_bytes) { + return Err(anyhow!("Tracker responded with failure: {}", failure.failure_reason)) + } + let tracker_response: TrackerResponseSuccess = from_bytes(&resp_bytes)?; + if let Some(ref warning)= tracker_response.warning_message { + println!("Tracker responded with warning: {warning}"); + } + println!("Response: {tracker_response:?}"); Ok(()) } diff --git a/src/torrent.rs b/src/torrent.rs index 20e1326..66534f1 100644 --- a/src/torrent.rs +++ b/src/torrent.rs @@ -94,6 +94,27 @@ impl Torrent { } } +#[derive(Deserialize, Debug)] +pub struct TrackerResponseFailure { + #[serde(rename(serialize = "failure reason", deserialize = "failure reason"))] + pub failure_reason: String, +} + +#[derive(Deserialize, Debug)] +pub struct TrackerResponseSuccess { + #[serde(rename(serialize = "warning message", deserialize = "warning message"))] + pub warning_message: Option, + pub interval: i64, + #[serde(rename(serialize = "min interval", deserialize = "min interval"))] + pub min_interval: Option, + #[serde(rename(serialize = "tracker id", deserialize = "tracker id"))] + pub tracker_id: Option, + pub complete: i64, + pub incomplete: i64, + // TODO deserialize with and split into endpoints + pub peers: ByteBuf, +} + #[cfg(test)] mod tests { use crate::torrent::Torrent;