diff --git a/aquatic_ws/src/lib/common.rs b/aquatic_ws/src/lib/common.rs index b38d0cd..00e5b28 100644 --- a/aquatic_ws/src/lib/common.rs +++ b/aquatic_ws/src/lib/common.rs @@ -14,7 +14,7 @@ pub struct ValidUntil(pub Instant); pub struct Peer { - pub peer_id: PeerId, + pub peer_id: PeerId, // FIXME: maybe this field can be removed pub complete: bool, pub valid_until: ValidUntil, pub connection_meta: ConnectionMeta, @@ -31,6 +31,17 @@ pub struct TorrentData { } +impl Default for TorrentData { + fn default() -> Self { + Self { + peers: IndexMap::new(), + seeders: 0, + leechers: 0, + } + } +} + + pub type TorrentMap = HashMap; @@ -48,6 +59,7 @@ impl Default for State { } +#[derive(Clone, Copy)] pub struct ConnectionMeta { /// Index of socket worker responsible for this connection. Required for /// sending back response through correct channel to correct worker. diff --git a/aquatic_ws/src/lib/handler.rs b/aquatic_ws/src/lib/handler.rs index 137e866..5100b2a 100644 --- a/aquatic_ws/src/lib/handler.rs +++ b/aquatic_ws/src/lib/handler.rs @@ -86,9 +86,42 @@ pub fn handle_announce_requests( messages_out: &mut Vec<(ConnectionMeta, OutMessage)>, requests: Drain<(ConnectionMeta, AnnounceRequest)>, ){ - // if offers are set, fetch same number of peers, send offers to all of them - // if answer is set, fetch that peer, send answer to it - // finally, return announce response, I think + for (sender_meta, request) in requests { + let torrent_data = torrents.entry(request.info_hash) + .or_default(); + + if let Some(offers) = request.offers { + // if offers are set, fetch same number of peers, send offers to all of them + } + + match (request.answer, request.to_peer_id, request.offer_id){ + (Some(answer), Some(to_peer_id), Some(offer_id)) => { + if let Some(to_peer) = torrent_data.peers.get(&to_peer_id){ + let middleman_answer = MiddlemanAnswerToPeer { + peer_id: request.peer_id, + info_hash: request.info_hash, + answer, + offer_id, + }; + + messages_out.push(( + to_peer.connection_meta, + OutMessage::Answer(middleman_answer) + )); + } + }, + _ => (), + } + + let response = OutMessage::AnnounceResponse(AnnounceResponse { + info_hash: request.info_hash, + complete: torrent_data.seeders, + incomplete: torrent_data.leechers, + announce_interval: 120, + }); + + messages_out.push((sender_meta, response)); + } } diff --git a/aquatic_ws/src/lib/protocol.rs b/aquatic_ws/src/lib/protocol.rs index 3a96a46..9f2b0d9 100644 --- a/aquatic_ws/src/lib/protocol.rs +++ b/aquatic_ws/src/lib/protocol.rs @@ -3,19 +3,19 @@ use serde::{Serialize, Deserialize}; /// FIXME: This is really just string with 20 length -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)] #[serde(transparent)] pub struct PeerId(pub [u8; 20]); /// FIXME: This is really just string with 20 length -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)] #[serde(transparent)] pub struct InfoHash(pub [u8; 20]); /// FIXME: This is really just string with 20 length -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(transparent)] pub struct OfferId(pub [u8; 20]); @@ -107,8 +107,10 @@ pub struct AnnounceRequest { /// I think using Option is good, it seems like this isn't always set /// (same as `offers`) pub answer: Option, - /// Only parsed to hex if answer == true, probably undefined otherwise + /// Likely undefined if !(answer == true) pub to_peer_id: Option, + /// Sent if answer is set + pub offer_id: Option, }