Skip to content

Commit 1b92b77

Browse files
committed
refactor: [#639] UDP client. Extract aquatic reponses wrappers
for serialization to JSON.
1 parent a2e123c commit 1b92b77

File tree

3 files changed

+109
-40
lines changed

3 files changed

+109
-40
lines changed

src/console/clients/udp/app.rs

+25-40
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ use aquatic_udp_protocol::Response::{self, AnnounceIpv4, AnnounceIpv6, Scrape};
6464
use aquatic_udp_protocol::{Port, TransactionId};
6565
use clap::{Parser, Subcommand};
6666
use log::{debug, LevelFilter};
67-
use serde_json::json;
6867
use url::Url;
6968

7069
use crate::console::clients::udp::checker;
70+
use crate::console::clients::udp::responses::{AnnounceResponseDto, ScrapeResponseDto};
7171
use crate::shared::bit_torrent::info_hash::InfoHash as TorrustInfoHash;
7272

7373
const ASSIGNED_BY_OS: u16 = 0;
@@ -117,45 +117,7 @@ pub async fn run() -> anyhow::Result<()> {
117117
} => handle_scrape(&tracker_socket_addr, &info_hashes).await?,
118118
};
119119

120-
match response {
121-
AnnounceIpv4(announce) => {
122-
let json = json!({
123-
"transaction_id": announce.transaction_id.0,
124-
"announce_interval": announce.announce_interval.0,
125-
"leechers": announce.leechers.0,
126-
"seeders": announce.seeders.0,
127-
"peers": announce.peers.iter().map(|peer| format!("{}:{}", peer.ip_address, peer.port.0)).collect::<Vec<_>>(),
128-
});
129-
let pretty_json = serde_json::to_string_pretty(&json).context("announce IPv4 response JSON serialization")?;
130-
println!("{pretty_json}");
131-
}
132-
AnnounceIpv6(announce) => {
133-
let json = json!({
134-
"transaction_id": announce.transaction_id.0,
135-
"announce_interval": announce.announce_interval.0,
136-
"leechers": announce.leechers.0,
137-
"seeders": announce.seeders.0,
138-
"peers6": announce.peers.iter().map(|peer| format!("{}:{}", peer.ip_address, peer.port.0)).collect::<Vec<_>>(),
139-
});
140-
let pretty_json = serde_json::to_string_pretty(&json).context("announce IPv6 response JSON serialization")?;
141-
println!("{pretty_json}");
142-
}
143-
Scrape(scrape) => {
144-
let json = json!({
145-
"transaction_id": scrape.transaction_id.0,
146-
"torrent_stats": scrape.torrent_stats.iter().map(|torrent_scrape_statistics| json!({
147-
"seeders": torrent_scrape_statistics.seeders.0,
148-
"completed": torrent_scrape_statistics.completed.0,
149-
"leechers": torrent_scrape_statistics.leechers.0,
150-
})).collect::<Vec<_>>(),
151-
});
152-
let pretty_json = serde_json::to_string_pretty(&json).context("scrape response JSON serialization")?;
153-
println!("{pretty_json}");
154-
}
155-
_ => println!("{response:#?}"), // todo: serialize to JSON all responses.
156-
};
157-
158-
Ok(())
120+
print_response(response)
159121
}
160122

161123
fn setup_logging(level: LevelFilter) {
@@ -207,6 +169,29 @@ async fn handle_scrape(tracker_socket_addr: &SocketAddr, info_hashes: &[TorrustI
207169
.await
208170
}
209171

172+
fn print_response(response: Response) -> anyhow::Result<()> {
173+
match response {
174+
AnnounceIpv4(response) => {
175+
let pretty_json = serde_json::to_string_pretty(&AnnounceResponseDto::from(response))
176+
.context("announce IPv4 response JSON serialization")?;
177+
println!("{pretty_json}");
178+
}
179+
AnnounceIpv6(response) => {
180+
let pretty_json = serde_json::to_string_pretty(&AnnounceResponseDto::from(response))
181+
.context("announce IPv6 response JSON serialization")?;
182+
println!("{pretty_json}");
183+
}
184+
Scrape(response) => {
185+
let pretty_json =
186+
serde_json::to_string_pretty(&ScrapeResponseDto::from(response)).context("scrape response JSON serialization")?;
187+
println!("{pretty_json}");
188+
}
189+
_ => println!("{response:#?}"), // todo: serialize to JSON all aquatic responses.
190+
};
191+
192+
Ok(())
193+
}
194+
210195
fn parse_socket_addr(tracker_socket_addr_str: &str) -> anyhow::Result<SocketAddr> {
211196
debug!("Tracker socket address: {tracker_socket_addr_str:#?}");
212197

src/console/clients/udp/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod app;
22
pub mod checker;
3+
pub mod responses;

src/console/clients/udp/responses.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Aquatic responses are not serializable. These are the serializable wrappers.
2+
use std::net::{Ipv4Addr, Ipv6Addr};
3+
4+
use aquatic_udp_protocol::{AnnounceResponse, ScrapeResponse};
5+
use serde::Serialize;
6+
7+
#[derive(Serialize)]
8+
pub struct AnnounceResponseDto {
9+
transaction_id: i32,
10+
announce_interval: i32,
11+
leechers: i32,
12+
seeders: i32,
13+
peers: Vec<String>,
14+
}
15+
16+
impl From<AnnounceResponse<Ipv4Addr>> for AnnounceResponseDto {
17+
fn from(announce: AnnounceResponse<Ipv4Addr>) -> Self {
18+
Self {
19+
transaction_id: announce.transaction_id.0,
20+
announce_interval: announce.announce_interval.0,
21+
leechers: announce.leechers.0,
22+
seeders: announce.seeders.0,
23+
peers: announce
24+
.peers
25+
.iter()
26+
.map(|peer| format!("{}:{}", peer.ip_address, peer.port.0))
27+
.collect::<Vec<_>>(),
28+
}
29+
}
30+
}
31+
32+
impl From<AnnounceResponse<Ipv6Addr>> for AnnounceResponseDto {
33+
fn from(announce: AnnounceResponse<Ipv6Addr>) -> Self {
34+
Self {
35+
transaction_id: announce.transaction_id.0,
36+
announce_interval: announce.announce_interval.0,
37+
leechers: announce.leechers.0,
38+
seeders: announce.seeders.0,
39+
peers: announce
40+
.peers
41+
.iter()
42+
.map(|peer| format!("{}:{}", peer.ip_address, peer.port.0))
43+
.collect::<Vec<_>>(),
44+
}
45+
}
46+
}
47+
48+
#[derive(Serialize)]
49+
pub struct ScrapeResponseDto {
50+
transaction_id: i32,
51+
torrent_stats: Vec<TorrentStats>,
52+
}
53+
54+
impl From<ScrapeResponse> for ScrapeResponseDto {
55+
fn from(scrape: ScrapeResponse) -> Self {
56+
Self {
57+
transaction_id: scrape.transaction_id.0,
58+
torrent_stats: scrape
59+
.torrent_stats
60+
.iter()
61+
.map(|torrent_scrape_statistics| TorrentStats {
62+
seeders: torrent_scrape_statistics.seeders.0,
63+
completed: torrent_scrape_statistics.completed.0,
64+
leechers: torrent_scrape_statistics.leechers.0,
65+
})
66+
.collect::<Vec<_>>(),
67+
}
68+
}
69+
}
70+
71+
#[derive(Serialize)]
72+
struct Peer {
73+
seeders: i32,
74+
completed: i32,
75+
leechers: i32,
76+
}
77+
78+
#[derive(Serialize)]
79+
struct TorrentStats {
80+
seeders: i32,
81+
completed: i32,
82+
leechers: i32,
83+
}

0 commit comments

Comments
 (0)