1use std::io::{ErrorKind, Write};
27use std::io::prelude::*;
28use std::net::{IpAddr, SocketAddr};
29use std::net::UdpSocket;
30use std::os::fd::{AsFd, BorrowedFd};
31use std::os::unix::prelude::AsRawFd;
32use std::time::Duration;
33use core::fmt::Debug;
34
35use std::net::TcpStream;
36
37
38
39use socket2::{Socket, Domain, Type, Protocol, SockAddr};
40
41use crate::{internal_error, internal_error_map};
42
43use crate::error::*;
44
45
46pub trait SocketTap
49{
50 fn connect(&mut self, timeout: Option<Duration>) -> CDnsResult<()>;
52
53 fn is_tcp(&self) -> bool;
55
56 fn is_conncected(&self) -> bool;
58
59 fn get_fd(&self) -> Option<BorrowedFd>;
61
62 fn get_remote_addr(&self) -> &SocketAddr;
64
65 fn send(&mut self, sndbuf: &[u8]) -> CDnsResult<usize> ;
67
68 fn recv(&mut self, rcvbuf: &mut [u8]) -> CDnsResult<usize>;
72}
73
74
75impl Debug for dyn SocketTap
76{
77 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
78 {
79 write!(f, "{:?}", self)
80 }
81}
82
83#[derive(Debug)]
85pub struct NetworkTap<T: AsRawFd>
86{
87 sock: Option<T>,
89 remote_addr: SocketAddr,
91 bind_addr: SocketAddr,
93 timeout: Option<Duration>,
95}
96
97impl SocketTap for NetworkTap<UdpSocket>
98{
99 fn connect(&mut self, timeout: Option<Duration>) -> CDnsResult<()>
100 {
101 if self.sock.is_some() == true
102 {
103 return Ok(());
105 }
106
107 let socket =
108 UdpSocket::bind(self.bind_addr)
109 .map_err(|e| internal_error_map!(CDnsErrorType::InternalError, "{}", e))?;
110
111 socket
113 .set_nonblocking(timeout.is_none())
114 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
115
116 socket
118 .set_read_timeout(timeout.clone())
119 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
120
121 self.timeout = timeout;
122
123 socket
124 .connect(&self.remote_addr)
125 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
126
127 self.sock = Some(socket);
128
129 return Ok(());
130 }
131
132 fn is_tcp(&self) -> bool
133 {
134 return false;
135 }
136
137 fn is_conncected(&self) -> bool
138 {
139 return self.sock.is_some();
140 }
141
142 fn get_fd(&self) -> Option<BorrowedFd>
143 {
144 return self.sock.as_ref().map(|v| v.as_fd());
145 }
146
147 fn get_remote_addr(&self) -> &SocketAddr
148 {
149 return &self.remote_addr;
150 }
151
152 fn send(&mut self, sndbuf: &[u8]) -> CDnsResult<usize>
153 {
154 return
155 self
156 .sock
157 .as_mut()
158 .unwrap()
159 .send(sndbuf)
160 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e));
161 }
162
163 fn recv(&mut self, rcvbuf: &mut [u8]) -> CDnsResult<usize>
164 {
165 let mut retry: u64 = 5;
166 loop
167 {
168 match self.sock.as_mut().unwrap().recv_from(rcvbuf)
169 {
170 Ok((rcv_len, rcv_src)) =>
171 {
172 if rcv_src != self.remote_addr
174 {
175 internal_error!(
176 CDnsErrorType::DnsResponse,
177 "received answer from unknown host: '{}' exp: '{}'",
178 self.remote_addr,
179 rcv_src
180 );
181 }
182
183 return Ok(rcv_len);
184 },
185 Err(ref e) if e.kind() == ErrorKind::WouldBlock =>
186 {
187 if self.timeout.is_some() == true
189 {
190 internal_error!(CDnsErrorType::RequestTimeout, "request timeout from: '{}'", self.remote_addr);
192 }
193 else
194 {
195 if retry == 0
197 {
198 internal_error!(CDnsErrorType::IoError, "can not receive from: '{}'", self.remote_addr);
199 }
200
201 retry -= 1;
202 continue;
203 }
204 },
205 Err(ref e) if e.kind() == ErrorKind::Interrupted =>
206 {
207 continue;
208 },
209 Err(e) =>
210 {
211 internal_error!(CDnsErrorType::IoError, "{}", e);
212 }
213 } } }
216}
217
218impl SocketTap for NetworkTap<TcpStream>
219{
220 fn connect(&mut self, timeout: Option<Duration>) -> CDnsResult<()>
221 {
222 if self.sock.is_some() == true
223 {
224 return Ok(());
226 }
227
228 let socket =
230 Socket::new(Domain::for_address(self.remote_addr), Type::STREAM, Some(Protocol::TCP))
231 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
232
233 socket.bind(&SockAddr::from(self.bind_addr))
235 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
236
237 socket.connect(&SockAddr::from(self.remote_addr))
239 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
240
241 let socket: TcpStream = socket.into();
243
244 socket.set_nonblocking(timeout.is_none())
246 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
247
248 socket.set_read_timeout(timeout.clone())
250 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e))?;
251
252 self.timeout = timeout;
253
254 self.sock = Some(socket);
255
256 return Ok(());
257 }
258
259 fn is_tcp(&self) -> bool
260 {
261 return true;
262 }
263
264 fn is_conncected(&self) -> bool
265 {
266 return self.sock.is_some();
267 }
268
269 fn get_fd(&self) -> Option<BorrowedFd>
270 {
271 return self.sock.as_ref().map(|v| v.as_fd());
272 }
273
274 fn get_remote_addr(&self) -> &SocketAddr
275 {
276 return &self.remote_addr;
277 }
278
279 fn send(&mut self, sndbuf: &[u8]) -> CDnsResult<usize>
280 {
281 return
282 self
283 .sock
284 .as_mut()
285 .unwrap()
286 .write(sndbuf)
287 .map_err(|e| internal_error_map!(CDnsErrorType::IoError, "{}", e));
288 }
289
290 fn recv(&mut self, rcvbuf: &mut [u8]) -> CDnsResult<usize>
291 {
292 let mut retry: u64 = 5;
293 loop
294 {
295 match self.sock.as_ref().unwrap().read(rcvbuf)
296 {
297 Ok(n) =>
298 {
299 return Ok(n);
300 },
301 Err(ref e) if e.kind() == ErrorKind::WouldBlock =>
302 {
303 if self.timeout.is_some() == true
305 {
306 internal_error!(CDnsErrorType::RequestTimeout, "request timeout from: '{}'", self.remote_addr);
308 }
309 else
310 {
311 if retry == 0
313 {
314 internal_error!(CDnsErrorType::IoError, "can not receive from: '{}'", self.remote_addr);
315 }
316
317 retry -= 1;
318 continue;
319 }
320 },
321 Err(ref e) if e.kind() == ErrorKind::Interrupted =>
322 {
323 continue;
324 },
325 Err(e) =>
326 {
327 internal_error!(CDnsErrorType::IoError, "{}", e);
328 }
329 }
330 }
331 }
332}
333
334impl<T: AsRawFd> NetworkTap<T>
335{
336
337}
338
339
340pub
357fn new_udp(
358 resolver_ip: &IpAddr,
359 resolver_port: u16,
360 bind_addr: &SocketAddr
361) -> CDnsResult<Box<dyn SocketTap>>
362{
363 let remote_dns_host = SocketAddr::from((resolver_ip.clone(), resolver_port));
365
366 let ret =
367 NetworkTap::<UdpSocket>
368 {
369 sock: None,
370 remote_addr: remote_dns_host,
371 bind_addr: bind_addr.clone(),
372 timeout: None
373 };
374
375 return Ok( Box::new(ret) );
376}
377
378pub
395fn new_tcp(
396 resolver_ip: &IpAddr,
397 resolver_port: u16,
398 bind_addr: &SocketAddr
399) -> CDnsResult<Box<dyn SocketTap>>
400{
401 let remote_dns_host = SocketAddr::from((resolver_ip.clone(), resolver_port));
403
404 let ret =
405 NetworkTap::<TcpStream>
406 {
407 sock: None,
408 remote_addr: remote_dns_host,
409 bind_addr: bind_addr.clone(),
410 timeout: None
411 };
412
413 return Ok( Box::new(ret) );
414}
415
416
417
418
419#[test]
420fn test_struct()
421{
422 use super::common::IPV4_BIND_ALL;
423
424 let ip0: IpAddr = "127.0.0.1".parse().unwrap();
425 let bind = SocketAddr::from((IPV4_BIND_ALL, 0));
426 let res = new_udp(&ip0, 53, &bind);
427
428 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
429
430 let _res = res.unwrap();
431}