From b30dfb48bdbeb83045f22ba05ad5170a82548f36 Mon Sep 17 00:00:00 2001 From: ishbosamiya Date: Tue, 8 Feb 2022 13:06:35 +0530 Subject: [PATCH 1/2] socket: fix: socket timeout handling rcv_from() would always overwrite the timeout parameter set by the user. Instead of setting the timeout within the socket when set_timeout() is called, store the timeout information within the options (along with hops) and read that data when the sockets timeout is actually set in rcv_from(). --- src/socket.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index 318fe52..b954172 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -37,9 +37,9 @@ pub trait IcmpSocket { /// The type of packet this socket handles. type PacketType; - /// Sets the timeout on the socket for rcv_from. A value of 0 will cause - /// rcv_from to block. - fn set_timeout(&mut self, timeout: Duration) -> std::io::Result<()>; + /// Sets the timeout on the socket for rcv_from. A value of None + /// will cause rcv_from to block. + fn set_timeout(&mut self, timeout: Option); /// Sets the ttl for packets sent on this socket. Controls the number of /// hops the packet will be allowed to traverse. @@ -58,6 +58,7 @@ pub trait IcmpSocket { /// Options for this socket. pub struct Opts { hops: u32, + timeout: Option, } /// An ICMPv4 socket. @@ -78,7 +79,10 @@ impl IcmpSocket4 { bound_to: None, inner: socket, buf: vec![0; 512], - opts: Opts { hops: 50 }, + opts: Opts { + hops: 50, + timeout: None, + }, }) } } @@ -108,7 +112,7 @@ impl IcmpSocket for IcmpSocket4 { } fn rcv_from(&mut self) -> std::io::Result<(Self::PacketType, SockAddr)> { - self.inner.set_read_timeout(None)?; + self.inner.set_read_timeout(self.opts.timeout)?; // NOTE(jwall): the `recv_from` implementation promises not to write uninitialised // bytes to the `buf`fer, so this casting is safe. // TODO(jwall): change to `Vec::spare_capacity_mut` when it stabilizes. @@ -118,8 +122,8 @@ impl IcmpSocket for IcmpSocket4 { Ok((self.buf[0..read_count].try_into()?, addr)) } - fn set_timeout(&mut self, timeout: Duration) -> std::io::Result<()> { - self.inner.set_read_timeout(Some(timeout)) + fn set_timeout(&mut self, timeout: Option) { + self.opts.timeout = timeout; } } @@ -141,7 +145,10 @@ impl IcmpSocket6 { bound_to: None, inner: socket, buf: vec![0; 512], - opts: Opts { hops: 50 }, + opts: Opts { + hops: 50, + timeout: None, + }, }) } } @@ -185,7 +192,7 @@ impl IcmpSocket for IcmpSocket6 { } fn rcv_from(&mut self) -> std::io::Result<(Self::PacketType, SockAddr)> { - self.inner.set_read_timeout(None)?; + self.inner.set_read_timeout(self.opts.timeout)?; // NOTE(jwall): the `recv_from` implementation promises not to write uninitialised // bytes to the `buf`fer, so this casting is safe. // TODO(jwall): change to `Vec::spare_capacity_mut` when it stabilizes. @@ -195,8 +202,8 @@ impl IcmpSocket for IcmpSocket6 { Ok((self.buf[0..read_count].try_into()?, addr)) } - fn set_timeout(&mut self, timeout: Duration) -> std::io::Result<()> { - self.inner.set_read_timeout(Some(timeout)) + fn set_timeout(&mut self, timeout: Option) { + self.opts.timeout = timeout; } } From 65ef9acf45a3c27712c311bcf6b9633b9b01dbad Mon Sep 17 00:00:00 2001 From: ishbosamiya Date: Tue, 8 Feb 2022 13:10:02 +0530 Subject: [PATCH 2/2] examples: fix examples for recent change to socket timeout --- examples/ping4.rs | 2 +- examples/ping6.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ping4.rs b/examples/ping4.rs index b6cd7e9..c4b257f 100644 --- a/examples/ping4.rs +++ b/examples/ping4.rs @@ -74,7 +74,7 @@ pub fn main() { socket4 .send_to(address.parse::().unwrap(), packet) .unwrap(); - socket4.set_timeout(Duration::from_secs(1)).unwrap(); + socket4.set_timeout(Some(Duration::from_secs(1))); loop { let (resp, sock_addr) = match socket4.rcv_from() { Ok(tpl) => tpl, diff --git a/examples/ping6.rs b/examples/ping6.rs index 61bac60..00c6943 100644 --- a/examples/ping6.rs +++ b/examples/ping6.rs @@ -72,7 +72,7 @@ pub fn main() { socket6 .send_to(address.parse::().unwrap(), packet) .unwrap(); - socket6.set_timeout(Duration::from_secs(1)).unwrap(); + socket6.set_timeout(Some(Duration::from_secs(1))); loop { let (resp, sock_addr) = match socket6.rcv_from() { Ok(tpl) => tpl,