1use std::{
2 io::IoSliceMut,
3 net::{Ipv4Addr, SocketAddr},
4 pin::Pin,
5 sync::Arc,
6 task::{Context, Poll, ready},
7};
8
9use arc_swap::ArcSwap;
10use fast_socks5::{new_udp_header, util::target_addr::TargetAddr as SocksTargetAddr};
11use tokio::io::Interest;
12use wind_core::{
13 types::TargetAddr,
14 udp::{AbstractUdpSocket, QuinnRecvMeta, RecvMeta, Transmit, UdpPollHelper, UdpPoller, UdpSocketState},
15};
16
17#[derive(Debug)]
21pub struct Socks5UdpSocket {
22 io: tokio::net::UdpSocket,
23 inner: UdpSocketState,
24 source_addr: ArcSwap<SocketAddr>,
25}
26
27impl Socks5UdpSocket {
28 pub fn new(sock: std::net::UdpSocket) -> std::io::Result<Self> {
29 Ok(Self {
30 inner: UdpSocketState::new((&sock).into())?,
31 io: tokio::net::UdpSocket::from_std(sock)?,
32 source_addr: ArcSwap::new(Arc::new(SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0))),
33 })
34 }
35
36 fn convert_target_addr(socks_addr: &SocksTargetAddr) -> TargetAddr {
38 match socks_addr {
39 SocksTargetAddr::Ip(socket_addr) => match socket_addr {
40 SocketAddr::V4(addr) => TargetAddr::IPv4(*addr.ip(), addr.port()),
41 SocketAddr::V6(addr) => TargetAddr::IPv6(*addr.ip(), addr.port()),
42 },
43 SocksTargetAddr::Domain(domain, port) => TargetAddr::Domain(domain.clone(), *port),
44 }
45 }
46
47 pub fn source_addr(&self) -> SocketAddr {
49 **self.source_addr.load()
50 }
51
52 fn parse_udp_request_sync(data: &[u8]) -> Result<(u8, SocksTargetAddr, &[u8]), Box<dyn std::error::Error>> {
55 if data.len() < 4 {
56 return Err("Packet too short for SOCKS5 UDP header".into());
57 }
58
59 if data[0] != 0x00 || data[1] != 0x00 {
61 return Err("Invalid reserved bytes in SOCKS5 UDP header".into());
62 }
63
64 let frag = data[2];
65 let atyp = data[3];
66
67 let mut offset = 4;
68
69 let target_addr = match atyp {
71 0x01 => {
72 if data.len() < offset + 6 {
74 return Err("Incomplete IPv4 address in SOCKS5 UDP header".into());
75 }
76 let ip = std::net::Ipv4Addr::new(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
77 let port = u16::from_be_bytes([data[offset + 4], data[offset + 5]]);
78 offset += 6;
79 SocksTargetAddr::Ip(SocketAddr::V4(std::net::SocketAddrV4::new(ip, port)))
80 }
81 0x03 => {
82 if data.len() < offset + 1 {
84 return Err("Incomplete domain length in SOCKS5 UDP header".into());
85 }
86 let domain_len = data[offset] as usize;
87 offset += 1;
88
89 if data.len() < offset + domain_len + 2 {
90 return Err("Incomplete domain name in SOCKS5 UDP header".into());
91 }
92
93 let domain = String::from_utf8_lossy(&data[offset..offset + domain_len]).to_string();
94 offset += domain_len;
95 let port = u16::from_be_bytes([data[offset], data[offset + 1]]);
96 offset += 2;
97 SocksTargetAddr::Domain(domain, port)
98 }
99 0x04 => {
100 if data.len() < offset + 18 {
102 return Err("Incomplete IPv6 address in SOCKS5 UDP header".into());
103 }
104 let mut ip_bytes = [0u8; 16];
105 ip_bytes.copy_from_slice(&data[offset..offset + 16]);
106 let ip = std::net::Ipv6Addr::from(ip_bytes);
107 let port = u16::from_be_bytes([data[offset + 16], data[offset + 17]]);
108 offset += 18;
109 SocksTargetAddr::Ip(SocketAddr::V6(std::net::SocketAddrV6::new(ip, port, 0, 0)))
110 }
111 _ => {
112 return Err(format!("Unsupported address type: {}", atyp).into());
113 }
114 };
115
116 let payload = &data[offset..];
117 Ok((frag, target_addr, payload))
118 }
119}
120
121impl AbstractUdpSocket for Socks5UdpSocket {
122 fn create_io_poller(self: Arc<Self>) -> Pin<Box<dyn UdpPoller>> {
123 Box::pin(UdpPollHelper::new(move || {
124 let socket = self.clone();
125 async move { socket.io.writable().await }
126 }))
127 }
128
129 fn try_send(&self, transmit: &Transmit) -> std::io::Result<()> {
130 let socks_target = self.source_addr();
133
134 if let Ok(mut packet_with_header) = new_udp_header(socks_target) {
136 packet_with_header.extend_from_slice(transmit.contents);
137
138 let new_transmit = Transmit {
140 destination: socks_target,
141 contents: &packet_with_header,
142 ecn: transmit.ecn,
143 segment_size: transmit.segment_size,
144 src_ip: transmit.src_ip,
145 };
146
147 self.io
148 .try_io(Interest::WRITABLE, || self.inner.send((&self.io).into(), &new_transmit))
149 } else {
150 self.io
152 .try_io(Interest::WRITABLE, || self.inner.send((&self.io).into(), transmit))
153 }
154 }
155
156 fn poll_recv(&self, cx: &mut Context, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) -> Poll<std::io::Result<usize>> {
157 loop {
159 ready!(self.io.poll_recv_ready(cx))?;
160
161 let mut temp_bufs: Vec<Vec<u8>> = Vec::new();
163
164 for buf in bufs.iter() {
166 let temp_buf = vec![0u8; buf.len()];
167 temp_bufs.push(temp_buf);
168 }
169
170 let mut temp_io_bufs: Vec<IoSliceMut<'_>> = temp_bufs.iter_mut().map(|buf| IoSliceMut::new(buf)).collect();
172
173 let mut temp_meta = vec![QuinnRecvMeta::default(); meta.len()];
175
176 if let Ok(res) = self.io.try_io(Interest::READABLE, || {
177 self.inner.recv((&self.io).into(), &mut temp_io_bufs, &mut temp_meta)
178 }) {
179 let mut processed_count = 0;
181 for i in 0..res {
182 if temp_meta[i].len > 0 {
183 let packet_data = &temp_bufs[i][..temp_meta[i].len];
184
185 self.source_addr.store(Arc::new(temp_meta[i].addr));
187
188 match Self::parse_udp_request_sync(packet_data) {
190 Ok((_frag, target_addr, payload)) => {
191 let payload_len = payload.len().min(bufs[processed_count].len());
193 bufs[processed_count][..payload_len].copy_from_slice(&payload[..payload_len]);
194
195 meta[processed_count] = RecvMeta::from(temp_meta[i]);
197 meta[processed_count].len = payload_len;
198 meta[processed_count].destination = Some(Self::convert_target_addr(&target_addr));
199 processed_count += 1;
200 }
201 Err(_) => {
202 let data_len = temp_meta[i].len.min(bufs[processed_count].len());
204 bufs[processed_count][..data_len].copy_from_slice(&packet_data[..data_len]);
205
206 meta[processed_count] = RecvMeta::from(temp_meta[i]);
208 meta[processed_count].len = data_len;
209 processed_count += 1;
210 }
211 }
212 }
213 }
214 return Poll::Ready(Ok(processed_count));
215 }
216 }
217 }
218
219 fn local_addr(&self) -> std::io::Result<SocketAddr> {
220 self.io.local_addr()
221 }
222
223 fn may_fragment(&self) -> bool {
224 self.inner.may_fragment()
225 }
226
227 fn max_transmit_segments(&self) -> usize {
228 self.inner.max_gso_segments()
229 }
230
231 fn max_receive_segments(&self) -> usize {
232 self.inner.gro_segments()
233 }
234}