From 41953febddd4a917ddd8f708a46319f52009f4ac Mon Sep 17 00:00:00 2001 From: Evgeny Kurnevsky Date: Sun, 26 Sep 2021 11:02:12 +0300 Subject: [PATCH] refactor: use thiserror instead of failure --- examples/Cargo.toml | 3 +- examples/dht_server.rs | 2 +- examples/echo.rs | 4 +- examples/onion_client.rs | 11 +- examples/tcp_client.rs | 4 +- examples/tcp_server.rs | 2 +- tox_core/Cargo.toml | 2 +- tox_core/src/dht/codec.rs | 100 +++--- tox_core/src/dht/daemon_state.rs | 35 +- tox_core/src/dht/lan_discovery.rs | 31 +- tox_core/src/dht/server/errors.rs | 147 +++++---- tox_core/src/dht/server/mod.rs | 157 ++++----- tox_core/src/dht/server_ext.rs | 16 +- tox_core/src/error.rs | 94 ------ tox_core/src/friend_connection/errors.rs | 93 +++--- tox_core/src/friend_connection/mod.rs | 29 +- tox_core/src/lib.rs | 2 - tox_core/src/net_crypto/errors.rs | 394 +++++++++++------------ tox_core/src/net_crypto/mod.rs | 137 ++++---- tox_core/src/net_crypto/packets_array.rs | 18 +- tox_core/src/onion/client/errors.rs | 146 ++++----- tox_core/src/onion/client/mod.rs | 67 ++-- tox_core/src/onion/onion_announce.rs | 21 +- tox_core/src/relay/client/client.rs | 96 +++--- tox_core/src/relay/client/connections.rs | 45 ++- tox_core/src/relay/client/errors.rs | 185 +++++------ tox_core/src/relay/codec.rs | 22 +- tox_core/src/relay/server/server_ext.rs | 49 ++- tox_core/src/udp.rs | 27 +- tox_encryptsave/Cargo.toml | 2 +- tox_encryptsave/src/lib.rs | 26 +- tox_packet/Cargo.toml | 2 +- tox_packet/src/dht/cookie.rs | 6 +- tox_packet/src/dht/cookie_response.rs | 6 +- tox_packet/src/dht/crypto_data.rs | 11 +- tox_packet/src/dht/crypto_handshake.rs | 6 +- tox_packet/src/dht/dht_request.rs | 6 +- tox_packet/src/dht/errors.rs | 75 +---- 38 files changed, 903 insertions(+), 1176 deletions(-) delete mode 100644 tox_core/src/error.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index ae0a97e9b..fee583165 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,8 +14,9 @@ log = "0.4" futures = { version = "0.3", default-features = false, features = ["std", "async-await"] } env_logger = "0.9" hex = "0.4" -failure = "0.1" +thiserror = "1.0" rand = "0.8" +anyhow = "1.0" [dev-dependencies.tokio] version = "1.12" diff --git a/examples/dht_server.rs b/examples/dht_server.rs index 2ed586fa6..688f6b3ae 100644 --- a/examples/dht_server.rs +++ b/examples/dht_server.rs @@ -7,7 +7,7 @@ extern crate log; use futures::future::FutureExt; use futures::channel::mpsc; -use failure::Error; +use anyhow::Error; use rand::thread_rng; use std::net::SocketAddr; diff --git a/examples/echo.rs b/examples/echo.rs index 5b689ed3c..b99e104d2 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -9,7 +9,7 @@ extern crate log; use futures::{*, future::TryFutureExt}; use futures::channel::mpsc; use hex::FromHex; -use failure::{err_msg, Error}; +use anyhow::Error; use rand::thread_rng; use std::net::SocketAddr; @@ -174,7 +174,7 @@ async fn main() -> Result<(), Error> { Ok((_, share_relays)) => friend_connections_c.handle_share_relays(pk, share_relays) .map_err(Error::from).await?, - _ => return Err(err_msg("Failed to parse ShareRelays")) + _ => return Err(Error::msg("Failed to parse ShareRelays")) } }, 0x18 => { // PACKET_ID_ONLINE diff --git a/examples/onion_client.rs b/examples/onion_client.rs index 76b263b1d..aef512839 100644 --- a/examples/onion_client.rs +++ b/examples/onion_client.rs @@ -3,7 +3,7 @@ extern crate log; use std::net::{SocketAddr, IpAddr}; -use failure::Error; +use anyhow::Error; use futures::future::FutureExt; use futures::stream::StreamExt; use futures::sink::SinkExt; @@ -91,11 +91,14 @@ async fn main() -> Result<(), Error> { while let Some(event) = stream.next().await { let (packet, addr) = match event { Ok(ev) => ev, - Err(ref e) => { + Err(e) => { error!("packet receive error = {:?}", e); - if *e.kind() == DecodeErrorKind::Io { continue } - else { unimplemented!() } + if let DecodeError::Io(e) = e { + return Err(Error::new(e)); + } else { + continue; + } } }; diff --git a/examples/tcp_client.rs b/examples/tcp_client.rs index 93eaeb2a0..b50576428 100644 --- a/examples/tcp_client.rs +++ b/examples/tcp_client.rs @@ -9,7 +9,7 @@ use tox_core::relay::handshake::make_client_handshake; use tox_core::relay::codec; use tox_core::stats::Stats; -use failure::{Error, err_msg}; +use anyhow::Error; use hex::FromHex; @@ -81,7 +81,7 @@ async fn create_client(mut rx: mpsc::Receiver, tx: mpsc::Sender) tx.clone().send(Packet::PongResponse( PongResponse { ping_id: ping.ping_id } )) - .map_err(|_| err_msg("Could not send pong") ) + .map_err(|_| Error::msg("Could not send pong") ) .await?; } } diff --git a/examples/tcp_server.rs b/examples/tcp_server.rs index fd759e3fb..2454436be 100644 --- a/examples/tcp_server.rs +++ b/examples/tcp_server.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate log; -use failure::Error; +use anyhow::Error; use tox_crypto::*; use tox_core::relay::server::{Server, tcp_run}; use tox_core::stats::Stats; diff --git a/tox_core/Cargo.toml b/tox_core/Cargo.toml index 4e631f3a3..b27161f14 100644 --- a/tox_core/Cargo.toml +++ b/tox_core/Cargo.toml @@ -27,7 +27,7 @@ log = "0.4" nom = "5.1" cookie-factory = "0.3" get_if_addrs = "0.5" -failure = "0.1" +thiserror = "1.0" lru = "0.6" bitflags = "1.3" itertools = "0.10" diff --git a/tox_core/src/dht/codec.rs b/tox_core/src/dht/codec.rs index 91a9bc470..a5f7c59b4 100644 --- a/tox_core/src/dht/codec.rs +++ b/tox_core/src/dht/codec.rs @@ -9,88 +9,74 @@ use crate::stats::*; use bytes::BytesMut; use cookie_factory::GenError; -use failure::Fail; +use thiserror::Error; use nom::{error::ErrorKind, Err}; use tokio_util::codec::{Decoder, Encoder}; /// A serialized `Packet` should be not longer than 2048 bytes. pub const MAX_DHT_PACKET_SIZE: usize = 2048; -error_kind! { - #[doc = "Error that can happen when decoding `Packet` from bytes."] - #[derive(Debug)] - DecodeError, - #[doc = "Error that can happen when decoding `Packet` from bytes."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - DecodeErrorKind { - #[doc = "Error indicates that we received too big packet."] - #[fail(display = "Packet should not be longer than 2048 bytes: {} bytes", len)] - TooBigPacket { - #[doc = "Length of received packet."] - len: usize - }, - #[doc = "Error indicates that received packet can't be parsed."] - #[fail(display = "Deserialize Packet error: {:?}, packet: {:?}", error, packet)] - Deserialize { - #[doc = "Parsing error."] - error: nom::Err<(Vec, ErrorKind)>, - #[doc = "Received packet."] - packet: Vec, - }, - #[doc = "General IO error that can happen with UDP socket."] - #[fail(display = "IO Error")] - Io, - } +/// Error that can happen when decoding `Packet` from bytes. +#[derive(Debug, Error)] +pub enum DecodeError { + /// Error indicates that we received too big packet. + #[error("Packet should not be longer than 2048 bytes: {} bytes", len)] + TooBigPacket { + /// Length of received packet. + len: usize + }, + /// Error indicates that received packet can't be parsed. + #[error("Deserialize Packet error: {:?}, packet: {:?}", error, packet)] + Deserialize { + /// Parsing error. + error: nom::Err<(Vec, ErrorKind)>, + /// Received packet. + packet: Vec, + }, + /// General IO error that can happen with UDP socket. + #[error("IO Error")] + Io(IoError), } impl DecodeError { pub(crate) fn too_big_packet(len: usize) -> DecodeError { - DecodeError::from(DecodeErrorKind::TooBigPacket { len }) + DecodeError::TooBigPacket { len } } pub(crate) fn deserialize(e: Err<(&[u8], ErrorKind)>, packet: Vec) -> DecodeError { - DecodeError::from(DecodeErrorKind::Deserialize { error: e.to_owned(), packet }) + DecodeError::Deserialize { error: e.to_owned(), packet } } } -error_kind! { - #[doc = "Error that can happen when encoding `Packet` to bytes."] - #[derive(Debug)] - EncodeError, - #[doc = "Error that can happen when encoding `Packet` to bytes."] - #[derive(Debug, Fail)] - EncodeErrorKind { - #[doc = "Error indicates that `Packet` is invalid and can't be serialized."] - #[fail(display = "Serialize Packet error: {:?}", error)] - Serialize { - #[doc = "Serialization error."] - error: GenError - }, - #[doc = "General IO error that can happen with UDP socket."] - #[fail(display = "IO Error")] - Io, - } +/// Error that can happen when encoding `Packet` to bytes. +#[derive(Debug, Error)] +pub enum EncodeError { + /// Error indicates that `Packet` is invalid and can't be serialized. + #[error("Serialize Packet error: {:?}", error)] + Serialize { + /// Serialization error. + error: GenError + }, + /// General IO error that can happen with UDP socket. + #[error("IO Error")] + Io(IoError), } impl EncodeError { pub(crate) fn serialize(error: GenError) -> EncodeError { - EncodeError::from(EncodeErrorKind::Serialize { error }) + EncodeError::Serialize { error } } } impl From for DecodeError { fn from(error: IoError) -> DecodeError { - DecodeError { - ctx: error.context(DecodeErrorKind::Io) - } + DecodeError::Io(error) } } impl From for EncodeError { fn from(error: IoError) -> EncodeError { - EncodeError { - ctx: error.context(EncodeErrorKind::Io) - } + EncodeError::Io(error) } } @@ -340,9 +326,8 @@ mod tests { buf.extend_from_slice(b"\xFF"); let res = codec.decode(&mut buf); - // not enought bytes to decode EncryptedPacket - let error = res.err().unwrap(); - assert_eq!(*error.kind(), DecodeErrorKind::Deserialize { error: Err::Error((vec![255], ErrorKind::Alt)) , packet: vec![0xff] }); + // not enough bytes to decode EncryptedPacket + assert!(matches!(res, Err(DecodeError::Deserialize { error: Err::Error((_, ErrorKind::Alt)), packet: _ }))); } #[test] @@ -372,9 +357,8 @@ mod tests { let res = codec.encode(packet, &mut buf); assert!(res.is_err()); let error = res.err().unwrap(); - let error_kind = error.kind(); - let error_serialize = unpack!(error_kind, EncodeErrorKind::Serialize, error); + let error_serialize = unpack!(error, EncodeError::Serialize, error); let too_small = unpack!(error_serialize, GenError::BufferTooSmall); - assert_eq!(*too_small, 2106 - MAX_DHT_PACKET_SIZE); + assert_eq!(too_small, 2106 - MAX_DHT_PACKET_SIZE); } } diff --git a/tox_core/src/dht/daemon_state.rs b/tox_core/src/dht/daemon_state.rs index 0ad23b47f..51348fae0 100644 --- a/tox_core/src/dht/daemon_state.rs +++ b/tox_core/src/dht/daemon_state.rs @@ -14,30 +14,25 @@ use tox_binary_io::*; use crate::dht::kbucket::*; use crate::dht::ktree::*; -use failure::Fail; +use thiserror::Error; use nom::{Err, error::ErrorKind as NomErrorKind}; -error_kind! { - #[doc = "An error that can occur while serializing/deserializing object."] - #[derive(Debug)] - DeserializeError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - DeserializeErrorKind { - #[doc = "Error indicates that object can't be parsed."] - #[fail(display = "Deserialize object error: {:?}, data: {:?}", error, data)] - Deserialize { - #[doc = "Parsing error."] - error: nom::Err<(Vec, NomErrorKind)>, - #[doc = "Object serialized data."] - data: Vec, - }, - } +/// An error that can occur while serializing/deserializing object. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum DeserializeError { + /// Error indicates that object can't be parsed. + #[error("Deserialize object error: {:?}, data: {:?}", error, data)] + Deserialize { + /// Parsing error. + error: nom::Err<(Vec, NomErrorKind)>, + /// Object serialized data. + data: Vec, + }, } impl DeserializeError { pub(crate) fn deserialize(e: Err<(&[u8], NomErrorKind)>, data: Vec) -> DeserializeError { - DeserializeError::from(DeserializeErrorKind::Deserialize { error: e.to_owned(), data }) + DeserializeError::Deserialize { error: e.to_owned(), data } } } @@ -143,14 +138,14 @@ mod tests { let error = res.err().unwrap(); let mut input = vec![2, 1, 2, 3, 4, 4, 210]; input.extend_from_slice(&pk_org.as_bytes()[..crypto_box::KEY_SIZE - 1]); - assert_eq!(*error.kind(), DeserializeErrorKind::Deserialize { error: Err::Error(( + assert_eq!(error, DeserializeError::Deserialize { error: Err::Error(( input, NomErrorKind::Eof)), data: serialized_vec[..serialized_len - 1].to_vec() }); // test with serialized data corrupted let serialized_vec = [42; 10]; let res = DaemonState::deserialize_old(&alice, &serialized_vec).await; let error = res.err().unwrap(); - assert_eq!(*error.kind(), DeserializeErrorKind::Deserialize { error: Err::Error(( + assert_eq!(error, DeserializeError::Deserialize { error: Err::Error(( vec![42; 10], NomErrorKind::Tag)), data: serialized_vec.to_vec() }); // test with empty close list diff --git a/tox_core/src/dht/lan_discovery.rs b/tox_core/src/dht/lan_discovery.rs index 01c28a46c..ca3a69c1f 100644 --- a/tox_core/src/dht/lan_discovery.rs +++ b/tox_core/src/dht/lan_discovery.rs @@ -2,30 +2,27 @@ use std::iter; use std::net::{IpAddr, SocketAddr}; -use std::time::{Duration}; +use std::time::Duration; -use failure::Fail; +use thiserror::Error; use futures::{stream, SinkExt}; use futures::channel::mpsc; use get_if_addrs::IfAddr; +use tokio::time::error::Elapsed; use tox_crypto::*; use tox_packet::dht::*; -error_kind! { - #[doc = "Error that can happen during lan discovery."] - #[derive(Debug)] - LanDiscoveryError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - LanDiscoveryErrorKind { - #[doc = "Ping wakeup timer error"] - #[fail(display = "Lan discovery wakeup timer error.")] - Wakeup, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } + +/// Error that can happen during lan discovery. +#[derive(Debug, PartialEq, Error)] +pub enum LanDiscoveryError { + /// Ping wakeup timer error + #[error("Lan discovery wakeup timer error.")] + Wakeup, + /// Send packet(s) time out. + #[error("Send packet(s) error")] + Timeout(Elapsed), } /// How many ports should be used on every iteration. @@ -150,7 +147,7 @@ impl LanDiscoverySender { if let Err(e) = tokio::time::timeout(interval, self.send()).await { warn!("Failed to send LAN discovery packets: {}", e); - return Err(e.context(LanDiscoveryErrorKind::SendTo).into()) + return Err(LanDiscoveryError::Timeout(e)) } } } diff --git a/tox_core/src/dht/server/errors.rs b/tox_core/src/dht/server/errors.rs index 0bf5a850a..0c936c599 100644 --- a/tox_core/src/dht/server/errors.rs +++ b/tox_core/src/dht/server/errors.rs @@ -1,83 +1,82 @@ /*! Errors enum for DHT server. */ -use failure::Fail; +use futures::channel::mpsc::SendError; +use thiserror::Error; +use tokio::time::error::Elapsed; +use tox_packet::dht::GetPayloadError; -error_kind! { - #[doc = "Error that can happen when calling `handle_*` of packet."] - #[derive(Debug)] - HandlePacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - HandlePacketErrorKind { - #[doc = "Error indicates that getting payload of received packet error."] - #[fail(display = "Get payload of received packet error")] - GetPayload, - #[doc = "Error indicates that next_onion_return is none."] - #[fail(display = "Next onion return is none")] - OnionResponseNext, - #[doc = "Error indicates that sending response packet faces redirecting failure."] - #[fail(display = "Sending response redirecting error")] - OnionResponseRedirect, - #[doc = "Error indicates that BootstrapInfo error."] - #[fail(display = "BootstrapInfo handling error")] - BootstrapInfoLength, - #[doc = "Error indicates that sending response packet error."] - #[fail(display = "Sending response error")] - SendTo, - #[doc = "Error indicates that received packet's ping_id is zero."] - #[fail(display = "Zero ping id error")] - ZeroPingId, - #[doc = "Error indicates that received packet's ping_id does not match."] - #[fail(display = "Ping id mismatch error")] - PingIdMismatch, - #[doc = "Error indicates that there is no friend."] - #[fail(display = "Friend does not exist error")] - NoFriend, - #[doc = "Error indicates that NetCrypto is not initialized."] - #[fail(display = "NetCrypto is not initialized error")] - NetCrypto, - #[doc = "Error indicates that OnionClient is not initialized."] - #[fail(display = "OnionClient is not initialized error")] - OnionClient, - #[doc = "Error indicates that handling NetCrypto packet made an error."] - #[fail(display = "Handling NetCrypto packet failed")] - HandleNetCrypto, - #[doc = "Error indicates that handling OnionClient packet made an error."] - #[fail(display = "Handling OnionClient packet failed")] - HandleOnionClient, - #[doc = "Error indicates that onion or net crypto processing fails."] - #[doc = "## This enum entry is temporary for onion or net crypto module's transition to failure"] - #[fail(display = "Onion or NetCrypto related error")] - OnionOrNetCrypto, - #[doc = "Failed to send friend's IP address to the sink."] - #[fail(display = "Failed to send friend's IP address to the sink")] - FriendSaddr - } +use crate::onion::{client::errors::{HandleAnnounceResponseError, HandleDataResponseError}, onion_announce::HandleDataRequestError}; +use crate::net_crypto::errors::HandlePacketError as HandleNetCryptoPacketError; + +/// Error that can happen when calling `handle_*` of packet. +#[derive(Debug, Error)] +pub enum HandlePacketError { + /// Error indicates that getting payload of received packet error. + #[error("Get payload of received packet error")] + GetPayload(GetPayloadError), + /// Error indicates that next_onion_return is none. + #[error("Next onion return is none")] + OnionResponseNext, + /// Error indicates that sending response packet faces redirecting failure. + #[error("Sending response redirecting error")] + OnionResponseRedirect, + /// Error indicates that sending response packet faces redirecting failure. + #[error("Sending response redirecting error")] + OnionResponseRedirectSend(SendError), + /// Error indicates that BootstrapInfo error. + #[error("BootstrapInfo handling error")] + BootstrapInfoLength, + /// Error indicates that sending response packet error. + #[error("Sending response error")] + SendTo(SendError), + /// Error indicates that received packet's ping_id is zero. + #[error("Zero ping id error")] + ZeroPingId, + /// Error indicates that received packet's ping_id does not match. + #[error("Ping id mismatch error")] + PingIdMismatch, + /// Error indicates that there is no friend. + #[error("Friend does not exist error")] + NoFriend, + /// Error indicates that NetCrypto is not initialized. + #[error("NetCrypto is not initialized error")] + NetCrypto, + /// Error indicates that OnionClient is not initialized. + #[error("OnionClient is not initialized error")] + OnionClient, + /// Error indicates that handling NetCrypto packet made an error. + #[error("Handling NetCrypto packet failed")] + HandleNetCrypto(HandleNetCryptoPacketError), + /// Error indicates that handling OnionClient data packet made an error. + #[error("Handling OnionClient data packet failed")] + HandleOnionClientData(HandleDataResponseError), + /// Error indicates that handling OnionClient announce packet made an error. + #[error("Handling OnionClient announce packet failed")] + HandleOnionClientAnnounce(HandleAnnounceResponseError), + /// Error indicates that onion processing fails. + #[error("Onion or NetCrypto related error")] + Onion(HandleDataRequestError), + /// Failed to send friend's IP address to the sink. + #[error("Failed to send friend's IP address to the sink")] + FriendSaddr(SendError), } -error_kind! { - #[doc = "Error that can happen when calling `run_*`."] - #[derive(Debug)] - RunError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - RunErrorKind { - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } +/// Error that can happen when calling `run_*`. +#[derive(Debug, PartialEq, Error)] +pub enum RunError { + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), + /// Send packet(s) time out. + #[error("Send packet(s) time out")] + Timeout(Elapsed), } -error_kind! { - #[doc = "Error that can happen when calling `run_*`."] - #[derive(Debug)] - PingError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - PingErrorKind { - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } +/// Error that can happen when calling `run_*`. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum PingError { + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), } diff --git a/tox_core/src/dht/server/mod.rs b/tox_core/src/dht/server/mod.rs index a24989701..1eceac604 100644 --- a/tox_core/src/dht/server/mod.rs +++ b/tox_core/src/dht/server/mod.rs @@ -6,7 +6,6 @@ This module works on top of other modules. pub mod hole_punching; pub mod errors; -use failure::Fail; use futures::{TryFutureExt, StreamExt, SinkExt, future}; use futures::channel::mpsc; use tokio::sync::RwLock; @@ -322,28 +321,28 @@ impl Server { // Send NodesRequest packets to nodes from the Server self.ping_nodes_to_bootstrap(&mut request_queue, &mut nodes_to_bootstrap, self.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; self.ping_close_nodes(&mut request_queue, close_nodes.iter_mut(), self.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; if send_random_request(&mut *self.last_nodes_req_time.write().await, &mut *self.random_requests_count.write().await) { self.send_nodes_req_random(&mut request_queue, close_nodes.iter(), self.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; } // Send NodesRequest packets to nodes from every DhtFriend for friend in friends.values_mut() { self.ping_nodes_to_bootstrap(&mut request_queue, &mut friend.nodes_to_bootstrap, friend.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; self.ping_close_nodes(&mut request_queue, friend.close_nodes.nodes.iter_mut(), friend.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; if send_random_request(&mut friend.last_nodes_req_time, &mut friend.random_requests_count) { self.send_nodes_req_random(&mut request_queue, friend.close_nodes.nodes.iter(), friend.pk.clone()).await - .map_err(|e| e.context(RunErrorKind::SendTo))? + .map_err(RunError::SendTo)? } } self.send_nat_ping_req(&mut request_queue, &mut friends).await - .map_err(|e| RunError::from(e.context(RunErrorKind::SendTo))) + .map_err(RunError::SendTo) } /// Run DHT periodical tasks. Result future will never be completed @@ -387,9 +386,9 @@ impl Server { match send_res { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => - Err(e.context(RunErrorKind::SendTo).into()), + Err(RunError::SendTo(e)), Err(e) => - Err(e.context(RunErrorKind::SendTo).into()), + Err(RunError::Timeout(e)), }; if let Err(ref e) = res { @@ -440,9 +439,9 @@ impl Server { let res = match loop_res { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => - Err(e.context(RunErrorKind::SendTo).into()), + Err(e), Err(e) => - Err(e.context(RunErrorKind::SendTo).into()), + Err(RunError::Timeout(e)), }; if let Err(ref e) = res { @@ -476,7 +475,7 @@ impl Server { wakeups.tick().await; self.send_pings().await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; } } @@ -597,7 +596,7 @@ impl Server { let mut request_queue = self.request_queue.write().await; self.send_nodes_req(node, &mut request_queue, self.pk.clone()) .await - .map_err(|e| e.context(PingErrorKind::SendTo).into()) + .map_err(PingError::SendTo) } /// Send `PingRequest` packet to the node. @@ -719,7 +718,7 @@ impl Server { -> Result<(), HandlePacketError> { let precomputed_key = self.precomputed_keys.get(packet.pk.clone()).await; let payload = match packet.get_payload(&precomputed_key) { - Err(e) => return future::err(e.context(HandlePacketErrorKind::GetPayload).into()).await, + Err(e) => return future::err(HandlePacketError::GetPayload(e)).await, Ok(payload) => payload, }; @@ -737,7 +736,7 @@ impl Server { self.send_to(addr, ping_resp), ) .map_ok(drop) - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) .await } @@ -751,7 +750,7 @@ impl Server { /// friend then send it's IP address to appropriate sink. async fn try_add_to_close(&self, payload_id: u64, node: PackedNode, check_ping_id: bool) -> Result<(), HandlePacketError> { if check_ping_id && !self.check_ping_id(payload_id, &node.pk).await { - return Err(HandlePacketError::from(HandlePacketErrorKind::PingIdMismatch)); + return Err(HandlePacketError::PingIdMismatch); } let mut close_nodes = self.close_nodes.write().await; @@ -763,7 +762,7 @@ impl Server { if friends.contains_key(&node.pk) { let sink = self.friend_saddr_sink.read().await.clone(); maybe_send_unbounded(sink, node).await - .map_err(|e| e.context(HandlePacketErrorKind::FriendSaddr).into()) + .map_err(HandlePacketError::FriendSaddr) } else { Ok(()) } @@ -774,14 +773,12 @@ impl Server { pub async fn handle_ping_resp(&self, packet: PingResponse, addr: SocketAddr) -> Result<(), HandlePacketError> { let precomputed_key = self.precomputed_keys.get(packet.pk.clone()).await; let payload = match packet.get_payload(&precomputed_key) { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; if payload.id == 0u64 { - return Err( - HandlePacketError::from( - HandlePacketErrorKind::ZeroPingId)); + return Err(HandlePacketError::ZeroPingId); } self.try_add_to_close(payload.id, PackedNode::new(addr, packet.pk), true).await @@ -794,7 +791,7 @@ impl Server { -> Result<(), HandlePacketError> { let precomputed_key = self.precomputed_keys.get(packet.pk.clone()).await; let payload = match packet.get_payload(&precomputed_key) { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -815,7 +812,7 @@ impl Server { self.send_to(addr, nodes_resp), ) .map_ok(drop) - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) .await } @@ -855,7 +852,7 @@ impl Server { let precomputed_key = self.precomputed_keys.get(packet.pk.clone()).await; let payload = match packet.get_payload(&precomputed_key) { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -906,7 +903,7 @@ impl Server { let precomputed_key = self.precomputed_keys.get(packet.spk.clone()).await; let payload = packet.get_payload(&precomputed_key); let payload = match payload { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -943,7 +940,7 @@ impl Server { if let Some(node) = close_nodes.get_node(&packet.rpk).and_then(|node| node.to_packed_node()) { let packet = Packet::DhtRequest(packet); self.send_to(node.saddr, packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo))?; + .map_err(HandlePacketError::SendTo)?; } Ok(()) @@ -954,7 +951,7 @@ impl Server { -> Result<(), HandlePacketError> { let mut friends = self.friends.write().await; match friends.get_mut(spk) { - None => Err(HandlePacketError::from(HandlePacketErrorKind::NoFriend)), + None => Err(HandlePacketError::NoFriend), Some(friend) => { friend.hole_punch.last_recv_ping_time = ping_time; Ok(()) @@ -977,20 +974,20 @@ impl Server { &resp_payload, )); self.send_to(addr, nat_ping_resp).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle received `NatPingResponse` packet and enable hole punching if /// it's correct. async fn handle_nat_ping_resp(&self, payload: NatPingResponse, spk: &PublicKey) -> Result<(), HandlePacketError> { if payload.id == 0 { - return Err(HandlePacketError::from(HandlePacketErrorKind::ZeroPingId)) + return Err(HandlePacketError::ZeroPingId) } let mut friends = self.friends.write().await; let friend = match friends.get_mut(spk) { - None => return Err(HandlePacketError::from(HandlePacketErrorKind::NoFriend)), + None => return Err(HandlePacketError::NoFriend), Some(friend) => friend, }; @@ -1004,7 +1001,7 @@ impl Server { friend.hole_punch.is_punching_done = false; Ok(()) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::PingIdMismatch)) + Err(HandlePacketError::PingIdMismatch) } } @@ -1024,7 +1021,7 @@ impl Server { self.send_nodes_req(PackedNode::new(addr, packet.pk.clone()), &mut *self.request_queue.write().await, self.pk.clone()) .await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle received `OnionRequest0` packet and send `OnionRequest1` packet @@ -1040,7 +1037,7 @@ impl Server { let shared_secret = self.precomputed_keys.get(packet.temporary_pk.clone()).await; let payload = packet.get_payload(&shared_secret); let payload = match payload { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -1051,7 +1048,7 @@ impl Server { onion_return, }); self.send_to(payload.ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle received `OnionRequest1` packet and send `OnionRequest2` packet @@ -1067,7 +1064,7 @@ impl Server { let shared_secret = self.precomputed_keys.get(packet.temporary_pk.clone()).await; let payload = packet.get_payload(&shared_secret); let payload = match payload { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; let next_packet = Packet::OnionRequest2(OnionRequest2 { @@ -1077,7 +1074,7 @@ impl Server { onion_return, }); self.send_to(payload.ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle received `OnionRequest2` packet and send `OnionAnnounceRequest` @@ -1093,7 +1090,7 @@ impl Server { let shared_secret = self.precomputed_keys.get(packet.temporary_pk.clone()).await; let payload = packet.get_payload(&shared_secret); let payload = match payload { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -1108,7 +1105,7 @@ impl Server { }), }; self.send_to(payload.ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Adapt `OnionAnnounce.handle_onion_announce_request()`. @@ -1136,7 +1133,7 @@ impl Server { pub async fn handle_onion_announce_request(&self, packet: OnionAnnounceRequest, addr: SocketAddr) -> Result<(), HandlePacketError> { let shared_secret = self.precomputed_keys.get(packet.inner.pk.clone()).await; let payload = match packet.inner.get_payload(&shared_secret) { - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), Ok(payload) => payload, }; @@ -1160,7 +1157,7 @@ impl Server { payload: InnerOnionResponse::OnionAnnounceResponse(response), })) .await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle received `OnionDataRequest` packet and send `OnionResponse3` @@ -1171,8 +1168,8 @@ impl Server { let onion_announce = self.onion_announce.read().await; match onion_announce.handle_data_request(packet) { Ok((response, addr)) => self.send_to(addr, Packet::OnionResponse3(response)).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()), - Err(e) => Err(e.context(HandlePacketErrorKind::OnionOrNetCrypto).into()) + .map_err(HandlePacketError::SendTo), + Err(e) => Err(HandlePacketError::Onion(e)) } } @@ -1198,9 +1195,9 @@ impl Server { payload: packet.payload }); self.send_to(ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } else { - Err(HandlePacketErrorKind::OnionResponseNext.into()) + Err(HandlePacketError::OnionResponseNext) } } @@ -1226,9 +1223,9 @@ impl Server { payload: packet.payload }); self.send_to(ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } else { - Err(HandlePacketErrorKind::OnionResponseNext.into()) + Err(HandlePacketError::OnionResponseNext) } } @@ -1257,19 +1254,19 @@ impl Server { InnerOnionResponse::OnionDataResponse(inner) => Packet::OnionDataResponse(inner), }; self.send_to(ip_port.to_saddr(), next_packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) }, ProtocolType::Tcp => { if let Some(ref tcp_onion_sink) = self.tcp_onion_sink { tcp_onion_sink.clone().send((packet.payload, ip_port.to_saddr())).await - .map_err(|e| e.context(HandlePacketErrorKind::OnionResponseRedirect).into()) + .map_err(HandlePacketError::OnionResponseRedirectSend) } else { - Err(HandlePacketErrorKind::OnionResponseRedirect.into()) + Err(HandlePacketError::OnionResponseRedirect) } }, } } else { - Err(HandlePacketErrorKind::OnionResponseNext.into()) + Err(HandlePacketError::OnionResponseNext) } } @@ -1303,7 +1300,7 @@ impl Server { /// Handle `BootstrapInfo` packet and response with `BootstrapInfo` packet. pub async fn handle_bootstrap_info(&self, packet: &BootstrapInfo, addr: SocketAddr) -> Result<(), HandlePacketError> { if packet.motd.len() != BOOSTRAP_CLIENT_MAX_MOTD_LENGTH { - return Err(HandlePacketError::from(HandlePacketErrorKind::BootstrapInfoLength)) + return Err(HandlePacketError::BootstrapInfoLength) } if let Some(ref bootstrap_info) = self.bootstrap_info { @@ -1321,7 +1318,7 @@ impl Server { motd, }); self.send_to(addr, packet).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo))?; + .map_err(HandlePacketError::SendTo)?; } Ok(()) @@ -1501,8 +1498,7 @@ mod tests { }; let res = alice.handle_bootstrap_info(&packet, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::BootstrapInfoLength); + assert!(matches!(res, Err(HandlePacketError::BootstrapInfoLength))); // Necessary to drop tx so that rx.collect::>() can be finished drop(alice); @@ -1576,8 +1572,7 @@ mod tests { let ping_req = PingRequest::new(&precomp, alice.pk.clone(), &req_payload); let res = alice.handle_ping_req(ping_req, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_ping_resp @@ -1679,8 +1674,7 @@ mod tests { let ping_resp = PingResponse::new(&precomp, alice.pk.clone(), &payload); let res = alice.handle_ping_resp(ping_resp, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } #[tokio::test] @@ -1694,8 +1688,7 @@ mod tests { let ping_resp = PingResponse::new(&precomp, bob_pk, &payload); let res = alice.handle_ping_resp(ping_resp, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::ZeroPingId); + assert!(matches!(res, Err(HandlePacketError::ZeroPingId))); } #[tokio::test] @@ -1711,8 +1704,7 @@ mod tests { let ping_resp = PingResponse::new(&precomp, bob_pk, &payload); let res = alice.handle_ping_resp(ping_resp, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::PingIdMismatch); + assert!(matches!(res, Err(HandlePacketError::PingIdMismatch))); } // handle_nodes_req @@ -1844,8 +1836,7 @@ mod tests { let nodes_req = NodesRequest::new(&precomp, alice.pk.clone(), &req_payload); let res = alice.handle_nodes_req(nodes_req, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_nodes_resp @@ -1931,8 +1922,7 @@ mod tests { let nodes_resp = NodesResponse::new(&precomp, alice.pk.clone(), &resp_payload); let res = alice.handle_nodes_resp(nodes_resp, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } #[tokio::test] @@ -2036,8 +2026,7 @@ mod tests { }; let res = alice.handle_dht_req(dht_req, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_nat_ping_request @@ -2103,8 +2092,7 @@ mod tests { let dht_req = DhtRequest::new(&precomp, alice.pk.clone(), bob_pk, &nat_payload); let res = alice.handle_dht_req(dht_req, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::ZeroPingId); + assert!(matches!(res, Err(HandlePacketError::ZeroPingId))); } #[tokio::test] @@ -2119,8 +2107,7 @@ mod tests { let dht_req = DhtRequest::new(&precomp, alice.pk.clone(), bob_pk, &nat_payload); let res = alice.handle_dht_req(dht_req, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::NoFriend); + assert!(matches!(res, Err(HandlePacketError::NoFriend))); } // handle_onion_request_0 @@ -2173,8 +2160,7 @@ mod tests { }; let res = alice.handle_onion_request_0(packet, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_onion_request_1 @@ -2235,8 +2221,7 @@ mod tests { }; let res = alice.handle_onion_request_1(packet, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_onion_request_2 @@ -2341,8 +2326,7 @@ mod tests { }; let res = alice.handle_onion_request_2(packet, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_onion_announce_request @@ -2407,8 +2391,7 @@ mod tests { }; let res = alice.handle_onion_announce_request(packet, addr).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert!(matches!(res, Err(HandlePacketError::GetPayload(GetPayloadError::Decrypt)))); } // handle_onion_data_request @@ -2583,8 +2566,7 @@ mod tests { }; let res = alice.handle_onion_response_3(packet).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::OnionResponseNext); + assert!(matches!(res, Err(HandlePacketError::OnionResponseNext))); } // handle_onion_response_2 @@ -2677,8 +2659,7 @@ mod tests { }; let res = alice.handle_onion_response_2(packet).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::OnionResponseNext); + assert!(matches!(res, Err(HandlePacketError::OnionResponseNext))); } // handle_onion_response_1 @@ -2807,8 +2788,7 @@ mod tests { }; let res = alice.handle_onion_response_1(packet).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::OnionResponseRedirect); + assert!(matches!(res, Err(HandlePacketError::OnionResponseRedirect))); } #[tokio::test] @@ -2865,8 +2845,7 @@ mod tests { }; let res = alice.handle_onion_response_1(packet).await; - assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::OnionResponseNext); + assert!(matches!(res, Err(HandlePacketError::OnionResponseNext))); } // send_nat_ping_req() diff --git a/tox_core/src/dht/server_ext.rs b/tox_core/src/dht/server_ext.rs index aa7c51679..e85289719 100644 --- a/tox_core/src/dht/server_ext.rs +++ b/tox_core/src/dht/server_ext.rs @@ -6,7 +6,6 @@ use std::net::{SocketAddr, IpAddr}; use futures::{FutureExt, SinkExt, StreamExt}; use futures::channel::mpsc::Receiver; use tokio::net::UdpSocket; -use failure::Fail; use crate::dht::codec::*; use tox_packet::dht::Packet; @@ -41,9 +40,8 @@ pub async fn dht_run_socket( Err(e) => { error!("packet receive error = {:?}", e); // ignore packet decode errors - if *e.kind() != DecodeErrorKind::Io { continue } - else { - return Err(Error::new(ErrorKind::Other, e.compat())) + if let DecodeError::Io(e) = e { + return Err(e); } } } @@ -65,7 +63,7 @@ pub async fn dht_run_socket( trace!("Sending packet {:?} to {:?}", packet, addr); sink.send((packet, addr)).await - .map_err(|e| Error::new(ErrorKind::Other, e.compat()))? + .map_err(|e| Error::new(ErrorKind::Other, e))? } Ok(()) @@ -76,7 +74,7 @@ pub async fn dht_run_socket( write = network_writer.fuse() => write, run = udp.dht.run().fuse() => { // TODO: should we run it here? let res: Result<_, _> = run; - res.map_err(|e| Error::new(ErrorKind::Other, e.compat())) + res.map_err(|e| Error::new(ErrorKind::Other, e)) } } } @@ -122,7 +120,7 @@ mod tests { // Send invalid request first to ensure that the server won't crash client_socket.send_to(&[42; 123][..], &server_addr) .await - .map_err(|e| Error::new(ErrorKind::Other, e.compat()))?; + .map_err(|e| Error::new(ErrorKind::Other, e))?; let stats = Stats::new(); let codec = DhtCodec::new(stats); @@ -136,7 +134,7 @@ mod tests { let ping_request = PingRequest::new(&shared_secret, client_pk, &ping_request_payload); sink.send((Packet::PingRequest(ping_request), server_addr)).await - .map_err(|e| Error::new(ErrorKind::Other, e.compat()))?; + .map_err(|e| Error::new(ErrorKind::Other, e))?; // And wait for ping response let ping_response = stream @@ -151,7 +149,7 @@ mod tests { .unwrap(); let ping_response = ping_response - .map_err(|e| Error::new(ErrorKind::Other, e.compat()))?; + .map_err(|e| Error::new(ErrorKind::Other, e))?; let ping_response_payload = ping_response.get_payload(&shared_secret).unwrap(); assert_eq!(ping_response_payload.id, ping_id); diff --git a/tox_core/src/error.rs b/tox_core/src/error.rs deleted file mode 100644 index d5f64aa2d..000000000 --- a/tox_core/src/error.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! `error_kind` macros that helps to construct errors using Error-ErrorKind -//! pair pattern. - -/// Helps to construct errors using Error-ErrorKind pair pattern. -macro_rules! error_kind { - ($(#[$error_attr:meta])* $error:ident, $(#[$kind_attr:meta])* $kind:ident { $($variants:tt)* }) => { - $(#[$error_attr])* - pub struct $error { - ctx: failure::Context<$kind>, - } - - impl $error { - /// Return the kind of this error. - #[allow(dead_code)] // might be unused if error is private - pub fn kind(&self) -> &$kind { - self.ctx.get_context() - } - } - - impl failure::Fail for $error { - fn cause(&self) -> Option<&dyn failure::Fail> { - self.ctx.cause() - } - - fn backtrace(&self) -> Option<&failure::Backtrace> { - self.ctx.backtrace() - } - } - - impl std::fmt::Display for $error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - self.ctx.fmt(f) - } - } - - $(#[$kind_attr])* - pub enum $kind { - $($variants)* - } - - impl From<$kind> for $error { - fn from(kind: $kind) -> $error { - $error::from(failure::Context::new(kind)) - } - } - - impl From> for $error { - fn from(ctx: failure::Context<$kind>) -> $error { - $error { ctx } - } - } - } -} - -#[cfg(test)] -mod tests { - use failure::Fail; - - error_kind! { - #[derive(Debug)] - TestError, - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - TestErrorKind { - #[fail(display = "Variant1")] - Variant1, - #[fail(display = "Variant2")] - Variant2, - } - } - - #[test] - fn test_error() { - assert_eq!(format!("{}", TestErrorKind::Variant1), "Variant1".to_owned()); - assert_eq!(format!("{}", TestErrorKind::Variant2), "Variant2".to_owned()); - } - - #[test] - fn test_error_variant_1() { - let error = TestError::from(TestErrorKind::Variant1); - assert_eq!(error.kind(), &TestErrorKind::Variant1); - assert!(error.cause().is_none()); - assert!(error.backtrace().is_some()); - assert_eq!(format!("{}", error), "Variant1".to_owned()); - } - - #[test] - fn test_error_variant_2() { - let error = TestError::from(TestErrorKind::Variant2); - assert_eq!(error.kind(), &TestErrorKind::Variant2); - assert!(error.cause().is_none()); - assert!(error.backtrace().is_some()); - assert_eq!(format!("{}", error), "Variant2".to_owned()); - } -} diff --git a/tox_core/src/friend_connection/errors.rs b/tox_core/src/friend_connection/errors.rs index b1d8c3878..39cef1cef 100644 --- a/tox_core/src/friend_connection/errors.rs +++ b/tox_core/src/friend_connection/errors.rs @@ -1,60 +1,49 @@ //! Errors for friend connections module. -use failure::Fail; +use futures::channel::mpsc::SendError; +use thiserror::Error; +use tokio::time::error::Elapsed; -error_kind! { - #[doc = "Error that can happen while removing a friend"] - #[derive(Debug)] - RemoveFriendError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - RemoveFriendErrorKind { - #[doc = "Failed to kill net_crypto connection."] - #[fail(display = "Failed to kill net_crypto connection")] - KillConnection, - #[doc = "There is no such friend."] - #[fail(display = "There is no such friend")] - NoFriend, - } +use crate::{net_crypto::errors::{KillConnectionError, SendLosslessPacketError}, relay::client::ConnectionError}; + +/// Error that can happen while removing a friend +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum RemoveFriendError { + /// Failed to kill net_crypto connection. + #[error("Failed to kill net_crypto connection")] + KillConnection(KillConnectionError), + /// There is no such friend. + #[error("There is no such friend")] + NoFriend, } -error_kind! { - #[doc = "Error that can happen while removing a frind"] - #[derive(Debug)] - RunError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - RunErrorKind { - #[doc = "Wakeup timer error."] - #[fail(display = "Wakeup timer error")] - Wakeup, - #[doc = "Timeout error."] - #[fail(display = "Timeout error")] - Timeout, - #[doc = "Failed to kill net_crypto connection."] - #[fail(display = "Failed to kill net_crypto connection")] - KillConnection, - #[doc = "Failed to send packet."] - #[fail(display = "Failed to send packet")] - SendTo, - #[doc = "Failed to add TCP connection."] - #[fail(display = "Failed to TCP connection")] - AddTcpConnection, - #[doc = "Failed to send connection status."] - #[fail(display = "Failed to send connection status")] - SendToConnectionStatus - } +/// Error that can happen while removing a friend +#[derive(Debug, Error)] +pub enum RunError { + /// Wakeup timer error. + #[error("Wakeup timer error")] + Wakeup, + /// Timeout error. + #[error("Timeout error")] + Timeout(Elapsed), + /// Failed to kill net_crypto connection. + #[error("Failed to kill net_crypto connection")] + KillConnection(KillConnectionError), + /// Failed to send packet. + #[error("Failed to send packet")] + SendTo(SendLosslessPacketError), + /// Failed to add TCP connection. + #[error("Failed to TCP connection")] + AddTcpConnection(ConnectionError), + /// Failed to send connection status. + #[error("Failed to send connection status")] + SendToConnectionStatus(SendError) } -error_kind! { - #[doc = "Error that can happen while handling `ShareRelays` packet."] - #[derive(Debug)] - HandleShareRelaysError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - HandleShareRelaysErrorKind { - #[doc = "Failed to add TCP connection."] - #[fail(display = "Failed to TCP connection")] - AddTcpConnection - } +/// Error that can happen while handling `ShareRelays` packet. +#[derive(Debug, Error)] +pub enum HandleShareRelaysError { + /// Failed to add TCP connection. + #[error("Failed to TCP connection")] + AddTcpConnection(ConnectionError) } diff --git a/tox_core/src/friend_connection/mod.rs b/tox_core/src/friend_connection/mod.rs index bf99658d3..a174e48d8 100644 --- a/tox_core/src/friend_connection/mod.rs +++ b/tox_core/src/friend_connection/mod.rs @@ -9,7 +9,6 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::{Duration, Instant}; -use failure::Fail; use futures::{FutureExt, StreamExt, SinkExt, future}; use futures::channel::mpsc; use tokio::sync::RwLock; @@ -22,7 +21,7 @@ use crate::dht::server::Server as DhtServer; use crate::friend_connection::errors::*; use tox_packet::friend_connection::*; use crate::net_crypto::NetCrypto; -use crate::net_crypto::errors::KillConnectionErrorKind; +use crate::net_crypto::errors::KillConnectionError; use crate::onion::client::OnionClient; use crate::relay::client::Connections as TcpConnections; use crate::time::*; @@ -155,13 +154,13 @@ impl FriendConnections { self.net_crypto.kill_connection(friend_pk.clone()) .then(|res| future::ready(match res { Err(ref e) - if *e.kind() == KillConnectionErrorKind::NoConnection => + if e == &KillConnectionError::NoConnection => Ok(()), res => res, })).await - .map_err(|e| e.context(RemoveFriendErrorKind::KillConnection).into()) + .map_err(RemoveFriendError::KillConnection) } else { - Err(RemoveFriendErrorKind::NoFriend.into()) + Err(RemoveFriendError::NoFriend) } } @@ -171,7 +170,7 @@ impl FriendConnections { if let Some(ref dht_pk) = friend.dht_pk { for node in share_relays.relays { self.tcp_connections.add_relay_connection(node.saddr, node.pk, dht_pk.clone()).await - .map_err(|e| e.context(HandleShareRelaysErrorKind::AddTcpConnection))?; + .map_err(HandleShareRelaysError::AddTcpConnection)?; } } } @@ -207,12 +206,12 @@ impl FriendConnections { .then(|res| future::ready( match res { Err(ref e) - if *e.kind() == KillConnectionErrorKind::NoConnection => + if e == &KillConnectionError::NoConnection => Ok(()), res => res, } )).await - .map_err(|e| e.context(RunErrorKind::KillConnection))?; + .map_err(RunError::KillConnection)?; // TODO: handle error properly after migrating the TCP client to failure tcp_connections.remove_connection(dht_pk.clone()).await.ok(); }; @@ -279,7 +278,7 @@ impl FriendConnections { onion_client.set_friend_connected(real_pk.clone(), status).await; if let Some(mut connection_status_tx) = connection_status_tx.read().await.clone() { connection_status_tx.send((real_pk, status)).await - .map_err(|e| e.context(RunErrorKind::SendToConnectionStatus))?; + .map_err(RunError::SendToConnectionStatus)?; } } } @@ -295,7 +294,7 @@ impl FriendConnections { if !relays.is_empty() { for relay in &relays { self.tcp_connections.add_connection(relay.pk.clone(), friend_pk.clone()).await - .map_err(|e| e.context(RunErrorKind::AddTcpConnection))?; + .map_err(RunError::AddTcpConnection)?; } let share_relays = ShareRelays { @@ -305,7 +304,7 @@ impl FriendConnections { let (_, size) = share_relays.to_bytes((&mut buf, 0)).unwrap(); buf.truncate(size); self.net_crypto.send_lossless(friend_pk, buf).await - .map_err(|e| e.context(RunErrorKind::SendTo).into()) + .map_err(RunError::SendTo) } else { Ok(()) } @@ -319,17 +318,17 @@ impl FriendConnections { self.net_crypto.kill_connection(friend.real_pk.clone()) .then(|res| future::ready(match res { Err(ref e) - if *e.kind() == KillConnectionErrorKind::NoConnection => + if e == &KillConnectionError::NoConnection => Ok(()), res => res, })).await - .map_err(|e| e.context(RunErrorKind::KillConnection))?; + .map_err(RunError::KillConnection)?; continue; } if friend.ping_sent_time.map_or(true, |time| clock_elapsed(time) >= FRIEND_PING_INTERVAL) { self.net_crypto.send_lossless(friend.real_pk.clone(), vec![PACKET_ID_ALIVE]).await - .map_err(|e| e.context(RunErrorKind::SendTo))?; + .map_err(RunError::SendTo)?; friend.ping_sent_time = Some(clock_now()); } @@ -372,7 +371,7 @@ impl FriendConnections { let fut = tokio::time::timeout(MAIN_LOOP_INTERVAL, self.main_loop()); let res = match fut.await { - Err(e) => Err(e.context(RunErrorKind::Timeout).into()), + Err(e) => Err(RunError::Timeout(e)), Ok(Err(e)) => Err(e), Ok(Ok(_)) => Ok(()), }; diff --git a/tox_core/src/lib.rs b/tox_core/src/lib.rs index 441b16b0d..7aa023975 100644 --- a/tox_core/src/lib.rs +++ b/tox_core/src/lib.rs @@ -18,8 +18,6 @@ extern crate nom; #[macro_use] extern crate cookie_factory; -#[macro_use] -mod error; pub mod io_tokio; pub mod time; pub mod state_format; diff --git a/tox_core/src/net_crypto/errors.rs b/tox_core/src/net_crypto/errors.rs index fd7fa0e16..18ffdecd8 100644 --- a/tox_core/src/net_crypto/errors.rs +++ b/tox_core/src/net_crypto/errors.rs @@ -4,261 +4,235 @@ Module for errors of NetCrypto. use std::net::SocketAddr; -use failure::Fail; +use futures::channel::mpsc::SendError; +use thiserror::Error; +use tokio::time::error::Elapsed; use tox_crypto::*; - -error_kind! { - #[doc = "Error that can happen while processing packets array"] - #[derive(Debug)] - PacketsArrayError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - PacketsArrayErrorKind { - #[doc = "Index is too big error."] - #[fail(display = "The index {:?} is too big and can't be hold", index)] - TooBig { - #[doc = "The index that can't be hold."] - index: u32, - }, - #[doc = "Index already exists error."] - #[fail(display = "The packet with index {:?} already exists", index)] - AlreadyExist { - #[doc = "The index that already exists."] - index: u32, - }, - #[doc = "Packets array is full."] - #[fail(display = "Packets array is full")] - ArrayFull, - #[doc = "Index is lower than the end index."] - #[fail(display = "Index {:?} is lower than the end index", index)] - LowerIndex { - #[doc = "The index that lower than end index."] - index: u32, - }, - #[doc = "Index is outside of buffer bounds."] - #[fail(display = "Index {:?} is outside of buffer bounds", index)] - OutsideIndex { - #[doc = "The index that is outside of buffer bounds."] - index: u32, - }, - } +use tox_packet::dht::GetPayloadError; + +/// Error that can happen while processing packets array +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum PacketsArrayError { + /// Index is too big error. + #[error("The index {:?} is too big and can't be hold", index)] + TooBig { + /// The index that can't be hold. + index: u32, + }, + /// Index already exists error. + #[error("The packet with index {:?} already exists", index)] + AlreadyExist { + /// The index that already exists. + index: u32, + }, + /// Packets array is full. + #[error("Packets array is full")] + ArrayFull, + /// Index is lower than the end index. + #[error("Index {:?} is lower than the end index", index)] + LowerIndex { + /// The index that lower than end index. + index: u32, + }, + /// Index is outside of buffer bounds. + #[error("Index {:?} is outside of buffer bounds", index)] + OutsideIndex { + /// The index that is outside of buffer bounds. + index: u32, + }, } impl PacketsArrayError { pub(crate) fn too_big(index: u32) -> PacketsArrayError { - PacketsArrayError::from(PacketsArrayErrorKind::TooBig { index }) + PacketsArrayError::TooBig { index } } pub(crate) fn already_exist(index: u32) -> PacketsArrayError { - PacketsArrayError::from(PacketsArrayErrorKind::AlreadyExist { index }) + PacketsArrayError::AlreadyExist { index } } pub(crate) fn lower_index(index: u32) -> PacketsArrayError { - PacketsArrayError::from(PacketsArrayErrorKind::LowerIndex { index }) + PacketsArrayError::LowerIndex { index } } pub(crate) fn outside_index(index: u32) -> PacketsArrayError { - PacketsArrayError::from(PacketsArrayErrorKind::OutsideIndex { index }) + PacketsArrayError::OutsideIndex { index } } } -error_kind! { - #[doc = "Error that can happen when calling `handle_*` of packet."] - #[derive(Debug)] - HandlePacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - HandlePacketErrorKind { - #[doc = "Error indicates that getting payload of received packet error."] - #[fail(display = "Get payload of received packet error")] - GetPayload, - #[doc = "Error indicates that sending response packet error."] - #[fail(display = "Sending response error")] - SendTo, - #[doc = "Error indicates that sending lossless response packet error."] - #[fail(display = "Sending lossless response error")] - SendToLossless, - #[doc = "Error indicates that sending lossy response packet error."] - #[fail(display = "Sending lossy response error")] - SendToLossy, - #[doc = "Error indicates that sending dhtpk packet error."] - #[fail(display = "Sending dhtpk packet error")] - SendToDhtpk, - #[doc = "Error indicates that sending connection status error."] - #[fail(display = "Sending connection status error")] - SendToConnectionStatus, - #[doc = "Error indicates that NetCrypto can't handle packet in current connection state."] - #[fail(display = "Can't handle CookieResponse in current connection state")] - InvalidState, - #[doc = "Error indicates that NetCrypto can't handle crypto data packet in current connection state."] - #[fail(display = "Can't handle CryptoData in current connection state")] - CannotHandleCryptoData, - #[doc = "Error indicates that invalid cookie request id."] - #[fail(display = "Invalid cookie request id: expected {:?} but got {:?}", expect, got)] - InvalidRequestId { - #[doc = "Expected request id."] - expect: u64, - #[doc = "Gotten request id."] - got: u64, - }, - #[doc = "Error indicates that no crypto connection for address."] - #[fail(display = "No crypto connection for address: {:?}", addr)] - NoUdpConnection { - #[doc = "The address for connection which don't exist."] - addr: SocketAddr, - }, - #[doc = "Error indicates that no crypto connection for address."] - #[fail(display = "No crypto connection for DHT key: {:?}", pk)] - NoTcpConnection { - #[doc = "The DHT key for connection which don't exist."] - pk: PublicKey, - }, - #[doc = "Unexpected crypto handshake."] - #[fail(display = "Unexpected crypto handshake")] - UnexpectedCryptoHandshake, - #[doc = "Error indicates that invalid SHA512 hash of cookie."] - #[fail(display = "Invalid SHA512 hash of cookie")] - BadSha512, - #[doc = "Error indicates that cookie is timed out."] - #[fail(display = "Cookie is timed out")] - CookieTimedOut, - #[doc = "Error indicates that cookie contains invalid real pk."] - #[fail(display = "Cookie contains invalid real pk")] - InvalidRealPk, - #[doc = "Error indicates that cookie contains invalid dht pk."] - #[fail(display = "Cookie contains invalid dht pk")] - InvalidDhtPk, - #[doc = "Error indicates that there is PacketsArrayError."] - #[fail(display = "PacketsArrayError occurs")] - PacketsArrayError, - #[doc = "Error indicates that real data is empty."] - #[fail(display = "Real data is empty")] - DataEmpty, - #[doc = "Error indicates that invalid packet id."] - #[fail(display = "Invalid packet id: {:?}", id)] - PacketId { - #[doc = "The packet id that is invalid."] - id: u8, - }, - } +/// Error that can happen when calling `handle_*` of packet. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum HandlePacketError { + /// Error indicates that getting payload of received packet error. + #[error("Get payload of received packet error")] + GetPayload(GetPayloadError), + /// Error indicates that sending response packet error. + #[error("Sending response error")] + SendTo(SendPacketError), + /// Error indicates that sending response packet error. + #[error("Sending response error")] + SendDataTo(SendDataError), + /// Error indicates that sending lossless response packet error. + #[error("Sending lossless response error")] + SendToLossless(SendError), + /// Error indicates that sending lossy response packet error. + #[error("Sending lossy response error")] + SendToLossy(SendError), + /// Error indicates that sending dhtpk packet error. + #[error("Sending dhtpk packet error")] + SendToDhtpk(SendError), + /// Error indicates that sending connection status error. + #[error("Sending connection status error")] + SendToConnectionStatus(SendError), + /// Error indicates that NetCrypto can't handle packet in current connection state. + #[error("Can't handle CookieResponse in current connection state")] + InvalidState, + /// Error indicates that NetCrypto can't handle crypto data packet in current connection state. + #[error("Can't handle CryptoData in current connection state")] + CannotHandleCryptoData, + /// Error indicates that invalid cookie request id. + #[error("Invalid cookie request id: expected {:?} but got {:?}", expect, got)] + InvalidRequestId { + /// Expected request id. + expect: u64, + /// Gotten request id. + got: u64, + }, + /// Error indicates that no crypto connection for address. + #[error("No crypto connection for address: {:?}", addr)] + NoUdpConnection { + /// The address for connection which don't exist. + addr: SocketAddr, + }, + /// Error indicates that no crypto connection for address. + #[error("No crypto connection for DHT key: {:?}", pk)] + NoTcpConnection { + /// The DHT key for connection which don't exist. + pk: PublicKey, + }, + /// Unexpected crypto handshake. + #[error("Unexpected crypto handshake")] + UnexpectedCryptoHandshake, + /// Error indicates that invalid SHA512 hash of cookie. + #[error("Invalid SHA512 hash of cookie")] + BadSha512, + /// Error indicates that cookie is timed out. + #[error("Cookie is timed out")] + CookieTimedOut, + /// Error indicates that cookie contains invalid real pk. + #[error("Cookie contains invalid real pk")] + InvalidRealPk, + /// Error indicates that cookie contains invalid dht pk. + #[error("Cookie contains invalid dht pk")] + InvalidDhtPk, + /// Error indicates that there is PacketsArrayError. + #[error("PacketsArrayError occurs")] + PacketsArrayError(PacketsArrayError), + /// Error indicates that real data is empty. + #[error("Real data is empty")] + DataEmpty, + /// Error indicates that invalid packet id. + #[error("Invalid packet id: {:?}", id)] + PacketId { + /// The packet id that is invalid. + id: u8, + }, } impl HandlePacketError { pub(crate) fn invalid_request_id(expect: u64, got: u64) -> HandlePacketError { - HandlePacketError::from(HandlePacketErrorKind::InvalidRequestId { + HandlePacketError::InvalidRequestId { expect, got, - }) + } } pub(crate) fn no_udp_connection(addr: SocketAddr) -> HandlePacketError { - HandlePacketError::from(HandlePacketErrorKind::NoUdpConnection { + HandlePacketError::NoUdpConnection { addr, - }) + } } pub(crate) fn no_tcp_connection(pk: PublicKey) -> HandlePacketError { - HandlePacketError::from(HandlePacketErrorKind::NoTcpConnection { + HandlePacketError::NoTcpConnection { pk, - }) + } } pub(crate) fn packet_id(id: u8) -> HandlePacketError { - HandlePacketError::from(HandlePacketErrorKind::PacketId { + HandlePacketError::PacketId { id, - }) + } } } -error_kind! { - #[doc = "Error that can happen while processing packets array."] - #[derive(Debug)] - SendDataError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - SendDataErrorKind { - #[doc = "Connection is not established."] - #[fail(display = "Connection is not established")] - NoConnection, - #[doc = "Error indicates that sending response packet error."] - #[fail(display = "Sending response error")] - SendTo, - #[doc = "Error indicates that sending connection status error."] - #[fail(display = "Sending connection status error")] - SendToConnectionStatus, - } +/// Error that can happen while processing packets array. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum SendDataError { + /// Connection is not established. + #[error("Connection is not established")] + NoConnection, + /// Error indicates that sending response packet error. + #[error("Sending response error")] + SendTo(SendPacketError), + /// Error indicates that sending connection status error. + #[error("Sending connection status error")] + SendToConnectionStatus(SendError), } -error_kind! { - #[doc = "Error that can happen when calling `run`."] - #[derive(Debug)] - RunError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, Fail)] - RunErrorKind { - #[doc = "Sending pings error."] - #[fail(display = "Sending crypto data packet error")] - SendData, - #[doc = "NetCrypto periodical wakeup timer error."] - #[fail(display = "Netcrypto periodical wakeup timer error")] - Wakeup, - } +/// Error that can happen when calling `run`. +#[derive(Debug, PartialEq, Error)] +pub enum RunError { + /// Sending pings error. + #[error("Sending crypto data packet error")] + SendData(SendDataError), + /// Timeout error. + #[error("Timeout error")] + Timeout(Elapsed), + /// NetCrypto periodical wakeup timer error. + #[error("Netcrypto periodical wakeup timer error")] + Wakeup, } -error_kind! { - #[doc = "Error that can happen during a lossless packet sending."] - #[derive(Debug)] - SendLosslessPacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - SendLosslessPacketErrorKind { - #[doc = "Packet ID is outside lossless packets range."] - #[fail(display = "Packet ID is outside lossless packets range")] - InvalidPacketId, - #[doc = "Connection to a friend is not established."] - #[fail(display = "Connection to a friend is not established")] - NoConnection, - #[doc = "Packets send array is full."] - #[fail(display = "Packets send array is full")] - FullSendArray, - #[doc = "Failed to send packet."] - #[fail(display = "Failed to send packet")] - SendTo, - } +/// Error that can happen during a lossless packet sending. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum SendLosslessPacketError { + /// Packet ID is outside lossless packets range. + #[error("Packet ID is outside lossless packets range")] + InvalidPacketId, + /// Connection to a friend is not established. + #[error("Connection to a friend is not established")] + NoConnection, + /// Packets send array is full. + #[error("Packets send array is full")] + FullSendArray(PacketsArrayError), + /// Failed to send packet. + #[error("Failed to send packet")] + SendTo(SendDataError), } -error_kind! { - #[doc = "Error that can happen during a lossless packet sending."] - #[derive(Debug)] - KillConnectionError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - KillConnectionErrorKind { - #[doc = "Connection to a friend is not established."] - #[fail(display = "Connection to a friend is not established")] - NoConnection, - #[doc = "Failed to send kill packet."] - #[fail(display = "Failed to send kill packet")] - SendTo, - #[doc = "Error indicates that sending connection status error."] - #[fail(display = "Sending connection status error")] - SendToConnectionStatus, - } +/// Error that can happen during a lossless packet sending. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum KillConnectionError { + /// Connection to a friend is not established. + #[error("Connection to a friend is not established")] + NoConnection, + /// Failed to send kill packet. + #[error("Failed to send kill packet")] + SendTo(SendDataError), + /// Error indicates that sending connection status error. + #[error("Sending connection status error")] + SendToConnectionStatus(SendError), } -error_kind! { - #[doc = "Error that can happen during a packet sending."] - #[derive(Debug)] - SendPacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Debug, Eq, PartialEq, Fail)] - SendPacketErrorKind { - #[doc = "Failed to send TCP packet."] - #[fail(display = "Failed to send TCP packet")] - Tcp, - #[doc = "Failed to send UDP packet."] - #[fail(display = "Failed to send UDP packet")] - Udp, - } +/// Error that can happen during a packet sending. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum SendPacketError { + /// Failed to send TCP packet. + #[error("Failed to send TCP packet")] + Tcp(SendError), + /// Failed to send UDP packet. + #[error("Failed to send UDP packet")] + Udp(SendError), } diff --git a/tox_core/src/net_crypto/mod.rs b/tox_core/src/net_crypto/mod.rs index 79c19e6e8..1a4900b0f 100644 --- a/tox_core/src/net_crypto/mod.rs +++ b/tox_core/src/net_crypto/mod.rs @@ -25,7 +25,6 @@ use std::time::{Duration, Instant}; use std::u16; use crypto_box::SalsaBox; -use failure::Fail; use futures::{TryFutureExt, SinkExt}; use futures::future; use futures::channel::mpsc; @@ -306,11 +305,11 @@ impl NetCrypto { self.clear_keys_by_addr(&connection).await; self.send_connection_status(&connection, false).await - .map_err(|e| e.context(KillConnectionErrorKind::SendToConnectionStatus))?; + .map_err(KillConnectionError::SendToConnectionStatus)?; self.send_kill_packet(&mut connection).await - .map_err(|e| e.context(KillConnectionErrorKind::SendTo).into()) + .map_err(KillConnectionError::SendTo) } else { - Err(KillConnectionErrorKind::NoConnection.into()) + Err(KillConnectionError::NoConnection) } } @@ -343,21 +342,21 @@ impl NetCrypto { /// Send lossless packet to a friend via established connection. pub async fn send_lossless(&self, real_pk: PublicKey, packet: Vec) -> Result<(), SendLosslessPacketError> { if packet.first().map_or(true, |&packet_id| packet_id <= PACKET_ID_CRYPTO_RANGE_END || packet_id >= PACKET_ID_LOSSY_RANGE_START) { - return Err(SendLosslessPacketErrorKind::InvalidPacketId.into()); + return Err(SendLosslessPacketError::InvalidPacketId); } if let Some(connection) = self.connections.read().await.get(&real_pk) { let mut connection = connection.write().await; let packet_number = connection.send_array.buffer_end; if let Err(e) = connection.send_array.push_back(SentPacket::new(packet.clone())) { - Err(e.context(SendLosslessPacketErrorKind::FullSendArray).into()) + Err(SendLosslessPacketError::FullSendArray(e)) } else { connection.packets_sent += 1; self.send_data_packet(&mut connection, packet, packet_number).await - .map_err(|e| e.context(SendLosslessPacketErrorKind::SendTo).into()) + .map_err(SendLosslessPacketError::SendTo) } } else { - Err(SendLosslessPacketErrorKind::NoConnection.into()) + Err(SendLosslessPacketError::NoConnection) } } @@ -399,7 +398,7 @@ impl NetCrypto { /// Create `CookieResponse` packet with `Cookie` requested by `CookieRequest` packet async fn handle_cookie_request(&self, packet: &CookieRequest) -> Result { let payload = packet.get_payload(&self.precomputed_keys.get(packet.pk.clone()).await) - .map_err(|e| e.context(HandlePacketErrorKind::GetPayload))?; + .map_err(HandlePacketError::GetPayload)?; let cookie = Cookie::new(payload.pk, packet.pk.clone()); let encrypted_cookie = EncryptedCookie::new(&mut thread_rng(), &self.symmetric_key, &cookie); @@ -418,7 +417,7 @@ impl NetCrypto { pub async fn handle_udp_cookie_request(&self, packet: &CookieRequest, addr: SocketAddr) -> Result<(), HandlePacketError> { match self.handle_cookie_request(packet).await { Ok(response) => self.send_to_udp(addr, DhtPacket::CookieResponse(response)).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()), + .map_err(|e| HandlePacketError::SendTo(SendPacketError::Udp(e))), Err(e) => Err(e), } } @@ -429,7 +428,7 @@ impl NetCrypto { Ok(response) => { let msg = (TcpDataPayload::CookieResponse(response), sender_pk); maybe_send_bounded(self.tcp_tx.read().await.clone(), msg).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(|e| HandlePacketError::SendTo(SendPacketError::Tcp(e))) } Err(e) => Err(e), } @@ -441,12 +440,12 @@ impl NetCrypto { let cookie_request_id = if let ConnectionStatus::CookieRequesting { cookie_request_id, .. } = connection.status { cookie_request_id } else { - return Err(HandlePacketError::from(HandlePacketErrorKind::InvalidState)) + return Err(HandlePacketError::InvalidState) }; let payload = match packet.get_payload(&self.precomputed_keys.get(connection.peer_dht_pk.clone()).await) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), }; if payload.id != cookie_request_id { @@ -471,7 +470,7 @@ impl NetCrypto { }; self.send_status_packet(connection) - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()).await + .map_err(HandlePacketError::SendTo).await } /// Handle `CookieResponse` packet received from UDP socket @@ -505,22 +504,22 @@ impl NetCrypto { -> Result<(Cookie, CryptoHandshakePayload, SalsaBox), HandlePacketError> { let cookie = match packet.cookie.get_payload(&self.symmetric_key) { Ok(cookie) => cookie, - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), }; if cookie.is_timed_out() { - return Err(HandlePacketErrorKind::CookieTimedOut.into()); + return Err(HandlePacketError::CookieTimedOut); } let real_precomputed_key = SalsaBox::new(&cookie.real_pk, &self.real_sk); let payload = match packet.get_payload(&real_precomputed_key) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()), + Err(e) => return Err(HandlePacketError::GetPayload(e)), }; if packet.cookie.hash() != payload.cookie_hash { - return Err(HandlePacketErrorKind::BadSha512.into()); + return Err(HandlePacketError::BadSha512); } Ok((cookie, payload, real_precomputed_key)) @@ -530,7 +529,7 @@ impl NetCrypto { pub async fn handle_crypto_handshake(&self, connection: &mut CryptoConnection, packet: &CryptoHandshake) -> Result<(), HandlePacketError> { if let ConnectionStatus::Established { .. } = connection.status { - return Err(HandlePacketError::from(HandlePacketErrorKind::InvalidState)) + return Err(HandlePacketError::InvalidState) } let (cookie, payload, real_precomputed_key) = match self.validate_crypto_handshake(packet) { @@ -539,17 +538,15 @@ impl NetCrypto { }; if cookie.real_pk != connection.peer_real_pk { - return Err(HandlePacketError::from(HandlePacketErrorKind::InvalidRealPk)) + return Err(HandlePacketError::InvalidRealPk) } if cookie.dht_pk != connection.peer_dht_pk { let msg = (connection.peer_real_pk.clone(), cookie.dht_pk); let dht_pk_future = maybe_send_unbounded(self.dht_pk_tx.read().await.clone(), msg) - .map_err(|e| e.context(HandlePacketErrorKind::SendToDhtpk).into()); + .map_err(HandlePacketError::SendToDhtpk); - return dht_pk_future.and_then(|()| future::err( - HandlePacketError::from(HandlePacketErrorKind::InvalidDhtPk) - )).await + return dht_pk_future.and_then(|()| future::err(HandlePacketError::InvalidDhtPk)).await } connection.status = match connection.status { @@ -583,7 +580,7 @@ impl NetCrypto { }; self.send_status_packet(connection).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Handle incoming `CryptoHandshake` in case when we don't have associated @@ -596,7 +593,7 @@ impl NetCrypto { }; if !self.friends.read().await.contains(&cookie.real_pk) { - return Err(HandlePacketErrorKind::UnexpectedCryptoHandshake.into()); + return Err(HandlePacketError::UnexpectedCryptoHandshake); } let mut connections = self.connections.write().await; @@ -611,13 +608,9 @@ impl NetCrypto { self.clear_keys_by_addr(&connection).await; self.send_connection_status(&connection, false).await - .map_err(|e| - HandlePacketError::from(e.context(HandlePacketErrorKind::SendToConnectionStatus)) - )?; + .map_err(HandlePacketError::SendToConnectionStatus)?; self.send_kill_packet(&mut connection).await - .map_err(|e| - HandlePacketError::from(e.context(HandlePacketErrorKind::SendTo)) - )?; + .map_err(HandlePacketError::SendDataTo)?; } else { // We received a handshake packet for an existent connection // from a new address and this packet contains the same DHT @@ -626,7 +619,7 @@ impl NetCrypto { // otherwise. if connection.is_established() || connection.is_not_confirmed() { - return Err(HandlePacketErrorKind::UnexpectedCryptoHandshake.into()); + return Err(HandlePacketError::UnexpectedCryptoHandshake); } self.clear_keys_by_addr(&connection).await; @@ -651,7 +644,7 @@ impl NetCrypto { let msg = (cookie.real_pk, cookie.dht_pk); maybe_send_unbounded(self.dht_pk_tx.read().await.clone(), msg).await - .map_err(|e| e.context(HandlePacketErrorKind::SendToDhtpk).into()) + .map_err(HandlePacketError::SendToDhtpk) } /// Handle `CryptoHandshake` packet received from UDP socket @@ -817,9 +810,7 @@ impl NetCrypto { (sent_nonce, received_nonce, session_precomputed_key.clone()) }, _ => { - return Err(HandlePacketError::from( - HandlePacketErrorKind::CannotHandleCryptoData) - ) + return Err(HandlePacketError::CannotHandleCryptoData) } }; @@ -831,7 +822,7 @@ impl NetCrypto { let payload = match packet.get_payload(&session_precomputed_key, &packet_nonce) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandlePacketErrorKind::GetPayload).into()) + Err(e) => return Err(HandlePacketError::GetPayload(e)) }; // Find the time when the last acknowledged packet was sent @@ -842,13 +833,13 @@ impl NetCrypto { // Remove all acknowledged packets and set new start index to the send buffer if let Err(e) = connection.send_array.set_buffer_start(payload.buffer_start) { - return Err(e.context(HandlePacketErrorKind::PacketsArrayError).into()) + return Err(HandlePacketError::PacketsArrayError(e)) } // And get the ID of the packet let packet_id = match payload.data.first() { Some(&packet_id) => packet_id, - None => return Err(HandlePacketError::from(HandlePacketErrorKind::DataEmpty)) + None => return Err(HandlePacketError::DataEmpty) }; if packet_id == PACKET_ID_KILL { @@ -856,7 +847,7 @@ impl NetCrypto { self.connections.write().await.remove(&connection.peer_real_pk); self.clear_keys_by_addr(connection).await; return self.send_connection_status(connection, false) - .map_err(|e| e.context(HandlePacketErrorKind::SendToConnectionStatus).into()).await; + .map_err(HandlePacketError::SendToConnectionStatus).await; } // Update nonce if diff is big enough @@ -865,7 +856,7 @@ impl NetCrypto { } self.send_connection_status(connection, true).await - .map_err(|e| e.context(HandlePacketErrorKind::SendToConnectionStatus))?; + .map_err(HandlePacketError::SendToConnectionStatus)?; connection.status = ConnectionStatus::Established { sent_nonce, @@ -886,11 +877,11 @@ impl NetCrypto { connection.recv_array.set_buffer_end(payload.packet_number).ok(); } else if packet_id > PACKET_ID_CRYPTO_RANGE_END && packet_id < PACKET_ID_LOSSY_RANGE_START { if let Err(e) = connection.recv_array.insert(payload.packet_number, RecvPacket::new(payload.data)) { - return Err(e.context(HandlePacketErrorKind::PacketsArrayError).into()) + return Err(HandlePacketError::PacketsArrayError(e)) } connection.packets_received += 1; self.process_ready_lossless_packets(&mut connection.recv_array, connection.peer_real_pk.clone()).await - .map_err(|e| e.context(HandlePacketErrorKind::SendToLossless))?; + .map_err(HandlePacketError::SendToLossless)?; } else if (PACKET_ID_LOSSY_RANGE_START..=PACKET_ID_LOSSY_RANGE_END).contains(&packet_id) { // Update end index of received buffer ignoring the error - we still // want to handle this packet even if connection is too slow @@ -900,7 +891,7 @@ impl NetCrypto { let data = payload.data.clone(); tx.send((peer_real_pk, data)).await - .map_err(|e| e.context(HandlePacketErrorKind::SendToLossy))?; + .map_err(HandlePacketError::SendToLossy)?; } else { return Err(HandlePacketError::packet_id(packet_id)) }; @@ -946,7 +937,7 @@ impl NetCrypto { if let Some(addr) = connection.get_udp_addr() { if connection.is_udp_alive() { return self.send_to_udp(addr, packet.into()).await - .map_err(|e| e.context(SendPacketErrorKind::Udp).into()) + .map_err(SendPacketError::Udp) } let dht_packet: DhtPacket = packet.clone().into(); @@ -959,13 +950,13 @@ impl NetCrypto { if udp_attempt_should_be_made { connection.update_udp_send_attempt_time(); self.send_to_udp(addr, dht_packet).await - .map_err(|e| e.context(SendPacketErrorKind::Udp))?; + .map_err(SendPacketError::Udp)?; } }; let tcp_tx = self.tcp_tx.read().await.clone(); maybe_send_bounded(tcp_tx, (packet.into(), connection.peer_dht_pk.clone())).await - .map_err(|e| e.context(SendPacketErrorKind::Tcp).into()) + .map_err(SendPacketError::Tcp) } /// Send `CookieRequest` or `CryptoHandshake` packet if needed depending on @@ -992,10 +983,10 @@ impl NetCrypto { increment_nonce(sent_nonce); packet }, - _ => return Err(SendDataError::from(SendDataErrorKind::NoConnection)), + _ => return Err(SendDataError::NoConnection), }; self.send_packet(Packet::CryptoData(packet), connection).await - .map_err(|e| e.context(SendDataErrorKind::SendTo).into()) + .map_err(SendDataError::SendTo) } /// Send request packet with indices of not received packets. @@ -1045,7 +1036,7 @@ impl NetCrypto { if connection.is_established() { self.send_connection_status(&connection, false).await - .map_err(|e| e.context(SendDataErrorKind::SendToConnectionStatus))?; + .map_err(SendDataError::SendToConnectionStatus)?; } if connection.is_established() || connection.is_not_confirmed() { @@ -1056,7 +1047,7 @@ impl NetCrypto { } self.send_status_packet(&mut connection).await - .map_err(|e| e.context(SendDataErrorKind::SendTo))?; + .map_err(SendDataError::SendTo)?; if connection.is_not_confirmed() || connection.is_established() { let should_send = connection.request_packet_sent_time.map_or(true, |time| @@ -1106,8 +1097,8 @@ impl NetCrypto { let res = match fut.await { - Err(e) => Err(e.context(RunErrorKind::SendData).into()), - Ok(Err(e)) => Err(e.context(RunErrorKind::SendData).into()), + Err(e) => Err(RunError::Timeout(e)), + Ok(Err(e)) => Err(RunError::SendData(e)), Ok(Ok(_)) => Ok(()), }; @@ -1305,7 +1296,7 @@ mod tests { let res = net_crypto.handle_cookie_request(&cookie_request).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert_eq!(res.err().unwrap(), HandlePacketError::GetPayload(GetPayloadError::Decrypt)); } #[tokio::test] @@ -1445,7 +1436,7 @@ mod tests { let res = net_crypto.handle_udp_cookie_request(&cookie_request, addr).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::GetPayload); + assert_eq!(res.err().unwrap(), HandlePacketError::GetPayload(GetPayloadError::Decrypt)); } #[tokio::test] @@ -1547,7 +1538,7 @@ mod tests { let res = net_crypto.handle_cookie_response(&mut connection, &cookie_response).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::InvalidState); + assert_eq!(res.err().unwrap(), HandlePacketError::InvalidState); } #[tokio::test] @@ -1713,7 +1704,7 @@ mod tests { let res = net_crypto.handle_udp_cookie_response(&cookie_response, addr).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::NoUdpConnection { addr: "127.0.0.1:12345".parse().unwrap() }); + assert_eq!(res.err().unwrap(), HandlePacketError::NoUdpConnection { addr: "127.0.0.1:12345".parse().unwrap() }); } #[tokio::test] @@ -1899,7 +1890,7 @@ mod tests { let res = net_crypto.handle_crypto_handshake(&mut connection, &crypto_handshake).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::InvalidState); + assert_eq!(res.err().unwrap(), HandlePacketError::InvalidState); } #[tokio::test] @@ -1949,7 +1940,7 @@ mod tests { let res = net_crypto.handle_crypto_handshake(&mut connection, &crypto_handshake).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::BadSha512); + assert_eq!(res.err().unwrap(), HandlePacketError::BadSha512); } #[tokio::test] @@ -2000,7 +1991,7 @@ mod tests { let res = net_crypto.handle_crypto_handshake(&mut connection, &crypto_handshake).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::CookieTimedOut); + assert_eq!(res.err().unwrap(), HandlePacketError::CookieTimedOut); } #[tokio::test] @@ -2051,7 +2042,7 @@ mod tests { let res = net_crypto.handle_crypto_handshake(&mut connection, &crypto_handshake).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::InvalidRealPk); + assert_eq!(res.err().unwrap(), HandlePacketError::InvalidRealPk); } #[tokio::test] @@ -2106,7 +2097,7 @@ mod tests { let res = net_crypto.handle_crypto_handshake(&mut connection, &crypto_handshake).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::InvalidDhtPk); + assert_eq!(res.err().unwrap(), HandlePacketError::InvalidDhtPk); let (keys, _dht_pk_rx) = dht_pk_rx.into_future().await; let (received_real_pk, received_dht_pk) = keys.unwrap(); @@ -2519,7 +2510,7 @@ mod tests { let new_addr = "127.0.0.2:12345".parse().unwrap(); let error = net_crypto.handle_udp_crypto_handshake(&crypto_handshake, new_addr).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::UnexpectedCryptoHandshake); + assert_eq!(error, HandlePacketError::UnexpectedCryptoHandshake); } #[tokio::test] @@ -2569,7 +2560,7 @@ mod tests { let error = net_crypto.handle_udp_crypto_handshake(&crypto_handshake, addr).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::UnexpectedCryptoHandshake); + assert_eq!(error, HandlePacketError::UnexpectedCryptoHandshake); } #[tokio::test] @@ -2828,7 +2819,7 @@ mod tests { let res = net_crypto.handle_crypto_data(&mut connection, &crypto_data, /* udp */ true).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::PacketsArrayError); + assert_eq!(res.err().unwrap(), HandlePacketError::PacketsArrayError(PacketsArrayError::OutsideIndex { index: 7 })); assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce); @@ -2974,7 +2965,7 @@ mod tests { let res = net_crypto.handle_crypto_data(&mut connection, &crypto_data, /* udp */ true).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::PacketsArrayError); + assert_eq!(res.err().unwrap(), HandlePacketError::PacketsArrayError(PacketsArrayError::TooBig { index: 32768 })); assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce); @@ -3231,7 +3222,7 @@ mod tests { let res = net_crypto.handle_crypto_data(&mut connection, &crypto_data, /* udp */ true).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::PacketId { id: 255 }); + assert_eq!(res.err().unwrap(), HandlePacketError::PacketId { id: 255 }); assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce); @@ -3287,7 +3278,7 @@ mod tests { let res = net_crypto.handle_crypto_data(&mut connection, &crypto_data, /* udp */ true).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::DataEmpty); + assert_eq!(res.err().unwrap(), HandlePacketError::DataEmpty); assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce); @@ -3337,7 +3328,7 @@ mod tests { let res = net_crypto.handle_crypto_data(&mut connection, &crypto_data, /* udp */ true).await; assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), HandlePacketErrorKind::CannotHandleCryptoData); + assert_eq!(res.err().unwrap(), HandlePacketError::CannotHandleCryptoData); } async fn handle_crypto_data_lossy_test<'a, R, F>(handle_function: F) @@ -4311,7 +4302,7 @@ mod tests { let peer_real_pk = SecretKey::generate(&mut rng).public_key(); let error = net_crypto.send_lossless(peer_real_pk, vec![16, 42]).await.err().unwrap(); - assert_eq!(*error.kind(), SendLosslessPacketErrorKind::NoConnection); + assert_eq!(error, SendLosslessPacketError::NoConnection); } #[tokio::test] @@ -4339,7 +4330,7 @@ mod tests { let peer_real_pk = SecretKey::generate(&mut rng).public_key(); let error = net_crypto.send_lossless(peer_real_pk, vec![10, 42]).await.err().unwrap(); - assert_eq!(*error.kind(), SendLosslessPacketErrorKind::InvalidPacketId); + assert_eq!(error, SendLosslessPacketError::InvalidPacketId); } #[tokio::test] @@ -4620,7 +4611,7 @@ mod tests { let peer_real_pk = SecretKey::generate(&mut rng).public_key(); let error = net_crypto.kill_connection(peer_real_pk).await.err().unwrap(); - assert_eq!(*error.kind(), KillConnectionErrorKind::NoConnection); + assert_eq!(error, KillConnectionError::NoConnection); } #[tokio::test] diff --git a/tox_core/src/net_crypto/packets_array.rs b/tox_core/src/net_crypto/packets_array.rs index fbf0cedd2..c20388ad6 100644 --- a/tox_core/src/net_crypto/packets_array.rs +++ b/tox_core/src/net_crypto/packets_array.rs @@ -94,7 +94,7 @@ impl PacketsArray { /// Returns an error when the buffer is full pub fn push_back(&mut self, packet: T) -> Result<(), PacketsArrayError> { if self.len() == CRYPTO_PACKET_BUFFER_SIZE { - return Err(PacketsArrayError::from(PacketsArrayErrorKind::ArrayFull)) + return Err(PacketsArrayError::ArrayFull) } self.buffer[real_index(self.buffer_end)] = Some(Box::new(packet)); @@ -254,7 +254,7 @@ mod tests { assert!(array.insert(7, ()).is_ok()); let res = array.insert(7, ()); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::AlreadyExist { index: 7 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::AlreadyExist { index: 7 }); assert!(array.insert(6, ()).is_ok()); assert!(array.insert(8, ()).is_ok()); } @@ -264,13 +264,13 @@ mod tests { let mut array = PacketsArray::<()>::new(); let res = array.insert(CRYPTO_PACKET_BUFFER_SIZE, ()); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE }); + assert_eq!(res.err().unwrap(), PacketsArrayError::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE }); assert_eq!(array.buffer_start, 0); assert_eq!(array.buffer_end, 0); array.buffer_start = u32::max_value(); let res = array.insert(CRYPTO_PACKET_BUFFER_SIZE - 1, ()); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE - 1 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE - 1 }); assert_eq!(array.buffer_start, u32::max_value()); assert_eq!(array.buffer_end, 0); } @@ -301,7 +301,7 @@ mod tests { array.buffer_end = CRYPTO_PACKET_BUFFER_SIZE; let res = array.push_back(()); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::ArrayFull); + assert_eq!(res.err().unwrap(), PacketsArrayError::ArrayFull); assert_eq!(array.buffer_start, 0); assert_eq!(array.buffer_end, CRYPTO_PACKET_BUFFER_SIZE); } @@ -389,7 +389,7 @@ mod tests { let mut array = PacketsArray::<()>::new(); let res = array.set_buffer_end(CRYPTO_PACKET_BUFFER_SIZE + 1); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE + 1 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::TooBig { index: CRYPTO_PACKET_BUFFER_SIZE + 1 }); assert_eq!(array.buffer_start, 0); assert_eq!(array.buffer_end, 0); } @@ -400,7 +400,7 @@ mod tests { array.buffer_end = 7; let res = array.set_buffer_end(6); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::LowerIndex { index: 6 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::LowerIndex { index: 6 }); assert_eq!(array.buffer_start, 0); assert_eq!(array.buffer_end, 7); } @@ -429,7 +429,7 @@ mod tests { let mut array = PacketsArray::<()>::new(); let res = array.set_buffer_start(1); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::OutsideIndex { index: 1 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::OutsideIndex { index: 1 }); assert_eq!(array.buffer_start, 0); assert_eq!(array.buffer_end, 0); } @@ -441,7 +441,7 @@ mod tests { array.buffer_end = 7; let res = array.set_buffer_start(1); assert!(res.is_err()); - assert_eq!(*res.err().unwrap().kind(), PacketsArrayErrorKind::OutsideIndex { index: 1 }); + assert_eq!(res.err().unwrap(), PacketsArrayError::OutsideIndex { index: 1 }); assert_eq!(array.buffer_start, 7); assert_eq!(array.buffer_end, 7); } diff --git a/tox_core/src/onion/client/errors.rs b/tox_core/src/onion/client/errors.rs index e7a1b7067..6f8660810 100644 --- a/tox_core/src/onion/client/errors.rs +++ b/tox_core/src/onion/client/errors.rs @@ -1,87 +1,73 @@ -error_kind! { - #[doc = "Error that can happen when handling `OnionAnnounceResponse` packet."] - #[derive(Debug)] - HandleAnnounceResponseError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - HandleAnnounceResponseErrorKind { - #[doc = "Invalid request ID when handling OnionAnnounceResponse."] - #[fail(display = "Invalid request ID when handling OnionAnnounceResponse")] - InvalidRequestId, - #[doc = "Invalid announce status in OnionAnnounceResponse."] - #[fail(display = "Invalid announce status in OnionAnnounceResponse")] - InvalidAnnounceStatus, - #[doc = "No friend with PK specified in OnionAnnounceResponse."] - #[fail(display = "No friend with PK specified in OnionAnnounceResponse")] - NoFriendWithPk, - #[doc = "Invalid payload."] - #[fail(display = "Invalid payload")] - InvalidPayload, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } +use futures::channel::mpsc::SendError; +use thiserror::Error; +use tox_packet::dht::GetPayloadError; + +use crate::{dht::server::errors::PingError, relay::client::ConnectionError}; + +/// Error that can happen when handling `OnionAnnounceResponse` packet. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum HandleAnnounceResponseError { + /// Invalid request ID when handling OnionAnnounceResponse. + #[error("Invalid request ID when handling OnionAnnounceResponse")] + InvalidRequestId, + /// Invalid announce status in OnionAnnounceResponse. + #[error("Invalid announce status in OnionAnnounceResponse")] + InvalidAnnounceStatus, + /// No friend with PK specified in OnionAnnounceResponse. + #[error("No friend with PK specified in OnionAnnounceResponse")] + NoFriendWithPk, + /// Invalid payload. + #[error("Invalid payload")] + InvalidPayload(GetPayloadError), + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), } -error_kind! { - #[doc = "Error that can happen when handling `DhtPkAnnounce` packet."] - #[derive(Debug)] - HandleDhtPkAnnounceError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - HandleDhtPkAnnounceErrorKind { - #[doc = "No friend with PK specified in OnionAnnounceResponse."] - #[fail(display = "No friend with PK specified in OnionAnnounceResponse")] - NoFriendWithPk, - #[doc = "Invalid no_reply."] - #[fail(display = "Invalid no_reply")] - InvalidNoReply, - #[doc = "Failed to ping node."] - #[fail(display = "Failed to ping node")] - PingNode, - #[doc = "Failed to add TCP relay."] - #[fail(display = "Failed to add TCP relay")] - AddRelay, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } +/// Error that can happen when handling `DhtPkAnnounce` packet. +#[derive(Debug, Error)] +pub enum HandleDhtPkAnnounceError { + /// No friend with PK specified in OnionAnnounceResponse. + #[error("No friend with PK specified in OnionAnnounceResponse")] + NoFriendWithPk, + /// Invalid no_reply. + #[error("Invalid no_reply")] + InvalidNoReply, + /// Failed to ping node. + #[error("Failed to ping node")] + PingNode(PingError), + /// Failed to add TCP relay. + #[error("Failed to add TCP relay")] + AddRelay(ConnectionError), + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), } -error_kind! { - #[doc = "Error that can happen when handling `OnionDataResponse` packet."] - #[derive(Debug)] - HandleDataResponseError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - HandleDataResponseErrorKind { - #[doc = "Invalid payload."] - #[fail(display = "Invalid payload")] - InvalidPayload, - #[doc = "Invalid inner payload."] - #[fail(display = "Invalid inner payload")] - InvalidInnerPayload, - #[doc = "Failed to handle DHT `PublicKey` announce."] - #[fail(display = "Failed to handle DHT PublicKey announce")] - DhtPkAnnounce, - #[doc = "Failed to send a friend request."] - #[fail(display = "Failed to send a friend request")] - FriendRequest, - } +/// Error that can happen when handling `OnionDataResponse` packet. +#[derive(Debug, Error)] +pub enum HandleDataResponseError { + /// Invalid payload. + #[error("Invalid payload")] + InvalidPayload(GetPayloadError), + /// Invalid inner payload. + #[error("Invalid inner payload")] + InvalidInnerPayload(GetPayloadError), + /// Failed to handle DHT `PublicKey` announce. + #[error("Failed to handle DHT PublicKey announce")] + DhtPkAnnounce(HandleDhtPkAnnounceError), + /// Failed to send a friend request. + #[error("Failed to send a friend request")] + FriendRequest(SendError), } -error_kind! { - #[doc = "Error that can happen when calling `run_*`."] - #[derive(Debug)] - RunError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - RunErrorKind { - #[doc = "Timer error."] - #[fail(display = "Timer error")] - Wakeup, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - } +/// Error that can happen when calling `run_*`. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum RunError { + /// Timer error. + #[error("Timer error")] + Wakeup, + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), } diff --git a/tox_core/src/onion/client/mod.rs b/tox_core/src/onion/client/mod.rs index 01680d397..0b380e4bb 100644 --- a/tox_core/src/onion/client/mod.rs +++ b/tox_core/src/onion/client/mod.rs @@ -1,6 +1,6 @@ //! Onion client implementation. -mod errors; +pub mod errors; mod nodes_pool; mod onion_path; mod paths_pool; @@ -11,7 +11,6 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use crypto_box::SalsaBox; -use failure::Fail; use futures::{StreamExt, SinkExt}; use futures::channel::mpsc; use futures::lock::Mutex; @@ -423,7 +422,7 @@ impl OnionClient { let announce_data = if let Some(announce_data) = state.announce_requests.check_ping_id(packet.sendback_data, |_| true) { announce_data } else { - return Err(HandleAnnounceResponseErrorKind::InvalidRequestId.into()); + return Err(HandleAnnounceResponseError::InvalidRequestId); }; // Assign variables depending on response type (was it announcing or searching request) @@ -437,7 +436,7 @@ impl OnionClient { }; (&mut friend.close_nodes, Some(&mut friend.last_seen), announce_packet_data) } else { - return Err(HandleAnnounceResponseErrorKind::NoFriendWithPk.into()); + return Err(HandleAnnounceResponseError::NoFriendWithPk); } } else { let announce_packet_data = AnnouncePacketData { @@ -451,14 +450,14 @@ impl OnionClient { let payload = match packet.get_payload(&SalsaBox::new(&announce_data.pk, announce_packet_data.packet_sk)) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandleAnnounceResponseErrorKind::InvalidPayload).into()) + Err(e) => return Err(HandleAnnounceResponseError::InvalidPayload(e)) }; trace!("OnionAnnounceResponse status: {:?}, data: {:?}", payload.announce_status, announce_data); if announce_data.friend_pk.is_some() && payload.announce_status == AnnounceStatus::Announced || announce_data.friend_pk.is_none() && payload.announce_status == AnnounceStatus::Found { - return Err(HandleAnnounceResponseErrorKind::InvalidAnnounceStatus.into()); + return Err(HandleAnnounceResponseError::InvalidAnnounceStatus); } state.paths_pool.set_timeouts(announce_data.path_id.clone(), announce_data.friend_pk.is_some()); @@ -523,7 +522,7 @@ impl OnionClient { let inner_announce_request = announce_packet_data.search_request(&node.pk, request_id); self.send_onion_request(path, InnerOnionRequest::InnerOnionAnnounceRequest(inner_announce_request), node.saddr) .await - .map_err(|e| e.context(HandleAnnounceResponseErrorKind::SendTo))?; + .map_err(HandleAnnounceResponseError::SendTo)?; } Ok(()) @@ -535,11 +534,11 @@ impl OnionClient { let friend = match state.friends.get_mut(&friend_pk) { Some(friend) => friend, - None => return Err(HandleDhtPkAnnounceErrorKind::NoFriendWithPk.into()) + None => return Err(HandleDhtPkAnnounceError::NoFriendWithPk) }; if dht_pk_announce.no_reply <= friend.last_no_reply { - return Err(HandleDhtPkAnnounceErrorKind::InvalidNoReply.into()) + return Err(HandleDhtPkAnnounceError::InvalidNoReply) } friend.last_no_reply = dht_pk_announce.no_reply; @@ -549,18 +548,18 @@ impl OnionClient { let tx = state.dht_pk_tx.clone(); let dht_pk = dht_pk_announce.dht_pk.clone(); maybe_send_unbounded(tx, (friend_pk, dht_pk)).await - .map_err(|e| e.context(HandleDhtPkAnnounceErrorKind::SendTo))?; + .map_err(HandleDhtPkAnnounceError::SendTo)?; for node in dht_pk_announce.nodes.into_iter() { match node.ip_port.protocol { ProtocolType::Udp => { let packed_node = PackedNode::new(node.ip_port.to_saddr(), node.pk.clone()); self.dht.ping_node(packed_node).await - .map_err(|e| e.context(HandleDhtPkAnnounceErrorKind::PingNode))?; + .map_err(HandleDhtPkAnnounceError::PingNode)?; }, ProtocolType::Tcp => { self.tcp_connections.add_relay_connection(node.ip_port.to_saddr(), node.pk, dht_pk_announce.dht_pk.clone()).await - .map_err(|e| e.context(HandleDhtPkAnnounceErrorKind::AddRelay))?; + .map_err(HandleDhtPkAnnounceError::AddRelay)?; } } } @@ -572,20 +571,20 @@ impl OnionClient { pub async fn handle_data_response(&self, packet: &OnionDataResponse) -> Result<(), HandleDataResponseError> { let payload = match packet.get_payload(&SalsaBox::new(&packet.temporary_pk, &self.data_sk)) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandleDataResponseErrorKind::InvalidPayload).into()) + Err(e) => return Err(HandleDataResponseError::InvalidPayload(e)) }; let iner_payload = match payload.get_payload(&packet.nonce, &SalsaBox::new(&payload.real_pk, &self.real_sk)) { Ok(payload) => payload, - Err(e) => return Err(e.context(HandleDataResponseErrorKind::InvalidInnerPayload).into()) + Err(e) => return Err(HandleDataResponseError::InvalidInnerPayload(e)) }; match iner_payload { OnionDataResponseInnerPayload::DhtPkAnnounce(dht_pk_announce) => self.handle_dht_pk_announce(payload.real_pk, dht_pk_announce).await - .map_err(|e| e.context(HandleDataResponseErrorKind::DhtPkAnnounce).into()), + .map_err(HandleDataResponseError::DhtPkAnnounce), OnionDataResponseInnerPayload::FriendRequest(friend_request) => { let tx = self.state.lock().await.friend_request_tx.clone(); maybe_send_unbounded(tx, (payload.real_pk, friend_request)).await - .map_err(|e| e.context(HandleDataResponseErrorKind::FriendRequest).into()) + .map_err(HandleDataResponseError::FriendRequest) } } } @@ -760,7 +759,7 @@ impl OnionClient { announce_packet_data, None, None, - ).await.map(drop).map_err(|e| e.context(RunErrorKind::SendTo).into()) + ).await.map(drop).map_err(RunError::SendTo) } /// Get nodes to include to DHT `PublicKey` announcement packet. @@ -894,18 +893,18 @@ impl OnionClient { announce_packet_data, Some(friend.real_pk.clone()), Some(interval), - ).await.map_err(|e| e.context(RunErrorKind::SendTo))?; + ).await.map_err(RunError::SendTo)?; if packets_sent { friend.search_count = friend.search_count.saturating_add(1); } if friend.last_dht_pk_onion_sent.map_or(true, |time| clock_elapsed(time) > ONION_DHTPK_SEND_INTERVAL) { - self.send_dht_pk_onion(friend, &mut state.paths_pool).await.map_err(|e| e.context(RunErrorKind::SendTo))?; + self.send_dht_pk_onion(friend, &mut state.paths_pool).await.map_err(RunError::SendTo)?; } if friend.last_dht_pk_dht_sent.map_or(true, |time| clock_elapsed(time) > DHT_DHTPK_SEND_INTERVAL) { - self.send_dht_pk_dht_request(friend).await.map_err(|e| e.context(RunErrorKind::SendTo))?; + self.send_dht_pk_dht_request(friend).await.map_err(RunError::SendTo)?; } } @@ -1348,7 +1347,7 @@ mod tests { let packet = OnionAnnounceResponse::new(&SalsaBox::new(&friend_temporary_pk, &sender_sk), request_id, &payload); let error = onion_client.handle_announce_response(&packet, true).await.err().unwrap(); - assert_eq!(error.kind(), &HandleAnnounceResponseErrorKind::InvalidAnnounceStatus); + assert_eq!(error, HandleAnnounceResponseError::InvalidAnnounceStatus); } #[tokio::test] @@ -1551,7 +1550,7 @@ mod tests { let packet = OnionAnnounceResponse::new(&SalsaBox::new(&real_pk, &sender_sk), request_id, &payload); let error = onion_client.handle_announce_response(&packet, true).await.err().unwrap(); - assert_eq!(error.kind(), &HandleAnnounceResponseErrorKind::InvalidAnnounceStatus); + assert_eq!(error, HandleAnnounceResponseError::InvalidAnnounceStatus); } #[tokio::test] @@ -1601,7 +1600,7 @@ mod tests { let packet = OnionAnnounceResponse::new(&SalsaBox::new(&friend_temporary_pk, &sender_sk), request_id, &payload); let error = onion_client.handle_announce_response(&packet, true).await.err().unwrap(); - assert_eq!(error.kind(), &HandleAnnounceResponseErrorKind::NoFriendWithPk); + assert_eq!(error, HandleAnnounceResponseError::NoFriendWithPk); } #[tokio::test] @@ -1650,7 +1649,7 @@ mod tests { }; let error = onion_client.handle_announce_response(&packet, true).await.err().unwrap(); - assert_eq!(error.kind(), &HandleAnnounceResponseErrorKind::InvalidPayload); + assert_eq!(error, HandleAnnounceResponseError::InvalidPayload(GetPayloadError::Decrypt)); } #[tokio::test] @@ -1872,10 +1871,8 @@ mod tests { let temporary_pk = temporary_sk.public_key(); let onion_data_response = OnionDataResponse::new(&SalsaBox::new(&onion_client.data_pk, &temporary_sk), temporary_pk, nonce, &onion_data_response_payload); - let error = onion_client.handle_data_response(&onion_data_response).await.err().unwrap(); - assert_eq!(error.kind(), &HandleDataResponseErrorKind::DhtPkAnnounce); - let cause = error.cause().unwrap().downcast_ref::().unwrap(); - assert_eq!(cause.kind(), &HandleDhtPkAnnounceErrorKind::NoFriendWithPk); + let res = onion_client.handle_data_response(&onion_data_response).await; + assert!(matches!(res, Err(HandleDataResponseError::DhtPkAnnounce(HandleDhtPkAnnounceError::NoFriendWithPk)))); } #[tokio::test] @@ -1913,10 +1910,8 @@ mod tests { onion_client.handle_data_response(&onion_data_response).await.unwrap(); // second announce with the same no_reply should be rejected - let error = onion_client.handle_data_response(&onion_data_response).await.err().unwrap(); - assert_eq!(error.kind(), &HandleDataResponseErrorKind::DhtPkAnnounce); - let cause = error.cause().unwrap().downcast_ref::().unwrap(); - assert_eq!(cause.kind(), &HandleDhtPkAnnounceErrorKind::InvalidNoReply); + let res = onion_client.handle_data_response(&onion_data_response).await; + assert!(matches!(res, Err(HandleDataResponseError::DhtPkAnnounce(HandleDhtPkAnnounceError::InvalidNoReply)))); } #[tokio::test] @@ -1938,8 +1933,8 @@ mod tests { payload: vec![42; 123], }; - let error = onion_client.handle_data_response(&onion_data_response).await.err().unwrap(); - assert_eq!(error.kind(), &HandleDataResponseErrorKind::InvalidPayload); + let res = onion_client.handle_data_response(&onion_data_response).await; + assert!(matches!(res, Err(HandleDataResponseError::InvalidPayload(GetPayloadError::Decrypt)))); } #[tokio::test] @@ -1968,8 +1963,8 @@ mod tests { &onion_data_response_payload, ); - let error = onion_client.handle_data_response(&onion_data_response).await.err().unwrap(); - assert_eq!(error.kind(), &HandleDataResponseErrorKind::InvalidInnerPayload); + let res = onion_client.handle_data_response(&onion_data_response).await; + assert!(matches!(res, Err(HandleDataResponseError::InvalidInnerPayload(GetPayloadError::Decrypt)))); } #[tokio::test] diff --git a/tox_core/src/onion/onion_announce.rs b/tox_core/src/onion/onion_announce.rs index aa918323f..687a37fc3 100644 --- a/tox_core/src/onion/onion_announce.rs +++ b/tox_core/src/onion/onion_announce.rs @@ -1,12 +1,12 @@ /*! The implementation of onion announce */ -use std::io::{ErrorKind, Error}; use std::net::{IpAddr, SocketAddr}; use std::time::{Duration, Instant, SystemTime}; use sha2::{Digest, Sha256}; use sha2::digest::generic_array::typenum::marker_traits::Unsigned; use rand::{CryptoRng, Rng}; +use thiserror::Error; use tox_binary_io::*; use tox_crypto::*; @@ -33,6 +33,16 @@ pub const ONION_ANNOUNCE_TIMEOUT: Duration = Duration::from_secs(300); /// Create onion ping id filled with zeros. pub const INITIAL_PING_ID: PingId = [0; ::OutputSize::USIZE]; +/// Error that can happen when handling data request. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum HandleDataRequestError { + /// No announced node with public key. + #[error("No announced node with public key")] + NoAnnouncedNode { + pk: PublicKey, + } +} + /** Entry that corresponds to announced onion node. When node successfully announce itself this entry is added to announced nodes @@ -310,7 +320,7 @@ impl OnionAnnounce { to this node through its onion path. */ - pub fn handle_data_request(&self, request: OnionDataRequest) -> Result<(OnionResponse3, SocketAddr), Error> { + pub fn handle_data_request(&self, request: OnionDataRequest) -> Result<(OnionResponse3, SocketAddr), HandleDataRequestError> { if let Some(entry) = self.find_in_entries(request.inner.destination_pk.clone()) { let response_payload = OnionDataResponse { nonce: request.inner.nonce, @@ -324,10 +334,9 @@ impl OnionAnnounce { let saddr = SocketAddr::new(entry.ip_addr, entry.port); Ok((response, saddr)) } else { - Err(Error::new( - ErrorKind::Other, - format!("No announced node with public key {:?}", request.inner.destination_pk) - )) + Err(HandleDataRequestError::NoAnnouncedNode { + pk: request.inner.destination_pk, + }) } } } diff --git a/tox_core/src/relay/client/client.rs b/tox_core/src/relay/client/client.rs index a74871027..e18eabd1c 100644 --- a/tox_core/src/relay/client/client.rs +++ b/tox_core/src/relay/client/client.rs @@ -3,7 +3,6 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::Instant; -use failure::Fail; use futures::{FutureExt, TryFutureExt, StreamExt, SinkExt}; use futures::channel::mpsc; use tokio_util::codec::Framed; @@ -121,38 +120,38 @@ impl Client { if let ClientStatus::Connected(ref tx) = *self.status.read().await { let mut tx = tx.clone(); tx.send(packet).await - .map_err(|e| e.context(SendPacketErrorKind::SendTo).into()) + .map_err(SendPacketError::SendTo) } else { // Attempt to send packet to TCP relay with wrong status. For // instance it can happen when we received ping request from the // relay and right after that relay became sleeping so we are not // able to respond anymore. - Err(SendPacketErrorKind::WrongStatus.into()) + Err(SendPacketError::WrongStatus) } } async fn handle_route_request(&self, _packet: &RouteRequest) -> Result<(), HandlePacketError> { - Err(HandlePacketErrorKind::MustNotSend.into()) + Err(HandlePacketError::MustNotSend) } async fn handle_route_response(&self, packet: &RouteResponse) -> Result<(), HandlePacketError> { let index = if let Some(index) = packet.connection_id.index() { index } else { - return Err(HandlePacketErrorKind::InvalidConnectionId.into()) + return Err(HandlePacketError::InvalidConnectionId) }; if self.connections.read().await.contains(&packet.pk) { if self.links.write().await.insert_by_id(packet.pk.clone(), index) { Ok(()) } else { - Err(HandlePacketErrorKind::AlreadyLinked.into()) + Err(HandlePacketError::AlreadyLinked) } } else { // in theory this can happen if we added connection and right // after that removed it // TODO: should it be handled better? - Err(HandlePacketErrorKind::UnexpectedRouteResponse.into()) + Err(HandlePacketError::UnexpectedRouteResponse) } } @@ -160,13 +159,13 @@ impl Client { let index = if let Some(index) = packet.connection_id.index() { index } else { - return Err(HandlePacketErrorKind::InvalidConnectionId.into()) + return Err(HandlePacketError::InvalidConnectionId) }; if self.links.write().await.upgrade(index) { Ok(()) } else { - Err(HandlePacketErrorKind::AlreadyLinked.into()) + Err(HandlePacketError::AlreadyLinked) } } @@ -174,20 +173,20 @@ impl Client { let index = if let Some(index) = packet.connection_id.index() { index } else { - return Err(HandlePacketErrorKind::InvalidConnectionId.into()) + return Err(HandlePacketError::InvalidConnectionId) }; if (*self.links.write().await).downgrade(index) { Ok(()) } else { - Err(HandlePacketErrorKind::AlreadyLinked.into()) + Err(HandlePacketError::AlreadyLinked) } } async fn handle_ping_request(&self, packet: &PingRequest) -> Result<(), HandlePacketError> { self.send_packet(Packet::PongResponse( PongResponse { ping_id: packet.ping_id } - )).await.map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + )).await.map_err(HandlePacketError::SendPacket) } async fn handle_pong_response(&self, _packet: &PongResponse) -> Result<(), HandlePacketError> { @@ -196,7 +195,7 @@ impl Client { } async fn handle_oob_send(&self, _packet: &OobSend) -> Result<(), HandlePacketError> { - Err(HandlePacketErrorKind::MustNotSend.into()) + Err(HandlePacketError::MustNotSend) } async fn handle_oob_receive(&self, packet: OobReceive) -> Result<(), HandlePacketError> { @@ -207,14 +206,14 @@ impl Client { ); tx.send(msg).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } async fn handle_data(&self, packet: Data) -> Result<(), HandlePacketError> { let index = if let Some(index) = packet.connection_id.index() { index } else { - return Err(HandlePacketErrorKind::InvalidConnectionId.into()) + return Err(HandlePacketError::InvalidConnectionId) }; let links = self.links.read().await; @@ -226,14 +225,14 @@ impl Client { ); tx.send(msg).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } else { - Err(HandlePacketErrorKind::AlreadyLinked.into()) + Err(HandlePacketError::AlreadyLinked) } } async fn handle_onion_request(&self, _packet: &OnionRequest) -> Result<(), HandlePacketError> { - Err(HandlePacketErrorKind::MustNotSend.into()) + Err(HandlePacketError::MustNotSend) } async fn handle_onion_response(&self, packet: OnionResponse) -> Result<(), HandlePacketError> { @@ -244,7 +243,7 @@ impl Client { ); tx.send(msg).await - .map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()) + .map_err(HandlePacketError::SendTo) } /// Spawn a connection to this TCP relay if it is not connected already. The @@ -260,11 +259,11 @@ impl Client { } let socket = TcpStream::connect(&self.addr).await - .map_err(|e| e.context(SpawnErrorKind::Io))?; + .map_err(SpawnError::Io)?; let (socket, channel) = make_client_handshake(socket, &dht_pk, &dht_sk, &relay_pk).await - .map_err(|e| e.context(SpawnErrorKind::Io))?; + .map_err(SpawnError::Io)?; let stats = Stats::new(); let secure_socket = @@ -284,21 +283,19 @@ impl Client { *self.connected_time.write().await = Some(clock_now()); self.send_route_requests().await - .map_err(|e| e.context(SpawnErrorKind::SendTo))?; + .map_err(SpawnError::SendTo)?; let mut to_server_rx = to_server_rx.map(Ok); let writer = to_server .send_all(&mut to_server_rx) - .map_err(|e| - SpawnError::from(e.context(SpawnErrorKind::Encode)) - ); + .map_err(SpawnError::Encode); let reader = async { while let Some(packet) = from_server.next().await { let packet = packet - .map_err(|e| e.context(SpawnErrorKind::ReadSocket))?; + .map_err(SpawnError::ReadSocket)?; self.handle_packet(packet).await - .map_err(|e| e.context(SpawnErrorKind::HandlePacket))?; + .map_err(SpawnError::HandlePacket)?; } Result::<(), SpawnError>::Ok(()) @@ -368,10 +365,10 @@ impl Client { data, })).await } else { - Err(SendPacketErrorKind::NotOnline.into()) + Err(SendPacketError::NotOnline) } } else { - Err(SendPacketErrorKind::NotLinked.into()) + Err(SendPacketError::NotLinked) } } @@ -414,7 +411,7 @@ impl Client { Ok(()) } else { - Err(SendPacketErrorKind::NoSuchConnection.into()) + Err(SendPacketError::NoSuchConnection) } } @@ -490,8 +487,7 @@ pub mod tests { use tox_binary_io::*; use std::time::{Duration, Instant}; - use failure::Error; - use std::io::{Error as IoError, ErrorKind as IoErrorKind}; + use std::io::{Error, ErrorKind}; use tokio::net::TcpListener; @@ -527,7 +523,7 @@ pub mod tests { }); let error = client.handle_packet(route_request).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::MustNotSend); + assert_eq!(error, HandlePacketError::MustNotSend); } #[tokio::test] @@ -590,7 +586,7 @@ pub mod tests { }); let error = client.handle_packet(route_response).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::UnexpectedRouteResponse); + assert_eq!(error, HandlePacketError::UnexpectedRouteResponse); assert!(client.links.read().await.by_id(index).is_none()); } @@ -606,7 +602,7 @@ pub mod tests { }); let error = client.handle_packet(route_response).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::InvalidConnectionId); + assert_eq!(error, HandlePacketError::InvalidConnectionId); } #[tokio::test] @@ -641,7 +637,7 @@ pub mod tests { }); let error = client.handle_packet(connect_notification).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::AlreadyLinked); + assert_eq!(error, HandlePacketError::AlreadyLinked); assert!(client.links.read().await.by_id(index).is_none()); } @@ -655,7 +651,7 @@ pub mod tests { }); let error = client.handle_packet(connect_notification).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::InvalidConnectionId); + assert_eq!(error, HandlePacketError::InvalidConnectionId); } #[tokio::test] @@ -691,7 +687,7 @@ pub mod tests { }); let error = client.handle_packet(disconnect_notification).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::AlreadyLinked); + assert_eq!(error, HandlePacketError::AlreadyLinked); assert!(client.links.read().await.by_id(index).is_none()); } @@ -705,7 +701,7 @@ pub mod tests { }); let error = client.handle_packet(disconnect_notification).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::InvalidConnectionId); + assert_eq!(error, HandlePacketError::InvalidConnectionId); } #[tokio::test] @@ -747,7 +743,7 @@ pub mod tests { }); let error = client.handle_packet(oob_send).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::MustNotSend); + assert_eq!(error, HandlePacketError::MustNotSend); } #[tokio::test] @@ -815,7 +811,7 @@ pub mod tests { }); let error = client.handle_packet(data_packet).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::AlreadyLinked); + assert_eq!(error, HandlePacketError::AlreadyLinked); // Necessary to drop tx so that rx.collect() can be finished drop(client); @@ -836,7 +832,7 @@ pub mod tests { }); let error = client.handle_packet(data_packet).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::InvalidConnectionId); + assert_eq!(error, HandlePacketError::InvalidConnectionId); // Necessary to drop tx so that rx.collect() can be finished drop(client); @@ -861,7 +857,7 @@ pub mod tests { }); let error = client.handle_packet(onion_request).await.err().unwrap(); - assert_eq!(*error.kind(), HandlePacketErrorKind::MustNotSend); + assert_eq!(error, HandlePacketError::MustNotSend); } #[tokio::test] @@ -922,7 +918,7 @@ pub mod tests { }); let error = client.send_data(destination_pk, data.clone()).await.err().unwrap(); - assert_eq!(*error.kind(), SendPacketErrorKind::NotLinked); + assert_eq!(error, SendPacketError::NotLinked); // Necessary to drop tx so that rx.collect() can be finished drop(client); @@ -945,7 +941,7 @@ pub mod tests { client.links.write().await.insert_by_id(destination_pk.clone(), connection_id - 16); let error = client.send_data(destination_pk, data.clone()).await.err().unwrap(); - assert_eq!(*error.kind(), SendPacketErrorKind::NotOnline); + assert_eq!(error, SendPacketError::NotOnline); // Necessary to drop tx so that rx.collect() can be finished drop(client); @@ -1041,7 +1037,7 @@ pub mod tests { let connection_pk = SecretKey::generate(&mut rng).public_key(); let error = client.remove_connection(connection_pk).await.err().unwrap(); - assert_eq!(*error.kind(), SendPacketErrorKind::NoSuchConnection); + assert_eq!(error, SendPacketError::NoSuchConnection); } #[tokio::test] @@ -1144,7 +1140,7 @@ pub mod tests { match *client.status.read().await { ClientStatus::Connecting => continue, ClientStatus::Connected(_) => return Ok(()), - ref other => return Err(Error::from(IoError::new(IoErrorKind::Other, format!("Invalid status: {:?}", other)))), + ref other => return Err(Error::new(ErrorKind::Other, format!("Invalid status: {:?}", other))), } } } @@ -1176,7 +1172,7 @@ pub mod tests { let stats = Stats::new(); let server_future = async { tcp_run(&Server::new(), listener, server_sk, stats, 2).await - .map_err(Error::from) + .map_err(|e| Error::new(ErrorKind::Other, e)) }; tokio::spawn(server_future); @@ -1262,7 +1258,7 @@ pub mod tests { let server_future = async { let (connection, _) = listener.accept().await.unwrap(); tcp_run_connection(&server, connection, server_sk, stats) - .map_err(Error::from).await + .map_err(|e| Error::new(ErrorKind::Other, e)).await }; // run a client with invalid server's pk @@ -1272,7 +1268,7 @@ pub mod tests { let (incoming_tx_1, _incoming_rx_1) = mpsc::unbounded(); let client = Client::new(invalid_server_pk, addr, incoming_tx_1); let client_future = client.run(client_sk_1, client_pk_1) - .map_err(Error::from); + .map_err(|e| Error::new(ErrorKind::Other, e)); let (server_res, client_res) = futures::join!(server_future, client_future); assert!(server_res.is_err()); // fail to process handshake diff --git a/tox_core/src/relay/client/connections.rs b/tox_core/src/relay/client/connections.rs index 633063cca..7733dac0d 100644 --- a/tox_core/src/relay/client/connections.rs +++ b/tox_core/src/relay/client/connections.rs @@ -28,7 +28,6 @@ use crate::relay::client::client::*; use tox_packet::relay::*; use crate::time::*; use crate::relay::client::errors::*; -use failure::Fail; /// The amount of maximum connections for each friend. const MAX_FRIEND_TCP_CONNECTIONS: usize = 6; @@ -123,7 +122,7 @@ impl Connections { let client = Client::new(relay_pk, relay_addr, self.incoming_tx.clone()); vacant.insert(client.clone()); client.spawn(self.dht_sk.clone(), self.dht_pk.clone()) - .map_err(|e| e.context(ConnectionErrorKind::Spawn).into()).await + .map_err(ConnectionError::Spawn).await } else { trace!("Attempt to add relay that already exists: {}", relay_addr); Ok(()) @@ -158,7 +157,7 @@ impl Connections { connection.connections.insert(relay_pk); client.add_connection(node_pk).await; client.spawn(self.dht_sk.clone(), self.dht_pk.clone()).await - .map_err(|e| e.context(ConnectionErrorKind::Spawn).into()) + .map_err(ConnectionError::Spawn) } else { Ok(()) } @@ -172,7 +171,7 @@ impl Connections { if let Some(client) = self.clients.read().await.get(&relay_pk) { self.add_connection_inner(client, node_pk).await } else { - Err(ConnectionErrorKind::NoSuchRelay.into()) + Err(ConnectionError::NoSuchRelay) } } @@ -186,7 +185,7 @@ impl Connections { Ok(()) } else { // TODO: what if we didn't receive relays from friend and delete him? - Err(ConnectionErrorKind::NoConnection.into()) + Err(ConnectionError::NoConnection) } } @@ -200,7 +199,7 @@ impl Connections { if connection.status == NodeConnectionStatus::Tcp && client.is_sleeping().await { // unsleep relay client.clone().spawn(self.dht_sk.clone(), self.dht_pk.clone()).await - .map_err(|e| ConnectionError::from(e.context(ConnectionErrorKind::Spawn)))?; + .map_err(ConnectionError::Spawn)?; }; client.add_connection(node_pk).await; @@ -234,9 +233,9 @@ impl Connections { let clients = self.clients.read().await; if let Some(client) = clients.get(&relay_pk) { client.send_oob(node_pk, data).await - .map_err(|e| e.context(ConnectionErrorKind::SendTo).into()) + .map_err(ConnectionError::SendTo) } else { - Err(ConnectionErrorKind::NotConnected.into()) + Err(ConnectionError::NotConnected) } } @@ -245,9 +244,9 @@ impl Connections { let clients = self.clients.read().await; if let Some(client) = clients.get(&relay_pk) { client.send_onion(onion_request).await - .map_err(|e| e.context(ConnectionErrorKind::SendTo).into()) + .map_err(ConnectionError::SendTo) } else { - Err(ConnectionErrorKind::NotConnected.into()) + Err(ConnectionError::NotConnected) } } @@ -260,13 +259,13 @@ impl Connections { let clients = self.clients.read().await; for client in connection.clients(&clients) { client.clone().spawn(self.dht_sk.clone(), self.dht_pk.clone()).await - .map_err(|e| e.context(ConnectionErrorKind::Spawn))?; + .map_err(ConnectionError::Spawn)?; } }; connection.status = status; Ok(()) } else { - Err(ConnectionErrorKind::NoSuchRelay.into()) + Err(ConnectionError::NoSuchRelay) } } @@ -328,7 +327,7 @@ impl Connections { to_remove.push(pk.clone()); } else { client.clone().spawn(self.dht_sk.clone(), self.dht_pk.clone()).await - .map_err(|e| e.context(ConnectionErrorKind::Spawn))?; + .map_err(ConnectionError::Spawn)?; } } } @@ -549,8 +548,8 @@ mod tests { let relay_pk = SecretKey::generate(&mut rng).public_key(); let node_pk = SecretKey::generate(&mut rng).public_key(); - let error = connections.add_connection(relay_pk, node_pk).await.err().unwrap(); - assert_eq!(*error.kind(), ConnectionErrorKind::NoSuchRelay); + let res = connections.add_connection(relay_pk, node_pk).await; + assert!(matches!(res, Err(ConnectionError::NoSuchRelay))); } #[tokio::test] @@ -594,8 +593,8 @@ mod tests { let node_pk = SecretKey::generate(&mut rng).public_key(); - let error = connections.remove_connection(node_pk).await.err().unwrap(); - assert_eq!(*error.kind(), ConnectionErrorKind::NoConnection); + let res = connections.remove_connection(node_pk).await; + assert!(matches!(res, Err(ConnectionError::NoConnection))); } #[tokio::test] @@ -714,8 +713,8 @@ mod tests { let destination_pk = SecretKey::generate(&mut rng).public_key(); let relay_pk = SecretKey::generate(&mut rng).public_key(); - let error = connections.send_oob(relay_pk, destination_pk, vec![42; 123]).await.err().unwrap(); - assert_eq!(*error.kind(), ConnectionErrorKind::NotConnected); + let res = connections.send_oob(relay_pk, destination_pk, vec![42; 123]).await; + assert!(matches!(res, Err(ConnectionError::NotConnected))); } #[tokio::test] @@ -770,8 +769,8 @@ mod tests { payload: vec![42; 123], }; - let error = connections.send_onion(relay_pk, onion_request.clone()).await.err().unwrap(); - assert_eq!(*error.kind(), ConnectionErrorKind::NotConnected); + let res = connections.send_onion(relay_pk, onion_request.clone()).await; + assert!(matches!(res, Err(ConnectionError::NotConnected))); } #[tokio::test] @@ -804,8 +803,8 @@ mod tests { let node_pk = SecretKey::generate(&mut rng).public_key(); - let error = connections.set_connection_status(node_pk, NodeConnectionStatus::Udp).await.err().unwrap(); - assert_eq!(*error.kind(), ConnectionErrorKind::NoSuchRelay); + let res = connections.set_connection_status(node_pk, NodeConnectionStatus::Udp).await; + assert!(matches!(res, Err(ConnectionError::NoSuchRelay))); } #[tokio::test] diff --git a/tox_core/src/relay/client/errors.rs b/tox_core/src/relay/client/errors.rs index d358ac878..0b9fe84a1 100644 --- a/tox_core/src/relay/client/errors.rs +++ b/tox_core/src/relay/client/errors.rs @@ -1,105 +1,94 @@ -error_kind! { - #[doc = "Error that can happen when handling `Tcp relay` packet."] - #[derive(Debug)] - HandlePacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - HandlePacketErrorKind { - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - #[doc = "Server must not send this packet to client."] - #[fail(display = "Server must not send this packet to client")] - MustNotSend, - #[doc = "Invalid connection ID when handling RouteResponse."] - #[fail(display = "Invalid connection ID when handling RouteResponse")] - InvalidConnectionId, - #[doc = "Connection ID is already linked."] - #[fail(display = "Connection ID is already linked")] - AlreadyLinked, - #[doc = "Unexpected route response packet is received."] - #[fail(display = "Unexpected route response packet is received")] - UnexpectedRouteResponse, - } +use std::io::Error as IoError; +use futures::channel::mpsc::SendError; +use thiserror::Error; + +use crate::relay::codec::{DecodeError, EncodeError}; + +/// Error that can happen when handling `Tcp relay` packet. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum HandlePacketError { + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendPacket(SendPacketError), + /// Server must not send this packet to client. + #[error("Server must not send this packet to client")] + MustNotSend, + /// Invalid connection ID when handling RouteResponse. + #[error("Invalid connection ID when handling RouteResponse")] + InvalidConnectionId, + /// Connection ID is already linked. + #[error("Connection ID is already linked")] + AlreadyLinked, + /// Unexpected route response packet is received. + #[error("Unexpected route response packet is received")] + UnexpectedRouteResponse, } -error_kind! { - #[doc = "Error that can happen when sending packet."] - #[derive(Debug)] - SendPacketError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - SendPacketErrorKind { - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - #[doc = "Send packet(s) with wrong status."] - #[fail(display = "Send packet(s) with wrong status")] - WrongStatus, - #[doc = "Send packet(s) with destination_pk is not online."] - #[fail(display = "Send packet(s) with destination_pk is not online")] - NotOnline, - #[doc = "Send packet(s) with destination_pk is not linked."] - #[fail(display = "Send packet(s) with destination_pk is not linked")] - NotLinked, - #[doc = "Send packet(s) to a connection but no such connection."] - #[fail(display = "Send packet(s) to a connection but no such connection")] - NoSuchConnection, - } +/// Error that can happen when sending packet. +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum SendPacketError { + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendError), + /// Send packet(s) with wrong status. + #[error("Send packet(s) with wrong status")] + WrongStatus, + /// Send packet(s) with destination_pk is not online. + #[error("Send packet(s) with destination_pk is not online")] + NotOnline, + /// Send packet(s) with destination_pk is not linked. + #[error("Send packet(s) with destination_pk is not linked")] + NotLinked, + /// Send packet(s) to a connection but no such connection. + #[error("Send packet(s) to a connection but no such connection")] + NoSuchConnection, } -error_kind! { - #[doc = "Error that can happen when spawning a connection."] - #[derive(Debug)] - SpawnError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - SpawnErrorKind { - #[doc = "Read socket to receive packet error."] - #[fail(display = "Read socket to receive packet error")] - ReadSocket, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - #[doc = "Handle packet(s) error."] - #[fail(display = "Handle packet(s) error")] - HandlePacket, - #[doc = "Tcp client io error."] - #[fail(display = "Tcp client io error")] - Io, - #[doc = "Tcp codec encode error."] - #[fail(display = "Tcp codec encode error")] - Encode, - } +/// Error that can happen when spawning a connection. +#[derive(Debug, Error)] +pub enum SpawnError { + /// Read socket to receive packet error. + #[error("Read socket to receive packet error")] + ReadSocket(DecodeError), + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendPacketError), + /// Handle packet(s) error. + #[error("Handle packet(s) error")] + HandlePacket(HandlePacketError), + /// Tcp client io error. + #[error("Tcp client io error")] + Io(IoError), + /// Tcp codec encode error. + #[error("Tcp codec encode error")] + Encode(EncodeError), } -error_kind! { - #[doc = "Error that can happen when handling a connection."] - #[derive(Debug)] - ConnectionError, - #[doc = "The specific kind of error that can occur."] - #[derive(Clone, Debug, Eq, PartialEq, failure::Fail)] - ConnectionErrorKind { - #[doc = "Spawing after adding global connection error."] - #[fail(display = "Spawing after adding global connection error")] - Spawn, - #[doc = "Search relay by relay's PK, but no such relay."] - #[fail(display = "Search relay by relay's PK, but no such relay")] - NoSuchRelay, - #[doc = "Send packet(s) error."] - #[fail(display = "Send packet(s) error")] - SendTo, - #[doc = "No connection to the node."] - #[fail(display = "No connection to the node")] - NoConnection, - #[doc = "Relay is not connected."] - #[fail(display = "Relay is not connected")] - NotConnected, - #[doc = "Tcp Connections wakeup timer error."] - #[fail(display = "Tcp Connections wakeup timer error")] - Wakeup, - #[doc = "Add connection to client error."] - #[fail(display = "Add connection to client error")] - AddConnection, - } +/// Error that can happen when handling a connection. +#[derive(Debug, Error)] +pub enum ConnectionError { + /// Spawing after adding global connection error. + #[error("Spawing after adding global connection error")] + Spawn(SpawnError), + /// Search relay by relay's PK, but no such relay. + #[error("Search relay by relay's PK, but no such relay")] + NoSuchRelay, + /// Send packet(s) error. + #[error("Send packet(s) error")] + SendTo(SendPacketError), + /// No connection to the node. + #[error("No connection to the node")] + NoConnection, + /// Relay is not connected. + #[error("Relay is not connected")] + NotConnected, + /// Tcp Connections wakeup timer error. + #[error("Tcp Connections wakeup timer error")] + Wakeup, + /// Add connection to client error. + #[error("Add connection to client error")] + AddConnection, } diff --git a/tox_core/src/relay/codec.rs b/tox_core/src/relay/codec.rs index 8cb58bf42..60a6b7a8b 100644 --- a/tox_core/src/relay/codec.rs +++ b/tox_core/src/relay/codec.rs @@ -8,16 +8,16 @@ use tox_packet::relay::*; use crate::relay::secure::*; use crate::stats::*; -use failure::Fail; +use thiserror::Error; use nom::{Needed, Offset, Err, error::ErrorKind}; use bytes::{BytesMut, Buf}; use tokio_util::codec::{Decoder, Encoder}; /// Error that can happen when decoding `Packet` from bytes -#[derive(Debug, Fail)] +#[derive(Debug, Error)] pub enum DecodeError { /// Error indicates that received encrypted packet can't be parsed - #[fail(display = "Deserialize EncryptedPacket error: {:?}, buffer: {:?}", error, buf)] + #[error("Deserialize EncryptedPacket error: {:?}, buffer: {:?}", error, buf)] DeserializeEncryptedError { /// Parsing error error: ErrorKind, @@ -25,10 +25,10 @@ pub enum DecodeError { buf: Vec, }, /// Error indicates that received encrypted packet can't be decrypted - #[fail(display = "Decrypt EncryptedPacket error")] + #[error("Decrypt EncryptedPacket error")] DecryptError, /// Error indicates that more data is needed to parse decrypted packet - #[fail(display = "Decrypted packet should not be incomplete: {:?}, packet: {:?}", needed, packet)] + #[error("Decrypted packet should not be incomplete: {:?}, packet: {:?}", needed, packet)] IncompleteDecryptedPacket { /// Required data size to be parsed needed: Needed, @@ -36,7 +36,7 @@ pub enum DecodeError { packet: Vec, }, /// Error indicates that decrypted packet can't be parsed - #[fail(display = "Deserialize decrypted packet error: {:?}, packet: {:?}", error, packet)] + #[error("Deserialize decrypted packet error: {:?}, packet: {:?}", error, packet)] DeserializeDecryptedError { /// Parsing error error: ErrorKind, @@ -44,10 +44,9 @@ pub enum DecodeError { packet: Vec, }, /// General IO error - #[fail(display = "IO error: {:?}", error)] + #[error("IO error: {:?}", error)] IoError { /// IO error - #[fail(cause)] error: IoError }, } @@ -61,19 +60,18 @@ impl From for DecodeError { } /// Error that can happen when encoding `Packet` to bytes -#[derive(Debug, Fail)] +#[derive(Debug, Error)] pub enum EncodeError { /// Error indicates that `Packet` is invalid and can't be serialized - #[fail(display = "Serialize Packet error: {:?}", error)] + #[error("Serialize Packet error: {:?}", error)] SerializeError { /// Serialization error error: GenError }, /// General IO error - #[fail(display = "IO error: {:?}", error)] + #[error("IO error: {:?}", error)] IoError { /// IO error - #[fail(cause)] error: IoError }, } diff --git a/tox_core/src/relay/server/server_ext.rs b/tox_core/src/relay/server/server_ext.rs index 2478bbb21..e154891c7 100644 --- a/tox_core/src/relay/server/server_ext.rs +++ b/tox_core/src/relay/server/server_ext.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; -use failure::Fail; +use thiserror::Error; use futures::{FutureExt, TryFutureExt, SinkExt, StreamExt, TryStreamExt}; use futures::channel::mpsc; use tokio::net::{TcpStream, TcpListener}; @@ -28,89 +28,80 @@ const TCP_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(10); const SERVER_CHANNEL_SIZE: usize = 64; /// Error that can happen during server execution -#[derive(Debug, Fail)] +#[derive(Debug, Error)] pub enum ServerRunError { /// Incoming IO error - #[fail(display = "Incoming IO error: {:?}", error)] + #[error("Incoming IO error: {:?}", error)] Incoming { /// IO error - #[fail(cause)] error: IoError }, /// Ping wakeups timer error - #[fail(display = "Ping wakeups timer error: {:?}", error)] + #[error("Ping wakeups timer error: {:?}", error)] PingWakeups { /// Timer error error: TimerError }, /// Send pings error - #[fail(display = "Send pings error: {:?}", error)] + #[error("Send pings error: {:?}", error)] SendPings { /// Send pings error - #[fail(cause)] error: IoError }, } /// Error that can happen during TCP connection execution -#[derive(Debug, Fail)] +#[derive(Debug, Error)] pub enum ConnectionError { /// Error indicates that we couldn't get peer address - #[fail(display = "Failed to get peer address: {}", error)] + #[error("Failed to get peer address: {}", error)] PeerAddr { /// Peer address error - #[fail(cause)] error: IoError, }, /// Sending packet error - #[fail(display = "Failed to send TCP packet: {}", error)] + #[error("Failed to send TCP packet: {}", error)] SendPacket { error: EncodeError }, /// Decode incoming packet error - #[fail(display = "Failed to decode incoming packet: {}", error)] + #[error("Failed to decode incoming packet: {}", error)] DecodePacket { error: DecodeError }, /// Incoming IO error - #[fail(display = "Incoming IO error: {:?}", error)] + #[error("Incoming IO error: {:?}", error)] Incoming { /// IO error - #[fail(cause)] error: IoError }, /// Server handshake error - #[fail(display = "Server handshake error: {:?}", error)] + #[error("Server handshake error: {:?}", error)] ServerHandshakeTimeout { /// Server handshake error - #[fail(cause)] error: tokio::time::error::Elapsed }, - #[fail(display = "Server handshake error: {:?}", error)] + #[error("Server handshake error: {:?}", error)] ServerHandshakeIo { /// Server handshake error - #[fail(cause)] error: IoError, }, /// Packet handling error - #[fail(display = "Packet handling error: {:?}", error)] + #[error("Packet handling error: {:?}", error)] PacketHandling { /// Packet handling error - #[fail(cause)] error: IoError }, /// Insert client error - #[fail(display = "Packet handling error: {:?}", error)] + #[error("Packet handling error: {:?}", error)] InsertClient { /// Insert client error - #[fail(cause)] error: IoError }, - #[fail(display = "Packet handling error: {:?}", error)] + #[error("Packet handling error: {:?}", error)] Shutdown { /// Insert client error - #[fail(cause)] error: IoError }, } @@ -246,7 +237,7 @@ mod tests { use super::*; use tox_binary_io::*; - use failure::Error; + use std::io::{Error, ErrorKind}; use rand::thread_rng; use crate::relay::codec::Codec; @@ -273,7 +264,7 @@ mod tests { // take the first connection let (connection, _) = listener.accept().await.unwrap(); tcp_run_connection(&Server::new(), connection, server_sk, stats.clone()) - .map_err(Error::from).await + .map_err(|e| Error::new(ErrorKind::Other, e)).await }; let client = async { @@ -286,7 +277,7 @@ mod tests { ping_id: 42 }); - to_server.send(packet).map_err(Error::from).await.unwrap(); + to_server.send(packet).map_err(|e| Error::new(ErrorKind::Other, e)).await.unwrap(); let packet = from_server.next().await.unwrap(); assert_eq!(packet.unwrap(), Packet::PongResponse(PongResponse { @@ -321,7 +312,7 @@ mod tests { let stats = Stats::new(); let server = async { tcp_run(&Server::new(), listener, server_sk, stats.clone(), 1).await - .map_err(Error::from) + .map_err(|e| Error::new(ErrorKind::Other, e)) }; let client = async { @@ -334,7 +325,7 @@ mod tests { let packet = Packet::PingRequest(PingRequest { ping_id: 42 }); - to_server.send(packet).map_err(Error::from).await?; + to_server.send(packet).map_err(|e| Error::new(ErrorKind::Other, e)).await?; let packet = from_server.next().await.unwrap(); assert_eq!(packet.unwrap(), Packet::PongResponse(PongResponse { diff --git a/tox_core/src/udp.rs b/tox_core/src/udp.rs index 16e1be830..a4664255b 100644 --- a/tox_core/src/udp.rs +++ b/tox_core/src/udp.rs @@ -3,7 +3,6 @@ use crate::dht::server::Server as DhtServer; use crate::dht::server::errors::*; use crate::net_crypto::NetCrypto; use crate::onion::client::OnionClient; -use failure::Fail; use tox_packet::dht::*; use tox_packet::onion::*; use std::net::SocketAddr; @@ -87,9 +86,9 @@ impl Server { async fn handle_onion_data_response(&self, packet: &OnionDataResponse) -> Result<(), HandlePacketError> { if let Some(ref onion_client) = self.onion_client { onion_client.handle_data_response(packet).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleOnionClient).into()) + .map_err(HandlePacketError::HandleOnionClientData) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::OnionClient)) + Err(HandlePacketError::OnionClient) } } @@ -97,9 +96,9 @@ impl Server { async fn handle_onion_announce_response(&self, packet: &OnionAnnounceResponse, addr: SocketAddr) -> Result<(), HandlePacketError> { if let Some(ref onion_client) = self.onion_client { onion_client.handle_announce_response(packet, IsGlobal::is_global(&addr.ip())).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleOnionClient).into()) + .map_err(HandlePacketError::HandleOnionClientAnnounce) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::OnionClient)) + Err(HandlePacketError::OnionClient) } } @@ -114,11 +113,9 @@ impl Server { -> Result<(), HandlePacketError> { if let Some(ref net_crypto) = self.net_crypto { net_crypto.handle_udp_cookie_request(packet, addr).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleNetCrypto).into()) + .map_err(HandlePacketError::HandleNetCrypto) } else { - Err( - HandlePacketError::from(HandlePacketErrorKind::NetCrypto) - ) + Err(HandlePacketError::NetCrypto) } } @@ -128,9 +125,9 @@ impl Server { -> Result<(), HandlePacketError> { if let Some(ref net_crypto) = self.net_crypto { net_crypto.handle_udp_cookie_response(packet, addr).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleNetCrypto).into()) + .map_err(HandlePacketError::HandleNetCrypto) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::NetCrypto)) + Err(HandlePacketError::NetCrypto) } } @@ -140,9 +137,9 @@ impl Server { -> Result<(), HandlePacketError> { if let Some(ref net_crypto) = self.net_crypto { net_crypto.handle_udp_crypto_handshake(packet, addr).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleNetCrypto).into()) + .map_err(HandlePacketError::HandleNetCrypto) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::NetCrypto)) + Err(HandlePacketError::NetCrypto) } } @@ -150,9 +147,9 @@ impl Server { pub async fn handle_crypto_data(&self, packet: &CryptoData, addr: SocketAddr) -> Result<(), HandlePacketError> { if let Some(ref net_crypto) = self.net_crypto { net_crypto.handle_udp_crypto_data(packet, addr).await - .map_err(|e| e.context(HandlePacketErrorKind::HandleNetCrypto).into()) + .map_err(HandlePacketError::HandleNetCrypto) } else { - Err(HandlePacketError::from(HandlePacketErrorKind::NetCrypto)) + Err(HandlePacketError::NetCrypto) } } diff --git a/tox_encryptsave/Cargo.toml b/tox_encryptsave/Cargo.toml index 2394b49fc..26915e15a 100644 --- a/tox_encryptsave/Cargo.toml +++ b/tox_encryptsave/Cargo.toml @@ -19,7 +19,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -failure = "0.1" +thiserror = "1.0" rand = "0.8" sha2 = "0.9" xsalsa20poly1305 = "0.8" diff --git a/tox_encryptsave/src/lib.rs b/tox_encryptsave/src/lib.rs index 4c2e43691..2de5e2f1d 100644 --- a/tox_encryptsave/src/lib.rs +++ b/tox_encryptsave/src/lib.rs @@ -23,7 +23,7 @@ assert_eq!(plaintext, use std::{convert::TryInto, ops::Deref}; -use failure::Fail; +use thiserror::Error; use rand::{Rng, thread_rng}; use sha2::{Digest, Sha256}; use xsalsa20poly1305::{XSalsa20Poly1305, aead::{Aead, NewAead}}; @@ -331,25 +331,25 @@ pub fn get_salt(data: &[u8]) -> Option<[u8; SALT_LENGTH]> { } /// Deriving secret key for [`PassKey`](./struct.PassKey.html). -#[derive(Clone, Copy, Debug, Eq, PartialEq, Fail)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Error)] pub enum KeyDerivationError { /// Provided passphrase is empty. - #[fail(display = "Provided passphrase is empty")] + #[error("Provided passphrase is empty")] Null, /// Failed to derive key, most likely due to OOM. - #[fail(display = "Failed to derive key, most likely due to OOM")] + #[error("Failed to derive key, most likely due to OOM")] Failed } /// Error encrypting data. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Fail)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Error)] pub enum EncryptionError { /// Data provided for encryption is empty. - #[fail(display = "Data provided for encryption is empty")] + #[error("Data provided for encryption is empty")] Null, /// Failed to derive key – [`KeyDerivationError`] /// (./enum.KeyDerivationError.html) - #[fail(display = "Failed to derive key: {}", _0)] + #[error("Failed to derive key: {}", _0)] KeyDerivation(KeyDerivationError), } @@ -360,19 +360,19 @@ impl From for EncryptionError { } /// Error when trying to decrypt data. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Fail)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Error)] pub enum DecryptionError { /// Data to be decrypted is empty. - #[fail(display = "Data to be decrypted is empty")] + #[error("Data to be decrypted is empty")] Null, /// There's not enough data to decrypt. - #[fail(display = "There's not enough data to decrypt")] + #[error("There's not enough data to decrypt")] InvalidLength, /// Provided data has invalid format, incompatible with **TES**. - #[fail(display = "Provided data has invalid format, incompatible with TES")] + #[error("Provided data has invalid format, incompatible with TES")] BadFormat, /// Deriving key failed. - #[fail(display = "Deriving key failed: {}", _0)] + #[error("Deriving key failed: {}", _0)] KeyDerivation(KeyDerivationError), /** Failure due to encrypted data being invalid. @@ -385,7 +385,7 @@ pub enum DecryptionError { * not all encrypted bytes were provided * some bytes that aren't encrypted were provided after encrypted bytes */ - #[fail(display = "Failure due to encrypted data being invalid")] + #[error("Failure due to encrypted data being invalid")] Failed } diff --git a/tox_packet/Cargo.toml b/tox_packet/Cargo.toml index 0a34f4011..998882fed 100644 --- a/tox_packet/Cargo.toml +++ b/tox_packet/Cargo.toml @@ -25,7 +25,7 @@ tox_crypto = { version = "0.1.0", path = "../tox_crypto" } nom = "5.1" cookie-factory = "0.3" bitflags = "1.3" -failure = "0.1" +thiserror = "1.0" sha2 = "0.9" xsalsa20poly1305 = "0.8" # for enabling rand_core feature diff --git a/tox_packet/src/dht/cookie.rs b/tox_packet/src/dht/cookie.rs index 5fb0c262f..470a95b70 100644 --- a/tox_packet/src/dht/cookie.rs +++ b/tox_packet/src/dht/cookie.rs @@ -220,7 +220,7 @@ mod tests { // try to decode payload with eve's symmetric key let decoded_payload = encrypted_cookie.get_payload(&eve_symmetric_key); assert!(decoded_payload.is_err()); - assert_eq!(*decoded_payload.err().unwrap().kind(), GetPayloadErrorKind::Decrypt); + assert_eq!(decoded_payload.err().unwrap(), GetPayloadError::Decrypt); } #[test] @@ -237,7 +237,7 @@ mod tests { }; let decoded_payload = invalid_encrypted_cookie.get_payload(&symmetric_key); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Error((vec![42; 51], ErrorKind::Eof)), payload: invalid_payload.to_vec() }); @@ -250,7 +250,7 @@ mod tests { }; let decoded_payload = invalid_encrypted_cookie.get_payload(&symmetric_key); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Error((vec![], ErrorKind::Eof)), payload: invalid_payload.to_vec() }); diff --git a/tox_packet/src/dht/cookie_response.rs b/tox_packet/src/dht/cookie_response.rs index fa590b6ef..dabde84b7 100644 --- a/tox_packet/src/dht/cookie_response.rs +++ b/tox_packet/src/dht/cookie_response.rs @@ -200,7 +200,7 @@ mod tests { // try to decode payload with eve's shared secret let decoded_payload = dht_packet.get_payload(&eve_shared_secret); assert!(decoded_payload.is_err()); - assert_eq!(*decoded_payload.err().unwrap().kind(), GetPayloadErrorKind::Decrypt); + assert_eq!(decoded_payload.err().unwrap(), GetPayloadError::Decrypt); } #[test] @@ -219,7 +219,7 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&shared_secret); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Error((vec![42; 3], ErrorKind::Eof)), payload: invalid_payload.to_vec() }); @@ -232,7 +232,7 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&shared_secret); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Incomplete(Needed::Size(24)), payload: invalid_payload.to_vec() }); diff --git a/tox_packet/src/dht/crypto_data.rs b/tox_packet/src/dht/crypto_data.rs index 4ae8f3620..921b58aca 100644 --- a/tox_packet/src/dht/crypto_data.rs +++ b/tox_packet/src/dht/crypto_data.rs @@ -96,11 +96,14 @@ impl CryptoData { pub fn get_payload(&self, shared_secret: &SalsaBox, nonce: &Nonce) -> Result { let decrypted = shared_secret.decrypt(nonce.into(), self.payload.as_slice()) .map_err(|AeadError| { - GetPayloadError::decrypt() + GetPayloadError::Decrypt })?; match CryptoDataPayload::from_bytes(&decrypted) { Err(error) => { - Err(GetPayloadError::deserialize(error, decrypted.clone())) + Err(GetPayloadError::Deserialize { + error: error.to_owned(), + payload: decrypted.clone(), + }) }, Ok((_, payload)) => { Ok(payload) @@ -232,7 +235,7 @@ mod tests { // try to decode payload with eve's shared secret let decoded_payload = crypto_data.get_payload(&eve_shared_secret, &nonce); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Decrypt); + assert_eq!(error, GetPayloadError::Decrypt); } #[test] @@ -252,6 +255,6 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&shared_secret, &nonce.into()); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { error: Err::Error((vec![], ErrorKind::Eof)), payload: invalid_payload.to_vec() }); + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Error((vec![], ErrorKind::Eof)), payload: invalid_payload.to_vec() }); } } diff --git a/tox_packet/src/dht/crypto_handshake.rs b/tox_packet/src/dht/crypto_handshake.rs index 6368e6436..e8e8e3434 100644 --- a/tox_packet/src/dht/crypto_handshake.rs +++ b/tox_packet/src/dht/crypto_handshake.rs @@ -248,7 +248,7 @@ mod tests { // try to decode payload with eve's shared secret let decoded_payload = dht_packet.get_payload(&eve_shared_secret); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Decrypt); + assert_eq!(error, GetPayloadError::Decrypt); } #[test] @@ -272,7 +272,7 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&shared_secret); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Incomplete(Needed::Size(24)), payload: invalid_payload.to_vec() }); @@ -286,7 +286,7 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&shared_secret); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Incomplete(Needed::Size(24)), payload: invalid_payload.to_vec() }); diff --git a/tox_packet/src/dht/dht_request.rs b/tox_packet/src/dht/dht_request.rs index b4c558034..1f5198b98 100644 --- a/tox_packet/src/dht/dht_request.rs +++ b/tox_packet/src/dht/dht_request.rs @@ -574,7 +574,7 @@ mod tests { let precomputed_key = SalsaBox::new(&dht_request.spk, &eve_sk); let decoded_payload = dht_request.get_payload(&precomputed_key); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Decrypt); + assert_eq!(error, GetPayloadError::Decrypt); } } @@ -601,7 +601,7 @@ mod tests { let decoded_payload = invalid_packet.get_payload(&precomputed_key); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Error((invalid_payload.to_vec(), ErrorKind::Alt)), payload: invalid_payload.to_vec() }); @@ -616,7 +616,7 @@ mod tests { }; let decoded_payload = invalid_packet.get_payload(&precomputed_key); let error = decoded_payload.err().unwrap(); - assert_eq!(*error.kind(), GetPayloadErrorKind::Deserialize { + assert_eq!(error, GetPayloadError::Deserialize { error: Err::Incomplete(Needed::Size(1)), payload: invalid_payload.to_vec() }); diff --git a/tox_packet/src/dht/errors.rs b/tox_packet/src/dht/errors.rs index 2e0f62d06..21ee310cf 100644 --- a/tox_packet/src/dht/errors.rs +++ b/tox_packet/src/dht/errors.rs @@ -1,9 +1,7 @@ /*! Errors enum for DHT packets. */ -use std::{str, fmt}; - -use failure::{Backtrace, Context, Fail}; +use thiserror::Error; use nom::{error::ErrorKind, Err}; use std::convert::From; @@ -11,50 +9,13 @@ use std::io::Error as IoError; use std::io::ErrorKind as IoErrorKind; /// Error that can happen when calling `get_payload` of packet. -#[derive(Debug)] -pub struct GetPayloadError { - ctx: Context, -} - -impl GetPayloadError { - /// Return the kind of this error. - pub fn kind(&self) -> &GetPayloadErrorKind { - self.ctx.get_context() - } - - pub(crate) fn decrypt() -> GetPayloadError { - GetPayloadError::from(GetPayloadErrorKind::Decrypt) - } - - pub(crate) fn deserialize(e: Err<(&[u8], ErrorKind)>, payload: Vec) -> GetPayloadError { - GetPayloadError::from(GetPayloadErrorKind::Deserialize { error: e.to_owned(), payload }) - } -} - -impl Fail for GetPayloadError { - fn cause(&self) -> Option<&dyn Fail> { - self.ctx.cause() - } - - fn backtrace(&self) -> Option<&Backtrace> { - self.ctx.backtrace() - } -} - -impl fmt::Display for GetPayloadError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.ctx.fmt(f) - } -} - -/// The specific kind of error that can occur. -#[derive(Clone, Debug, Eq, PartialEq, Fail)] -pub enum GetPayloadErrorKind { +#[derive(Clone, Debug, Eq, PartialEq, Error)] +pub enum GetPayloadError { /// Error indicates that received payload of encrypted packet can't be decrypted - #[fail(display = "Decrypt payload error")] + #[error("Decrypt payload error")] Decrypt, /// Error indicates that decrypted payload of packet can't be parsed - #[fail(display = "Deserialize payload error: {:?}, data: {:?}", error, payload)] + #[error("Deserialize payload error: {:?}, data: {:?}", error, payload)] Deserialize { /// Parsing error error: nom::Err<(Vec, ErrorKind)>, @@ -63,15 +24,13 @@ pub enum GetPayloadErrorKind { } } -impl From for GetPayloadError { - fn from(kind: GetPayloadErrorKind) -> GetPayloadError { - GetPayloadError::from(Context::new(kind)) +impl GetPayloadError { + pub(crate) fn decrypt() -> GetPayloadError { + GetPayloadError::Decrypt } -} -impl From> for GetPayloadError { - fn from(ctx: Context) -> GetPayloadError { - GetPayloadError { ctx } + pub(crate) fn deserialize(e: Err<(&[u8], ErrorKind)>, payload: Vec) -> GetPayloadError { + GetPayloadError::Deserialize { error: e.to_owned(), payload } } } @@ -87,23 +46,15 @@ mod tests { use super::*; use nom::Needed; - #[test] - fn get_payload_error() { - let error = GetPayloadError::deserialize(Err::Error((&[], ErrorKind::Eof)), vec![1, 2, 3, 4]); - assert!(error.cause().is_none()); - assert!(error.backtrace().is_some()); - assert_eq!(format!("{}", error), "Deserialize payload error: Error(([], Eof)), data: [1, 2, 3, 4]".to_owned()); - } - #[test] fn get_payload_error_kind() { - let decrypt = GetPayloadErrorKind::Decrypt; + let decrypt = GetPayloadError::Decrypt; assert_eq!(format!("{}", decrypt), "Decrypt payload error".to_owned()); - let incomplete = GetPayloadErrorKind::Deserialize { error: Err::Incomplete(Needed::Size(5)), payload: vec![1, 2, 3, 4] }; + let incomplete = GetPayloadError::Deserialize { error: Err::Incomplete(Needed::Size(5)), payload: vec![1, 2, 3, 4] }; assert_eq!(format!("{}", incomplete), "Deserialize payload error: Incomplete(Size(5)), data: [1, 2, 3, 4]".to_owned()); - let deserialize = GetPayloadErrorKind::Deserialize { error: Err::Error((vec![], ErrorKind::Eof)), payload: vec![1, 2, 3, 4] }; + let deserialize = GetPayloadError::Deserialize { error: Err::Error((vec![], ErrorKind::Eof)), payload: vec![1, 2, 3, 4] }; assert_eq!(format!("{}", deserialize), "Deserialize payload error: Error(([], Eof)), data: [1, 2, 3, 4]".to_owned()); } }