diff --git a/Cargo.toml b/Cargo.toml index 75b92a35..7d9287a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,8 @@ all = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 } pedantic = { level = "warn", priority = -1 } +unwrap_used = "warn" + cast_possible_truncation = "allow" cast_precision_loss = "allow" cast_sign_loss = "allow" diff --git a/README.md b/README.md index 6e99980c..5af20160 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,8 @@ This crate aims to be: - Correct and non-panicking - Error handling is explicit - it's clear what operations can fail, how they may fail, and how you should handle it - - If any aeronet code panics during normal operation, it's a bug - open an issue! + - No `unwrap`s - all panicking paths are a bug unless explicitly stated otherwise. If you + encounter one, open an issue! - Transport implementations are designed to be resilient against denial-of-service attacks, be it from memory exhaustion, malicious peers, etc., and the problems + mitigations are documented - Integrated with Bevy diff --git a/crates/aeronet_webtransport/src/internal/backend.rs b/crates/aeronet_webtransport/src/internal/backend.rs index bd0802f7..5e12afd3 100644 --- a/crates/aeronet_webtransport/src/internal/backend.rs +++ b/crates/aeronet_webtransport/src/internal/backend.rs @@ -53,9 +53,9 @@ pub async fn handle_connection( let conn = conn.clone(); let mut send_err = send_err.clone(); async move { - let err = send_loop(conn, recv_sending_closed, recv_s) - .await - .unwrap_err(); + let Err(err) = send_loop(conn, recv_sending_closed, recv_s).await else { + unreachable!(); + }; let _ = send_err.try_send(err); } }); @@ -65,9 +65,9 @@ pub async fn handle_connection( let conn = conn.clone(); let mut send_err = send_err.clone(); async move { - let err = recv_loop(conn, recv_receiving_closed, send_r) - .await - .unwrap_err(); + let Err(err) = recv_loop(conn, recv_receiving_closed, send_r).await else { + unreachable!(); + }; let _ = send_err.try_send(err); } }); @@ -78,9 +78,9 @@ pub async fn handle_connection( let conn = conn.clone(); let mut send_err = send_err.clone(); async move { - let err = meta_loop(runtime, conn, recv_meta_closed, send_meta) - .await - .unwrap_err(); + let Err(err) = meta_loop(runtime, conn, recv_meta_closed, send_meta).await else { + unreachable!(); + }; let _ = send_err.try_send(err); } }); @@ -150,11 +150,11 @@ async fn send_loop( conn: Arc, mut recv_closed: oneshot::Receiver<()>, mut recv_s: mpsc::UnboundedReceiver, -) -> Result<(), InternalError> { +) -> Result> { loop { let packet = futures::select! { x = recv_s.next() => x, - _ = recv_closed => return Ok(()), + _ = recv_closed => return Err(InternalError::FrontendClosed), } .ok_or(InternalError::FrontendClosed)?; @@ -204,12 +204,12 @@ async fn recv_loop( conn: Arc, mut recv_closed: oneshot::Receiver<()>, mut send_r: mpsc::Sender, -) -> Result<(), InternalError> { +) -> Result> { loop { #[allow(clippy::useless_conversion)] // multi-target support let packet = futures::select! { x = conn.receive_datagram().fuse() => x, - _ = recv_closed => return Ok(()), + _ = recv_closed => return Err(InternalError::FrontendClosed), } .map_err(|err| InternalError::ConnectionLost(err.into()))?; @@ -236,14 +236,13 @@ async fn meta_loop( conn: Arc, mut recv_closed: oneshot::Receiver<()>, mut send_meta: mpsc::Sender, -) -> Result<(), InternalError> { +) -> Result> { loop { - { - futures::select! { - () = runtime.sleep(STATS_UPDATE_INTERVAL).fuse() => {}, - _ = recv_closed => return Ok(()), - }; - } + futures::select! { + () = runtime.sleep(STATS_UPDATE_INTERVAL).fuse() => {}, + _ = recv_closed => return Err(InternalError::FrontendClosed), + }; + let meta = ConnectionMeta { #[cfg(not(target_family = "wasm"))] rtt: conn.0.rtt(), diff --git a/examples/move_box_client/src/main.rs b/examples/move_box_client/src/main.rs index 506e4819..9559178d 100644 --- a/examples/move_box_client/src/main.rs +++ b/examples/move_box_client/src/main.rs @@ -143,7 +143,7 @@ fn net_config(cert_hash: String) -> ClientConfig { config .keep_alive_interval(Some(Duration::from_secs(1))) .max_idle_timeout(Some(Duration::from_secs(5))) - .unwrap() + .expect("should be a valid max idle timeout") .build() } diff --git a/examples/move_box_server/src/server.rs b/examples/move_box_server/src/server.rs index 9e7ec161..c70ccb74 100644 --- a/examples/move_box_server/src/server.rs +++ b/examples/move_box_server/src/server.rs @@ -82,9 +82,11 @@ fn open_server( args: Res, channels: Res, ) { - let identity = wtransport::Identity::self_signed(["localhost", "127.0.0.1", "::1"]).unwrap(); + let identity = wtransport::Identity::self_signed(["localhost", "127.0.0.1", "::1"]) + .expect("should be able to generate self-signed certs"); let cert = &identity.certificate_chain().as_slice()[0]; - let spki_fingerprint = cert::spki_fingerprint_b64(cert).unwrap(); + let spki_fingerprint = + cert::spki_fingerprint_b64(cert).expect("should be able to get SPKI fingerprint of cert"); let cert_hash = cert::hash_to_b64(cert.hash()); info!("************************"); info!("SPKI FINGERPRINT"); @@ -98,14 +100,14 @@ fn open_server( .with_identity(&identity) .keep_alive_interval(Some(Duration::from_secs(1))) .max_idle_timeout(Some(Duration::from_secs(5))) - .unwrap() + .expect("should be a valid max idle timeout") .build(); let session_config = move_box::session_config(channels.as_ref()); server .open(runtime.as_ref(), net_config, session_config) - .unwrap(); + .expect("server should be closed"); } fn on_opened( @@ -149,7 +151,9 @@ fn on_server_event( for event in events.read() { match event { ServerEvent::ClientConnected { client_id } => { - let client_key = client_keys.get_by_right(client_id).unwrap(); + let Some(client_key) = client_keys.get_by_right(client_id) else { + continue; + }; info!("{client_id:?} controlled by {client_key:?} connected"); let color = Color::srgb(rand::random(), rand::random(), rand::random()); commands.spawn((