From caac50d77ef7e7101ec8713466f9c62798af5ff3 Mon Sep 17 00:00:00 2001 From: Yevhenii Babichenko Date: Wed, 20 Nov 2019 17:33:16 +0200 Subject: [PATCH 1/4] allow adding `public_peers` with DNS name --- Cargo.lock | 78 +++++++++++++++ jormungandr/Cargo.toml | 3 + jormungandr/src/network/mod.rs | 5 +- jormungandr/src/settings/start/config.rs | 112 +++++++++++++++++++++- jormungandr/src/settings/start/mod.rs | 13 ++- jormungandr/src/settings/start/network.rs | 9 -- 6 files changed, 204 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b67001df26..89e0ca8d20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -923,6 +923,16 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "enum-as-inner" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "env_logger" version = "0.6.2" @@ -1396,6 +1406,17 @@ dependencies = [ "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ipconfig" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.7.11" @@ -1480,6 +1501,7 @@ dependencies = [ "juniper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "network-core 0.1.0-dev", "network-grpc 0.1.0-dev", @@ -1502,6 +1524,8 @@ dependencies = [ "thiserror 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "versionisator 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3664,6 +3688,29 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trust-dns-proto" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "trust-dns-resolver" version = "0.10.3" @@ -3682,6 +3729,27 @@ dependencies = [ "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trust-dns-resolver" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "try-lock" version = "0.2.2" @@ -3899,6 +3967,11 @@ name = "widestring" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "widestring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -4066,6 +4139,7 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" +"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" @@ -4116,6 +4190,7 @@ dependencies = [ "checksum integer-encoding 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1aec89c15e2cfa0f0eae8ca60e03cb10b30d25ea2c0ad7d6be60a95e32729994" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" +"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" "checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" @@ -4331,7 +4406,9 @@ dependencies = [ "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" +"checksum trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05457ece29839d056d8cb66ec080209d34492b3d2e7e00641b486977be973db9" "checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" +"checksum trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb1b3a41ee784f8da051cd342c6f42a3a75ee45818164acad867eac8f2f85332" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" @@ -4360,6 +4437,7 @@ dependencies = [ "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" +"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/jormungandr/Cargo.toml b/jormungandr/Cargo.toml index 8008335fa5..f28b250682 100644 --- a/jormungandr/Cargo.toml +++ b/jormungandr/Cargo.toml @@ -36,6 +36,7 @@ hyper = "0.12" jormungandr-lib = { path = "../jormungandr-lib" } lazy_static = "1.3" linked-hash-map = "0.5" +multiaddr = "0.3" native-tls = "0.2.2" network-core = { path = "../chain-deps/network-core" } network-grpc = { path = "../chain-deps/network-grpc" } @@ -56,6 +57,8 @@ slog-term = "2.4.0" structopt = "^0.2" thiserror = "1.0" tokio = "^0.1.16" +trust-dns-proto = "0.8.0" +trust-dns-resolver = "0.12.0" tk-listen = "0.2" bech32 = "0.7" diff --git a/jormungandr/src/network/mod.rs b/jormungandr/src/network/mod.rs index c5a2f9db37..2268b2337d 100644 --- a/jormungandr/src/network/mod.rs +++ b/jormungandr/src/network/mod.rs @@ -137,7 +137,7 @@ impl GlobalState { .map(|tp| { let mut builder = poldercast::NodeProfileBuilder::new(); builder.id(tp.id.into()); - builder.address(tp.address.into()); + builder.address(tp.address); builder.build() }) .map(p2p::Gossip::from) @@ -432,7 +432,8 @@ fn trusted_peers_shuffled(config: &Configuration) -> Vec { let mut peers = config .trusted_peers .iter() - .filter_map(|peer| peer.address.to_socketaddr()) + .map(|peer| peer.address.to_socketaddr().into_iter()) + .flatten() .collect::>(); let mut rng = rand::thread_rng(); peers.shuffle(&mut rng); diff --git a/jormungandr/src/settings/start/config.rs b/jormungandr/src/settings/start/config.rs index a812585336..62808cc1b5 100644 --- a/jormungandr/src/settings/start/config.rs +++ b/jormungandr/src/settings/start/config.rs @@ -113,7 +113,7 @@ pub struct P2pConfig { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct TrustedPeer { - pub address: Address, + pub address: TrustedAddress, pub id: Id, } @@ -130,6 +130,9 @@ pub struct Leadership { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Address(pub poldercast::Address); +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TrustedAddress(pub multiaddr::Multiaddr); + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Topic(pub poldercast::Topic); @@ -188,9 +191,8 @@ impl std::str::FromStr for TrustedPeer { let mut split = s.split('@'); let address = if let Some(address) = split.next() { - address - .parse::() - .map(Address) + multiaddr::Multiaddr::from_bytes(address.as_bytes().iter().cloned().collect()) + .map(TrustedAddress) .map_err(|e| e.to_string())? } else { return Err("Missing address component".to_owned()); @@ -212,12 +214,76 @@ impl Address { } } +// FIXME: in DnsLookupError we cannot specify the error source because it +// doesn't implement the Error trait +custom_error! {pub AddressError + DnsResolverInitError { source: std::io::Error } = "failed to initialize the DNS resolver: {source}", + DnsLookupError = "failed to resolve DNS name", +} + +impl TrustedAddress { + pub fn to_addresses(&self) -> Result, AddressError> { + use multiaddr::AddrComponent; + use std::iter::FromIterator; + use trust_dns_proto::rr::{record_data::RData, RecordType}; + + let resolver = trust_dns_resolver::Resolver::from_system_conf() + .map_err(|e| AddressError::DnsResolverInitError { source: e })?; + + let mut components = self.0.iter(); + let protocol = components.next(); + + let addresses = match protocol { + Some(AddrComponent::DNS4(fqdn)) => resolver + .lookup(&fqdn, RecordType::A) + .map_err(|_| AddressError::DnsLookupError)? + .into_iter() + .filter_map(|r| match r { + RData::A(addr) => Some(AddrComponent::IP4(addr)), + _ => None, + }) + .collect(), + Some(AddrComponent::DNS6(fqdn)) => resolver + .lookup(&fqdn, RecordType::AAAA) + .map_err(|_| AddressError::DnsLookupError)? + .into_iter() + .filter_map(|r| match r { + RData::AAAA(addr) => Some(AddrComponent::IP6(addr)), + _ => None, + }) + .collect(), + Some(AddrComponent::IP4(addr)) => vec![AddrComponent::IP4(addr)], + Some(AddrComponent::IP6(addr)) => vec![AddrComponent::IP6(addr)], + _ => Vec::new(), + }; + + if let Some(AddrComponent::TCP(port)) = components.next() { + Ok(addresses + .into_iter() + .map(|addr| { + let new_components = vec![addr, AddrComponent::TCP(port)]; + let new_multiaddr = multiaddr::Multiaddr::from_iter(new_components.into_iter()); + Address(poldercast::Address::new(new_multiaddr).unwrap()) + }) + .collect()) + } else { + Ok(Vec::new()) + } + } +} + impl std::fmt::Display for Address { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.0.fmt(f) } } +impl std::fmt::Display for TrustedAddress { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.0.fmt(f) + } +} + impl Serialize for Address { fn serialize(&self, serializer: S) -> Result where @@ -226,6 +292,16 @@ impl Serialize for Address { serializer.serialize_str(&format!("{}", self.0)) } } + +impl Serialize for TrustedAddress { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{}", self.0)) + } +} + impl Serialize for Topic { fn serialize(&self, serializer: S) -> Result where @@ -282,6 +358,34 @@ impl<'de> Deserialize<'de> for Address { } } +impl<'de> Deserialize<'de> for TrustedAddress { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TrustedAddressVisitor; + impl<'de> Visitor<'de> for TrustedAddressVisitor { + type Value = TrustedAddress; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "Multiaddr (example: /ip4/192.168.0.1/tcp/443)") + } + + fn visit_str<'a, E>(self, v: &'a str) -> std::result::Result + where + E: serde::de::Error, + { + use serde::de::Unexpected; + match v.parse() { + Err(_err) => Err(E::invalid_value(Unexpected::Str(v), &self)), + Ok(addr) => Ok(TrustedAddress(addr)), + } + } + } + deserializer.deserialize_str(TrustedAddressVisitor) + } +} + impl<'de> Deserialize<'de> for Topic { fn deserialize(deserializer: D) -> Result where diff --git a/jormungandr/src/settings/start/mod.rs b/jormungandr/src/settings/start/mod.rs index 80b4160562..2bb03b5e28 100644 --- a/jormungandr/src/settings/start/mod.rs +++ b/jormungandr/src/settings/start/mod.rs @@ -6,6 +6,7 @@ pub use self::config::{Cors, Rest}; use self::network::Protocol; use crate::rest::Error as RestError; use crate::settings::logging::{LogFormat, LogOutput, LogSettings, LogSettingsEntry}; +use crate::settings::start::config::AddressError; use crate::settings::{command_arguments::*, Block0Info}; use jormungandr_lib::interfaces::Mempool; use slog::{FilterLevel, Logger}; @@ -233,7 +234,17 @@ fn generate_network( .clone() .unwrap_or(vec![]) .into_iter() - .map(Into::into) + .filter_map(|tp| { + tp.address.to_addresses().ok().map(|addrs| { + addrs.into_iter().map(move |address| { + crate::settings::start::network::TrustedPeer { + id: tp.id.clone(), + address: address.0, + } + }) + }) + }) + .flatten() .collect(), protocol: Protocol::Grpc, policy: p2p.policy.clone(), diff --git a/jormungandr/src/settings/start/network.rs b/jormungandr/src/settings/start/network.rs index 7f0f27c91b..0c4a205d61 100644 --- a/jormungandr/src/settings/start/network.rs +++ b/jormungandr/src/settings/start/network.rs @@ -76,15 +76,6 @@ pub struct TrustedPeer { pub id: Id, } -impl From for TrustedPeer { - fn from(tp: super::config::TrustedPeer) -> Self { - TrustedPeer { - address: tp.address.0, - id: tp.id, - } - } -} - impl Peer { pub fn new(connection: SocketAddr, protocol: Protocol) -> Self { Peer { From f914eefbdd613ac433bf99067941c8d6d1f9f9c5 Mon Sep 17 00:00:00 2001 From: Yevhenii Babichenko Date: Wed, 20 Nov 2019 19:39:00 +0200 Subject: [PATCH 2/4] avoid empty vectors in TrustedAddress::to_addresses --- jormungandr/src/settings/start/config.rs | 29 +++++++++++++++--------- jormungandr/src/settings/start/mod.rs | 16 ++++++++----- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/jormungandr/src/settings/start/config.rs b/jormungandr/src/settings/start/config.rs index 62808cc1b5..6578c630b8 100644 --- a/jormungandr/src/settings/start/config.rs +++ b/jormungandr/src/settings/start/config.rs @@ -222,7 +222,7 @@ custom_error! {pub AddressError } impl TrustedAddress { - pub fn to_addresses(&self) -> Result, AddressError> { + pub fn to_addresses(&self) -> Result>, AddressError> { use multiaddr::AddrComponent; use std::iter::FromIterator; use trust_dns_proto::rr::{record_data::RData, RecordType}; @@ -254,20 +254,27 @@ impl TrustedAddress { .collect(), Some(AddrComponent::IP4(addr)) => vec![AddrComponent::IP4(addr)], Some(AddrComponent::IP6(addr)) => vec![AddrComponent::IP6(addr)], - _ => Vec::new(), + _ => return Ok(None), }; + if addresses.is_empty() { + return Ok(None); + } + if let Some(AddrComponent::TCP(port)) = components.next() { - Ok(addresses - .into_iter() - .map(|addr| { - let new_components = vec![addr, AddrComponent::TCP(port)]; - let new_multiaddr = multiaddr::Multiaddr::from_iter(new_components.into_iter()); - Address(poldercast::Address::new(new_multiaddr).unwrap()) - }) - .collect()) + Ok(Some( + addresses + .into_iter() + .map(|addr| { + let new_components = vec![addr, AddrComponent::TCP(port)]; + let new_multiaddr = + multiaddr::Multiaddr::from_iter(new_components.into_iter()); + Address(poldercast::Address::new(new_multiaddr).unwrap()) + }) + .collect(), + )) } else { - Ok(Vec::new()) + Ok(None) } } } diff --git a/jormungandr/src/settings/start/mod.rs b/jormungandr/src/settings/start/mod.rs index 2bb03b5e28..cfac2c7191 100644 --- a/jormungandr/src/settings/start/mod.rs +++ b/jormungandr/src/settings/start/mod.rs @@ -182,6 +182,8 @@ fn generate_network( command_arguments: &StartArguments, config: &Option, ) -> Result { + use crate::settings::start::network::TrustedPeer; + let mut p2p = if let Some(cfg) = config { cfg.p2p.clone() } else { @@ -235,14 +237,16 @@ fn generate_network( .unwrap_or(vec![]) .into_iter() .filter_map(|tp| { - tp.address.to_addresses().ok().map(|addrs| { - addrs.into_iter().map(move |address| { - crate::settings::start::network::TrustedPeer { + tp.address + .to_addresses() + .ok() + .and_then(std::convert::identity) + .map(|addrs| { + addrs.into_iter().map(move |addr| TrustedPeer { id: tp.id.clone(), - address: address.0, - } + address: addr.0, + }) }) - }) }) .flatten() .collect(), From 2685020ed996a90f891f03deb5066585370e7429 Mon Sep 17 00:00:00 2001 From: Yevhenii Babichenko Date: Thu, 21 Nov 2019 20:26:33 +0200 Subject: [PATCH 3/4] refactor to remove `trust-dns` from dependencies --- Cargo.lock | 77 ------------------------ jormungandr/Cargo.toml | 2 - jormungandr/src/settings/start/config.rs | 76 +++++++++++------------ jormungandr/src/settings/start/mod.rs | 15 ++--- 4 files changed, 43 insertions(+), 127 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89e0ca8d20..edcc430d88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -923,16 +923,6 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "enum-as-inner" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.6.2" @@ -1406,17 +1396,6 @@ dependencies = [ "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ipconfig" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itertools" version = "0.7.11" @@ -1524,8 +1503,6 @@ dependencies = [ "thiserror 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "versionisator 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3688,29 +3665,6 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "trust-dns-proto" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "trust-dns-resolver" version = "0.10.3" @@ -3729,27 +3683,6 @@ dependencies = [ "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "trust-dns-resolver" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "try-lock" version = "0.2.2" @@ -3967,11 +3900,6 @@ name = "widestring" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "widestring" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.2.8" @@ -4139,7 +4067,6 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" -"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" @@ -4190,7 +4117,6 @@ dependencies = [ "checksum integer-encoding 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1aec89c15e2cfa0f0eae8ca60e03cb10b30d25ea2c0ad7d6be60a95e32729994" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" -"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" "checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" @@ -4406,9 +4332,7 @@ dependencies = [ "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum trust-dns-proto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0838272e89f1c693b4df38dc353412e389cf548ceed6f9fd1af5a8d6e0e7cf74" "checksum trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09144f0992b0870fa8d2972cc069cbf1e3c0fda64d1f3d45c4d68d0e0b52ad4e" -"checksum trust-dns-proto 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05457ece29839d056d8cb66ec080209d34492b3d2e7e00641b486977be973db9" "checksum trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a9f877f7a1ad821ab350505e1f1b146a4960402991787191d6d8cab2ce2de2c" -"checksum trust-dns-resolver 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb1b3a41ee784f8da051cd342c6f42a3a75ee45818164acad867eac8f2f85332" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" @@ -4437,7 +4361,6 @@ dependencies = [ "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" -"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/jormungandr/Cargo.toml b/jormungandr/Cargo.toml index f28b250682..3c83a05273 100644 --- a/jormungandr/Cargo.toml +++ b/jormungandr/Cargo.toml @@ -57,8 +57,6 @@ slog-term = "2.4.0" structopt = "^0.2" thiserror = "1.0" tokio = "^0.1.16" -trust-dns-proto = "0.8.0" -trust-dns-resolver = "0.12.0" tk-listen = "0.2" bech32 = "0.7" diff --git a/jormungandr/src/settings/start/config.rs b/jormungandr/src/settings/start/config.rs index 6578c630b8..ce8c7360e7 100644 --- a/jormungandr/src/settings/start/config.rs +++ b/jormungandr/src/settings/start/config.rs @@ -214,68 +214,68 @@ impl Address { } } -// FIXME: in DnsLookupError we cannot specify the error source because it -// doesn't implement the Error trait custom_error! {pub AddressError - DnsResolverInitError { source: std::io::Error } = "failed to initialize the DNS resolver: {source}", - DnsLookupError = "failed to resolve DNS name", + DnsLookupError { source: std::io::Error } = "failed to resolve DNS name {source}", + NoPortSpecified = "no TCP port specified", + NoAppropriateDNSFound = "the address was resolved, but it doesn't provide IPv4 or IPv6 addresses", + UnsupportedProtocol = "the provided protocol is unsupported, please use one of ip4/ip6/dns4/dns6", } impl TrustedAddress { - pub fn to_addresses(&self) -> Result>, AddressError> { + pub fn to_addresses(&self) -> Result, AddressError> { use multiaddr::AddrComponent; - use std::iter::FromIterator; - use trust_dns_proto::rr::{record_data::RData, RecordType}; - - let resolver = trust_dns_resolver::Resolver::from_system_conf() - .map_err(|e| AddressError::DnsResolverInitError { source: e })?; + use std::{iter::FromIterator, net::ToSocketAddrs}; let mut components = self.0.iter(); let protocol = components.next(); - let addresses = match protocol { - Some(AddrComponent::DNS4(fqdn)) => resolver - .lookup(&fqdn, RecordType::A) - .map_err(|_| AddressError::DnsLookupError)? + if let Some(AddrComponent::IP4(_)) | Some(AddrComponent::IP6(_)) = protocol { + return Ok(vec![Address( + poldercast::Address::new(self.0.clone()).unwrap(), + )]); + } + + let port = match components.next() { + Some(AddrComponent::TCP(port)) => port, + _ => return Err(AddressError::NoPortSpecified), + }; + + let addresses: Vec = match protocol { + Some(AddrComponent::DNS4(fqdn)) => format!("{}:{}", fqdn, port) + .to_socket_addrs() + .map_err(|e| AddressError::DnsLookupError { source: e })? .into_iter() .filter_map(|r| match r { - RData::A(addr) => Some(AddrComponent::IP4(addr)), + SocketAddr::V4(addr) => Some(AddrComponent::IP4(*addr.ip())), _ => None, }) .collect(), - Some(AddrComponent::DNS6(fqdn)) => resolver - .lookup(&fqdn, RecordType::AAAA) - .map_err(|_| AddressError::DnsLookupError)? + Some(AddrComponent::DNS6(fqdn)) => format!("{}:{}", fqdn, port) + .to_socket_addrs() + .map_err(|e| AddressError::DnsLookupError { source: e })? .into_iter() .filter_map(|r| match r { - RData::AAAA(addr) => Some(AddrComponent::IP6(addr)), + SocketAddr::V6(addr) => Some(AddrComponent::IP6(*addr.ip())), _ => None, }) .collect(), - Some(AddrComponent::IP4(addr)) => vec![AddrComponent::IP4(addr)], - Some(AddrComponent::IP6(addr)) => vec![AddrComponent::IP6(addr)], - _ => return Ok(None), + _ => return Err(AddressError::UnsupportedProtocol), }; if addresses.is_empty() { - return Ok(None); + return Err(AddressError::NoAppropriateDNSFound); } - if let Some(AddrComponent::TCP(port)) = components.next() { - Ok(Some( - addresses - .into_iter() - .map(|addr| { - let new_components = vec![addr, AddrComponent::TCP(port)]; - let new_multiaddr = - multiaddr::Multiaddr::from_iter(new_components.into_iter()); - Address(poldercast::Address::new(new_multiaddr).unwrap()) - }) - .collect(), - )) - } else { - Ok(None) - } + let addresses = addresses + .into_iter() + .map(|addr| { + let new_components = vec![addr, AddrComponent::TCP(port)]; + let new_multiaddr = multiaddr::Multiaddr::from_iter(new_components.into_iter()); + Address(poldercast::Address::new(new_multiaddr).unwrap()) + }) + .collect(); + + Ok(addresses) } } diff --git a/jormungandr/src/settings/start/mod.rs b/jormungandr/src/settings/start/mod.rs index cfac2c7191..17d01c6761 100644 --- a/jormungandr/src/settings/start/mod.rs +++ b/jormungandr/src/settings/start/mod.rs @@ -6,7 +6,6 @@ pub use self::config::{Cors, Rest}; use self::network::Protocol; use crate::rest::Error as RestError; use crate::settings::logging::{LogFormat, LogOutput, LogSettings, LogSettingsEntry}; -use crate::settings::start::config::AddressError; use crate::settings::{command_arguments::*, Block0Info}; use jormungandr_lib::interfaces::Mempool; use slog::{FilterLevel, Logger}; @@ -237,16 +236,12 @@ fn generate_network( .unwrap_or(vec![]) .into_iter() .filter_map(|tp| { - tp.address - .to_addresses() - .ok() - .and_then(std::convert::identity) - .map(|addrs| { - addrs.into_iter().map(move |addr| TrustedPeer { - id: tp.id.clone(), - address: addr.0, - }) + tp.address.to_addresses().ok().map(|addrs| { + addrs.into_iter().map(move |addr| TrustedPeer { + id: tp.id.clone(), + address: addr.0, }) + }) }) .flatten() .collect(), From bb4218aacb09a8bf8fc9cb054a287e3be4f82db8 Mon Sep 17 00:00:00 2001 From: Yevhenii Babichenko Date: Fri, 22 Nov 2019 10:38:25 +0200 Subject: [PATCH 4/4] move TrustedPeer to a separate module --- jormungandr/src/settings/command_arguments.rs | 2 +- jormungandr/src/settings/start/config.rs | 141 +---------------- jormungandr/src/settings/start/mod.rs | 1 + .../src/settings/start/trusted_peer.rs | 146 ++++++++++++++++++ 4 files changed, 153 insertions(+), 137 deletions(-) create mode 100644 jormungandr/src/settings/start/trusted_peer.rs diff --git a/jormungandr/src/settings/command_arguments.rs b/jormungandr/src/settings/command_arguments.rs index 7cd4be84a9..d1a6a620dc 100644 --- a/jormungandr/src/settings/command_arguments.rs +++ b/jormungandr/src/settings/command_arguments.rs @@ -1,4 +1,4 @@ -use crate::settings::{start::config::TrustedPeer, LOG_FILTER_LEVEL_POSSIBLE_VALUES}; +use crate::settings::{start::trusted_peer::*, LOG_FILTER_LEVEL_POSSIBLE_VALUES}; use slog::FilterLevel; use std::net::SocketAddr; use std::path::PathBuf; diff --git a/jormungandr/src/settings/start/config.rs b/jormungandr/src/settings/start/config.rs index ce8c7360e7..0518243b48 100644 --- a/jormungandr/src/settings/start/config.rs +++ b/jormungandr/src/settings/start/config.rs @@ -1,7 +1,10 @@ use crate::{ network::p2p::{topic, Id, PolicyConfig}, - settings::logging::{LogFormat, LogOutput}, - settings::LOG_FILTER_LEVEL_POSSIBLE_VALUES, + settings::{ + logging::{LogFormat, LogOutput}, + start::trusted_peer::*, + LOG_FILTER_LEVEL_POSSIBLE_VALUES, + }, }; use jormungandr_lib::{interfaces::Mempool, time::Duration}; use poldercast; @@ -110,13 +113,6 @@ pub struct P2pConfig { pub max_unreachable_nodes_to_connect_per_event: Option, } -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(deny_unknown_fields)] -pub struct TrustedPeer { - pub address: TrustedAddress, - pub id: Id, -} - #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct Leadership { @@ -130,9 +126,6 @@ pub struct Leadership { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Address(pub poldercast::Address); -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TrustedAddress(pub multiaddr::Multiaddr); - #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Topic(pub poldercast::Topic); @@ -185,29 +178,6 @@ impl Default for Leadership { } } -impl std::str::FromStr for TrustedPeer { - type Err = String; - fn from_str(s: &str) -> Result { - let mut split = s.split('@'); - - let address = if let Some(address) = split.next() { - multiaddr::Multiaddr::from_bytes(address.as_bytes().iter().cloned().collect()) - .map(TrustedAddress) - .map_err(|e| e.to_string())? - } else { - return Err("Missing address component".to_owned()); - }; - - let id = if let Some(id) = split.next() { - id.parse::().map_err(|e| e.to_string())? - } else { - return Err("Missing id component".to_owned()); - }; - - Ok(TrustedPeer { address, id }) - } -} - impl Address { pub fn to_socketaddr(&self) -> Option { self.0.to_socketaddr() @@ -221,76 +191,12 @@ custom_error! {pub AddressError UnsupportedProtocol = "the provided protocol is unsupported, please use one of ip4/ip6/dns4/dns6", } -impl TrustedAddress { - pub fn to_addresses(&self) -> Result, AddressError> { - use multiaddr::AddrComponent; - use std::{iter::FromIterator, net::ToSocketAddrs}; - - let mut components = self.0.iter(); - let protocol = components.next(); - - if let Some(AddrComponent::IP4(_)) | Some(AddrComponent::IP6(_)) = protocol { - return Ok(vec![Address( - poldercast::Address::new(self.0.clone()).unwrap(), - )]); - } - - let port = match components.next() { - Some(AddrComponent::TCP(port)) => port, - _ => return Err(AddressError::NoPortSpecified), - }; - - let addresses: Vec = match protocol { - Some(AddrComponent::DNS4(fqdn)) => format!("{}:{}", fqdn, port) - .to_socket_addrs() - .map_err(|e| AddressError::DnsLookupError { source: e })? - .into_iter() - .filter_map(|r| match r { - SocketAddr::V4(addr) => Some(AddrComponent::IP4(*addr.ip())), - _ => None, - }) - .collect(), - Some(AddrComponent::DNS6(fqdn)) => format!("{}:{}", fqdn, port) - .to_socket_addrs() - .map_err(|e| AddressError::DnsLookupError { source: e })? - .into_iter() - .filter_map(|r| match r { - SocketAddr::V6(addr) => Some(AddrComponent::IP6(*addr.ip())), - _ => None, - }) - .collect(), - _ => return Err(AddressError::UnsupportedProtocol), - }; - - if addresses.is_empty() { - return Err(AddressError::NoAppropriateDNSFound); - } - - let addresses = addresses - .into_iter() - .map(|addr| { - let new_components = vec![addr, AddrComponent::TCP(port)]; - let new_multiaddr = multiaddr::Multiaddr::from_iter(new_components.into_iter()); - Address(poldercast::Address::new(new_multiaddr).unwrap()) - }) - .collect(); - - Ok(addresses) - } -} - impl std::fmt::Display for Address { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.0.fmt(f) } } -impl std::fmt::Display for TrustedAddress { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - self.0.fmt(f) - } -} - impl Serialize for Address { fn serialize(&self, serializer: S) -> Result where @@ -300,15 +206,6 @@ impl Serialize for Address { } } -impl Serialize for TrustedAddress { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&format!("{}", self.0)) - } -} - impl Serialize for Topic { fn serialize(&self, serializer: S) -> Result where @@ -365,34 +262,6 @@ impl<'de> Deserialize<'de> for Address { } } -impl<'de> Deserialize<'de> for TrustedAddress { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct TrustedAddressVisitor; - impl<'de> Visitor<'de> for TrustedAddressVisitor { - type Value = TrustedAddress; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "Multiaddr (example: /ip4/192.168.0.1/tcp/443)") - } - - fn visit_str<'a, E>(self, v: &'a str) -> std::result::Result - where - E: serde::de::Error, - { - use serde::de::Unexpected; - match v.parse() { - Err(_err) => Err(E::invalid_value(Unexpected::Str(v), &self)), - Ok(addr) => Ok(TrustedAddress(addr)), - } - } - } - deserializer.deserialize_str(TrustedAddressVisitor) - } -} - impl<'de> Deserialize<'de> for Topic { fn deserialize(deserializer: D) -> Result where diff --git a/jormungandr/src/settings/start/mod.rs b/jormungandr/src/settings/start/mod.rs index 17d01c6761..ce52cf3c6a 100644 --- a/jormungandr/src/settings/start/mod.rs +++ b/jormungandr/src/settings/start/mod.rs @@ -1,5 +1,6 @@ pub mod config; pub mod network; +pub mod trusted_peer; use self::config::{Config, Leadership}; pub use self::config::{Cors, Rest}; diff --git a/jormungandr/src/settings/start/trusted_peer.rs b/jormungandr/src/settings/start/trusted_peer.rs new file mode 100644 index 0000000000..32221d5241 --- /dev/null +++ b/jormungandr/src/settings/start/trusted_peer.rs @@ -0,0 +1,146 @@ +use crate::{network::p2p::Id, settings::start::config::Address}; +use multiaddr::AddrComponent; +use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; +use std::{ + fmt, + iter::FromIterator, + net::{SocketAddr, ToSocketAddrs}, +}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TrustedPeer { + pub address: TrustedAddress, + pub id: Id, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TrustedAddress(pub multiaddr::Multiaddr); + +custom_error! {pub AddressError + DnsLookupError { source: std::io::Error } = "failed to resolve DNS name {source}", + NoPortSpecified = "no TCP port specified", + NoAppropriateDNSFound = "the address was resolved, but it doesn't provide IPv4 or IPv6 addresses", + UnsupportedProtocol = "the provided protocol is unsupported, please use one of ip4/ip6/dns4/dns6", +} + +impl TrustedAddress { + pub fn to_addresses(&self) -> Result, AddressError> { + let mut components = self.0.iter(); + let protocol = components.next(); + + if let Some(AddrComponent::IP4(_)) | Some(AddrComponent::IP6(_)) = protocol { + return Ok(vec![Address( + poldercast::Address::new(self.0.clone()).unwrap(), + )]); + } + + let port = match components.next() { + Some(AddrComponent::TCP(port)) => port, + _ => return Err(AddressError::NoPortSpecified), + }; + + let addresses: Vec = match protocol { + Some(AddrComponent::DNS4(fqdn)) => format!("{}:{}", fqdn, port) + .to_socket_addrs() + .map_err(|e| AddressError::DnsLookupError { source: e })? + .into_iter() + .filter_map(|r| match r { + SocketAddr::V4(addr) => Some(AddrComponent::IP4(*addr.ip())), + _ => None, + }) + .collect(), + Some(AddrComponent::DNS6(fqdn)) => format!("{}:{}", fqdn, port) + .to_socket_addrs() + .map_err(|e| AddressError::DnsLookupError { source: e })? + .into_iter() + .filter_map(|r| match r { + SocketAddr::V6(addr) => Some(AddrComponent::IP6(*addr.ip())), + _ => None, + }) + .collect(), + _ => return Err(AddressError::UnsupportedProtocol), + }; + + if addresses.is_empty() { + return Err(AddressError::NoAppropriateDNSFound); + } + + let addresses = addresses + .into_iter() + .map(|addr| { + let new_components = vec![addr, AddrComponent::TCP(port)]; + let new_multiaddr = multiaddr::Multiaddr::from_iter(new_components.into_iter()); + Address(poldercast::Address::new(new_multiaddr).unwrap()) + }) + .collect(); + + Ok(addresses) + } +} + +impl std::str::FromStr for TrustedPeer { + type Err = String; + fn from_str(s: &str) -> Result { + let mut split = s.split('@'); + + let address = if let Some(address) = split.next() { + multiaddr::Multiaddr::from_bytes(address.as_bytes().iter().cloned().collect()) + .map(TrustedAddress) + .map_err(|e| e.to_string())? + } else { + return Err("Missing address component".to_owned()); + }; + + let id = if let Some(id) = split.next() { + id.parse::().map_err(|e| e.to_string())? + } else { + return Err("Missing id component".to_owned()); + }; + + Ok(TrustedPeer { address, id }) + } +} + +impl Serialize for TrustedAddress { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("{}", self.0)) + } +} + +impl std::fmt::Display for TrustedAddress { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl<'de> Deserialize<'de> for TrustedAddress { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TrustedAddressVisitor; + impl<'de> Visitor<'de> for TrustedAddressVisitor { + type Value = TrustedAddress; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "Multiaddr (example: /ip4/192.168.0.1/tcp/443)") + } + + fn visit_str<'a, E>(self, v: &'a str) -> std::result::Result + where + E: serde::de::Error, + { + use serde::de::Unexpected; + match v.parse() { + Err(_err) => Err(E::invalid_value(Unexpected::Str(v), &self)), + Ok(addr) => Ok(TrustedAddress(addr)), + } + } + } + deserializer.deserialize_str(TrustedAddressVisitor) + } +}