harden network errors

This commit is contained in:
John Smith 2022-08-04 12:48:19 -04:00
parent 44cde7a939
commit 0106f682f7
3 changed files with 68 additions and 47 deletions

View File

@ -316,7 +316,7 @@ impl Network {
let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr)
.await
.wrap_err("create socket failure")?;
network_result_try!(h
let _ = network_result_try!(h
.send_message(data, peer_socket_addr)
.await
.map(NetworkResult::Value)
@ -375,9 +375,10 @@ impl Network {
let h = RawUdpProtocolHandler::new_unspecified_bound_handler(&peer_socket_addr)
.await
.wrap_err("create socket failure")?;
h.send_message(data, peer_socket_addr)
network_result_try!(h
.send_message(data, peer_socket_addr)
.await
.wrap_err("send message failure")?;
.wrap_err("send message failure")?);
self.network_manager()
.stats_packet_sent(dial_info.to_ip_addr(), data_len as u64);
@ -449,10 +450,10 @@ impl Network {
&peer_socket_addr,
&descriptor.local().map(|sa| sa.to_socket_addr()),
) {
ph.clone()
.send_message(data, peer_socket_addr)
network_result_value_or_log!(debug ph.clone()
.send_message(data.clone(), peer_socket_addr)
.await
.wrap_err("sending data to existing conection")?;
.wrap_err("sending data to existing conection")? => { return Ok(Some(data)); } );
// Network accounting
self.network_manager()
@ -506,7 +507,7 @@ impl Network {
Some(ph) => ph,
None => bail!("no appropriate UDP protocol handler for dial_info"),
};
network_result_try!(ph
let _ = network_result_try!(ph
.send_message(data, peer_socket_addr)
.await
.into_network_result()
@ -532,7 +533,7 @@ impl Network {
self.network_manager()
.stats_packet_sent(dial_info.to_ip_addr(), data_len as u64);
Ok(NetworkResult::Value(()))
Ok(NetworkResult::value(()))
}
/////////////////////////////////////////////////////////////////

View File

@ -14,21 +14,12 @@ impl RawUdpProtocolHandler {
#[instrument(level = "trace", err, skip(self, data), fields(data.len = data.len(), ret.len, ret.from))]
pub async fn recv_message(&self, data: &mut [u8]) -> io::Result<(usize, ConnectionDescriptor)> {
let (size, remote_addr) = loop {
match self.socket.recv_from(data).await {
Ok((size, remote_addr)) => {
if size > MAX_MESSAGE_SIZE {
bail_io_error_other!("received too large UDP message");
}
break (size, remote_addr);
}
Err(e) => {
if e.kind() == io::ErrorKind::ConnectionReset {
// Ignore icmp
} else {
return Err(e);
}
}
let (size, remote_addr) = network_result_value_or_log!(debug self.socket.recv_from(data).await.into_network_result()? => continue);
if size > MAX_MESSAGE_SIZE {
log_net!(debug "{}({}) at {}@{}:{}", "Invalid message".green(), "received too large UDP message", file!(), line!(), column!());
continue;
}
break (size, remote_addr);
};
let peer_addr = PeerAddress::new(
@ -47,17 +38,25 @@ impl RawUdpProtocolHandler {
}
#[instrument(level = "trace", err, skip(self, data), fields(data.len = data.len(), ret.len, ret.from))]
pub async fn send_message(&self, data: Vec<u8>, socket_addr: SocketAddr) -> io::Result<()> {
pub async fn send_message(
&self,
data: Vec<u8>,
socket_addr: SocketAddr,
) -> io::Result<NetworkResult<()>> {
if data.len() > MAX_MESSAGE_SIZE {
bail_io_error_other!("sending too large UDP message");
}
let len = self.socket.send_to(&data, socket_addr).await?;
let len = network_result_try!(self
.socket
.send_to(&data, socket_addr)
.await
.into_network_result()?);
if len != data.len() {
bail_io_error_other!("UDP partial send")
}
Ok(())
Ok(NetworkResult::value(()))
}
#[instrument(level = "trace", err)]

View File

@ -38,13 +38,20 @@ impl<T> IoNetworkResultExt<T> for io::Result<T> {
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
},
Err(e) => {
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
}
}
}
}
}
@ -85,13 +92,20 @@ impl<T> FoldedNetworkResultExt<T> for io::Result<TimeoutOr<T>> {
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
},
Err(e) => {
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
}
}
}
}
}
@ -111,13 +125,20 @@ impl<T> FoldedNetworkResultExt<T> for io::Result<NetworkResult<T>> {
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
},
Err(e) => {
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
_ => Err(e),
}
}
}
}
}
@ -270,7 +291,7 @@ macro_rules! network_result_value_or_log {
$f
}
NetworkResult::InvalidMessage(s) => {
log_net!($level "{}({}) at {}@{}:{}", "No connection".green(), s, file!(), line!(), column!());
log_net!($level "{}({}) at {}@{}:{}", "Invalid message".green(), s, file!(), line!(), column!());
$f
}
NetworkResult::Value(v) => v,