diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/config.rs | 26 | ||||
-rw-r--r-- | src/util/data.rs | 12 | ||||
-rw-r--r-- | src/util/error.rs | 82 |
3 files changed, 72 insertions, 48 deletions
diff --git a/src/util/config.rs b/src/util/config.rs index ee153dfa..08ece5b7 100644 --- a/src/util/config.rs +++ b/src/util/config.rs @@ -7,6 +7,7 @@ use serde::de::Error as SerdeError; use serde::{de, Deserialize}; use netapp::NodeID; +use netapp::util::parse_and_resolve_peer_addr; use crate::error::Error; @@ -34,11 +35,13 @@ pub struct Config { /// Address to bind for RPC pub rpc_bind_addr: SocketAddr, + /// Public IP address of this node + pub rpc_public_addr: Option<SocketAddr>, /// Bootstrap peers RPC address #[serde(deserialize_with = "deserialize_vec_addr")] pub bootstrap_peers: Vec<(NodeID, SocketAddr)>, - /// Consule host to connect to to discover more peers + /// Consul host to connect to to discover more peers pub consul_host: Option<String>, /// Consul service name to use pub consul_service_name: Option<String>, @@ -111,26 +114,13 @@ fn deserialize_vec_addr<'de, D>(deserializer: D) -> Result<Vec<(NodeID, SocketAd where D: de::Deserializer<'de>, { - use std::net::ToSocketAddrs; - let mut ret = vec![]; for peer in <Vec<&str>>::deserialize(deserializer)? { - let delim = peer - .find('@') - .ok_or_else(|| D::Error::custom("Invalid bootstrap peer: public key not specified"))?; - let (key, host) = peer.split_at(delim); - let pubkey = NodeID::from_slice(&hex::decode(&key).map_err(D::Error::custom)?) - .ok_or_else(|| D::Error::custom("Invalid bootstrap peer public key"))?; - let hosts = host[1..] - .to_socket_addrs() - .map_err(D::Error::custom)? - .collect::<Vec<_>>(); - if hosts.is_empty() { - return Err(D::Error::custom(format!("Error resolving {}", &host[1..]))); - } - for host in hosts { - ret.push((pubkey.clone(), host)); + let (pubkey, addrs) = parse_and_resolve_peer_addr(peer) + .ok_or_else(|| D::Error::custom(format!("Unable to parse or resolve peer: {}", peer)))?; + for ip in addrs { + ret.push((pubkey.clone(), ip)); } } diff --git a/src/util/data.rs b/src/util/data.rs index 6df51cd0..d4fe0009 100644 --- a/src/util/data.rs +++ b/src/util/data.rs @@ -87,6 +87,18 @@ impl FixedBytes32 { } } +impl From<netapp::NodeID> for FixedBytes32 { + fn from(node_id: netapp::NodeID) -> FixedBytes32 { + FixedBytes32::try_from(node_id.as_ref()).unwrap() + } +} + +impl Into<netapp::NodeID> for FixedBytes32 { + fn into(self) -> netapp::NodeID { + netapp::NodeID::from_slice(self.as_slice()).unwrap() + } +} + /// A 32 bytes UUID pub type Uuid = FixedBytes32; /// A 256 bit cryptographic hash, can be sha256 or blake2 depending on provenance diff --git a/src/util/error.rs b/src/util/error.rs index 804a0d4d..390327f1 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -1,34 +1,12 @@ //! Module containing error types used in Garage -use err_derive::Error; -use hyper::StatusCode; +use std::fmt; use std::io; -use crate::data::*; - -/// RPC related errors -#[derive(Debug, Error)] -pub enum RpcError { - #[error(display = "Node is down: {:?}.", _0)] - NodeDown(Uuid), - - #[error(display = "Timeout")] - Timeout, - - #[error(display = "HTTP error: {}", _0)] - Http(#[error(source)] http::Error), - - #[error(display = "Hyper error: {}", _0)] - Hyper(#[error(source)] hyper::Error), +use err_derive::Error; - #[error(display = "Messagepack encode error: {}", _0)] - RmpEncode(#[error(source)] rmp_serde::encode::Error), +use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; - #[error(display = "Messagepack decode error: {}", _0)] - RmpDecode(#[error(source)] rmp_serde::decode::Error), - - #[error(display = "Too many errors: {:?}", _0)] - TooManyErrors(Vec<String>), -} +use crate::data::*; /// Regroup all Garage errors #[derive(Debug, Error)] @@ -63,11 +41,14 @@ pub enum Error { #[error(display = "Tokio join error: {}", _0)] TokioJoin(#[error(source)] tokio::task::JoinError), - #[error(display = "RPC call error: {}", _0)] - Rpc(#[error(source)] RpcError), + #[error(display = "Remote error: {}", _0)] + RemoteError(String), + + #[error(display = "Timeout")] + Timeout, - #[error(display = "Remote error: {} (status code {})", _0, _1)] - RemoteError(String, StatusCode), + #[error(display = "Too many errors: {:?}", _0)] + TooManyErrors(Vec<String>), #[error(display = "Bad RPC: {}", _0)] BadRpc(String), @@ -99,3 +80,44 @@ impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error { Error::Message("MPSC send error".to_string()) } } + +// Custom serialization for our error type, for use in RPC. +// Errors are serialized as a string of their Display representation. +// Upon deserialization, they all become a RemoteError with the +// given representation. + +impl Serialize for Error { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_str(&format!("{}", self)) + } +} + +impl<'de> Deserialize<'de> for Error { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_string(ErrorVisitor) + } +} + +struct ErrorVisitor; + +impl<'de> Visitor<'de> for ErrorVisitor { + type Value = Error; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a string that represents an error value") + } + + fn visit_str<E>(self, error_msg: &str) -> Result<Self::Value, E> { + Ok(Error::RemoteError(error_msg.to_string())) + } + + fn visit_string<E>(self, error_msg: String) -> Result<Self::Value, E> { + Ok(Error::RemoteError(error_msg)) + } +} |