Skip to content

Commit 91525af

Browse files
committed
refactor: [torrust#1275] move authentication in udp tracker to core
1 parent 4fd79b7 commit 91525af

File tree

10 files changed

+160
-76
lines changed

10 files changed

+160
-76
lines changed

src/packages/udp_tracker_core/connection_cookie.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ use zerocopy::AsBytes;
8686
use crate::shared::crypto::keys::CipherArrayBlowfish;
8787

8888
/// Error returned when there was an error with the connection cookie.
89-
#[derive(Error, Debug)]
89+
#[derive(Error, Debug, Clone)]
9090
pub enum ConnectionCookieError {
9191
#[error("cookie value is not normal: {not_normal_value}")]
9292
ValueNotNormal { not_normal_value: f64 },
@@ -123,6 +123,8 @@ pub fn make(fingerprint: u64, issue_at: f64) -> Result<Cookie, ConnectionCookieE
123123
Ok(zerocopy::FromBytes::read_from(cookie.as_slice()).expect("it should be the same size"))
124124
}
125125

126+
use std::hash::{DefaultHasher, Hash, Hasher};
127+
use std::net::SocketAddr;
126128
use std::ops::Range;
127129

128130
/// Checks if the supplied `connection_cookie` is valid.
@@ -166,6 +168,13 @@ pub fn check(cookie: &Cookie, fingerprint: u64, valid_range: Range<f64>) -> Resu
166168
Ok(issue_time)
167169
}
168170

171+
#[must_use]
172+
pub(crate) fn gen_remote_fingerprint(remote_addr: &SocketAddr) -> u64 {
173+
let mut state = DefaultHasher::new();
174+
remote_addr.hash(&mut state);
175+
state.finish()
176+
}
177+
169178
mod cookie_builder {
170179
use cipher::{BlockDecrypt, BlockEncrypt};
171180
use tracing::instrument;

src/packages/udp_tracker_core/services/announce.rs

+50-2
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,57 @@
88
//! It also sends an [`udp_tracker_core::statistics::event::Event`]
99
//! because events are specific for the HTTP tracker.
1010
use std::net::{IpAddr, SocketAddr};
11+
use std::ops::Range;
1112
use std::sync::Arc;
1213

1314
use aquatic_udp_protocol::AnnounceRequest;
1415
use bittorrent_primitives::info_hash::InfoHash;
1516
use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted};
16-
use bittorrent_tracker_core::error::AnnounceError;
17+
use bittorrent_tracker_core::error::{AnnounceError, WhitelistError};
1718
use bittorrent_tracker_core::whitelist;
1819
use bittorrent_udp_protocol::peer_builder;
1920
use torrust_tracker_primitives::core::AnnounceData;
2021
use torrust_tracker_primitives::peer;
2122

23+
use crate::packages::udp_tracker_core::connection_cookie::{check, gen_remote_fingerprint, ConnectionCookieError};
2224
use crate::packages::udp_tracker_core::{self};
2325

26+
/// Errors related to announce requests.
27+
#[derive(thiserror::Error, Debug, Clone)]
28+
pub enum UdpAnnounceError {
29+
/// Error returned when there was an error with the connection cookie.
30+
#[error("Connection cookie error: {source}")]
31+
ConnectionCookieError { source: ConnectionCookieError },
32+
33+
/// Error returned when there was an error with the tracker core announce handler.
34+
#[error("Tracker core announce error: {source}")]
35+
TrackerCoreAnnounceError { source: AnnounceError },
36+
37+
/// Error returned when there was an error with the tracker core whitelist.
38+
#[error("Tracker core whitelist error: {source}")]
39+
TrackerCoreWhitelistError { source: WhitelistError },
40+
}
41+
42+
impl From<ConnectionCookieError> for UdpAnnounceError {
43+
fn from(connection_cookie_error: ConnectionCookieError) -> Self {
44+
Self::ConnectionCookieError {
45+
source: connection_cookie_error,
46+
}
47+
}
48+
}
49+
50+
impl From<AnnounceError> for UdpAnnounceError {
51+
fn from(announce_error: AnnounceError) -> Self {
52+
Self::TrackerCoreAnnounceError { source: announce_error }
53+
}
54+
}
55+
56+
impl From<WhitelistError> for UdpAnnounceError {
57+
fn from(whitelist_error: WhitelistError) -> Self {
58+
Self::TrackerCoreWhitelistError { source: whitelist_error }
59+
}
60+
}
61+
2462
/// It handles the `Announce` request.
2563
///
2664
/// # Errors
@@ -36,7 +74,17 @@ pub async fn handle_announce(
3674
announce_handler: &Arc<AnnounceHandler>,
3775
whitelist_authorization: &Arc<whitelist::authorization::WhitelistAuthorization>,
3876
opt_udp_stats_event_sender: &Arc<Option<Box<dyn udp_tracker_core::statistics::event::sender::Sender>>>,
39-
) -> Result<AnnounceData, AnnounceError> {
77+
cookie_valid_range: Range<f64>,
78+
) -> Result<AnnounceData, UdpAnnounceError> {
79+
// todo: return a UDP response like the HTTP tracker instead of raw AnnounceData.
80+
81+
// Authentication
82+
check(
83+
&request.connection_id,
84+
gen_remote_fingerprint(&remote_addr),
85+
cookie_valid_range,
86+
)?;
87+
4088
let info_hash = request.info_hash.into();
4189
let remote_client_ip = remote_addr.ip();
4290

src/packages/udp_tracker_core/services/scrape.rs

+49-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,53 @@
88
//! It also sends an [`udp_tracker_core::statistics::event::Event`]
99
//! because events are specific for the UDP tracker.
1010
use std::net::SocketAddr;
11+
use std::ops::Range;
1112
use std::sync::Arc;
1213

1314
use aquatic_udp_protocol::ScrapeRequest;
1415
use bittorrent_primitives::info_hash::InfoHash;
15-
use bittorrent_tracker_core::error::ScrapeError;
16+
use bittorrent_tracker_core::error::{ScrapeError, WhitelistError};
1617
use bittorrent_tracker_core::scrape_handler::ScrapeHandler;
1718
use torrust_tracker_primitives::core::ScrapeData;
1819

1920
use crate::packages::udp_tracker_core;
21+
use crate::packages::udp_tracker_core::connection_cookie::{check, gen_remote_fingerprint, ConnectionCookieError};
22+
23+
/// Errors related to scrape requests.
24+
#[derive(thiserror::Error, Debug, Clone)]
25+
pub enum UdpScrapeError {
26+
/// Error returned when there was an error with the connection cookie.
27+
#[error("Connection cookie error: {source}")]
28+
ConnectionCookieError { source: ConnectionCookieError },
29+
30+
/// Error returned when there was an error with the tracker core scrape handler.
31+
#[error("Tracker core scrape error: {source}")]
32+
TrackerCoreScrapeError { source: ScrapeError },
33+
34+
/// Error returned when there was an error with the tracker core whitelist.
35+
#[error("Tracker core whitelist error: {source}")]
36+
TrackerCoreWhitelistError { source: WhitelistError },
37+
}
38+
39+
impl From<ConnectionCookieError> for UdpScrapeError {
40+
fn from(connection_cookie_error: ConnectionCookieError) -> Self {
41+
Self::ConnectionCookieError {
42+
source: connection_cookie_error,
43+
}
44+
}
45+
}
46+
47+
impl From<ScrapeError> for UdpScrapeError {
48+
fn from(scrape_error: ScrapeError) -> Self {
49+
Self::TrackerCoreScrapeError { source: scrape_error }
50+
}
51+
}
52+
53+
impl From<WhitelistError> for UdpScrapeError {
54+
fn from(whitelist_error: WhitelistError) -> Self {
55+
Self::TrackerCoreWhitelistError { source: whitelist_error }
56+
}
57+
}
2058

2159
/// It handles the `Scrape` request.
2260
///
@@ -28,7 +66,16 @@ pub async fn handle_scrape(
2866
request: &ScrapeRequest,
2967
scrape_handler: &Arc<ScrapeHandler>,
3068
opt_udp_stats_event_sender: &Arc<Option<Box<dyn udp_tracker_core::statistics::event::sender::Sender>>>,
31-
) -> Result<ScrapeData, ScrapeError> {
69+
cookie_valid_range: Range<f64>,
70+
) -> Result<ScrapeData, UdpScrapeError> {
71+
// todo: return a UDP response like the HTTP tracker instead of raw ScrapeData.
72+
73+
check(
74+
&request.connection_id,
75+
gen_remote_fingerprint(&remote_addr),
76+
cookie_valid_range,
77+
)?;
78+
3279
// Convert from aquatic infohashes
3380
let info_hashes: Vec<InfoHash> = request.info_hashes.iter().map(|&x| x.into()).collect();
3481

src/servers/udp/error.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use derive_more::derive::Display;
66
use thiserror::Error;
77
use torrust_tracker_located_error::LocatedError;
88

9-
use crate::packages::udp_tracker_core::connection_cookie::ConnectionCookieError;
9+
use crate::packages::udp_tracker_core::services::announce::UdpAnnounceError;
10+
use crate::packages::udp_tracker_core::services::scrape::UdpScrapeError;
1011

1112
#[derive(Display, Debug)]
1213
#[display(":?")]
@@ -15,18 +16,17 @@ pub struct ConnectionCookie(pub ConnectionId);
1516
/// Error returned by the UDP server.
1617
#[derive(Error, Debug)]
1718
pub enum Error {
18-
/// Error returned when there was an error with the connection cookie.
19-
#[error("Connection cookie error: {source}")]
20-
ConnectionCookieError { source: ConnectionCookieError },
21-
19+
/// Error returned when the request is invalid.
2220
#[error("error when phrasing request: {request_parse_error:?}")]
2321
RequestParseError { request_parse_error: RequestParseError },
2422

25-
/// Error returned when the domain tracker returns an error.
26-
#[error("tracker server error: {source}")]
27-
TrackerError {
28-
source: LocatedError<'static, dyn std::error::Error + Send + Sync>,
29-
},
23+
/// Error returned when the domain tracker returns an announce error.
24+
#[error("tracker announce error: {source}")]
25+
UdpAnnounceError { source: UdpAnnounceError },
26+
27+
/// Error returned when the domain tracker returns an scrape error.
28+
#[error("tracker scrape error: {source}")]
29+
UdpScrapeError { source: UdpScrapeError },
3030

3131
/// Error returned from a third-party library (`aquatic_udp_protocol`).
3232
#[error("internal server error: {message}, {location}")]
@@ -52,10 +52,18 @@ impl From<RequestParseError> for Error {
5252
}
5353
}
5454

55-
impl From<ConnectionCookieError> for Error {
56-
fn from(connection_cookie_error: ConnectionCookieError) -> Self {
57-
Self::ConnectionCookieError {
58-
source: connection_cookie_error,
55+
impl From<UdpAnnounceError> for Error {
56+
fn from(udp_announce_error: UdpAnnounceError) -> Self {
57+
Self::UdpAnnounceError {
58+
source: udp_announce_error,
59+
}
60+
}
61+
}
62+
63+
impl From<UdpScrapeError> for Error {
64+
fn from(udp_scrape_error: UdpScrapeError) -> Self {
65+
Self::UdpScrapeError {
66+
source: udp_scrape_error,
5967
}
6068
}
6169
}

src/servers/udp/handlers/announce.rs

+10-23
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ use torrust_tracker_configuration::Core;
1414
use tracing::{instrument, Level};
1515
use zerocopy::network_endian::I32;
1616

17-
use crate::packages::udp_tracker_core::connection_cookie::check;
1817
use crate::packages::udp_tracker_core::{self};
1918
use crate::servers::udp::error::Error;
20-
use crate::servers::udp::handlers::gen_remote_fingerprint;
2119

2220
/// It handles the `Announce` request. Refer to [`Announce`](crate::servers::udp#announce)
2321
/// request for more information.
@@ -43,27 +41,16 @@ pub async fn handle_announce(
4341

4442
tracing::trace!("handle announce");
4543

46-
// todo: move authentication to `udp_tracker_core::services::announce::handle_announce`
47-
48-
check(
49-
&request.connection_id,
50-
gen_remote_fingerprint(&remote_addr),
51-
cookie_valid_range,
52-
)
53-
.map_err(|e| (e.into(), request.transaction_id))?;
54-
5544
let response = udp_tracker_core::services::announce::handle_announce(
5645
remote_addr,
5746
request,
5847
announce_handler,
5948
whitelist_authorization,
6049
opt_udp_stats_event_sender,
50+
cookie_valid_range,
6151
)
6252
.await
63-
.map_err(|e| Error::TrackerError {
64-
source: (Arc::new(e) as Arc<dyn std::error::Error + Send + Sync>).into(),
65-
})
66-
.map_err(|e| (e, request.transaction_id))?;
53+
.map_err(|e| (e.into(), request.transaction_id))?;
6754

6855
// todo: extract `build_response` function.
6956

@@ -213,15 +200,15 @@ mod tests {
213200
use mockall::predicate::eq;
214201
use torrust_tracker_configuration::Core;
215202

216-
use crate::packages::udp_tracker_core::connection_cookie::make;
203+
use crate::packages::udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make};
217204
use crate::packages::{self, udp_tracker_core};
218205
use crate::servers::udp::handlers::announce::tests::announce_request::AnnounceRequestBuilder;
206+
use crate::servers::udp::handlers::handle_announce;
219207
use crate::servers::udp::handlers::tests::{
220208
initialize_core_tracker_services_for_default_tracker_configuration,
221209
initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv4_socket_address,
222210
sample_issue_time, MockUdpStatsEventSender, TorrentPeerBuilder,
223211
};
224-
use crate::servers::udp::handlers::{gen_remote_fingerprint, handle_announce};
225212

226213
#[tokio::test]
227214
async fn an_announced_peer_should_be_added_to_the_tracker() {
@@ -447,13 +434,13 @@ mod tests {
447434

448435
use aquatic_udp_protocol::{InfoHash as AquaticInfoHash, PeerId as AquaticPeerId};
449436

450-
use crate::packages::udp_tracker_core::connection_cookie::make;
437+
use crate::packages::udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make};
451438
use crate::servers::udp::handlers::announce::tests::announce_request::AnnounceRequestBuilder;
439+
use crate::servers::udp::handlers::handle_announce;
452440
use crate::servers::udp::handlers::tests::{
453441
initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_issue_time,
454442
TorrentPeerBuilder,
455443
};
456-
use crate::servers::udp::handlers::{gen_remote_fingerprint, handle_announce};
457444

458445
#[tokio::test]
459446
async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration_if_defined() {
@@ -520,15 +507,15 @@ mod tests {
520507
use mockall::predicate::eq;
521508
use torrust_tracker_configuration::Core;
522509

523-
use crate::packages::udp_tracker_core::connection_cookie::make;
510+
use crate::packages::udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make};
524511
use crate::packages::{self, udp_tracker_core};
525512
use crate::servers::udp::handlers::announce::tests::announce_request::AnnounceRequestBuilder;
513+
use crate::servers::udp::handlers::handle_announce;
526514
use crate::servers::udp::handlers::tests::{
527515
initialize_core_tracker_services_for_default_tracker_configuration,
528516
initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv6_remote_addr,
529517
sample_issue_time, MockUdpStatsEventSender, TorrentPeerBuilder,
530518
};
531-
use crate::servers::udp::handlers::{gen_remote_fingerprint, handle_announce};
532519

533520
#[tokio::test]
534521
async fn an_announced_peer_should_be_added_to_the_tracker() {
@@ -776,12 +763,12 @@ mod tests {
776763
use mockall::predicate::eq;
777764

778765
use crate::packages::udp_tracker_core;
779-
use crate::packages::udp_tracker_core::connection_cookie::make;
766+
use crate::packages::udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make};
780767
use crate::servers::udp::handlers::announce::tests::announce_request::AnnounceRequestBuilder;
768+
use crate::servers::udp::handlers::handle_announce;
781769
use crate::servers::udp::handlers::tests::{
782770
sample_cookie_valid_range, sample_issue_time, MockUdpStatsEventSender, TrackerConfigurationBuilder,
783771
};
784-
use crate::servers::udp::handlers::{gen_remote_fingerprint, handle_announce};
785772

786773
#[tokio::test]
787774
async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration() {

src/servers/udp/handlers/connect.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, Response};
66
use tracing::{instrument, Level};
77

88
use crate::packages::udp_tracker_core;
9-
use crate::packages::udp_tracker_core::connection_cookie::make;
10-
use crate::servers::udp::handlers::gen_remote_fingerprint;
9+
use crate::packages::udp_tracker_core::connection_cookie::{gen_remote_fingerprint, make};
1110

1211
/// It handles the `Connect` request. Refer to [`Connect`](crate::servers::udp#connect)
1312
/// request for more information.

src/servers/udp/handlers/error.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ use uuid::Uuid;
99
use zerocopy::network_endian::I32;
1010

1111
use crate::packages::udp_tracker_core;
12-
use crate::packages::udp_tracker_core::connection_cookie::check;
12+
use crate::packages::udp_tracker_core::connection_cookie::{check, gen_remote_fingerprint};
1313
use crate::servers::udp::error::Error;
14-
use crate::servers::udp::handlers::gen_remote_fingerprint;
1514
use crate::servers::udp::UDP_TRACKER_LOG_TARGET;
1615

1716
#[allow(clippy::too_many_arguments)]

0 commit comments

Comments
 (0)