aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/config.rs26
-rw-r--r--src/util/data.rs12
-rw-r--r--src/util/error.rs82
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))
+ }
+}