diff --git a/src/protocol/clock/time_extent.rs b/src/protocol/clock/time_extent.rs index d0713645b..3fa60de82 100644 --- a/src/protocol/clock/time_extent.rs +++ b/src/protocol/clock/time_extent.rs @@ -133,6 +133,7 @@ where } } } + fn now_before(increment: &TimeExtentBase, sub_time: &Duration) -> Option> { match Clock::sub(sub_time) { None => None, diff --git a/src/protocol/utils.rs b/src/protocol/utils.rs index 48fe4eb17..ac20aa41e 100644 --- a/src/protocol/utils.rs +++ b/src/protocol/utils.rs @@ -1,16 +1,4 @@ -use std::net::SocketAddr; - -use aquatic_udp_protocol::ConnectionId; - -use super::clock::{DefaultClock, DurationSinceUnixEpoch, Time}; - -pub fn get_connection_id(remote_address: &SocketAddr) -> ConnectionId { - ConnectionId(((current_time() / 3600) | ((remote_address.port() as u64) << 36)) as i64) -} - -pub fn current_time() -> u64 { - DefaultClock::now().as_secs() -} +use super::clock::DurationSinceUnixEpoch; pub fn ser_unix_time_value(unix_time_value: &DurationSinceUnixEpoch, ser: S) -> Result { ser.serialize_u64(unix_time_value.as_millis() as u64) diff --git a/src/tracker/peer.rs b/src/tracker/peer.rs index 09509e50f..7ac35179a 100644 --- a/src/tracker/peer.rs +++ b/src/tracker/peer.rs @@ -130,8 +130,7 @@ mod test { }; use crate::peer::TorrentPeer; - use crate::protocol::utils::get_connection_id; - + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; // todo: duplicate functions is PR 82. Remove duplication once both PR are merged. fn sample_ipv4_remote_addr() -> SocketAddr { @@ -153,7 +152,7 @@ mod test { let info_hash_aquatic = aquatic_udp_protocol::InfoHash([0u8; 20]); let default_request = AnnounceRequest { - connection_id: get_connection_id(&sample_ipv4_remote_addr()), + connection_id: into_connection_id(&make_connection_cookie(&sample_ipv4_remote_addr())), transaction_id: TransactionId(0i32), info_hash: info_hash_aquatic, peer_id: AquaticPeerId(*b"-qB00000000000000000"), diff --git a/src/udp/connection_cookie.rs b/src/udp/connection_cookie.rs new file mode 100644 index 000000000..a17431b9c --- /dev/null +++ b/src/udp/connection_cookie.rs @@ -0,0 +1,245 @@ +use std::net::SocketAddr; + +use aquatic_udp_protocol::ConnectionId; + +use crate::protocol::clock::time_extent::{Extent, TimeExtent}; +use crate::udp::ServerError; + +pub type Cookie = [u8; 8]; + +pub type SinceUnixEpochTimeExtent = TimeExtent; + +pub const COOKIE_LIFETIME: TimeExtent = TimeExtent::from_sec(2, &60); + +pub fn from_connection_id(connection_id: &ConnectionId) -> Cookie { + connection_id.0.to_le_bytes() +} + +pub fn into_connection_id(connection_cookie: &Cookie) -> ConnectionId { + ConnectionId(i64::from_le_bytes(*connection_cookie)) +} + +pub fn make_connection_cookie(remote_address: &SocketAddr) -> Cookie { + let time_extent = cookie_builder::get_last_time_extent(); + + let cookie = cookie_builder::build(remote_address, &time_extent); + //println!("remote_address: {remote_address:?}, time_extent: {time_extent:?}, cookie: {cookie:?}"); + cookie +} + +pub fn check_connection_cookie( + remote_address: &SocketAddr, + connection_cookie: &Cookie, +) -> Result { + // we loop backwards testing each time_extent until we find one that matches. + // (or the lifetime of time_extents is exhausted) + for offset in 0..=COOKIE_LIFETIME.amount { + let checking_time_extent = cookie_builder::get_last_time_extent().decrease(offset).unwrap(); + + let checking_cookie = cookie_builder::build(remote_address, &checking_time_extent); + //println!("remote_address: {remote_address:?}, time_extent: {checking_time_extent:?}, cookie: {checking_cookie:?}"); + + if *connection_cookie == checking_cookie { + return Ok(checking_time_extent); + } + } + Err(ServerError::InvalidConnectionId) +} + +mod cookie_builder { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + use std::net::SocketAddr; + + use super::{Cookie, SinceUnixEpochTimeExtent, COOKIE_LIFETIME}; + use crate::protocol::clock::time_extent::{DefaultTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent}; + use crate::protocol::crypto::keys::seeds::{DefaultSeed, SeedKeeper}; + + pub(super) fn get_last_time_extent() -> SinceUnixEpochTimeExtent { + DefaultTimeExtentMaker::now(&COOKIE_LIFETIME.increment) + .unwrap() + .unwrap() + .increase(COOKIE_LIFETIME.amount) + .unwrap() + } + + pub(super) fn build(remote_address: &SocketAddr, time_extent: &TimeExtent) -> Cookie { + let seed = DefaultSeed::get_seed(); + + let mut hasher = DefaultHasher::new(); + + remote_address.hash(&mut hasher); + time_extent.hash(&mut hasher); + seed.hash(&mut hasher); + + hasher.finish().to_le_bytes() + } +} + +#[cfg(test)] +mod tests { + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; + + use super::cookie_builder::{self}; + use crate::protocol::clock::time_extent::{self, Extent}; + use crate::protocol::clock::{StoppedClock, StoppedTime}; + use crate::udp::connection_cookie::{check_connection_cookie, make_connection_cookie, Cookie, COOKIE_LIFETIME}; + + // #![feature(const_socketaddr)] + // const REMOTE_ADDRESS_IPV4_ZERO: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + #[test] + fn it_should_make_a_connection_cookie() { + let cookie = make_connection_cookie(&SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)); + + // Note: This constant may need to be updated in the future as the hash is not guaranteed to to be stable between versions. + const ID_COOKIE: Cookie = [23, 204, 198, 29, 48, 180, 62, 19]; + + assert_eq!(cookie, ID_COOKIE) + } + + #[test] + fn it_should_make_the_same_connection_cookie_for_the_same_input_data() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + let time_extent_zero = time_extent::ZERO; + + let cookie = cookie_builder::build(&remote_address, &time_extent_zero); + let cookie_2 = cookie_builder::build(&remote_address, &time_extent_zero); + + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie:?}"); + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie_2:?}"); + + //remote_address: 127.0.0.1:8080, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [212, 9, 204, 223, 176, 190, 150, 153] + //remote_address: 127.0.0.1:8080, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [212, 9, 204, 223, 176, 190, 150, 153] + + assert_eq!(cookie, cookie_2) + } + + #[test] + fn it_should_make_the_different_connection_cookie_for_different_ip() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + let remote_address_2 = SocketAddr::new(IpAddr::V4(Ipv4Addr::BROADCAST), 0); + let time_extent_zero = time_extent::ZERO; + + let cookie = cookie_builder::build(&remote_address, &time_extent_zero); + let cookie_2 = cookie_builder::build(&remote_address_2, &time_extent_zero); + + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie:?}"); + println!("remote_address: {remote_address_2:?}, time_extent: {time_extent_zero:?}, cookie: {cookie_2:?}"); + + //remote_address: 0.0.0.0:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [151, 130, 30, 157, 190, 41, 179, 135] + //remote_address: 255.255.255.255:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [217, 87, 239, 178, 182, 126, 66, 166] + + assert_ne!(cookie, cookie_2) + } + + #[test] + fn it_should_make_the_different_connection_cookie_for_different_ip_version() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + let remote_address_2 = SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0); + let time_extent_zero = time_extent::ZERO; + + let cookie = cookie_builder::build(&remote_address, &time_extent_zero); + let cookie_2 = cookie_builder::build(&remote_address_2, &time_extent_zero); + + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie:?}"); + println!("remote_address: {remote_address_2:?}, time_extent: {time_extent_zero:?}, cookie: {cookie_2:?}"); + + //remote_address: 0.0.0.0:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [151, 130, 30, 157, 190, 41, 179, 135] + //remote_address: [::]:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [99, 119, 230, 177, 20, 220, 163, 187] + + assert_ne!(cookie, cookie_2) + } + + #[test] + fn it_should_make_the_different_connection_cookie_for_different_socket() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + let remote_address_2 = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 1); + let time_extent_zero = time_extent::ZERO; + + let cookie = cookie_builder::build(&remote_address, &time_extent_zero); + let cookie_2 = cookie_builder::build(&remote_address_2, &time_extent_zero); + + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie:?}"); + println!("remote_address: {remote_address_2:?}, time_extent: {time_extent_zero:?}, cookie: {cookie_2:?}"); + + //remote_address: 0.0.0.0:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [151, 130, 30, 157, 190, 41, 179, 135] + //remote_address: 0.0.0.0:1, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [38, 8, 0, 102, 92, 170, 220, 11] + + assert_ne!(cookie, cookie_2) + } + + #[test] + fn it_should_make_the_different_connection_cookie_for_different_time_extents() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + let time_extent_zero = time_extent::ZERO; + let time_extent_max = time_extent::MAX; + + let cookie = cookie_builder::build(&remote_address, &time_extent_zero); + let cookie_2 = cookie_builder::build(&remote_address, &time_extent_max); + + println!("remote_address: {remote_address:?}, time_extent: {time_extent_zero:?}, cookie: {cookie:?}"); + println!("remote_address: {remote_address:?}, time_extent: {time_extent_max:?}, cookie: {cookie_2:?}"); + + //remote_address: 0.0.0.0:0, time_extent: TimeExtent { increment: 0ns, amount: 0 }, cookie: [151, 130, 30, 157, 190, 41, 179, 135] + //remote_address: 0.0.0.0:0, time_extent: TimeExtent { increment: 18446744073709551615.999999999s, amount: 18446744073709551615 }, cookie: [87, 111, 109, 125, 182, 206, 3, 201] + + assert_ne!(cookie, cookie_2) + } + + #[test] + fn it_should_make_different_cookies_for_the_next_time_extent() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + let cookie = make_connection_cookie(&remote_address); + + StoppedClock::local_add(&COOKIE_LIFETIME.increment).unwrap(); + + let cookie_next = make_connection_cookie(&remote_address); + + assert_ne!(cookie, cookie_next) + } + + #[test] + fn it_should_be_valid_for_this_time_extent() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + let cookie = make_connection_cookie(&remote_address); + + check_connection_cookie(&remote_address, &cookie).unwrap(); + } + + #[test] + fn it_should_be_valid_for_the_next_time_extent() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + let cookie = make_connection_cookie(&remote_address); + + StoppedClock::local_add(&COOKIE_LIFETIME.increment).unwrap(); + + check_connection_cookie(&remote_address, &cookie).unwrap(); + } + + #[test] + fn it_should_be_valid_for_the_last_time_extent() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + let cookie = make_connection_cookie(&remote_address); + + StoppedClock::local_set(&COOKIE_LIFETIME.total().unwrap().unwrap()); + + check_connection_cookie(&remote_address, &cookie).unwrap(); + } + + #[test] + #[should_panic] + fn it_should_be_not_valid_after_their_last_time_extent() { + let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); + + let cookie = make_connection_cookie(&remote_address); + + StoppedClock::local_set(&COOKIE_LIFETIME.total_next().unwrap().unwrap()); + + check_connection_cookie(&remote_address, &cookie).unwrap(); + } +} diff --git a/src/udp/handlers.rs b/src/udp/handlers.rs index 5e286b9f7..d46cd9231 100644 --- a/src/udp/handlers.rs +++ b/src/udp/handlers.rs @@ -6,8 +6,8 @@ use aquatic_udp_protocol::{ NumberOfPeers, Port, Request, Response, ResponsePeer, ScrapeRequest, ScrapeResponse, TorrentScrapeStatistics, TransactionId, }; +use super::connection_cookie::{check_connection_cookie, from_connection_id, into_connection_id, make_connection_cookie}; use crate::peer::TorrentPeer; -use crate::protocol::utils::get_connection_id; use crate::tracker::statistics::TrackerStatisticsEvent; use crate::tracker::torrent::TorrentError; use crate::tracker::tracker::TorrentTracker; @@ -69,7 +69,8 @@ pub async fn handle_connect( request: &ConnectRequest, tracker: Arc, ) -> Result { - let connection_id = get_connection_id(&remote_addr); + let connection_cookie = make_connection_cookie(&remote_addr); + let connection_id = into_connection_id(&connection_cookie); let response = Response::from(ConnectResponse { transaction_id: request.transaction_id, @@ -94,6 +95,13 @@ pub async fn handle_announce( announce_request: &AnnounceRequest, tracker: Arc, ) -> Result { + match check_connection_cookie(&remote_addr, &from_connection_id(&announce_request.connection_id)) { + Ok(_) => {} + Err(e) => { + return Err(e); + } + } + let wrapped_announce_request = AnnounceRequestWrapper::new(announce_request.clone()); authenticate(&wrapped_announce_request.info_hash, tracker.clone()).await?; @@ -401,9 +409,9 @@ mod tests { use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, Response, TransactionId}; use super::{default_tracker_config, sample_ipv4_socket_address, sample_ipv6_remote_addr, TrackerStatsServiceMock}; - use crate::protocol::utils::get_connection_id; use crate::statistics::TrackerStatisticsEvent; use crate::tracker::tracker::TorrentTracker; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_connect; use crate::udp::handlers::tests::{initialized_public_tracker, sample_ipv4_remote_addr}; @@ -426,7 +434,7 @@ mod tests { assert_eq!( response, Response::Connect(ConnectResponse { - connection_id: get_connection_id(&sample_ipv4_remote_addr()), + connection_id: into_connection_id(&make_connection_cookie(&sample_ipv4_remote_addr())), transaction_id: request.transaction_id }) ); @@ -445,7 +453,7 @@ mod tests { assert_eq!( response, Response::Connect(ConnectResponse { - connection_id: get_connection_id(&sample_ipv4_remote_addr()), + connection_id: into_connection_id(&make_connection_cookie(&sample_ipv4_remote_addr())), transaction_id: request.transaction_id }) ); @@ -482,10 +490,11 @@ mod tests { use std::net::Ipv4Addr; use aquatic_udp_protocol::{ - AnnounceEvent, AnnounceRequest, NumberOfBytes, NumberOfPeers, PeerId as AquaticPeerId, PeerKey, Port, TransactionId, + AnnounceEvent, AnnounceRequest, ConnectionId, NumberOfBytes, NumberOfPeers, PeerId as AquaticPeerId, PeerKey, Port, + TransactionId, }; - use crate::protocol::utils::get_connection_id; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handlers::tests::sample_ipv4_remote_addr; struct AnnounceRequestBuilder { @@ -499,7 +508,7 @@ mod tests { let info_hash_aquatic = aquatic_udp_protocol::InfoHash([0u8; 20]); let default_request = AnnounceRequest { - connection_id: get_connection_id(&sample_ipv4_remote_addr()), + connection_id: into_connection_id(&make_connection_cookie(&sample_ipv4_remote_addr())), transaction_id: TransactionId(0i32), info_hash: info_hash_aquatic, peer_id: AquaticPeerId([255u8; 20]), @@ -517,6 +526,11 @@ mod tests { } } + pub fn with_connection_id(mut self, connection_id: ConnectionId) -> Self { + self.request.connection_id = connection_id; + self + } + pub fn with_info_hash(mut self, info_hash: aquatic_udp_protocol::InfoHash) -> Self { self.request.info_hash = info_hash; self @@ -554,6 +568,7 @@ mod tests { use crate::statistics::TrackerStatisticsEvent; use crate::tracker::tracker::TorrentTracker; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_announce; use crate::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::udp::handlers::tests::{ @@ -571,14 +586,16 @@ mod tests { let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); + let remote_addr = SocketAddr::new(IpAddr::V4(client_ip), client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(client_ip) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V4(client_ip), client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -593,9 +610,12 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let request = AnnounceRequestBuilder::default().into(); let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) + .into(); + let response = handle_announce(remote_addr, &request, initialized_public_tracker()) .await .unwrap(); @@ -629,14 +649,16 @@ mod tests { let remote_client_port = 8081; let peer_address = Ipv4Addr::new(126, 0, 0, 2); + let remote_addr = SocketAddr::new(IpAddr::V4(remote_client_ip), remote_client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(peer_address) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V4(remote_client_ip), remote_client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -663,8 +685,10 @@ mod tests { } async fn announce_a_new_peer_using_ipv4(tracker: Arc) -> Response { - let request = AnnounceRequestBuilder::default().into(); let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) + .into(); let response = handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); response } @@ -707,6 +731,7 @@ mod tests { use aquatic_udp_protocol::{InfoHash as AquaticInfoHash, PeerId as AquaticPeerId}; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_announce; use crate::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::udp::handlers::tests::{initialized_public_tracker, TorrentPeerBuilder}; @@ -721,14 +746,16 @@ mod tests { let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); + let remote_addr = SocketAddr::new(IpAddr::V4(client_ip), client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(client_ip) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V4(client_ip), client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -758,6 +785,7 @@ mod tests { use crate::statistics::TrackerStatisticsEvent; use crate::tracker::tracker::TorrentTracker; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_announce; use crate::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::udp::handlers::tests::{ @@ -776,14 +804,16 @@ mod tests { let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); + let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(client_ip_v4) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -798,11 +828,15 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let request = AnnounceRequestBuilder::default().into(); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); + let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), 8080); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) + .into(); + let response = handle_announce(remote_addr, &request, initialized_public_tracker()) .await .unwrap(); @@ -836,14 +870,16 @@ mod tests { let remote_client_port = 8081; let peer_address = "126.0.0.1".parse().unwrap(); + let remote_addr = SocketAddr::new(IpAddr::V6(remote_client_ip), remote_client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(peer_address) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V6(remote_client_ip), remote_client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -874,7 +910,9 @@ mod tests { let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); let client_port = 8080; let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), client_port); - let request = AnnounceRequestBuilder::default().into(); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) + .into(); let response = handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); response } @@ -903,13 +941,16 @@ mod tests { tracker_stats_service.should_throw_event(TrackerStatisticsEvent::Udp6Announce); let tracker = Arc::new(TorrentTracker::new(default_tracker_config(), tracker_stats_service).unwrap()); - handle_announce( - sample_ipv6_remote_addr(), - &AnnounceRequestBuilder::default().into(), - tracker.clone(), - ) - .await - .unwrap(); + + let remote_addr = sample_ipv6_remote_addr(); + + let announce_request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) + .into(); + + handle_announce(remote_addr, &announce_request, tracker.clone()) + .await + .unwrap(); } mod from_a_loopback_ip { @@ -920,6 +961,7 @@ mod tests { use crate::statistics::StatsTracker; use crate::tracker::tracker::TorrentTracker; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_announce; use crate::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::udp::handlers::tests::TrackerConfigurationBuilder; @@ -940,14 +982,16 @@ mod tests { let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); + let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), client_port); + let request = AnnounceRequestBuilder::default() + .with_connection_id(into_connection_id(&make_connection_cookie(&remote_addr))) .with_info_hash(info_hash) .with_peer_id(peer_id) .with_ip_address(client_ip_v4) .with_port(client_port) .into(); - let remote_addr = SocketAddr::new(IpAddr::V6(client_ip_v6), client_port); handle_announce(remote_addr, &request, tracker.clone()).await.unwrap(); let peers = tracker.get_all_torrent_peers(&info_hash.0.into()).await; @@ -976,8 +1020,8 @@ mod tests { }; use super::TorrentPeerBuilder; - use crate::protocol::utils::get_connection_id; use crate::tracker::tracker::TorrentTracker; + use crate::udp::connection_cookie::{into_connection_id, make_connection_cookie}; use crate::udp::handle_scrape; use crate::udp::handlers::tests::{initialized_public_tracker, sample_ipv4_remote_addr}; use crate::PeerId; @@ -998,7 +1042,7 @@ mod tests { let info_hashes = vec![info_hash]; let request = ScrapeRequest { - connection_id: get_connection_id(&remote_addr), + connection_id: into_connection_id(&make_connection_cookie(&remote_addr)), transaction_id: TransactionId(0i32), info_hashes, }; @@ -1036,7 +1080,7 @@ mod tests { let info_hashes = vec![*info_hash]; ScrapeRequest { - connection_id: get_connection_id(remote_addr), + connection_id: into_connection_id(&make_connection_cookie(&remote_addr)), transaction_id: TransactionId(0i32), info_hashes, } @@ -1181,7 +1225,7 @@ mod tests { let info_hashes = vec![info_hash]; ScrapeRequest { - connection_id: get_connection_id(remote_addr), + connection_id: into_connection_id(&make_connection_cookie(&remote_addr)), transaction_id: TransactionId(0i32), info_hashes, } diff --git a/src/udp/mod.rs b/src/udp/mod.rs index ae87973f1..4c98875c5 100644 --- a/src/udp/mod.rs +++ b/src/udp/mod.rs @@ -3,6 +3,7 @@ pub use self::handlers::*; pub use self::request::*; pub use self::server::*; +pub mod connection_cookie; pub mod errors; pub mod handlers; pub mod request;