Skip to content

Commit

Permalink
refactor: [#1270] inline http tracker announce invoke fn
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Feb 17, 2025
1 parent dbee7ad commit 096d503
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 89 deletions.
11 changes: 11 additions & 0 deletions packages/http-protocol/src/v1/requests/announce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ impl fmt::Display for Event {
}
}

impl From<aquatic_udp_protocol::request::AnnounceEvent> for Event {
fn from(value: aquatic_udp_protocol::request::AnnounceEvent) -> Self {
match value {
AnnounceEvent::Started => Self::Started,
AnnounceEvent::Stopped => Self::Stopped,
AnnounceEvent::Completed => Self::Completed,
AnnounceEvent::None => panic!("can't convert announce event from aquatic for None variant"),
}
}
}

/// Whether the `announce` response should be in compact mode or not.
///
/// Depending on the value of this param, the tracker will return a different
Expand Down
184 changes: 95 additions & 89 deletions src/packages/http_tracker_core/services/announce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ use std::sync::Arc;
use bittorrent_http_protocol::v1::requests::announce::{peer_from_request, Announce};
use bittorrent_http_protocol::v1::responses;
use bittorrent_http_protocol::v1::services::peer_ip_resolver::{self, ClientIpSources};
use bittorrent_primitives::info_hash::InfoHash;
use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted};
use bittorrent_tracker_core::authentication::service::AuthenticationService;
use bittorrent_tracker_core::error::AnnounceError;
use bittorrent_tracker_core::whitelist;
use torrust_tracker_configuration::Core;
use torrust_tracker_primitives::core::AnnounceData;
use torrust_tracker_primitives::peer;

use crate::packages::http_tracker_core;

Expand Down Expand Up @@ -69,34 +66,11 @@ pub async fn handle_announce(
None => PeersWanted::AsManyAsPossible,
};

let announce_data = invoke(
announce_handler.clone(),
opt_http_stats_event_sender.clone(),
announce_request.info_hash,
&mut peer,
&peers_wanted,
)
.await
.map_err(responses::error::Error::from)?;

Ok(announce_data)
}

/// # Errors
///
/// This function will return an error if the announce requests failed.
pub async fn invoke(
announce_handler: Arc<AnnounceHandler>,
opt_http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>>,
info_hash: InfoHash,
peer: &mut peer::Peer,
peers_wanted: &PeersWanted,
) -> Result<AnnounceData, AnnounceError> {
let original_peer_ip = peer.peer_addr.ip();

// The tracker could change the original peer ip
let announce_data = announce_handler
.announce(&info_hash, peer, &original_peer_ip, peers_wanted)
.announce(&announce_request.info_hash, &mut peer, &original_peer_ip, &peers_wanted)
.await?;

if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() {
Expand All @@ -123,34 +97,45 @@ mod tests {
use std::sync::Arc;

use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId};
use bittorrent_http_protocol::v1::requests::announce::Announce;
use bittorrent_http_protocol::v1::services::peer_ip_resolver::ClientIpSources;
use bittorrent_tracker_core::announce_handler::AnnounceHandler;
use bittorrent_tracker_core::authentication::key::repository::in_memory::InMemoryKeyRepository;
use bittorrent_tracker_core::authentication::service::AuthenticationService;
use bittorrent_tracker_core::databases::setup::initialize_database;
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository;
use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization;
use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist;
use torrust_tracker_configuration::Core;
use torrust_tracker_configuration::{Configuration, Core};
use torrust_tracker_primitives::peer::Peer;
use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch};
use torrust_tracker_test_helpers::configuration;

struct CoreTrackerServices {
pub core_config: Arc<Core>,
pub announce_handler: Arc<AnnounceHandler>,
pub authentication_service: Arc<AuthenticationService>,
pub whitelist_authorization: Arc<WhitelistAuthorization>,
}

struct CoreHttpTrackerServices {
pub http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>>,
}

fn initialize_core_tracker_services() -> (CoreTrackerServices, CoreHttpTrackerServices) {
let config = configuration::ephemeral_public();
initialize_core_tracker_services_with_config(&configuration::ephemeral_public())
}

fn initialize_core_tracker_services_with_config(config: &Configuration) -> (CoreTrackerServices, CoreHttpTrackerServices) {
let core_config = Arc::new(config.core.clone());
let database = initialize_database(&config.core);
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database));
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());
let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone()));
let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default());
let authentication_service = Arc::new(AuthenticationService::new(&core_config, &in_memory_key_repository));

let announce_handler = Arc::new(AnnounceHandler::new(
&config.core,
Expand All @@ -169,6 +154,8 @@ mod tests {
CoreTrackerServices {
core_config,
announce_handler,
authentication_service,
whitelist_authorization,
},
CoreHttpTrackerServices { http_stats_event_sender },
)
Expand Down Expand Up @@ -199,11 +186,33 @@ mod tests {
}
}

fn sample_announce_request_for_peer(peer: Peer) -> (Announce, ClientIpSources) {
let announce_request = Announce {
info_hash: sample_info_hash(),
peer_id: peer.peer_id,
port: peer.peer_addr.port(),
uploaded: Some(peer.uploaded),
downloaded: Some(peer.downloaded),
left: Some(peer.left),
event: Some(peer.event.into()),
compact: None,
numwant: None,
};

let client_ip_sources = ClientIpSources {
right_most_x_forwarded_for: None,
connection_info_ip: Some(peer.peer_addr.ip()),
};

(announce_request, client_ip_sources)
}

use futures::future::BoxFuture;
use mockall::mock;
use tokio::sync::mpsc::error::SendError;

use crate::packages::http_tracker_core;
use crate::servers::http::test_helpers::tests::sample_info_hash;

mock! {
HttpStatsEventSender {}
Expand All @@ -217,55 +226,37 @@ mod tests {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::sync::Arc;

use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted};
use bittorrent_tracker_core::databases::setup::initialize_database;
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository;
use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization;
use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist;
use mockall::predicate::eq;
use torrust_tracker_configuration::Configuration;
use torrust_tracker_primitives::core::AnnounceData;
use torrust_tracker_primitives::peer;
use torrust_tracker_primitives::swarm_metadata::SwarmMetadata;
use torrust_tracker_test_helpers::configuration;

use super::{sample_peer_using_ipv4, sample_peer_using_ipv6};
use crate::packages::http_tracker_core;
use crate::packages::http_tracker_core::services::announce::invoke;
use crate::packages::http_tracker_core::services::announce::handle_announce;
use crate::packages::http_tracker_core::services::announce::tests::{
initialize_core_tracker_services, sample_peer, MockHttpStatsEventSender,
initialize_core_tracker_services, initialize_core_tracker_services_with_config, sample_announce_request_for_peer,
sample_peer, MockHttpStatsEventSender,
};
use crate::servers::http::test_helpers::tests::sample_info_hash;

fn initialize_announce_handler() -> Arc<AnnounceHandler> {
let config = configuration::ephemeral();

let database = initialize_database(&config.core);
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database));
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());
let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone()));

Arc::new(AnnounceHandler::new(
&config.core,
&whitelist_authorization,
&in_memory_torrent_repository,
&db_torrent_repository,
))
}

#[tokio::test]
async fn it_should_return_the_announce_data() {
let (core_tracker_services, core_http_tracker_services) = initialize_core_tracker_services();

let mut peer = sample_peer();
let peer = sample_peer();

let announce_data = invoke(
core_tracker_services.announce_handler.clone(),
core_http_tracker_services.http_stats_event_sender.clone(),
sample_info_hash(),
&mut peer,
&PeersWanted::AsManyAsPossible,
let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer);

let announce_data = handle_announce(
&core_tracker_services.core_config,
&core_tracker_services.announce_handler,
&core_tracker_services.authentication_service,
&core_tracker_services.whitelist_authorization,
&core_http_tracker_services.http_stats_event_sender,
&announce_request,
&client_ip_sources,
)
.await
.unwrap();
Expand Down Expand Up @@ -294,28 +285,32 @@ mod tests {
let http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>> =
Arc::new(Some(Box::new(http_stats_event_sender_mock)));

let announce_handler = initialize_announce_handler();
let (core_tracker_services, mut core_http_tracker_services) = initialize_core_tracker_services();
core_http_tracker_services.http_stats_event_sender = http_stats_event_sender;

let mut peer = sample_peer_using_ipv4();
let peer = sample_peer_using_ipv4();

let _announce_data = invoke(
announce_handler,
http_stats_event_sender,
sample_info_hash(),
&mut peer,
&PeersWanted::AsManyAsPossible,
let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer);

let _announce_data = handle_announce(
&core_tracker_services.core_config,
&core_tracker_services.announce_handler,
&core_tracker_services.authentication_service,
&core_tracker_services.whitelist_authorization,
&core_http_tracker_services.http_stats_event_sender,
&announce_request,
&client_ip_sources,
)
.await
.unwrap();
}

fn tracker_with_an_ipv6_external_ip() -> Arc<AnnounceHandler> {
fn tracker_with_an_ipv6_external_ip() -> Configuration {
let mut configuration = configuration::ephemeral();
configuration.core.net.external_ip = Some(IpAddr::V6(Ipv6Addr::new(
0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969,
)));

initialize_announce_handler()
configuration
}

fn peer_with_the_ipv4_loopback_ip() -> peer::Peer {
Expand All @@ -340,16 +335,22 @@ mod tests {
let http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>> =
Arc::new(Some(Box::new(http_stats_event_sender_mock)));

let mut peer = peer_with_the_ipv4_loopback_ip();
let (core_tracker_services, mut core_http_tracker_services) =
initialize_core_tracker_services_with_config(&tracker_with_an_ipv6_external_ip());
core_http_tracker_services.http_stats_event_sender = http_stats_event_sender;

let announce_handler = tracker_with_an_ipv6_external_ip();
let peer = peer_with_the_ipv4_loopback_ip();

let _announce_data = invoke(
announce_handler,
http_stats_event_sender,
sample_info_hash(),
&mut peer,
&PeersWanted::AsManyAsPossible,
let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer);

let _announce_data = handle_announce(
&core_tracker_services.core_config,
&core_tracker_services.announce_handler,
&core_tracker_services.authentication_service,
&core_tracker_services.whitelist_authorization,
&core_http_tracker_services.http_stats_event_sender,
&announce_request,
&client_ip_sources,
)
.await
.unwrap();
Expand All @@ -367,16 +368,21 @@ mod tests {
let http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>> =
Arc::new(Some(Box::new(http_stats_event_sender_mock)));

let announce_handler = initialize_announce_handler();
let (core_tracker_services, mut core_http_tracker_services) = initialize_core_tracker_services();
core_http_tracker_services.http_stats_event_sender = http_stats_event_sender;

let mut peer = sample_peer_using_ipv6();
let peer = sample_peer_using_ipv6();

let _announce_data = invoke(
announce_handler,
http_stats_event_sender,
sample_info_hash(),
&mut peer,
&PeersWanted::AsManyAsPossible,
let (announce_request, client_ip_sources) = sample_announce_request_for_peer(peer);

let _announce_data = handle_announce(
&core_tracker_services.core_config,
&core_tracker_services.announce_handler,
&core_tracker_services.authentication_service,
&core_tracker_services.whitelist_authorization,
&core_http_tracker_services.http_stats_event_sender,
&announce_request,
&client_ip_sources,
)
.await
.unwrap();
Expand Down

0 comments on commit 096d503

Please sign in to comment.