1#![allow(clippy::integer_arithmetic)]
3use {
4 log::*,
5 rand::{thread_rng, Rng},
6 socket2::{Domain, SockAddr, Socket, Type},
7 std::{
8 collections::{BTreeMap, HashSet},
9 io::{self, Read, Write},
10 net::{IpAddr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket},
11 sync::{mpsc::channel, Arc, RwLock},
12 time::{Duration, Instant},
13 },
14 url::Url,
15};
16
17mod ip_echo_server;
18pub use ip_echo_server::{ip_echo_server, IpEchoServer, MAX_PORT_COUNT_PER_MESSAGE};
19use ip_echo_server::{IpEchoServerMessage, IpEchoServerResponse};
20
21pub struct UdpSocketPair {
23 pub addr: SocketAddr, pub receiver: UdpSocket, pub sender: UdpSocket, }
27
28pub type PortRange = (u16, u16);
29
30pub(crate) const HEADER_LENGTH: usize = 4;
31pub(crate) const IP_ECHO_SERVER_RESPONSE_LENGTH: usize = HEADER_LENGTH + 23;
32
33fn ip_echo_server_request(
34 ip_echo_server_addr: &SocketAddr,
35 msg: IpEchoServerMessage,
36) -> Result<IpEchoServerResponse, String> {
37 let timeout = Duration::new(5, 0);
38 TcpStream::connect_timeout(ip_echo_server_addr, timeout)
39 .and_then(|mut stream| {
40 let mut bytes = vec![0; HEADER_LENGTH];
42
43 bytes.append(&mut bincode::serialize(&msg).expect("serialize IpEchoServerMessage"));
44
45 bytes.push(b'\n');
48
49 stream.set_read_timeout(Some(Duration::new(10, 0)))?;
50 stream.write_all(&bytes)?;
51 stream.shutdown(std::net::Shutdown::Write)?;
52 let mut data = vec![0u8; IP_ECHO_SERVER_RESPONSE_LENGTH];
53 let _ = stream.read(&mut data[..])?;
54 Ok(data)
55 })
56 .and_then(|data| {
57 if data.len() < HEADER_LENGTH {
61 return Err(io::Error::new(
62 io::ErrorKind::Other,
63 format!("Response too short, received {} bytes", data.len()),
64 ));
65 }
66
67 let response_header: String =
68 data[0..HEADER_LENGTH].iter().map(|b| *b as char).collect();
69 if response_header != "\0\0\0\0" {
70 if response_header == "HTTP" {
71 let http_response = data.iter().map(|b| *b as char).collect::<String>();
72 return Err(io::Error::new(
73 io::ErrorKind::Other,
74 format!(
75 "Invalid gossip entrypoint. {} looks to be an HTTP port: {}",
76 ip_echo_server_addr, http_response
77 ),
78 ));
79 }
80 return Err(io::Error::new(
81 io::ErrorKind::Other,
82 format!(
83 "Invalid gossip entrypoint. {} provided an invalid response header: '{}'",
84 ip_echo_server_addr, response_header
85 ),
86 ));
87 }
88
89 bincode::deserialize(&data[HEADER_LENGTH..]).map_err(|err| {
90 io::Error::new(
91 io::ErrorKind::Other,
92 format!("Failed to deserialize: {:?}", err),
93 )
94 })
95 })
96 .map_err(|err| err.to_string())
97}
98
99pub fn get_public_ip_addr(ip_echo_server_addr: &SocketAddr) -> Result<IpAddr, String> {
102 let resp = ip_echo_server_request(ip_echo_server_addr, IpEchoServerMessage::default())?;
103 Ok(resp.address)
104}
105
106pub fn get_cluster_shred_version(ip_echo_server_addr: &SocketAddr) -> Result<u16, String> {
107 let resp = ip_echo_server_request(ip_echo_server_addr, IpEchoServerMessage::default())?;
108 resp.shred_version
109 .ok_or_else(|| String::from("IP echo server does not return a shred-version"))
110}
111
112const DEFAULT_TIMEOUT_SECS: u64 = 5;
115const DEFAULT_RETRY_COUNT: usize = 5;
116
117fn do_verify_reachable_ports(
118 ip_echo_server_addr: &SocketAddr,
119 tcp_listeners: Vec<(u16, TcpListener)>,
120 udp_sockets: &[&UdpSocket],
121 timeout: u64,
122 udp_retry_count: usize,
123) -> bool {
124 info!(
125 "Checking that tcp ports {:?} are reachable from {:?}",
126 tcp_listeners, ip_echo_server_addr
127 );
128
129 let tcp_ports: Vec<_> = tcp_listeners.iter().map(|(port, _)| *port).collect();
130 let _ = ip_echo_server_request(
131 ip_echo_server_addr,
132 IpEchoServerMessage::new(&tcp_ports, &[]),
133 )
134 .map_err(|err| warn!("ip_echo_server request failed: {}", err));
135
136 let mut ok = true;
137 let timeout = Duration::from_secs(timeout);
138
139 for (port, tcp_listener) in tcp_listeners {
141 let (sender, receiver) = channel();
142 let listening_addr = tcp_listener.local_addr().unwrap();
143 let thread_handle = std::thread::spawn(move || {
144 debug!("Waiting for incoming connection on tcp/{}", port);
145 match tcp_listener.incoming().next() {
146 Some(_) => sender
147 .send(())
148 .unwrap_or_else(|err| warn!("send failure: {}", err)),
149 None => warn!("tcp incoming failed"),
150 }
151 });
152 match receiver.recv_timeout(timeout) {
153 Ok(_) => {
154 info!("tcp/{} is reachable", port);
155 }
156 Err(err) => {
157 error!(
158 "Received no response at tcp/{}, check your port configuration: {}",
159 port, err
160 );
161 TcpStream::connect_timeout(&listening_addr, timeout).unwrap();
166 ok = false;
167 }
168 }
169 thread_handle.join().unwrap();
171 }
172
173 if !ok {
174 return ok;
176 }
177
178 let mut udp_ports: BTreeMap<_, _> = BTreeMap::new();
179 udp_sockets.iter().for_each(|udp_socket| {
180 let port = udp_socket.local_addr().unwrap().port();
181 udp_ports
182 .entry(port)
183 .or_insert_with(Vec::new)
184 .push(udp_socket);
185 });
186 let udp_ports: Vec<_> = udp_ports.into_iter().collect();
187
188 info!(
189 "Checking that udp ports {:?} are reachable from {:?}",
190 udp_ports.iter().map(|(port, _)| port).collect::<Vec<_>>(),
191 ip_echo_server_addr
192 );
193
194 'outer: for checked_ports_and_sockets in udp_ports.chunks(MAX_PORT_COUNT_PER_MESSAGE) {
195 ok = false;
196
197 for udp_remaining_retry in (0_usize..udp_retry_count).rev() {
198 let (checked_ports, checked_socket_iter) = (
199 checked_ports_and_sockets
200 .iter()
201 .map(|(port, _)| *port)
202 .collect::<Vec<_>>(),
203 checked_ports_and_sockets
204 .iter()
205 .flat_map(|(_, sockets)| sockets),
206 );
207
208 let _ = ip_echo_server_request(
209 ip_echo_server_addr,
210 IpEchoServerMessage::new(&[], &checked_ports),
211 )
212 .map_err(|err| warn!("ip_echo_server request failed: {}", err));
213
214 let reachable_ports = Arc::new(RwLock::new(HashSet::new()));
216 let thread_handles: Vec<_> = checked_socket_iter
217 .map(|udp_socket| {
218 let port = udp_socket.local_addr().unwrap().port();
219 let udp_socket = udp_socket.try_clone().expect("Unable to clone udp socket");
220 let reachable_ports = reachable_ports.clone();
221 std::thread::spawn(move || {
222 let start = Instant::now();
223
224 let original_read_timeout = udp_socket.read_timeout().unwrap();
225 udp_socket
226 .set_read_timeout(Some(Duration::from_millis(250)))
227 .unwrap();
228 loop {
229 if reachable_ports.read().unwrap().contains(&port)
230 || Instant::now().duration_since(start) >= timeout
231 {
232 break;
233 }
234
235 let recv_result = udp_socket.recv(&mut [0; 1]);
236 debug!(
237 "Waited for incoming datagram on udp/{}: {:?}",
238 port, recv_result
239 );
240
241 if recv_result.is_ok() {
242 reachable_ports.write().unwrap().insert(port);
243 break;
244 }
245 }
246 udp_socket.set_read_timeout(original_read_timeout).unwrap();
247 })
248 })
249 .collect();
250
251 for thread in thread_handles {
256 thread.join().unwrap();
257 }
258
259 let reachable_ports = reachable_ports.read().unwrap().clone();
260 if reachable_ports.len() == checked_ports.len() {
261 info!(
262 "checked udp ports: {:?}, reachable udp ports: {:?}",
263 checked_ports, reachable_ports
264 );
265 ok = true;
266 break;
267 } else if udp_remaining_retry > 0 {
268 error!(
270 "checked udp ports: {:?}, reachable udp ports: {:?}",
271 checked_ports, reachable_ports
272 );
273 error!("There are some udp ports with no response!! Retrying...");
274 } else {
275 error!("Maximum retry count is reached....");
276 break 'outer;
277 }
278 }
279 }
280
281 ok
282}
283
284pub fn verify_reachable_ports(
285 ip_echo_server_addr: &SocketAddr,
286 tcp_listeners: Vec<(u16, TcpListener)>,
287 udp_sockets: &[&UdpSocket],
288) -> bool {
289 do_verify_reachable_ports(
290 ip_echo_server_addr,
291 tcp_listeners,
292 udp_sockets,
293 DEFAULT_TIMEOUT_SECS,
294 DEFAULT_RETRY_COUNT,
295 )
296}
297
298pub fn parse_port_or_addr(optstr: Option<&str>, default_addr: SocketAddr) -> SocketAddr {
299 if let Some(addrstr) = optstr {
300 if let Ok(port) = addrstr.parse() {
301 let mut addr = default_addr;
302 addr.set_port(port);
303 addr
304 } else if let Ok(addr) = addrstr.parse() {
305 addr
306 } else {
307 default_addr
308 }
309 } else {
310 default_addr
311 }
312}
313
314pub fn parse_port_range(port_range: &str) -> Option<PortRange> {
315 let ports: Vec<&str> = port_range.split('-').collect();
316 if ports.len() != 2 {
317 return None;
318 }
319
320 let start_port = ports[0].parse();
321 let end_port = ports[1].parse();
322
323 if start_port.is_err() || end_port.is_err() {
324 return None;
325 }
326 let start_port = start_port.unwrap();
327 let end_port = end_port.unwrap();
328 if end_port < start_port {
329 return None;
330 }
331 Some((start_port, end_port))
332}
333
334pub fn parse_host(host: &str) -> Result<IpAddr, String> {
335 let parsed_url = Url::parse(&format!("http://{}", host)).map_err(|e| e.to_string())?;
338 if parsed_url.port().is_some() {
339 return Err(format!("Expected port in URL: {}", host));
340 }
341
342 let ips: Vec<_> = (host, 0)
344 .to_socket_addrs()
345 .map_err(|err| err.to_string())?
346 .map(|socket_address| socket_address.ip())
347 .collect();
348 if ips.is_empty() {
349 Err(format!("Unable to resolve host: {}", host))
350 } else {
351 Ok(ips[0])
352 }
353}
354
355pub fn is_host(string: String) -> Result<(), String> {
356 parse_host(&string).map(|_| ())
357}
358
359pub fn parse_host_port(host_port: &str) -> Result<SocketAddr, String> {
360 let addrs: Vec<_> = host_port
361 .to_socket_addrs()
362 .map_err(|err| format!("Unable to resolve host {}: {}", host_port, err))?
363 .collect();
364 if addrs.is_empty() {
365 Err(format!("Unable to resolve host: {}", host_port))
366 } else {
367 Ok(addrs[0])
368 }
369}
370
371pub fn is_host_port(string: String) -> Result<(), String> {
372 parse_host_port(&string).map(|_| ())
373}
374
375#[cfg(windows)]
376fn udp_socket(_reuseaddr: bool) -> io::Result<Socket> {
377 let sock = Socket::new(Domain::IPV4, Type::DGRAM, None)?;
378 Ok(sock)
379}
380
381#[cfg(not(windows))]
382fn udp_socket(reuseaddr: bool) -> io::Result<Socket> {
383 use nix::sys::socket::setsockopt;
384 use nix::sys::socket::sockopt::{ReuseAddr, ReusePort};
385 use std::os::unix::io::AsRawFd;
386
387 let sock = Socket::new(Domain::IPV4, Type::DGRAM, None)?;
388 let sock_fd = sock.as_raw_fd();
389
390 if reuseaddr {
391 setsockopt(sock_fd, ReusePort, &true).ok();
393 setsockopt(sock_fd, ReuseAddr, &true).ok();
394 }
395
396 Ok(sock)
397}
398
399pub fn bind_common_in_range(
401 ip_addr: IpAddr,
402 range: PortRange,
403) -> io::Result<(u16, (UdpSocket, TcpListener))> {
404 for port in range.0..range.1 {
405 if let Ok((sock, listener)) = bind_common(ip_addr, port, false) {
406 return Result::Ok((sock.local_addr().unwrap().port(), (sock, listener)));
407 }
408 }
409
410 Err(io::Error::new(
411 io::ErrorKind::Other,
412 format!("No available TCP/UDP ports in {:?}", range),
413 ))
414}
415
416pub fn bind_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result<(u16, UdpSocket)> {
417 let sock = udp_socket(false)?;
418
419 for port in range.0..range.1 {
420 let addr = SocketAddr::new(ip_addr, port);
421
422 if sock.bind(&SockAddr::from(addr)).is_ok() {
423 let sock: UdpSocket = sock.into();
424 return Result::Ok((sock.local_addr().unwrap().port(), sock));
425 }
426 }
427
428 Err(io::Error::new(
429 io::ErrorKind::Other,
430 format!("No available UDP ports in {:?}", range),
431 ))
432}
433
434pub fn multi_bind_in_range(
436 ip_addr: IpAddr,
437 range: PortRange,
438 mut num: usize,
439) -> io::Result<(u16, Vec<UdpSocket>)> {
440 if cfg!(windows) && num != 1 {
441 warn!(
443 "multi_bind_in_range() only supports 1 socket in windows ({} requested)",
444 num
445 );
446 num = 1;
447 }
448 let mut sockets = Vec::with_capacity(num);
449
450 const NUM_TRIES: usize = 100;
451 let mut port = 0;
452 let mut error = None;
453 for _ in 0..NUM_TRIES {
454 port = {
455 let (port, _) = bind_in_range(ip_addr, range)?;
456 port
457 }; for _ in 0..num {
460 let sock = bind_to(ip_addr, port, true);
461 if let Ok(sock) = sock {
462 sockets.push(sock);
463 } else {
464 error = Some(sock);
465 break;
466 }
467 }
468 if sockets.len() == num {
469 break;
470 } else {
471 sockets.clear();
472 }
473 }
474 if sockets.len() != num {
475 error.unwrap()?;
476 }
477 Ok((port, sockets))
478}
479
480pub fn bind_to(ip_addr: IpAddr, port: u16, reuseaddr: bool) -> io::Result<UdpSocket> {
481 let sock = udp_socket(reuseaddr)?;
482
483 let addr = SocketAddr::new(ip_addr, port);
484
485 sock.bind(&SockAddr::from(addr)).map(|_| sock.into())
486}
487
488pub fn bind_common(
490 ip_addr: IpAddr,
491 port: u16,
492 reuseaddr: bool,
493) -> io::Result<(UdpSocket, TcpListener)> {
494 let sock = udp_socket(reuseaddr)?;
495
496 let addr = SocketAddr::new(ip_addr, port);
497 let sock_addr = SockAddr::from(addr);
498 sock.bind(&sock_addr)
499 .and_then(|_| TcpListener::bind(&addr).map(|listener| (sock.into(), listener)))
500}
501
502pub fn find_available_port_in_range(ip_addr: IpAddr, range: PortRange) -> io::Result<u16> {
503 let (start, end) = range;
504 let mut tries_left = end - start;
505 let mut rand_port = thread_rng().gen_range(start, end);
506 loop {
507 match bind_common(ip_addr, rand_port, false) {
508 Ok(_) => {
509 break Ok(rand_port);
510 }
511 Err(err) => {
512 if tries_left == 0 {
513 return Err(err);
514 }
515 }
516 }
517 rand_port += 1;
518 if rand_port == end {
519 rand_port = start;
520 }
521 tries_left -= 1;
522 }
523}
524
525#[cfg(test)]
526mod tests {
527 use super::*;
528 use std::net::Ipv4Addr;
529
530 #[test]
531 fn test_response_length() {
532 let resp = IpEchoServerResponse {
533 address: IpAddr::from([u16::MAX; 8]), shred_version: Some(u16::MAX),
535 };
536 let resp_size = bincode::serialized_size(&resp).unwrap();
537 assert_eq!(
538 IP_ECHO_SERVER_RESPONSE_LENGTH,
539 HEADER_LENGTH + resp_size as usize
540 );
541 }
542
543 #[test]
545 fn test_backward_compat() {
546 let address = IpAddr::from([
547 525u16, 524u16, 523u16, 522u16, 521u16, 520u16, 519u16, 518u16,
548 ]);
549 let response = IpEchoServerResponse {
550 address,
551 shred_version: Some(42),
552 };
553 let mut data = vec![0u8; IP_ECHO_SERVER_RESPONSE_LENGTH];
554 bincode::serialize_into(&mut data[HEADER_LENGTH..], &response).unwrap();
555 data.truncate(HEADER_LENGTH + 20);
556 assert_eq!(
557 bincode::deserialize::<IpAddr>(&data[HEADER_LENGTH..]).unwrap(),
558 address
559 );
560 }
561
562 #[test]
564 fn test_forward_compat() {
565 let address = IpAddr::from([
566 525u16, 524u16, 523u16, 522u16, 521u16, 520u16, 519u16, 518u16,
567 ]);
568 let mut data = vec![0u8; IP_ECHO_SERVER_RESPONSE_LENGTH];
569 bincode::serialize_into(&mut data[HEADER_LENGTH..], &address).unwrap();
570 let response: Result<IpEchoServerResponse, _> =
571 bincode::deserialize(&data[HEADER_LENGTH..]);
572 assert_eq!(
573 response.unwrap(),
574 IpEchoServerResponse {
575 address,
576 shred_version: None,
577 }
578 );
579 }
580
581 #[test]
582 fn test_parse_port_or_addr() {
583 let p1 = parse_port_or_addr(Some("9000"), SocketAddr::from(([1, 2, 3, 4], 1)));
584 assert_eq!(p1.port(), 9000);
585 let p2 = parse_port_or_addr(Some("127.0.0.1:7000"), SocketAddr::from(([1, 2, 3, 4], 1)));
586 assert_eq!(p2.port(), 7000);
587 let p2 = parse_port_or_addr(Some("hi there"), SocketAddr::from(([1, 2, 3, 4], 1)));
588 assert_eq!(p2.port(), 1);
589 let p3 = parse_port_or_addr(None, SocketAddr::from(([1, 2, 3, 4], 1)));
590 assert_eq!(p3.port(), 1);
591 }
592
593 #[test]
594 fn test_parse_port_range() {
595 assert_eq!(parse_port_range("garbage"), None);
596 assert_eq!(parse_port_range("1-"), None);
597 assert_eq!(parse_port_range("1-2"), Some((1, 2)));
598 assert_eq!(parse_port_range("1-2-3"), None);
599 assert_eq!(parse_port_range("2-1"), None);
600 }
601
602 #[test]
603 fn test_parse_host() {
604 parse_host("localhost:1234").unwrap_err();
605 parse_host("localhost").unwrap();
606 parse_host("127.0.0.0:1234").unwrap_err();
607 parse_host("127.0.0.0").unwrap();
608 }
609
610 #[test]
611 fn test_parse_host_port() {
612 parse_host_port("localhost:1234").unwrap();
613 parse_host_port("localhost").unwrap_err();
614 parse_host_port("127.0.0.0:1234").unwrap();
615 parse_host_port("127.0.0.0").unwrap_err();
616 }
617
618 #[test]
619 fn test_is_host_port() {
620 assert!(is_host_port("localhost:1234".to_string()).is_ok());
621 assert!(is_host_port("localhost".to_string()).is_err());
622 }
623
624 #[test]
625 fn test_bind() {
626 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
627 assert_eq!(bind_in_range(ip_addr, (2000, 2001)).unwrap().0, 2000);
628 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
629 let x = bind_to(ip_addr, 2002, true).unwrap();
630 let y = bind_to(ip_addr, 2002, true).unwrap();
631 assert_eq!(
632 x.local_addr().unwrap().port(),
633 y.local_addr().unwrap().port()
634 );
635 bind_to(ip_addr, 2002, false).unwrap_err();
636 bind_in_range(ip_addr, (2002, 2003)).unwrap_err();
637
638 let (port, v) = multi_bind_in_range(ip_addr, (2010, 2110), 10).unwrap();
639 for sock in &v {
640 assert_eq!(port, sock.local_addr().unwrap().port());
641 }
642 }
643
644 #[test]
645 fn test_bind_in_range_nil() {
646 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
647 bind_in_range(ip_addr, (2000, 2000)).unwrap_err();
648 bind_in_range(ip_addr, (2000, 1999)).unwrap_err();
649 }
650
651 #[test]
652 fn test_find_available_port_in_range() {
653 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
654 assert_eq!(
655 find_available_port_in_range(ip_addr, (3000, 3001)).unwrap(),
656 3000
657 );
658 let port = find_available_port_in_range(ip_addr, (3000, 3050)).unwrap();
659 assert!((3000..3050).contains(&port));
660
661 let _socket = bind_to(ip_addr, port, false).unwrap();
662 find_available_port_in_range(ip_addr, (port, port + 1)).unwrap_err();
663 }
664
665 #[test]
666 fn test_bind_common_in_range() {
667 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
668 let (port, _sockets) = bind_common_in_range(ip_addr, (3100, 3150)).unwrap();
669 assert!((3100..3150).contains(&port));
670
671 bind_common_in_range(ip_addr, (port, port + 1)).unwrap_err();
672 }
673
674 #[test]
675 fn test_get_public_ip_addr_none() {
676 gemachain_logger::setup();
677 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
678 let (_server_port, (server_udp_socket, server_tcp_listener)) =
679 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
680
681 let _runtime = ip_echo_server(server_tcp_listener, Some(42));
682
683 let server_ip_echo_addr = server_udp_socket.local_addr().unwrap();
684 assert_eq!(
685 get_public_ip_addr(&server_ip_echo_addr),
686 parse_host("127.0.0.1"),
687 );
688 assert_eq!(get_cluster_shred_version(&server_ip_echo_addr), Ok(42));
689 assert!(verify_reachable_ports(&server_ip_echo_addr, vec![], &[],));
690 }
691
692 #[test]
693 fn test_get_public_ip_addr_reachable() {
694 gemachain_logger::setup();
695 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
696 let (_server_port, (server_udp_socket, server_tcp_listener)) =
697 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
698 let (client_port, (client_udp_socket, client_tcp_listener)) =
699 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
700
701 let _runtime = ip_echo_server(server_tcp_listener, Some(65535));
702
703 let ip_echo_server_addr = server_udp_socket.local_addr().unwrap();
704 assert_eq!(
705 get_public_ip_addr(&ip_echo_server_addr),
706 parse_host("127.0.0.1"),
707 );
708 assert_eq!(get_cluster_shred_version(&ip_echo_server_addr), Ok(65535));
709 assert!(verify_reachable_ports(
710 &ip_echo_server_addr,
711 vec![(client_port, client_tcp_listener)],
712 &[&client_udp_socket],
713 ));
714 }
715
716 #[test]
717 fn test_get_public_ip_addr_tcp_unreachable() {
718 gemachain_logger::setup();
719 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
720 let (_server_port, (server_udp_socket, _server_tcp_listener)) =
721 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
722
723 let server_ip_echo_addr = server_udp_socket.local_addr().unwrap();
726
727 let (correct_client_port, (_client_udp_socket, client_tcp_listener)) =
728 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
729
730 assert!(!do_verify_reachable_ports(
731 &server_ip_echo_addr,
732 vec![(correct_client_port, client_tcp_listener)],
733 &[],
734 2,
735 3,
736 ));
737 }
738
739 #[test]
740 fn test_get_public_ip_addr_udp_unreachable() {
741 gemachain_logger::setup();
742 let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
743 let (_server_port, (server_udp_socket, _server_tcp_listener)) =
744 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
745
746 let server_ip_echo_addr = server_udp_socket.local_addr().unwrap();
749
750 let (_correct_client_port, (client_udp_socket, _client_tcp_listener)) =
751 bind_common_in_range(ip_addr, (3200, 3250)).unwrap();
752
753 assert!(!do_verify_reachable_ports(
754 &server_ip_echo_addr,
755 vec![],
756 &[&client_udp_socket],
757 2,
758 3,
759 ));
760 }
761}