forked from torrust/torrust-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.rs
More file actions
84 lines (68 loc) · 2.62 KB
/
Copy pathclient.rs
File metadata and controls
84 lines (68 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::io::Cursor;
use std::sync::Arc;
use aquatic_udp_protocol::{Request, Response};
use tokio::net::UdpSocket;
use torrust_tracker::servers::udp::MAX_PACKET_SIZE;
use crate::servers::udp::source_address;
#[allow(clippy::module_name_repetitions)]
pub struct UdpClient {
pub socket: Arc<UdpSocket>,
}
impl UdpClient {
pub async fn bind(local_address: &str) -> Self {
let socket = UdpSocket::bind(local_address).await.unwrap();
Self {
socket: Arc::new(socket),
}
}
pub async fn connect(&self, remote_address: &str) {
self.socket.connect(remote_address).await.unwrap();
}
pub async fn send(&self, bytes: &[u8]) -> usize {
self.socket.writable().await.unwrap();
self.socket.send(bytes).await.unwrap()
}
pub async fn receive(&self, bytes: &mut [u8]) -> usize {
self.socket.readable().await.unwrap();
self.socket.recv(bytes).await.unwrap()
}
}
/// Creates a new `UdpClient` connected to a Udp server
pub async fn new_udp_client_connected(remote_address: &str) -> UdpClient {
let port = 0; // Let OS choose an unused port.
let client = UdpClient::bind(&source_address(port)).await;
client.connect(remote_address).await;
client
}
#[allow(clippy::module_name_repetitions)]
pub struct UdpTrackerClient {
pub udp_client: UdpClient,
}
impl UdpTrackerClient {
pub async fn send(&self, request: Request) -> usize {
// Write request into a buffer
let request_buffer = vec![0u8; MAX_PACKET_SIZE];
let mut cursor = Cursor::new(request_buffer);
let request_data = match request.write(&mut cursor) {
Ok(_) => {
#[allow(clippy::cast_possible_truncation)]
let position = cursor.position() as usize;
let inner_request_buffer = cursor.get_ref();
// Return slice which contains written request data
&inner_request_buffer[..position]
}
Err(e) => panic!("could not write request to bytes: {e}."),
};
self.udp_client.send(request_data).await
}
pub async fn receive(&self) -> Response {
let mut response_buffer = [0u8; MAX_PACKET_SIZE];
let payload_size = self.udp_client.receive(&mut response_buffer).await;
Response::from_bytes(&response_buffer[..payload_size], true).unwrap()
}
}
/// Creates a new `UdpTrackerClient` connected to a Udp Tracker server
pub async fn new_udp_tracker_client_connected(remote_address: &str) -> UdpTrackerClient {
let udp_client = new_udp_client_connected(remote_address).await;
UdpTrackerClient { udp_client }
}