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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use dashmap::DashMap;
use std::{fmt::Display, sync::Arc, time::Duration};
use tokio::{
net::UdpSocket,
select,
sync::mpsc::{self, Sender},
};
#[derive(Debug)]
pub struct UdpProxy {
pub listen: String,
pub upstream: String,
pub buffer_size: usize,
}
impl Display for UdpProxy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}->{}", self.listen, self.upstream)
}
}
impl UdpProxy {
pub fn new(listen: String, upstream: String, buffer_size: usize) -> Self {
Self {
listen,
upstream,
buffer_size,
}
}
pub async fn run(self: Arc<Self>) -> std::io::Result<()> {
let server = Arc::new(UdpSocket::bind(&self.listen).await?);
println!("[info][udp][{self}] Listening");
let map: Arc<DashMap<_, Sender<Vec<u8>>>> = Arc::new(DashMap::new());
let mut buf = Vec::with_capacity(self.buffer_size);
unsafe {
buf.set_len(self.buffer_size);
}
loop {
let (len, addr) = match server.recv_from(&mut buf).await {
Ok(res) => res,
Err(e) => {
eprintln!("[warning][udp][{self}] Failed to recv from downstream: {e}");
continue;
}
};
match map.get(&addr) {
Some(tx) => {
if let Err(e) = tx.send(buf[..len].to_vec()).await {
eprintln!("[warning][udp][{self}] Tokio channel error: {e}");
continue;
}
}
None => {
let (tx, mut rx) = mpsc::channel(100);
let self_clone = self.clone();
let server_clone = server.clone();
if let Err(e) = tx.send(buf[..len].to_vec()).await {
eprintln!("[warning][udp][{self}] Tokio channel error: {e}");
}
map.insert(addr, tx);
let map_clone = map.clone();
tokio::spawn(async move {
let client = match UdpSocket::bind("127.0.0.1:0").await {
Ok(client) => client,
Err(e) => {
eprintln!(
"[warning][udp][{self_clone}] Failed to bind client socket: {e}"
);
return;
}
};
if let Err(e) = client.connect(&self_clone.upstream).await {
eprintln!(
"[warning][udp][{self_clone}] Failed to connect to upstream: {e}"
);
return;
};
let mut buf = Vec::with_capacity(self_clone.buffer_size);
unsafe {
buf.set_len(self_clone.buffer_size);
}
loop {
select! {
Some(received) = rx.recv() => {
if let Err(e) = client.send(&received).await {
eprintln!(
"[warning][udp][{self_clone}] Failed to send to upstream: {e}"
);
}
}
Ok(len) = client.recv(&mut buf) => {
if let Err(e) = server_clone.send_to(&buf[..len], &addr).await {
eprintln!(
"[warning][udp][{self_clone}] Failed to send to downstream: {e}"
);
}
}
_ = tokio::time::sleep(Duration::from_secs(60)) => {
println!(
"[info][udp][{self_clone}] No data transport for 60 seconds, closing connection"
);
break;
}
}
}
map_clone.remove(&addr);
});
}
}
}
}
}