fkm_proxy/utils/
udp.rs

1use anyhow::Result;
2use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration};
3use tokio::{
4    io::{AsyncReadExt, AsyncWriteExt},
5    net::{TcpStream, UdpSocket},
6    sync::{
7        mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
8        RwLock,
9    },
10};
11
12type TunnelMapTest = Arc<RwLock<HashMap<SocketAddr, UnboundedSender<Vec<u8>>>>>;
13pub async fn server_accept(
14    listener: &Arc<UdpSocket>,
15    recv_buf: &mut [u8],
16    tunnel_map: &TunnelMapTest,
17) -> Result<(UdpClient, SocketAddr)> {
18    loop {
19        let (n, addr) = listener.recv_from(recv_buf).await?;
20        let rx = {
21            let mut tunnel_map_rw = tunnel_map.write().await;
22            if let Some(sock) = tunnel_map_rw.get_mut(&addr) {
23                if sock.is_closed() {
24                    let (tx, rx) = unbounded_channel();
25                    *sock = tx;
26                    sock.send(recv_buf[..n].to_vec())?;
27
28                    return Ok((UdpClient::new(tunnel_map, rx, addr), addr));
29                }
30
31                sock.send(recv_buf[..n].to_vec())?;
32                continue;
33            } else {
34                let (tx, rx) = unbounded_channel();
35                tx.send(recv_buf[..n].to_vec())?;
36                tunnel_map_rw.insert(addr, tx);
37
38                rx
39            }
40        };
41
42        return Ok((UdpClient::new(tunnel_map, rx, addr), addr));
43    }
44}
45
46pub struct UdpClient {
47    tunnel_map: TunnelMapTest,
48    rx: UnboundedReceiver<Vec<u8>>,
49    addr: SocketAddr,
50}
51
52impl UdpClient {
53    pub fn new(
54        tunnel_map: &TunnelMapTest,
55        rx: UnboundedReceiver<Vec<u8>>,
56        addr: SocketAddr,
57    ) -> Self {
58        Self {
59            tunnel_map: tunnel_map.clone(),
60            rx,
61            addr,
62        }
63    }
64
65    async fn recv(&mut self) -> Option<Vec<u8>> {
66        let timeout = tokio::time::timeout(Duration::from_secs(45), self.rx.recv()).await;
67        match timeout {
68            Ok(recv) => recv,
69            Err(_) => None,
70        }
71    }
72
73    pub async fn copy_bidirectional_udp(
74        &mut self,
75        listener: &Arc<UdpSocket>,
76        sock: UdpSocket,
77    ) -> Result<()> {
78        let mut recv_buf = [0; 65536];
79        loop {
80            tokio::select! {
81                res = self.recv() => {
82                    match res {
83                        Some(res) => sock.send(&res).await?,
84                        None => break
85                    };
86                }
87                res = sock.recv(&mut recv_buf) => {
88                    let n = res?;
89                    listener.send_to(&recv_buf[..n], self.addr).await?;
90                }
91            }
92        }
93
94        self.remove().await;
95        Ok(())
96    }
97
98    pub async fn copy_bidirectional_tcp(
99        &mut self,
100        listener: &Arc<UdpSocket>,
101        mut sock: TcpStream,
102    ) -> Result<()> {
103        let mut recv_buf = [0; 65536];
104        loop {
105            tokio::select! {
106                res = self.recv() => {
107                    match res {
108                        Some(res) => {
109                            sock.write_u16(res.len() as u16).await?;
110                            sock.write_all(&res).await?;
111                        },
112                        None => break
113                    };
114                }
115                n = sock.read_u16() => {
116                    let n = n?;
117                    sock.read_exact(&mut recv_buf[..n as usize]).await?;
118                    listener.send_to(&recv_buf[..n as usize], self.addr).await?;
119                }
120            }
121        }
122
123        self.remove().await;
124        Ok(())
125    }
126
127    async fn remove(&self) {
128        self.tunnel_map.write().await.remove(&self.addr);
129    }
130}