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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::upstream::UpstreamHttpsClient;
use std::{io, net::SocketAddr, sync::Arc};
use tokio::net::UdpSocket;
use trust_dns_proto::op::message::Message;
pub struct LocalUdpSocket {
udp_socket: Arc<UdpSocket>,
upstream_https_client: UpstreamHttpsClient,
}
impl LocalUdpSocket {
pub async fn new(host: String, port: u16, upstream_https_client: UpstreamHttpsClient) -> Self {
let socket_addr = match format!("{}:{}", host, port).parse::<SocketAddr>() {
Ok(socket_addr) => socket_addr,
Err(_) => {
panic!("[local] failed to parse the address {}:{}", host, port,);
}
};
let udp_socket = match UdpSocket::bind(socket_addr).await {
Ok(udp_socket) => {
println!("[local] listening on {}:{}", host, port);
Arc::new(udp_socket)
}
Err(error) => match error.kind() {
io::ErrorKind::PermissionDenied => {
panic!(
"[local] failed to bind to the address {}:{} (Permission denied)",
host, port
);
}
_ => {
panic!("[local] failed to bind to the address {}:{}", host, port);
}
},
};
LocalUdpSocket {
udp_socket,
upstream_https_client,
}
}
pub async fn listen(&self) {
loop {
let mut buffer = [0; 512];
let udp_socket = self.udp_socket.clone();
let upstream_https_client = self.upstream_https_client.clone();
let (_, addr) = match udp_socket.recv_from(&mut buffer).await {
Ok(udp_recv_from_result) => udp_recv_from_result,
Err(_) => {
println!("[local] failed to receive the datagram message");
continue;
}
};
tokio::spawn(async move {
LocalUdpSocket::process(upstream_https_client, udp_socket, addr, &buffer).await;
});
}
}
pub async fn process(
mut upstream_https_client: UpstreamHttpsClient,
udp_socket: Arc<UdpSocket>,
addr: SocketAddr,
buffer: &[u8; 512],
) {
let request_message = match Message::from_vec(buffer) {
Ok(request_message) => request_message,
Err(_) => {
return;
}
};
let response_message = match upstream_https_client.process(request_message).await {
Ok(response_message) => response_message,
Err(error) => {
println!("{}", error);
return;
}
};
let raw_response_message = match response_message.to_vec() {
Ok(raw_response_message) => raw_response_message,
Err(_) => {
return;
}
};
match udp_socket.send_to(&raw_response_message, &addr).await {
Ok(_) => (),
Err(_) => {
println!("[local] failed to send the inbound response to the client");
}
};
}
}