Skip to content

Commit 9a43815

Browse files
committed
dev: move torrent/repository to packages
1 parent 4b2d6fe commit 9a43815

File tree

99 files changed

+2072
-1953
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+2072
-1953
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@
3131
"evenBetterToml.formatter.trailingNewline": true,
3232
"evenBetterToml.formatter.reorderKeys": true,
3333
"evenBetterToml.formatter.reorderArrays": true,
34+
3435
}

Cargo.lock

Lines changed: 17 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ axum = { version = "0", features = ["macros"] }
3737
axum-client-ip = "0"
3838
axum-extra = { version = "0", features = ["query"] }
3939
axum-server = { version = "0", features = ["tls-rustls"] }
40-
binascii = "0"
4140
chrono = { version = "0", default-features = false, features = ["clock"] }
4241
clap = { version = "4", features = ["derive", "env"] }
4342
colored = "2"
@@ -62,14 +61,13 @@ serde_bencode = "0"
6261
serde_bytes = "0"
6362
serde_json = "1"
6463
serde_repr = "0"
65-
tdyne-peer-id = "1"
66-
tdyne-peer-id-registry = "0"
6764
thiserror = "1"
6865
tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] }
6966
torrust-tracker-configuration = { version = "3.0.0-alpha.12-develop", path = "packages/configuration" }
7067
torrust-tracker-contrib-bencode = { version = "3.0.0-alpha.12-develop", path = "contrib/bencode" }
7168
torrust-tracker-located-error = { version = "3.0.0-alpha.12-develop", path = "packages/located-error" }
7269
torrust-tracker-primitives = { version = "3.0.0-alpha.12-develop", path = "packages/primitives" }
70+
torrust-tracker-torrent-repository = { version = "3.0.0-alpha.12-develop", path = "packages/torrent-repository" }
7371
tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] }
7472
trace = "0"
7573
tracing = "0"
@@ -91,7 +89,7 @@ members = [
9189
"packages/located-error",
9290
"packages/primitives",
9391
"packages/test-helpers",
94-
"packages/torrent-repository-benchmarks",
92+
"packages/torrent-repository"
9593
]
9694

9795
[profile.dev]

cSpell.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"filesd",
5151
"flamegraph",
5252
"Freebox",
53+
"Frostegård",
5354
"gecos",
5455
"Grcov",
5556
"hasher",
@@ -68,6 +69,7 @@
6869
"Intermodal",
6970
"intervali",
7071
"kcachegrind",
72+
"Joakim",
7173
"keyout",
7274
"lcov",
7375
"leecher",
@@ -96,6 +98,7 @@
9698
"oneshot",
9799
"ostr",
98100
"Pando",
101+
"peekable",
99102
"proot",
100103
"proto",
101104
"Quickstart",
@@ -109,6 +112,7 @@
109112
"reqwest",
110113
"rerequests",
111114
"ringbuf",
115+
"ringsize",
112116
"rngs",
113117
"rosegment",
114118
"routable",

packages/configuration/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@ use thiserror::Error;
243243
use torrust_tracker_located_error::{DynError, Located, LocatedError};
244244
use torrust_tracker_primitives::{DatabaseDriver, TrackerMode};
245245

246+
#[derive(Copy, Clone, Debug, PartialEq, Default, Constructor)]
247+
pub struct TrackerPolicy {
248+
pub remove_peerless_torrents: bool,
249+
pub max_peer_timeout: u32,
250+
pub persistent_torrent_completed_stat: bool,
251+
}
252+
246253
/// Information required for loading config
247254
#[derive(Debug, Default, Clone)]
248255
pub struct Info {

packages/primitives/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ version.workspace = true
1616

1717
[dependencies]
1818
derive_more = "0"
19+
thiserror = "1"
20+
binascii = "0"
1921
serde = { version = "1", features = ["derive"] }
22+
tdyne-peer-id = "1"
23+
tdyne-peer-id-registry = "0"
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Copyright (c) 2020-2023 Joakim Frostegård and The Torrust Developers
2+
//!
3+
//! Distributed under Apache 2.0 license
4+
5+
use serde::{Deserialize, Serialize};
6+
7+
/// Announce events. Described on the
8+
/// [BEP 3. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html)
9+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
10+
pub enum AnnounceEvent {
11+
/// The peer has started downloading the torrent.
12+
Started,
13+
/// The peer has ceased downloading the torrent.
14+
Stopped,
15+
/// The peer has completed downloading the torrent.
16+
Completed,
17+
/// This is one of the announcements done at regular intervals.
18+
None,
19+
}
20+
21+
impl AnnounceEvent {
22+
#[inline]
23+
#[must_use]
24+
pub fn from_i32(i: i32) -> Self {
25+
match i {
26+
1 => Self::Completed,
27+
2 => Self::Started,
28+
3 => Self::Stopped,
29+
_ => Self::None,
30+
}
31+
}
32+
33+
#[inline]
34+
#[must_use]
35+
pub fn to_i32(&self) -> i32 {
36+
match self {
37+
AnnounceEvent::None => 0,
38+
AnnounceEvent::Completed => 1,
39+
AnnounceEvent::Started => 2,
40+
AnnounceEvent::Stopped => 3,
41+
}
42+
}
43+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
use std::panic::Location;
2+
3+
use thiserror::Error;
4+
5+
/// `BitTorrent` Info Hash v1
6+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug)]
7+
pub struct InfoHash(pub [u8; 20]);
8+
9+
pub const INFO_HASH_BYTES_LEN: usize = 20;
10+
11+
impl InfoHash {
12+
/// Create a new `InfoHash` from a byte slice.
13+
///
14+
/// # Panics
15+
///
16+
/// Will panic if byte slice does not contains the exact amount of bytes need for the `InfoHash`.
17+
#[must_use]
18+
pub fn from_bytes(bytes: &[u8]) -> Self {
19+
assert_eq!(bytes.len(), INFO_HASH_BYTES_LEN);
20+
let mut ret = Self([0u8; INFO_HASH_BYTES_LEN]);
21+
ret.0.clone_from_slice(bytes);
22+
ret
23+
}
24+
25+
/// Returns the `InfoHash` internal byte array.
26+
#[must_use]
27+
pub fn bytes(&self) -> [u8; 20] {
28+
self.0
29+
}
30+
31+
/// Returns the `InfoHash` as a hex string.
32+
#[must_use]
33+
pub fn to_hex_string(&self) -> String {
34+
self.to_string()
35+
}
36+
}
37+
38+
impl Ord for InfoHash {
39+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
40+
self.0.cmp(&other.0)
41+
}
42+
}
43+
44+
impl std::cmp::PartialOrd<InfoHash> for InfoHash {
45+
fn partial_cmp(&self, other: &InfoHash) -> Option<std::cmp::Ordering> {
46+
Some(self.cmp(other))
47+
}
48+
}
49+
50+
impl std::fmt::Display for InfoHash {
51+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52+
let mut chars = [0u8; 40];
53+
binascii::bin2hex(&self.0, &mut chars).expect("failed to hexlify");
54+
write!(f, "{}", std::str::from_utf8(&chars).unwrap())
55+
}
56+
}
57+
58+
impl std::str::FromStr for InfoHash {
59+
type Err = binascii::ConvertError;
60+
61+
fn from_str(s: &str) -> Result<Self, Self::Err> {
62+
let mut i = Self([0u8; 20]);
63+
if s.len() != 40 {
64+
return Err(binascii::ConvertError::InvalidInputLength);
65+
}
66+
binascii::hex2bin(s.as_bytes(), &mut i.0)?;
67+
Ok(i)
68+
}
69+
}
70+
71+
impl std::convert::From<&[u8]> for InfoHash {
72+
fn from(data: &[u8]) -> InfoHash {
73+
assert_eq!(data.len(), 20);
74+
let mut ret = InfoHash([0u8; 20]);
75+
ret.0.clone_from_slice(data);
76+
ret
77+
}
78+
}
79+
80+
impl std::convert::From<[u8; 20]> for InfoHash {
81+
fn from(val: [u8; 20]) -> Self {
82+
InfoHash(val)
83+
}
84+
}
85+
86+
/// Errors that can occur when converting from a `Vec<u8>` to an `InfoHash`.
87+
#[derive(Error, Debug)]
88+
pub enum ConversionError {
89+
/// Not enough bytes for infohash. An infohash is 20 bytes.
90+
#[error("not enough bytes for infohash: {message} {location}")]
91+
NotEnoughBytes {
92+
location: &'static Location<'static>,
93+
message: String,
94+
},
95+
/// Too many bytes for infohash. An infohash is 20 bytes.
96+
#[error("too many bytes for infohash: {message} {location}")]
97+
TooManyBytes {
98+
location: &'static Location<'static>,
99+
message: String,
100+
},
101+
}
102+
103+
impl TryFrom<Vec<u8>> for InfoHash {
104+
type Error = ConversionError;
105+
106+
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
107+
if bytes.len() < INFO_HASH_BYTES_LEN {
108+
return Err(ConversionError::NotEnoughBytes {
109+
location: Location::caller(),
110+
message: format! {"got {} bytes, expected {}", bytes.len(), INFO_HASH_BYTES_LEN},
111+
});
112+
}
113+
if bytes.len() > INFO_HASH_BYTES_LEN {
114+
return Err(ConversionError::TooManyBytes {
115+
location: Location::caller(),
116+
message: format! {"got {} bytes, expected {}", bytes.len(), INFO_HASH_BYTES_LEN},
117+
});
118+
}
119+
Ok(Self::from_bytes(&bytes))
120+
}
121+
}
122+
123+
impl serde::ser::Serialize for InfoHash {
124+
fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
125+
let mut buffer = [0u8; 40];
126+
let bytes_out = binascii::bin2hex(&self.0, &mut buffer).ok().unwrap();
127+
let str_out = std::str::from_utf8(bytes_out).unwrap();
128+
serializer.serialize_str(str_out)
129+
}
130+
}
131+
132+
impl<'de> serde::de::Deserialize<'de> for InfoHash {
133+
fn deserialize<D: serde::de::Deserializer<'de>>(des: D) -> Result<Self, D::Error> {
134+
des.deserialize_str(InfoHashVisitor)
135+
}
136+
}
137+
138+
struct InfoHashVisitor;
139+
140+
impl<'v> serde::de::Visitor<'v> for InfoHashVisitor {
141+
type Value = InfoHash;
142+
143+
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144+
write!(formatter, "a 40 character long hash")
145+
}
146+
147+
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
148+
if v.len() != 40 {
149+
return Err(serde::de::Error::invalid_value(
150+
serde::de::Unexpected::Str(v),
151+
&"a 40 character long string",
152+
));
153+
}
154+
155+
let mut res = InfoHash([0u8; 20]);
156+
157+
if binascii::hex2bin(v.as_bytes(), &mut res.0).is_err() {
158+
return Err(serde::de::Error::invalid_value(
159+
serde::de::Unexpected::Str(v),
160+
&"a hexadecimal string",
161+
));
162+
};
163+
Ok(res)
164+
}
165+
}

0 commit comments

Comments
 (0)