relay_man/client/
response.rs

1use std::{
2    mem::MaybeUninit,
3    net::{SocketAddr, ToSocketAddrs},
4    time::{Duration, SystemTime, UNIX_EPOCH},
5};
6
7use socket2::{Domain, Protocol, SockAddr, Socket, Type};
8
9use crate::common::{adress::Adress, packets::Packets, FromRawSock, IntoRawSock, RawSock};
10
11use super::TConnection;
12
13pub struct Response<T, R> {
14    pub connection: T,
15    pub packets: Packets,
16    pub fn_has: fn(&T, &Packets) -> bool,
17    pub fn_get: fn(T, Packets) -> R,
18}
19
20impl<T, R> Response<T, R> {
21    pub fn has(&self) -> bool {
22        (self.fn_has)(&self.connection, &self.packets)
23    }
24
25    pub fn get(self) -> R {
26        while !self.has() {
27            std::thread::sleep(Duration::from_millis(0));
28        }
29        (self.fn_get)(self.connection, self.packets)
30    }
31}
32
33pub enum RequestStage {
34    NewRequest(NewRequest),
35    NewRequestResponse(NewRequestResponse),
36    NewRequestFinal(NewRequestFinal),
37    ConnectOn(ConnectOn),
38}
39
40pub struct NewRequest {
41    pub connection: Box<dyn TConnection>,
42    pub from: Adress,
43    pub secret: String,
44}
45
46impl NewRequest {
47    pub fn accept(self, accept: bool) -> Response<Box<dyn TConnection>, NewRequestFinal> {
48        self.connection.request_response(&self.from, accept)
49    }
50}
51
52pub struct NewRequestResponse {
53    pub connection: Box<dyn TConnection>,
54    pub from: Adress,
55    pub accept: bool,
56    pub secret: String,
57}
58
59impl NewRequestResponse {
60    pub fn add_port(&self, port: u16) {
61        self.connection.add_port(port)
62    }
63
64    /// `time_offset` should be in nanosecconds
65    pub fn accept(
66        self,
67        accept: bool,
68        time_offset: Option<u128>,
69    ) -> Response<Box<dyn TConnection>, ConnectOn> {
70        self.connection
71            .request_final(&self.from, accept, time_offset)
72    }
73}
74
75pub struct NewRequestFinal {
76    pub connection: Box<dyn TConnection>,
77    pub from: Adress,
78    pub accept: bool,
79}
80
81impl NewRequestFinal {
82    pub fn add_port(&self, port: u16) {
83        self.connection.add_port(port)
84    }
85}
86
87pub struct ConnectOn {
88    pub connection: Box<dyn TConnection + Send>,
89    pub adress: Adress,
90    pub to: String,
91    pub port: u16,
92    pub time: u128,
93}
94
95impl std::fmt::Debug for ConnectOn {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        f.debug_struct("ConnectOn")
98            .field("adress", &self.adress)
99            .field("to", &self.to)
100            .field("port", &self.port)
101            .field("time", &self.time)
102            .finish()
103    }
104}
105
106#[derive(Debug)]
107pub enum ConnectOnError {
108    CannotBind,
109    CannotSetNonBlocking,
110    TimoutIsLesTheResend,
111    StageOneFailed,
112    StageTwoFailed,
113}
114
115#[derive(Debug)]
116pub struct Conn {
117    my_adress: SocketAddr,
118    addr: SocketAddr,
119    port: u16,
120    fd: RawSock,
121    pub socket: Socket,
122    pub had_upnp: bool,
123}
124
125impl Conn {
126    pub fn fd(&self) -> RawSock {
127        self.fd
128    }
129
130    pub fn addr(&self) -> SocketAddr {
131        self.addr
132    }
133
134    pub fn my_addr(&self) -> SocketAddr {
135        self.my_adress
136    }
137
138    pub fn port(&self) -> u16 {
139        self.port
140    }
141
142    pub fn socket(&self) -> &Socket {
143        &self.socket
144    }
145
146    pub fn mut_socket(&mut self) -> &mut Socket {
147        &mut self.socket
148    }
149}
150
151impl std::ops::Deref for Conn {
152    type Target = Socket;
153
154    fn deref(&self) -> &Self::Target {
155        &self.socket
156    }
157}
158
159impl std::ops::DerefMut for Conn {
160    fn deref_mut(&mut self) -> &mut Self::Target {
161        &mut self.socket
162    }
163}
164
165impl Drop for Conn {
166    fn drop(&mut self) {
167        if self.had_upnp {
168            if let Ok(upnp_gateway) = igd::search_gateway(igd::SearchOptions::default()) {
169                if let SocketAddr::V4(_) = self.my_adress {
170                    let _ = upnp_gateway.remove_port(igd::PortMappingProtocol::UDP, self.port);
171                }
172            }
173        }
174    }
175}
176
177impl ConnectOn {
178    /// timeout need to be bigger then resend
179    pub fn connect(
180        self,
181        timeout: Duration,
182        resend: Duration,
183        nonblocking: bool,
184    ) -> Result<Conn, ConnectOnError> {
185        if timeout < resend {
186            return Err(ConnectOnError::TimoutIsLesTheResend);
187        }
188
189        let local_adress = local_ip_address::local_ip().unwrap();
190        let addr = self.to.to_socket_addrs().unwrap().next().unwrap();
191        let my_addr = format!("{}:{}", local_adress, self.port)
192            .to_socket_addrs()
193            .unwrap()
194            .next()
195            .unwrap();
196
197        let sock_my_addr = SockAddr::from(my_addr);
198        let sock_addr = SockAddr::from(addr);
199
200        println!("SockAddr: {}", sock_addr.as_socket().unwrap());
201
202        let socket = Socket::new(
203            Domain::for_address(addr),
204            Type::DGRAM,
205            Some(Protocol::from(0)),
206        )
207        .unwrap();
208        let fd = socket.into_raw();
209        let mut conn = Conn {
210            my_adress: my_addr,
211            addr,
212            fd,
213            port: self.port,
214            socket: Socket::from_raw(fd),
215            had_upnp: false,
216        };
217        let Ok(_) = conn.bind(&sock_my_addr) else{return Err(ConnectOnError::CannotBind)};
218        let Ok(_) = conn.set_nonblocking(nonblocking) else {return Err(ConnectOnError::CannotSetNonBlocking)};
219        let _ = conn.set_read_timeout(Some(resend));
220        let _ = conn.set_write_timeout(Some(resend));
221
222        'try_to_port_forword: {
223            let mut n = natpmp::Natpmp::new().unwrap();
224            n.send_port_mapping_request(natpmp::Protocol::UDP, self.port, self.port, 30)
225                .unwrap();
226
227            loop {
228                match n.read_response_or_retry() {
229                    Ok(ok) => match ok {
230                        natpmp::Response::UDP(res) => {
231                            println!(
232                                "PMP Open: public: {}, private: {}, lifetime: {:?}",
233                                res.public_port(),
234                                res.private_port(),
235                                res.lifetime()
236                            );
237                            break 'try_to_port_forword;
238                        }
239                        _ => {
240                            println!("PMP Failed: {:?}", ok);
241                            break;
242                        }
243                    },
244                    Err(err) => {
245                        std::thread::sleep(Duration::from_millis(500));
246                        match err {
247                            natpmp::Error::NATPMP_TRYAGAIN => {}
248                            _ => {
249                                println!("PMP Error: {:?}", err);
250                                break;
251                            }
252                        }
253                    }
254                }
255            }
256
257            if let Ok(upnp_gateway) = igd::search_gateway(igd::SearchOptions::default()) {
258                if let SocketAddr::V4(ip) = my_addr {
259                    let res = upnp_gateway.add_port(
260                        igd::PortMappingProtocol::UDP,
261                        self.port,
262                        ip,
263                        30,
264                        "RelayMan",
265                    );
266
267                    match res {
268                        Ok(_) => {
269                            println!("UPNP Open port: {} for: {}", self.port, my_addr);
270                            conn.had_upnp = true;
271                            break 'try_to_port_forword;
272                        }
273                        Err(err) => println!("UPNP Error: {:?}", err),
274                    }
275                }
276            } else {
277                println!("No UPNP gateway");
278            }
279        }
280
281        while SystemTime::now()
282            .duration_since(UNIX_EPOCH)
283            .unwrap()
284            .as_nanos()
285            < self.time
286        {}
287
288        println!("Start");
289
290        let time = SystemTime::now();
291        let mut time_send = time;
292
293        let mut buffer = [MaybeUninit::new(0); 4];
294        let message = [1, 4, 21, 6];
295
296        // conn.connect(&sock_addr).unwrap();
297        // conn.send(&message).unwrap();
298        let _ = conn.send_to(&message, &sock_addr);
299
300        loop {
301            if time.elapsed().unwrap() > timeout {
302                return Err(ConnectOnError::StageOneFailed);
303            }
304
305            if let Ok((len, from)) = conn.recv_from(&mut buffer) {
306                if from.as_socket().unwrap() == sock_addr.as_socket().unwrap()
307                    && unsafe { std::mem::transmute::<&[MaybeUninit<u8>], &[u8]>(&buffer[0..len]) }
308                        == message
309                {
310                    conn.connect(&sock_addr).unwrap();
311                    println!("First stage succesful!");
312                    break;
313                }
314            }
315
316            if time_send.elapsed().unwrap() > resend {
317                time_send = SystemTime::now();
318                let _ = conn.send_to(&message, &sock_addr);
319            }
320        }
321
322        let message = [21, 20, 20, 21];
323        let time = SystemTime::now();
324        let mut time_send = time;
325        let _ = conn.send(&message);
326
327        loop {
328            if time.elapsed().unwrap() > timeout {
329                return Err(ConnectOnError::StageTwoFailed);
330            }
331
332            if let Ok(len) = conn.recv(&mut buffer) {
333                let buffer =
334                    unsafe { std::mem::transmute::<&[MaybeUninit<u8>], &[u8]>(&buffer[0..len]) };
335                if buffer == message {
336                    break;
337                }
338            }
339
340            if time_send.elapsed().unwrap() > resend {
341                time_send = SystemTime::now();
342                let _ = conn.send(&message);
343            }
344        }
345
346        Ok(conn)
347    }
348}
349
350pub struct SearchResponse {
351    pub adresses: Vec<Adress>,
352}