Skip to content

Commit 4d788d2

Browse files
committed
Merge #119: Refactor: rename peer.updated field in torrent detail endpoint
e1b84f6 refactor: [#61] extract struct ApiClient for API testing (Jose Celano) bc3d246 feat(api): in torrent endpoint rename field to (Jose Celano) 7e03714 refactor: [#61] use StatsResource in API stats endpoint (Jose Celano) b974ce0 refactor: [#61] use TorrentListItemResource in torrent list API endpoint (Jose Celano) 284c91b test: [#61] add e2e test for torrent list API endpoint (Jose Celano) 7298701 refactor: [#61] extract converter from TorrentPeer to TorrentPeerResource (Jose Celano) 801dfe6 refactor: [#61] use TorrentResource in torrent info API endpoint (Jose Celano) ea92ceb test: [#61] add e2e test to API torrent info endpoint before refactoring (Jose Celano) Pull request description: TODO: - [x] Add an e2e test before refactoring. - [x] Refactor the API endpoint to use the resource `TorrentResource` like `AuthKeyResource`. - [x] Refactor endpoint ` /api/torrents?offset=:u32&limit=:u32` to use `TorrentResource`. - [x] Add a new field (`updated_milliseconds_ago`) to the JSON response keeping the old one for backwards compatibility. ACKs for top commit: josecelano: ACK e1b84f6 da2ce7: ACK e1b84f6 Tree-SHA512: be96ae16aa4214e600d6679f35a47ec3b95132ee8243352a11f7aca579a2a000843591556b8279abd073a9cb1079d32b961ee3c71892d4d925fcd202be2826a8
2 parents 8ac31a9 + e1b84f6 commit 4d788d2

File tree

8 files changed

+366
-82
lines changed

8 files changed

+366
-82
lines changed

src/api/resources/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
//! WIP. Not all endpoints have their resource structs.
44
//!
55
//! - [x] AuthKeys
6-
//! - [ ] ...
7-
//! - [ ] ...
6+
//! - [ ] TorrentResource, TorrentListItemResource, TorrentPeerResource, PeerIdResource
7+
//! - [ ] StatsResource
88
//! - [ ] ...
99
pub mod auth_key_resource;
10+
pub mod stats_resource;
11+
pub mod torrent_resource;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
4+
pub struct StatsResource {
5+
pub torrents: u32,
6+
pub seeders: u32,
7+
pub completed: u32,
8+
pub leechers: u32,
9+
pub tcp4_connections_handled: u32,
10+
pub tcp4_announces_handled: u32,
11+
pub tcp4_scrapes_handled: u32,
12+
pub tcp6_connections_handled: u32,
13+
pub tcp6_announces_handled: u32,
14+
pub tcp6_scrapes_handled: u32,
15+
pub udp4_connections_handled: u32,
16+
pub udp4_announces_handled: u32,
17+
pub udp4_scrapes_handled: u32,
18+
pub udp6_connections_handled: u32,
19+
pub udp6_announces_handled: u32,
20+
pub udp6_scrapes_handled: u32,
21+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
use crate::peer::TorrentPeer;
4+
use crate::PeerId;
5+
6+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
7+
pub struct TorrentResource {
8+
pub info_hash: String,
9+
pub seeders: u32,
10+
pub completed: u32,
11+
pub leechers: u32,
12+
#[serde(skip_serializing_if = "Option::is_none")]
13+
pub peers: Option<Vec<TorrentPeerResource>>,
14+
}
15+
16+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
17+
pub struct TorrentListItemResource {
18+
pub info_hash: String,
19+
pub seeders: u32,
20+
pub completed: u32,
21+
pub leechers: u32,
22+
// todo: this is always None. Remove field from endpoint?
23+
pub peers: Option<Vec<TorrentPeerResource>>,
24+
}
25+
26+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
27+
pub struct TorrentPeerResource {
28+
pub peer_id: PeerIdResource,
29+
pub peer_addr: String,
30+
#[deprecated(since = "2.0.0", note = "please use `updated_milliseconds_ago` instead")]
31+
pub updated: u128,
32+
pub updated_milliseconds_ago: u128,
33+
pub uploaded: i64,
34+
pub downloaded: i64,
35+
pub left: i64,
36+
pub event: String,
37+
}
38+
39+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
40+
pub struct PeerIdResource {
41+
pub id: Option<String>,
42+
pub client: Option<String>,
43+
}
44+
45+
impl From<PeerId> for PeerIdResource {
46+
fn from(peer_id: PeerId) -> Self {
47+
PeerIdResource {
48+
id: peer_id.get_id(),
49+
client: peer_id.get_client_name().map(|client_name| client_name.to_string()),
50+
}
51+
}
52+
}
53+
54+
impl From<TorrentPeer> for TorrentPeerResource {
55+
fn from(peer: TorrentPeer) -> Self {
56+
TorrentPeerResource {
57+
peer_id: PeerIdResource::from(peer.peer_id),
58+
peer_addr: peer.peer_addr.to_string(),
59+
updated: peer.updated.as_millis(),
60+
updated_milliseconds_ago: peer.updated.as_millis(),
61+
uploaded: peer.uploaded.0,
62+
downloaded: peer.downloaded.0,
63+
left: peer.left.0,
64+
event: format!("{:?}", peer.event),
65+
}
66+
}
67+
}

src/api/server.rs

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use serde::{Deserialize, Serialize};
88
use warp::{filters, reply, serve, Filter};
99

1010
use super::resources::auth_key_resource::AuthKeyResource;
11-
use crate::peer::TorrentPeer;
11+
use super::resources::stats_resource::StatsResource;
12+
use super::resources::torrent_resource::{TorrentListItemResource, TorrentPeerResource, TorrentResource};
1213
use crate::protocol::common::*;
1314
use crate::tracker::TorrentTracker;
1415

@@ -18,36 +19,6 @@ struct TorrentInfoQuery {
1819
limit: Option<u32>,
1920
}
2021

21-
#[derive(Serialize)]
22-
struct Torrent<'a> {
23-
info_hash: &'a InfoHash,
24-
seeders: u32,
25-
completed: u32,
26-
leechers: u32,
27-
#[serde(skip_serializing_if = "Option::is_none")]
28-
peers: Option<Vec<&'a TorrentPeer>>,
29-
}
30-
31-
#[derive(Serialize)]
32-
struct Stats {
33-
torrents: u32,
34-
seeders: u32,
35-
completed: u32,
36-
leechers: u32,
37-
tcp4_connections_handled: u32,
38-
tcp4_announces_handled: u32,
39-
tcp4_scrapes_handled: u32,
40-
tcp6_connections_handled: u32,
41-
tcp6_announces_handled: u32,
42-
tcp6_scrapes_handled: u32,
43-
udp4_connections_handled: u32,
44-
udp4_announces_handled: u32,
45-
udp4_scrapes_handled: u32,
46-
udp6_connections_handled: u32,
47-
udp6_announces_handled: u32,
48-
udp6_scrapes_handled: u32,
49-
}
50-
5122
#[derive(Serialize, Debug)]
5223
#[serde(tag = "status", rename_all = "snake_case")]
5324
enum ActionStatus<'a> {
@@ -109,8 +80,8 @@ pub fn start(socket_addr: SocketAddr, tracker: Arc<TorrentTracker>) -> impl warp
10980
.iter()
11081
.map(|(info_hash, torrent_entry)| {
11182
let (seeders, completed, leechers) = torrent_entry.get_stats();
112-
Torrent {
113-
info_hash,
83+
TorrentListItemResource {
84+
info_hash: info_hash.to_string(),
11485
seeders,
11586
completed,
11687
leechers,
@@ -132,7 +103,7 @@ pub fn start(socket_addr: SocketAddr, tracker: Arc<TorrentTracker>) -> impl warp
132103
.and(filters::path::end())
133104
.map(move || api_stats.clone())
134105
.and_then(|tracker: Arc<TorrentTracker>| async move {
135-
let mut results = Stats {
106+
let mut results = StatsResource {
136107
torrents: 0,
137108
seeders: 0,
138109
completed: 0,
@@ -206,12 +177,14 @@ pub fn start(socket_addr: SocketAddr, tracker: Arc<TorrentTracker>) -> impl warp
206177

207178
let peers = torrent_entry.get_peers(None);
208179

209-
Ok(reply::json(&Torrent {
210-
info_hash: &info_hash,
180+
let peer_resources = peers.iter().map(|peer| TorrentPeerResource::from(**peer)).collect();
181+
182+
Ok(reply::json(&TorrentResource {
183+
info_hash: info_hash.to_string(),
211184
seeders,
212185
completed,
213186
leechers,
214-
peers: Some(peers),
187+
peers: Some(peer_resources),
215188
}))
216189
});
217190

src/protocol/common.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<'v> serde::de::Visitor<'v> for InfoHashVisitor {
217217
}
218218
}
219219

220-
#[derive(PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
220+
#[derive(PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord, Copy)]
221221
pub struct PeerId(pub [u8; 20]);
222222

223223
impl std::fmt::Display for PeerId {
@@ -232,6 +232,14 @@ impl std::fmt::Display for PeerId {
232232
}
233233

234234
impl PeerId {
235+
pub fn get_id(&self) -> Option<String> {
236+
let buff_size = self.0.len() * 2;
237+
let mut tmp: Vec<u8> = vec![0; buff_size];
238+
binascii::bin2hex(&self.0, &mut tmp).unwrap();
239+
240+
std::str::from_utf8(&tmp).ok().map(|id| id.to_string())
241+
}
242+
235243
pub fn get_client_name(&self) -> Option<&'static str> {
236244
if self.0[0] == b'M' {
237245
return Some("BitTorrent");
@@ -316,19 +324,14 @@ impl Serialize for PeerId {
316324
where
317325
S: serde::Serializer,
318326
{
319-
let buff_size = self.0.len() * 2;
320-
let mut tmp: Vec<u8> = vec![0; buff_size];
321-
binascii::bin2hex(&self.0, &mut tmp).unwrap();
322-
let id = std::str::from_utf8(&tmp).ok();
323-
324327
#[derive(Serialize)]
325328
struct PeerIdInfo<'a> {
326-
id: Option<&'a str>,
329+
id: Option<String>,
327330
client: Option<&'a str>,
328331
}
329332

330333
let obj = PeerIdInfo {
331-
id,
334+
id: self.get_id(),
332335
client: self.get_client_name(),
333336
};
334337
obj.serialize(serializer)

src/tracker/peer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::protocol::clock::{DefaultClock, DurationSinceUnixEpoch, Time};
99
use crate::protocol::common::{AnnounceEventDef, NumberOfBytesDef, PeerId};
1010
use crate::protocol::utils::ser_unix_time_value;
1111

12-
#[derive(PartialEq, Eq, Debug, Clone, Serialize)]
12+
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Copy)]
1313
pub struct TorrentPeer {
1414
pub peer_id: PeerId,
1515
pub peer_addr: SocketAddr,

src/tracker/torrent.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ impl TorrentEntry {
3232
let _ = self.peers.remove(&peer.peer_id);
3333
}
3434
AnnounceEvent::Completed => {
35-
let peer_old = self.peers.insert(peer.peer_id.clone(), peer.clone());
35+
let peer_old = self.peers.insert(peer.peer_id, *peer);
3636
// Don't count if peer was not previously known
3737
if peer_old.is_some() {
3838
self.completed += 1;
3939
did_torrent_stats_change = true;
4040
}
4141
}
4242
_ => {
43-
let _ = self.peers.insert(peer.peer_id.clone(), peer.clone());
43+
let _ = self.peers.insert(peer.peer_id, *peer);
4444
}
4545
}
4646

0 commit comments

Comments
 (0)