|
56 | 56 | //! ``` |
57 | 57 | //! |
58 | 58 | //! The protocol (`udp://`) in the URL is mandatory. The path (`\scrape`) is optional. It always uses `\scrape`. |
59 | | -use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs}; |
| 59 | +use std::net::{SocketAddr, ToSocketAddrs}; |
60 | 60 | use std::str::FromStr; |
61 | 61 |
|
62 | 62 | use anyhow::Context; |
63 | | -use aquatic_udp_protocol::common::InfoHash; |
64 | 63 | use aquatic_udp_protocol::Response::{AnnounceIpv4, AnnounceIpv6, Scrape}; |
65 | | -use aquatic_udp_protocol::{ |
66 | | - AnnounceEvent, AnnounceRequest, ConnectRequest, ConnectionId, NumberOfBytes, NumberOfPeers, PeerId, PeerKey, Port, Response, |
67 | | - ScrapeRequest, TransactionId, |
68 | | -}; |
| 64 | +use aquatic_udp_protocol::{Port, TransactionId}; |
69 | 65 | use clap::{Parser, Subcommand}; |
70 | 66 | use log::{debug, LevelFilter}; |
71 | 67 | use serde_json::json; |
72 | 68 | use url::Url; |
73 | 69 |
|
| 70 | +use crate::console::clients::udp::checker; |
74 | 71 | use crate::shared::bit_torrent::info_hash::InfoHash as TorrustInfoHash; |
75 | | -use crate::shared::bit_torrent::tracker::udp::client::{UdpClient, UdpTrackerClient}; |
| 72 | +use crate::shared::bit_torrent::tracker::udp::client::UdpClient; |
76 | 73 |
|
77 | | -const ASSIGNED_BY_OS: i32 = 0; |
| 74 | +const ASSIGNED_BY_OS: u16 = 0; |
78 | 75 | const RANDOM_TRANSACTION_ID: i32 = -888_840_697; |
79 | 76 |
|
80 | 77 | #[derive(Parser, Debug)] |
@@ -119,32 +116,42 @@ pub async fn run() -> anyhow::Result<()> { |
119 | 116 | debug!("Binding to: {local_bind_to}"); |
120 | 117 | let udp_client = UdpClient::bind(&local_bind_to).await; |
121 | 118 | let bound_to = udp_client.socket.local_addr().context("binding local address")?; |
122 | | - debug!("Bound to: {bound_to}"); |
123 | | - |
124 | | - let transaction_id = TransactionId(transaction_id); |
| 119 | + debug!("Bound to: {bound_to}"); |
125 | 120 |
|
126 | 121 | let response = match args.command { |
127 | 122 | Command::Announce { |
128 | 123 | tracker_socket_addr, |
129 | 124 | info_hash, |
130 | 125 | } => { |
131 | | - let (connection_id, udp_tracker_client) = connect(&tracker_socket_addr, udp_client, transaction_id).await; |
132 | | - |
133 | | - send_announce_request( |
134 | | - connection_id, |
135 | | - transaction_id, |
136 | | - info_hash, |
137 | | - Port(bound_to.port()), |
138 | | - &udp_tracker_client, |
139 | | - ) |
140 | | - .await |
| 126 | + let transaction_id = TransactionId(transaction_id); |
| 127 | + |
| 128 | + let mut new_udp_client = checker::Client::default(); |
| 129 | + let _bound_to = new_udp_client.bind(local_port).await?; |
| 130 | + |
| 131 | + new_udp_client.connect(&tracker_socket_addr, udp_client).await; |
| 132 | + |
| 133 | + let connection_id = new_udp_client.send_connection_request(transaction_id).await?; |
| 134 | + |
| 135 | + new_udp_client |
| 136 | + .send_announce_request(connection_id, transaction_id, info_hash, Port(bound_to.port())) |
| 137 | + .await? |
141 | 138 | } |
142 | 139 | Command::Scrape { |
143 | 140 | tracker_socket_addr, |
144 | 141 | info_hashes, |
145 | 142 | } => { |
146 | | - let (connection_id, udp_tracker_client) = connect(&tracker_socket_addr, udp_client, transaction_id).await; |
147 | | - send_scrape_request(connection_id, transaction_id, info_hashes, &udp_tracker_client).await |
| 143 | + let transaction_id = TransactionId(transaction_id); |
| 144 | + |
| 145 | + let mut new_udp_client = checker::Client::default(); |
| 146 | + let _bound_to = new_udp_client.bind(local_port).await?; |
| 147 | + |
| 148 | + new_udp_client.connect(&tracker_socket_addr, udp_client).await; |
| 149 | + |
| 150 | + let connection_id = new_udp_client.send_connection_request(transaction_id).await?; |
| 151 | + |
| 152 | + new_udp_client |
| 153 | + .send_scrape_request(connection_id, transaction_id, info_hashes) |
| 154 | + .await? |
148 | 155 | } |
149 | 156 | }; |
150 | 157 |
|
@@ -265,95 +272,3 @@ fn parse_info_hash(info_hash_str: &str) -> anyhow::Result<TorrustInfoHash> { |
265 | 272 | TorrustInfoHash::from_str(info_hash_str) |
266 | 273 | .map_err(|e| anyhow::Error::msg(format!("failed to parse info-hash `{info_hash_str}`: {e:?}"))) |
267 | 274 | } |
268 | | - |
269 | | -async fn connect( |
270 | | - tracker_socket_addr: &SocketAddr, |
271 | | - udp_client: UdpClient, |
272 | | - transaction_id: TransactionId, |
273 | | -) -> (ConnectionId, UdpTrackerClient) { |
274 | | - debug!("Connecting to tracker: udp://{tracker_socket_addr}"); |
275 | | - |
276 | | - udp_client.connect(&tracker_socket_addr.to_string()).await; |
277 | | - |
278 | | - let udp_tracker_client = UdpTrackerClient { udp_client }; |
279 | | - |
280 | | - let connection_id = send_connection_request(transaction_id, &udp_tracker_client).await; |
281 | | - |
282 | | - (connection_id, udp_tracker_client) |
283 | | -} |
284 | | - |
285 | | -async fn send_connection_request(transaction_id: TransactionId, client: &UdpTrackerClient) -> ConnectionId { |
286 | | - debug!("Sending connection request with transaction id: {transaction_id:#?}"); |
287 | | - |
288 | | - let connect_request = ConnectRequest { transaction_id }; |
289 | | - |
290 | | - client.send(connect_request.into()).await; |
291 | | - |
292 | | - let response = client.receive().await; |
293 | | - |
294 | | - debug!("connection request response:\n{response:#?}"); |
295 | | - |
296 | | - match response { |
297 | | - Response::Connect(connect_response) => connect_response.connection_id, |
298 | | - _ => panic!("error connecting to udp server. Unexpected response"), |
299 | | - } |
300 | | -} |
301 | | - |
302 | | -async fn send_announce_request( |
303 | | - connection_id: ConnectionId, |
304 | | - transaction_id: TransactionId, |
305 | | - info_hash: TorrustInfoHash, |
306 | | - port: Port, |
307 | | - client: &UdpTrackerClient, |
308 | | -) -> Response { |
309 | | - debug!("Sending announce request with transaction id: {transaction_id:#?}"); |
310 | | - |
311 | | - let announce_request = AnnounceRequest { |
312 | | - connection_id, |
313 | | - transaction_id, |
314 | | - info_hash: InfoHash(info_hash.bytes()), |
315 | | - peer_id: PeerId(*b"-qB00000000000000001"), |
316 | | - bytes_downloaded: NumberOfBytes(0i64), |
317 | | - bytes_uploaded: NumberOfBytes(0i64), |
318 | | - bytes_left: NumberOfBytes(0i64), |
319 | | - event: AnnounceEvent::Started, |
320 | | - ip_address: Some(Ipv4Addr::new(0, 0, 0, 0)), |
321 | | - key: PeerKey(0u32), |
322 | | - peers_wanted: NumberOfPeers(1i32), |
323 | | - port, |
324 | | - }; |
325 | | - |
326 | | - client.send(announce_request.into()).await; |
327 | | - |
328 | | - let response = client.receive().await; |
329 | | - |
330 | | - debug!("announce request response:\n{response:#?}"); |
331 | | - |
332 | | - response |
333 | | -} |
334 | | - |
335 | | -async fn send_scrape_request( |
336 | | - connection_id: ConnectionId, |
337 | | - transaction_id: TransactionId, |
338 | | - info_hashes: Vec<TorrustInfoHash>, |
339 | | - client: &UdpTrackerClient, |
340 | | -) -> Response { |
341 | | - debug!("Sending scrape request with transaction id: {transaction_id:#?}"); |
342 | | - |
343 | | - let scrape_request = ScrapeRequest { |
344 | | - connection_id, |
345 | | - transaction_id, |
346 | | - info_hashes: info_hashes |
347 | | - .iter() |
348 | | - .map(|torrust_info_hash| InfoHash(torrust_info_hash.bytes())) |
349 | | - .collect(), |
350 | | - }; |
351 | | - |
352 | | - client.send(scrape_request.into()).await; |
353 | | - |
354 | | - let response = client.receive().await; |
355 | | - |
356 | | - debug!("scrape request response:\n{response:#?}"); |
357 | | - |
358 | | - response |
359 | | -} |
0 commit comments