diff options
| -rw-r--r-- | talpid-core/src/ping_monitor/win.rs | 83 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_go.rs | 11 |
2 files changed, 78 insertions, 16 deletions
diff --git a/talpid-core/src/ping_monitor/win.rs b/talpid-core/src/ping_monitor/win.rs index 6c2018c253..40fa523584 100644 --- a/talpid-core/src/ping_monitor/win.rs +++ b/talpid-core/src/ping_monitor/win.rs @@ -70,6 +70,8 @@ pub struct Pinger { seq: u16, } +const NUM_PINGS_TO_SEND: usize = 3; + impl Pinger { pub fn new(addr: Ipv4Addr, _interface_name: &str) -> Result<Self> { let sock = Socket::new(Domain::ipv4(), Type::raw(), Some(Protocol::icmpv4())) @@ -88,9 +90,14 @@ impl Pinger { /// Sends an ICMP echo request pub fn send_ping(&mut self, timeout: Duration) -> Result<()> { let dest = SocketAddr::new(IpAddr::from(self.addr), 0); - let request = self.next_ping_request(); - self.send_ping_request(&request, dest.into())?; - self.wait_for_response(Instant::now() + timeout, &request) + let requests = (0..NUM_PINGS_TO_SEND) + .map(|_| { + let request = self.next_ping_request(); + self.send_ping_request(&request, dest)?; + Ok(request) + }) + .collect::<Result<Vec<_>>>()?; + self.wait_for_response(Instant::now() + timeout, &requests) } fn send_ping_request( @@ -120,10 +127,12 @@ impl Pinger { /// returns the next ping packet fn next_ping_request(&mut self) -> EchoRequestPacket<'static> { + use rand::Rng; const ICMP_HEADER_LENGTH: usize = 8; - const ICMP_PAYLOAD_LENGTH: usize = 24; + const ICMP_PAYLOAD_LENGTH: usize = 150; const ICMP_PACKET_LENGTH: usize = ICMP_HEADER_LENGTH + ICMP_PAYLOAD_LENGTH; - let payload: [u8; ICMP_PAYLOAD_LENGTH] = rand::random(); + let mut payload = [0u8; ICMP_PAYLOAD_LENGTH]; + rand::thread_rng().fill(&mut payload[..]); let mut packet = MutableEchoRequestPacket::owned(vec![0u8; ICMP_PACKET_LENGTH]) .expect("Failed to construct an empty packet"); packet.set_icmp_type(IcmpType::new(8)); @@ -142,24 +151,39 @@ impl Pinger { } - fn wait_for_response(&mut self, deadline: Instant, req: &EchoRequestPacket<'_>) -> Result<()> { + fn wait_for_response( + &mut self, + deadline: Instant, + requests: &[EchoRequestPacket<'_>], + ) -> Result<()> { let mut recv_buffer = [0u8; 4096]; - while Instant::now() < deadline { + let mut bytes_received = 0; + let mut success = false; + let mut requests = requests.iter().map(|req| (false, req)).collect::<Vec<_>>(); + 'outer: while Instant::now() < deadline { match self.sock.recv(&mut recv_buffer) { Ok(recv_len) => { + bytes_received += recv_len; if recv_len > 20 { // have to slice off first 20 bytes for the IP header. if let Some(reply) = Self::parse_response(&recv_buffer[20..recv_len]) { - if reply.get_identifier() == req.get_identifier() - && reply.get_sequence_number() == req.get_sequence_number() - && req.payload() == reply.payload() - { - return Ok(()); + for (used, req) in requests.iter_mut() { + if *used { + continue; + } + if Self::request_and_response_match(req, &reply) { + *used = true; + success = true; + continue 'outer; + } } } } } Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + if success { + return Ok(()); + } std::thread::sleep(Duration::from_millis(100)); continue; } @@ -168,9 +192,44 @@ impl Pinger { } } } + log::debug!( + "Timing out whilst waiting for ICMP response after receiving {} bytes", + bytes_received + ); Err(Error::TimeoutError) } + fn request_and_response_match(req: &EchoRequestPacket<'_>, resp: &EchoReplyPacket<'_>) -> bool { + if req.get_identifier() != resp.get_identifier() { + log::debug!( + "Expected idnetifier {} - got {}", + req.get_identifier(), + resp.get_identifier() + ); + return false; + } + + if req.get_sequence_number() != resp.get_sequence_number() { + log::debug!( + "Expected sequence number {} - got {}", + req.get_sequence_number(), + resp.get_sequence_number() + ); + return false; + } + + if req.payload() != resp.payload() { + log::debug!( + "Expected payload {:?} - got {:?}", + req.payload(), + resp.payload() + ); + return false; + } + + return true; + } + fn parse_response<'a>(buffer: &'a [u8]) -> Option<EchoReplyPacket<'a>> { let icmp_checksum = icmp::checksum(&IcmpPacket::new(buffer)?); let reply = EchoReplyPacket::new(buffer)?; diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs index 2058b5a1ee..50df570d01 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs @@ -6,12 +6,15 @@ use std::{ffi::CString, path::Path}; #[cfg(not(target_os = "windows"))] use { crate::tunnel::tun_provider::TunConfig, - std::{ptr, net::IpAddr, os::unix::io::{RawFd}}, + std::{net::IpAddr, os::unix::io::RawFd, ptr}, }; #[cfg(target_os = "windows")] -use crate::{tunnel::tun_provider::windows::WinTun, winnet::{self, add_device_ip_addresses}}; +use crate::{ + tunnel::tun_provider::windows::WinTun, + winnet::{self, add_device_ip_addresses}, +}; #[cfg(target_os = "android")] use talpid_types::BoxedError; @@ -21,9 +24,9 @@ const MAX_PREPARE_TUN_ATTEMPTS: usize = 4; #[cfg(target_os = "windows")] use { - parking_lot::Mutex, - std::{collections::HashMap, io::Write, fs}, chrono, + parking_lot::Mutex, + std::{collections::HashMap, fs, io::Write}, }; |
