diff options
author | Jake McGinty <me@jake.su> | 2018-04-22 13:57:08 -0700 |
---|---|---|
committer | Jake McGinty <me@jake.su> | 2018-04-22 14:09:19 -0700 |
commit | c7a274357bf73bfa47727140acf54076257e9621 (patch) | |
tree | 0895d4166313c31260ce5aa7fbd3dc13aa326bee | |
parent | udp: fix bug with ipv6 pktinfo (diff) | |
download | wireguard-rs-c7a274357bf73bfa47727140acf54076257e9621.tar.xz wireguard-rs-c7a274357bf73bfa47727140acf54076257e9621.zip |
udp: retry sends without pktinfo if they failed
-rw-r--r-- | src/udp/mod.rs | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/src/udp/mod.rs b/src/udp/mod.rs index b937fda..e332a33 100644 --- a/src/udp/mod.rs +++ b/src/udp/mod.rs @@ -55,6 +55,13 @@ impl Endpoint { Endpoint::V6(sock, _) => sock, } } + + fn to_cleared_pktinfo(&self) -> Endpoint { + match *self { + Endpoint::V4(sock, _) => Endpoint::V4(sock, None), + Endpoint::V6(sock, _) => Endpoint::V6(sock, None), + } + } } impl Deref for Endpoint { @@ -151,24 +158,21 @@ impl UdpSocket { } } - /// Sends data on the socket to the given address. On success, returns the - /// number of bytes written. - /// - /// Address type can be any implementer of `ToSocketAddrs` trait. See its - /// documentation for concrete examples. pub fn send_to(&self, buf: &[u8], target: &Endpoint) -> io::Result<usize> { + self.sendmsg(buf, target, false) + } + + pub fn sendmsg(&self, buf: &[u8], target: &Endpoint, is_retry: bool) -> io::Result<usize> { let io = self.get_io(target); if let Async::NotReady = io.poll_write() { return Err(io::ErrorKind::WouldBlock.into()) } - // let cmsgs = match *target { - // Endpoint::V4(addr, Some(ref pktinfo)) => vec![ControlMessage::Ipv4PacketInfo(pktinfo)], - // Endpoint::V6(addr, Some(ref pktinfo)) => vec![ControlMessage::Ipv6PacketInfo(pktinfo)], - // _ => vec![] - // }; - - let cmsgs = vec![]; + let cmsgs = match *target { + Endpoint::V4(addr, Some(ref pktinfo)) => vec![ControlMessage::Ipv4PacketInfo(pktinfo)], + Endpoint::V6(addr, Some(ref pktinfo)) => vec![ControlMessage::Ipv6PacketInfo(pktinfo)], + _ => vec![] + }; match *target { Endpoint::V4(addr, Some(ref pktinfo)) => trace!("sending cmsg: {:?}", pktinfo), @@ -188,6 +192,14 @@ impl UdpSocket { io.need_write(); Err(io::ErrorKind::WouldBlock.into()) }, + Err(nix::Error::Sys(Errno::EINVAL)) => { + if !is_retry { + // TODO: bubble up that the existing Endpoint pktinfo is now invalid. + self.sendmsg(buf, &target.to_cleared_pktinfo(), true) + } else { + Err(io::Error::last_os_error()) + } + } Err(nix::Error::Sys(errno)) => { Err(io::Error::last_os_error()) }, @@ -235,9 +247,7 @@ impl UdpSocket { let endpoint = Endpoint::V6(addr.to_std(), Some(*info)); Ok((msg.bytes, endpoint)) }, - _ => { - Err(io::Error::new(io::ErrorKind::Other, "missing pktinfo")) - } + _ => Err(io::Error::new(io::ErrorKind::Other, "missing pktinfo")) } } else { Err(io::Error::new(io::ErrorKind::Other, "invalid source address")) |