Skip to content

Commit

Permalink
dev: use aquatic_udp_protocol InfoHash inside our type
Browse files Browse the repository at this point in the history
  • Loading branch information
da2ce7 committed Jul 13, 2024
1 parent f71ca54 commit 8d4b6f8
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 35 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ rust-version.workspace = true
version.workspace = true

[dependencies]
aquatic_udp_protocol = "0"
binascii = "0"
derive_more = "0"
serde = { version = "1", features = ["derive"] }
tdyne-peer-id = "1"
tdyne-peer-id-registry = "0"
thiserror = "1"
zerocopy = "0"
64 changes: 50 additions & 14 deletions packages/primitives/src/info_hash.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use std::hash::{DefaultHasher, Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::panic::Location;

use thiserror::Error;
use zerocopy::FromBytes;

/// `BitTorrent` Info Hash v1
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug)]
pub struct InfoHash(pub [u8; 20]);
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub struct InfoHash {
data: aquatic_udp_protocol::InfoHash,
}

pub const INFO_HASH_BYTES_LEN: usize = 20;

Expand All @@ -17,10 +21,9 @@ impl InfoHash {
/// Will panic if byte slice does not contains the exact amount of bytes need for the `InfoHash`.
#[must_use]
pub fn from_bytes(bytes: &[u8]) -> Self {
assert_eq!(bytes.len(), INFO_HASH_BYTES_LEN);
let mut ret = Self([0u8; INFO_HASH_BYTES_LEN]);
ret.0.clone_from_slice(bytes);
ret
let data = aquatic_udp_protocol::InfoHash::read_from(bytes).expect("it should have the exact amount of bytes");

Self { data }
}

/// Returns the `InfoHash` internal byte array.
Expand All @@ -36,6 +39,34 @@ impl InfoHash {
}
}

impl Default for InfoHash {
fn default() -> Self {
Self {
data: aquatic_udp_protocol::InfoHash(Default::default()),
}
}
}

impl From<aquatic_udp_protocol::InfoHash> for InfoHash {
fn from(data: aquatic_udp_protocol::InfoHash) -> Self {
Self { data }
}
}

impl Deref for InfoHash {
type Target = aquatic_udp_protocol::InfoHash;

fn deref(&self) -> &Self::Target {
&self.data
}
}

impl DerefMut for InfoHash {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}

impl Ord for InfoHash {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.cmp(&other.0)
Expand All @@ -60,7 +91,7 @@ impl std::str::FromStr for InfoHash {
type Err = binascii::ConvertError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut i = Self([0u8; 20]);
let mut i = Self::default();
if s.len() != 40 {
return Err(binascii::ConvertError::InvalidInputLength);
}
Expand All @@ -72,7 +103,7 @@ impl std::str::FromStr for InfoHash {
impl std::convert::From<&[u8]> for InfoHash {
fn from(data: &[u8]) -> InfoHash {
assert_eq!(data.len(), 20);
let mut ret = InfoHash([0u8; 20]);
let mut ret = Self::default();
ret.0.clone_from_slice(data);
ret
}
Expand All @@ -82,23 +113,28 @@ impl std::convert::From<&[u8]> for InfoHash {
impl std::convert::From<&DefaultHasher> for InfoHash {
fn from(data: &DefaultHasher) -> InfoHash {
let n = data.finish().to_le_bytes();
InfoHash([
let bytes = [
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[0], n[1], n[2],
n[3],
])
];
let data = aquatic_udp_protocol::InfoHash(bytes);
Self { data }
}
}

impl std::convert::From<&i32> for InfoHash {
fn from(n: &i32) -> InfoHash {
let n = n.to_le_bytes();
InfoHash([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, n[0], n[1], n[2], n[3]])
let bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, n[0], n[1], n[2], n[3]];
let data = aquatic_udp_protocol::InfoHash(bytes);
Self { data }
}
}

impl std::convert::From<[u8; 20]> for InfoHash {
fn from(val: [u8; 20]) -> Self {
InfoHash(val)
fn from(bytes: [u8; 20]) -> Self {
let data = aquatic_udp_protocol::InfoHash(bytes);
Self { data }
}
}

Expand Down Expand Up @@ -171,7 +207,7 @@ impl<'v> serde::de::Visitor<'v> for InfoHashVisitor {
));
}

let mut res = InfoHash([0u8; 20]);
let mut res = InfoHash::default();

if binascii::hex2bin(v.as_bytes(), &mut res.0).is_err() {
return Err(serde::de::Error::invalid_value(
Expand Down
12 changes: 6 additions & 6 deletions packages/torrent-repository/benches/helpers/asyn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ where
for _ in 0..samples {
let torrent_repository = V::default();

let info_hash = InfoHash([0; 20]);
let info_hash = InfoHash::default();

torrent_repository.upsert_peer(&info_hash, &DEFAULT_PEER).await;

Expand All @@ -33,23 +33,23 @@ where
Arc<V>: Clone + Send + Sync + 'static,
{
let torrent_repository = Arc::<V>::default();
let info_hash: &'static InfoHash = &InfoHash([0; 20]);
let info_hash = InfoHash::default();
let handles = FuturesUnordered::new();

// Add the torrent/peer to the torrent repository
torrent_repository.upsert_peer(info_hash, &DEFAULT_PEER).await;
torrent_repository.upsert_peer(&info_hash, &DEFAULT_PEER).await;

torrent_repository.get_swarm_metadata(info_hash).await;
torrent_repository.get_swarm_metadata(&info_hash).await;

let start = Instant::now();

for _ in 0..samples {
let torrent_repository_clone = torrent_repository.clone();

let handle = runtime.spawn(async move {
torrent_repository_clone.upsert_peer(info_hash, &DEFAULT_PEER).await;
torrent_repository_clone.upsert_peer(&info_hash, &DEFAULT_PEER).await;

torrent_repository_clone.get_swarm_metadata(info_hash).await;
torrent_repository_clone.get_swarm_metadata(&info_hash).await;

if let Some(sleep_time) = sleep {
let start_time = std::time::Instant::now();
Expand Down
12 changes: 6 additions & 6 deletions packages/torrent-repository/benches/helpers/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ where
for _ in 0..samples {
let torrent_repository = V::default();

let info_hash = InfoHash([0; 20]);
let info_hash = InfoHash::default();

torrent_repository.upsert_peer(&info_hash, &DEFAULT_PEER);

Expand All @@ -35,23 +35,23 @@ where
Arc<V>: Clone + Send + Sync + 'static,
{
let torrent_repository = Arc::<V>::default();
let info_hash: &'static InfoHash = &InfoHash([0; 20]);
let info_hash = InfoHash::default();
let handles = FuturesUnordered::new();

// Add the torrent/peer to the torrent repository
torrent_repository.upsert_peer(info_hash, &DEFAULT_PEER);
torrent_repository.upsert_peer(&info_hash, &DEFAULT_PEER);

torrent_repository.get_swarm_metadata(info_hash);
torrent_repository.get_swarm_metadata(&info_hash);

let start = Instant::now();

for _ in 0..samples {
let torrent_repository_clone = torrent_repository.clone();

let handle = runtime.spawn(async move {
torrent_repository_clone.upsert_peer(info_hash, &DEFAULT_PEER);
torrent_repository_clone.upsert_peer(&info_hash, &DEFAULT_PEER);

torrent_repository_clone.get_swarm_metadata(info_hash);
torrent_repository_clone.get_swarm_metadata(&info_hash);

if let Some(sleep_time) = sleep {
let start_time = std::time::Instant::now();
Expand Down
2 changes: 1 addition & 1 deletion packages/torrent-repository/benches/helpers/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn generate_unique_info_hashes(size: usize) -> Vec<InfoHash> {
bytes[2] = ((i >> 16) & 0xFF) as u8;
bytes[3] = ((i >> 24) & 0xFF) as u8;

let info_hash = InfoHash(bytes);
let info_hash = InfoHash::from_bytes(&bytes);
result.insert(info_hash);
}

Expand Down
7 changes: 3 additions & 4 deletions src/console/clients/checker/checks/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::time::Duration;
use aquatic_udp_protocol::TransactionId;
use hex_literal::hex;
use serde::Serialize;
use torrust_tracker_primitives::info_hash::InfoHash;

use crate::console::clients::udp::checker::Client;
use crate::console::clients::udp::Error;
Expand All @@ -29,7 +28,7 @@ pub async fn run(udp_trackers: Vec<SocketAddr>, timeout: Duration) -> Vec<Result

tracing::debug!("UDP trackers ...");

let info_hash = InfoHash(hex!("9c38422213e30bff212b30c360d26f9a02136422")); // # DevSkim: ignore DS173237
let info_hash = aquatic_udp_protocol::InfoHash(hex!("9c38422213e30bff212b30c360d26f9a02136422")); // # DevSkim: ignore DS173237

for remote_addr in udp_trackers {
let mut checks = Checks {
Expand Down Expand Up @@ -70,7 +69,7 @@ pub async fn run(udp_trackers: Vec<SocketAddr>, timeout: Duration) -> Vec<Result
// Announce
{
let check = client
.send_announce_request(transaction_id, connection_id, info_hash)
.send_announce_request(transaction_id, connection_id, info_hash.into())
.await
.map(|_| ());

Expand All @@ -80,7 +79,7 @@ pub async fn run(udp_trackers: Vec<SocketAddr>, timeout: Duration) -> Vec<Result
// Scrape
{
let check = client
.send_scrape_request(connection_id, transaction_id, &[info_hash])
.send_scrape_request(connection_id, transaction_id, &[info_hash.into()])
.await
.map(|_| ());

Expand Down
2 changes: 1 addition & 1 deletion src/servers/http/v1/responses/scrape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ mod tests {
use crate::servers::http::v1::responses::scrape::Bencoded;

fn sample_scrape_data() -> ScrapeData {
let info_hash = InfoHash([0x69; 20]);
let info_hash = InfoHash::from_bytes(&[0x69; 20]);
let mut scrape_data = ScrapeData::empty();
scrape_data.add_file(
&info_hash,
Expand Down
6 changes: 3 additions & 3 deletions src/servers/udp/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ pub async fn handle_announce(

check(&remote_addr, &from_connection_id(&announce_request.connection_id))?;

let info_hash = InfoHash(announce_request.info_hash.0);
let info_hash = announce_request.info_hash.into();
let remote_client_ip = remote_addr.ip();

// Authorization
Expand Down Expand Up @@ -240,9 +240,9 @@ pub async fn handle_scrape(remote_addr: SocketAddr, request: &ScrapeRequest, tra
debug!("udp scrape request: {:#?}", request);

// Convert from aquatic infohashes
let mut info_hashes = vec![];
let mut info_hashes: Vec<InfoHash> = vec![];
for info_hash in &request.info_hashes {
info_hashes.push(InfoHash(info_hash.0));
info_hashes.push((*info_hash).into());
}

let scrape_data = if tracker.requires_authentication() {
Expand Down

0 comments on commit 8d4b6f8

Please sign in to comment.