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        timeout.unwrap_or_default()
68    }
69
70    pub async fn copy_bidirectional_udp(
71        &mut self,
72        listener: &Arc<UdpSocket>,
73        sock: UdpSocket,
74    ) -> Result<()> {
75        let mut recv_buf = [0; 65536];
76        loop {
77            tokio::select! {
78                res = self.recv() => {
79                    match res {
80                        Some(res) => sock.send(&res).await?,
81                        None => break
82                    };
83                }
84                res = sock.recv(&mut recv_buf) => {
85                    let n = res?;
86                    listener.send_to(&recv_buf[..n], self.addr).await?;
87                }
88            }
89        }
90
91        self.remove().await;
92        Ok(())
93    }
94
95    pub async fn copy_bidirectional_tcp(
96        &mut self,
97        listener: &Arc<UdpSocket>,
98        mut sock: TcpStream,
99    ) -> Result<()> {
100        let mut recv_buf = [0; 65536];
101        loop {
102            tokio::select! {
103                res = self.recv() => {
104                    match res {
105                        Some(res) => {
106                            sock.write_u16(res.len() as u16).await?;
107                            sock.write_all(&res).await?;
108                        },
109                        None => break
110                    };
111                }
112                n = sock.read_u16() => {
113                    let n = n?;
114                    sock.read_exact(&mut recv_buf[..n as usize]).await?;
115                    listener.send_to(&recv_buf[..n as usize], self.addr).await?;
116                }
117            }
118        }
119
120        self.remove().await;
121        Ok(())
122    }
123
124    async fn remove(&self) {
125        self.tunnel_map.write().await.remove(&self.addr);
126    }
127}