Skip to content

Commit 7bf84f2

Browse files
committed
dev: Announce Responce Cleanup
1 parent c588b6a commit 7bf84f2

File tree

21 files changed

+464
-551
lines changed

21 files changed

+464
-551
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,14 @@ serde_urlencoded = "0"
7979
torrust-tracker-test-helpers = { version = "3.0.0-alpha.12-develop", path = "packages/test-helpers" }
8080

8181
[workspace]
82-
members = ["contrib/bencode", "packages/configuration", "packages/located-error", "packages/primitives", "packages/test-helpers", "packages/torrent-repository-benchmarks"]
82+
members = [
83+
"contrib/bencode",
84+
"packages/configuration",
85+
"packages/located-error",
86+
"packages/primitives",
87+
"packages/test-helpers",
88+
"packages/torrent-repository-benchmarks",
89+
]
8390

8491
[profile.dev]
8592
debug = 1

cSpell.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"Hydranode",
5050
"Icelake",
5151
"imdl",
52+
"impls",
5253
"incompletei",
5354
"infohash",
5455
"infohashes",
@@ -79,6 +80,7 @@
7980
"nonroot",
8081
"Norberg",
8182
"numwant",
83+
"nvCFlJCq7fz7Qx6KoKTDiMZvns8l5Kw7",
8284
"oneshot",
8385
"ostr",
8486
"Pando",
@@ -129,8 +131,7 @@
129131
"Xtorrent",
130132
"Xunlei",
131133
"xxxxxxxxxxxxxxxxxxxxd",
132-
"yyyyyyyyyyyyyyyyyyyyd",
133-
"nvCFlJCq7fz7Qx6KoKTDiMZvns8l5Kw7"
134+
"yyyyyyyyyyyyyyyyyyyyd"
134135
],
135136
"enableFiletypes": [
136137
"dockerfile",

packages/configuration/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ version.workspace = true
1616

1717
[dependencies]
1818
config = "0"
19+
derive_more = "0"
1920
log = { version = "0", features = ["release_max_level_info"] }
2021
serde = { version = "1", features = ["derive"] }
2122
serde_with = "3"

packages/configuration/src/lib.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ use std::sync::Arc;
236236
use std::{env, fs};
237237

238238
use config::{Config, ConfigError, File, FileFormat};
239+
use derive_more::Constructor;
239240
use serde::{Deserialize, Serialize};
240241
use serde_with::{serde_as, NoneAsEmptyString};
241242
use thiserror::Error;
@@ -303,6 +304,47 @@ impl Info {
303304
}
304305
}
305306

307+
/// Announce policy
308+
#[derive(Copy, Clone, Debug, PartialEq, Constructor)]
309+
pub struct AnnouncePolicy {
310+
/// Interval in seconds that the client should wait between sending regular
311+
/// announce requests to the tracker.
312+
///
313+
/// It's a **recommended** wait time between announcements.
314+
///
315+
/// This is the standard amount of time that clients should wait between
316+
/// sending consecutive announcements to the tracker. This value is set by
317+
/// the tracker and is typically provided in the tracker's response to a
318+
/// client's initial request. It serves as a guideline for clients to know
319+
/// how often they should contact the tracker for updates on the peer list,
320+
/// while ensuring that the tracker is not overwhelmed with requests.
321+
pub interval: u32,
322+
323+
/// Minimum announce interval. Clients must not reannounce more frequently
324+
/// than this.
325+
///
326+
/// It establishes the shortest allowed wait time.
327+
///
328+
/// This is an optional parameter in the protocol that the tracker may
329+
/// provide in its response. It sets a lower limit on the frequency at which
330+
/// clients are allowed to send announcements. Clients should respect this
331+
/// value to prevent sending too many requests in a short period, which
332+
/// could lead to excessive load on the tracker or even getting banned by
333+
/// the tracker for not adhering to the rules.
334+
pub interval_min: u32,
335+
}
336+
337+
impl Default for AnnouncePolicy {
338+
fn default() -> Self {
339+
let announce_interval = 120;
340+
let min_announce_interval = 120;
341+
Self {
342+
interval: announce_interval,
343+
interval_min: min_announce_interval,
344+
}
345+
}
346+
}
347+
306348
/// Configuration for each UDP tracker.
307349
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
308350
pub struct UdpTracker {
@@ -516,13 +558,15 @@ impl From<ConfigError> for Error {
516558

517559
impl Default for Configuration {
518560
fn default() -> Self {
561+
let announce_policy = AnnouncePolicy::default();
562+
519563
let mut configuration = Configuration {
520564
log_level: Option::from(String::from("info")),
521565
mode: TrackerMode::Public,
522566
db_driver: DatabaseDriver::Sqlite3,
523567
db_path: String::from("./storage/tracker/lib/database/sqlite3.db"),
524-
announce_interval: 120,
525-
min_announce_interval: 120,
568+
announce_interval: announce_policy.interval,
569+
min_announce_interval: announce_policy.interval_min,
526570
max_peer_timeout: 900,
527571
on_reverse_proxy: false,
528572
external_ip: Some(String::from("0.0.0.0")),

src/core/databases/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub trait Database: Sync + Send {
134134
/// # Errors
135135
///
136136
/// Will return `Err` if unable to save.
137-
async fn save_persistent_torrent(&self, info_hash: &InfoHash, completed: u32) -> Result<(), Error>;
137+
async fn save_persistent_torrent(&self, info_hash: &InfoHash, downloaded: u32) -> Result<(), Error>;
138138

139139
// Whitelist
140140

src/core/mod.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@
9898
//!
9999
//! ```rust,no_run
100100
//! use torrust_tracker::core::peer::Peer;
101+
//! use torrust_tracker_configuration::AnnouncePolicy;
101102
//!
102103
//! pub struct AnnounceData {
103104
//! pub peers: Vec<Peer>,
104105
//! pub swarm_stats: SwarmStats,
105-
//! pub interval: u32, // Option `announce_interval` from core tracker configuration
106-
//! pub interval_min: u32, // Option `min_announce_interval` from core tracker configuration
106+
//! pub policy: AnnouncePolicy, // the tracker announce policy.
107107
//! }
108108
//!
109109
//! pub struct SwarmStats {
@@ -445,9 +445,10 @@ use std::panic::Location;
445445
use std::sync::Arc;
446446
use std::time::Duration;
447447

448+
use derive_more::Constructor;
448449
use futures::future::join_all;
449450
use tokio::sync::mpsc::error::SendError;
450-
use torrust_tracker_configuration::Configuration;
451+
use torrust_tracker_configuration::{AnnouncePolicy, Configuration};
451452
use torrust_tracker_primitives::TrackerMode;
452453

453454
use self::auth::Key;
@@ -487,7 +488,7 @@ pub struct Tracker {
487488
/// Structure that holds general `Tracker` torrents metrics.
488489
///
489490
/// Metrics are aggregate values for all torrents.
490-
#[derive(Debug, PartialEq, Default)]
491+
#[derive(Copy, Clone, Debug, PartialEq, Default)]
491492
pub struct TorrentsMetrics {
492493
/// Total number of seeders for all torrents
493494
pub seeders: u64,
@@ -500,20 +501,14 @@ pub struct TorrentsMetrics {
500501
}
501502

502503
/// Structure that holds the data returned by the `announce` request.
503-
#[derive(Debug, PartialEq, Default)]
504+
#[derive(Clone, Debug, PartialEq, Constructor, Default)]
504505
pub struct AnnounceData {
505506
/// The list of peers that are downloading the same torrent.
506507
/// It excludes the peer that made the request.
507508
pub peers: Vec<Peer>,
508509
/// Swarm statistics
509-
pub swarm_stats: SwarmStats,
510-
/// The interval in seconds that the client should wait between sending
511-
/// regular requests to the tracker.
512-
/// Refer to [`announce_interval`](torrust_tracker_configuration::Configuration::announce_interval).
513-
pub interval: u32,
514-
/// The minimum announce interval in seconds that the client should wait.
515-
/// Refer to [`min_announce_interval`](torrust_tracker_configuration::Configuration::min_announce_interval).
516-
pub interval_min: u32,
510+
pub stats: SwarmStats,
511+
pub policy: AnnouncePolicy,
517512
}
518513

519514
/// Structure that holds the data returned by the `scrape` request.
@@ -628,11 +623,12 @@ impl Tracker {
628623

629624
let peers = self.get_torrent_peers_for_peer(info_hash, peer).await;
630625

626+
let policy = AnnouncePolicy::new(self.config.announce_interval, self.config.min_announce_interval);
627+
631628
AnnounceData {
632629
peers,
633-
swarm_stats,
634-
interval: self.config.announce_interval,
635-
interval_min: self.config.min_announce_interval,
630+
stats: swarm_stats,
631+
policy,
636632
}
637633
}
638634

@@ -732,7 +728,7 @@ impl Tracker {
732728
let (stats, stats_updated) = self.torrents.update_torrent_with_peer_and_get_stats(info_hash, peer).await;
733729

734730
if self.config.persistent_torrent_completed_stat && stats_updated {
735-
let completed = stats.completed;
731+
let completed = stats.downloaded; // i.e `completed`
736732
let info_hash = *info_hash;
737733

738734
drop(self.database.save_persistent_torrent(&info_hash, completed).await);
@@ -1390,7 +1386,7 @@ mod tests {
13901386

13911387
let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip()).await;
13921388

1393-
assert_eq!(announce_data.swarm_stats.seeders, 1);
1389+
assert_eq!(announce_data.stats.complete, 1);
13941390
}
13951391

13961392
#[tokio::test]
@@ -1401,7 +1397,7 @@ mod tests {
14011397

14021398
let announce_data = tracker.announce(&sample_info_hash(), &mut peer, &peer_ip()).await;
14031399

1404-
assert_eq!(announce_data.swarm_stats.leechers, 1);
1400+
assert_eq!(announce_data.stats.incomplete, 1);
14051401
}
14061402

14071403
#[tokio::test]
@@ -1415,7 +1411,7 @@ mod tests {
14151411
let mut completed_peer = completed_peer();
14161412
let announce_data = tracker.announce(&sample_info_hash(), &mut completed_peer, &peer_ip()).await;
14171413

1418-
assert_eq!(announce_data.swarm_stats.completed, 1);
1414+
assert_eq!(announce_data.stats.downloaded, 1);
14191415
}
14201416
}
14211417
}
@@ -1739,11 +1735,11 @@ mod tests {
17391735

17401736
peer.event = AnnounceEvent::Started;
17411737
let swarm_stats = tracker.update_torrent_with_peer_and_get_stats(&info_hash, &peer).await;
1742-
assert_eq!(swarm_stats.completed, 0);
1738+
assert_eq!(swarm_stats.downloaded, 0);
17431739

17441740
peer.event = AnnounceEvent::Completed;
17451741
let swarm_stats = tracker.update_torrent_with_peer_and_get_stats(&info_hash, &peer).await;
1746-
assert_eq!(swarm_stats.completed, 1);
1742+
assert_eq!(swarm_stats.downloaded, 1);
17471743

17481744
// Remove the newly updated torrent from memory
17491745
tracker.torrents.get_torrents_mut().await.remove(&info_hash);

src/core/peer.rs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,85 @@ impl Serialize for Id {
277277
}
278278
}
279279

280-
#[cfg(test)]
281-
mod test {
280+
pub mod fixture {
281+
use std::net::SocketAddr;
282+
283+
use aquatic_udp_protocol::NumberOfBytes;
284+
285+
use super::{Id, Peer};
286+
287+
#[derive(PartialEq, Debug)]
288+
289+
pub struct PeerBuilder {
290+
peer: Peer,
291+
}
292+
293+
#[allow(clippy::derivable_impls)]
294+
impl Default for PeerBuilder {
295+
fn default() -> Self {
296+
Self { peer: Peer::default() }
297+
}
298+
}
299+
300+
impl PeerBuilder {
301+
#[allow(dead_code)]
302+
#[must_use]
303+
pub fn with_peer_id(mut self, peer_id: &Id) -> Self {
304+
self.peer.peer_id = *peer_id;
305+
self
306+
}
307+
308+
#[allow(dead_code)]
309+
#[must_use]
310+
pub fn with_peer_addr(mut self, peer_addr: &SocketAddr) -> Self {
311+
self.peer.peer_addr = *peer_addr;
312+
self
313+
}
314+
315+
#[allow(dead_code)]
316+
#[must_use]
317+
pub fn with_bytes_pending_to_download(mut self, left: i64) -> Self {
318+
self.peer.left = NumberOfBytes(left);
319+
self
320+
}
282321

322+
#[allow(dead_code)]
323+
#[must_use]
324+
pub fn with_no_bytes_pending_to_download(mut self) -> Self {
325+
self.peer.left = NumberOfBytes(0);
326+
self
327+
}
328+
329+
#[allow(dead_code)]
330+
#[must_use]
331+
pub fn build(self) -> Peer {
332+
self.into()
333+
}
334+
335+
#[allow(dead_code)]
336+
#[must_use]
337+
pub fn into(self) -> Peer {
338+
self.peer
339+
}
340+
}
341+
342+
impl Default for Peer {
343+
fn default() -> Self {
344+
Self {
345+
peer_id: Id(*b"-qB00000000000000000"),
346+
peer_addr: std::net::SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(126, 0, 0, 1)), 8080),
347+
updated: crate::shared::clock::DurationSinceUnixEpoch::new(1_669_397_478_934, 0),
348+
uploaded: NumberOfBytes(0),
349+
downloaded: NumberOfBytes(0),
350+
left: NumberOfBytes(0),
351+
event: aquatic_udp_protocol::AnnounceEvent::Started,
352+
}
353+
}
354+
}
355+
}
356+
357+
#[cfg(test)]
358+
pub mod test {
283359
mod torrent_peer_id {
284360
use crate::core::peer;
285361

0 commit comments

Comments
 (0)