Skip to content

Commit ab4e10c

Browse files
committed
dev: improve announce ip logic test
1 parent 6b5f87b commit ab4e10c

File tree

4 files changed

+72
-15
lines changed

4 files changed

+72
-15
lines changed

src/core/torrent/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub mod repository;
3333
use std::time::Duration;
3434

3535
use aquatic_udp_protocol::AnnounceEvent;
36+
use log::debug;
3637
use serde::{Deserialize, Serialize};
3738

3839
use super::peer::{self, Peer};
@@ -138,6 +139,7 @@ impl Entry {
138139
///
139140
/// It filters out the input peer, typically because we want to return this
140141
/// list of peers to that client peer.
142+
///
141143
#[must_use]
142144
pub fn get_all_peers_for_peer(&self, client: &Peer) -> Vec<&peer::Peer> {
143145
self.peers
@@ -154,6 +156,9 @@ impl Entry {
154156
/// list of peers to that client peer.
155157
#[must_use]
156158
pub fn get_peers_for_peer(&self, client: &Peer, limit: usize) -> Vec<&peer::Peer> {
159+
debug!("In db: {:?}", self.peers);
160+
debug!("client: {client:?}");
161+
157162
self.peers
158163
.values()
159164
// Take peers which are not the client peer

src/servers/http/v1/handlers/announce.rs

+5
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ async fn handle(
7777
See https://github.com/torrust/torrust-tracker/discussions/240.
7878
*/
7979

80+
/* code-review (da2ce7): The IP that is supplied with the announce request is completely dropped
81+
in favour of the IP supplied by the `client_ip_sources`.
82+
Is this intended behavior, is the IP in the client announce request completely untrusted?
83+
*/
84+
8085
async fn handle_announce(
8186
tracker: &Arc<Tracker>,
8287
announce_request: &Announce,

tests/servers/http/asserts.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use reqwest::Response;
44

55
use super::responses::announce::{Announce, Compact, DeserializedCompact};
66
use super::responses::scrape;
7+
use crate::servers::http::responses::announce::DictionaryPeer;
78
use crate::servers::http::responses::error::Error;
89

910
pub fn assert_bencoded_error(response_text: &String, expected_failure_reason: &str, location: &'static Location<'static>) {
@@ -22,10 +23,11 @@ pub fn assert_bencoded_error(response_text: &String, expected_failure_reason: &s
2223
);
2324
}
2425

26+
#[allow(dead_code)]
2527
pub async fn assert_empty_announce_response(response: Response) {
2628
assert_eq!(response.status(), 200);
2729
let announce_response: Announce = serde_bencode::from_str(&response.text().await.unwrap()).unwrap();
28-
assert!(announce_response.peers.is_empty());
30+
assert_eq!(announce_response.peers, Vec::<DictionaryPeer>::new());
2931
}
3032

3133
pub async fn assert_announce_response(response: Response, expected_announce_response: &Announce) {

tests/servers/http/v1/contract.rs

+59-14
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ mod for_all_config_modes {
9696
use crate::common::fixtures::{invalid_info_hashes, PeerBuilder};
9797
use crate::servers::http::asserts::{
9898
assert_announce_response, assert_bad_announce_request_error_response, assert_cannot_parse_query_param_error_response,
99-
assert_cannot_parse_query_params_error_response, assert_compact_announce_response, assert_empty_announce_response,
100-
assert_is_announce_response, assert_missing_query_params_for_announce_request_error_response,
99+
assert_cannot_parse_query_params_error_response, assert_compact_announce_response, assert_is_announce_response,
100+
assert_missing_query_params_for_announce_request_error_response,
101101
};
102102
use crate::servers::http::client::Client;
103103
use crate::servers::http::requests::announce::{Compact, QueryBuilder};
@@ -497,26 +497,71 @@ mod for_all_config_modes {
497497
test_env.stop().await;
498498
}
499499

500+
/// code-review (da2ce7): is this really intended behavior?
500501
#[tokio::test]
501-
async fn should_consider_two_peers_to_be_the_same_when_they_have_the_same_peer_id_even_if_the_ip_is_different() {
502+
async fn it_should_drop_the_client_supplied_ip_and_ignore_peers_with_the_same_ip() {
502503
let test_env = running_test_environment(configuration::ephemeral_mode_public()).await;
503504

504-
let info_hash = InfoHash::from_str("9c38422213e30bff212b30c360d26f9a02136422").unwrap();
505-
let peer = PeerBuilder::default().build();
505+
let announce_policy = test_env.tracker.get_announce_policy();
506506

507-
// Add a peer
508-
test_env.add_torrent_peer(&info_hash, &peer).await;
507+
let info_hash = InfoHash::from([0; 20]);
508+
let id_a = peer::Id(*b"-qB00000000000000000");
509+
let id_b = peer::Id(*b"-qB00000000000000001");
509510

510-
let announce_query = QueryBuilder::default()
511-
.with_info_hash(&info_hash)
512-
.with_peer_id(&peer.peer_id)
513-
.query();
511+
let addr_a = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080);
512+
let addr_b = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 2)), 8080);
513+
let addr_c = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 3)), 8080);
514+
515+
let peer_a = PeerBuilder::default().with_peer_id(&id_a).with_peer_addr(&addr_a).build();
516+
let peer_b = PeerBuilder::default().with_peer_id(&id_b).with_peer_addr(&addr_b).build();
517+
518+
// Add both Peers into DB.
519+
test_env.add_torrent_peer(&info_hash, &peer_a).await;
520+
test_env.add_torrent_peer(&info_hash, &peer_b).await;
521+
522+
// The first query will overwrite the IP of the peer, no matter what ip we use.
523+
{
524+
let announce = QueryBuilder::default()
525+
.with_info_hash(&info_hash)
526+
.with_peer_id(&id_a)
527+
.with_peer_addr(&addr_c.ip()) // different ip, but this is erased.
528+
.query();
529+
530+
let response = Client::new(*test_env.bind_address()).announce(&announce).await;
531+
532+
let response_assert = Announce {
533+
complete: 2,
534+
incomplete: 0,
535+
interval: announce_policy.interval,
536+
min_interval: announce_policy.interval_min,
537+
peers: vec![peer_b.into()], // peer_b still has it's original ip.
538+
};
539+
540+
println!("Query 1");
541+
assert_announce_response(response, &response_assert).await;
542+
}
543+
544+
// The Seconds Query will result with no listed peers, as both peer id's are now
545+
// associated with the same client ip. i.e (0.0.0.0).
546+
{
547+
let announce = QueryBuilder::default()
548+
.with_info_hash(&info_hash)
549+
.with_peer_id(&id_b) // now we use peer b
550+
.query();
514551

515-
assert_ne!(peer.peer_addr.ip(), announce_query.peer_addr);
552+
let response = Client::new(*test_env.bind_address()).announce(&announce).await;
516553

517-
let response = Client::new(*test_env.bind_address()).announce(&announce_query).await;
554+
let response_assert = Announce {
555+
complete: 2,
556+
incomplete: 0,
557+
interval: announce_policy.interval,
558+
min_interval: announce_policy.interval_min,
559+
peers: vec![], // peer_a now has host ip.
560+
};
518561

519-
assert_empty_announce_response(response).await;
562+
println!("Query 2");
563+
assert_announce_response(response, &response_assert).await;
564+
}
520565

521566
test_env.stop().await;
522567
}

0 commit comments

Comments
 (0)