Skip to content

Commit

Permalink
allow adding public_peers with DNS name
Browse files Browse the repository at this point in the history
  • Loading branch information
eugene-babichenko committed Nov 20, 2019
1 parent 6d2951f commit caac50d
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 16 deletions.
78 changes: 78 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions jormungandr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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"

Expand Down
5 changes: 3 additions & 2 deletions jormungandr/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -432,7 +432,8 @@ fn trusted_peers_shuffled(config: &Configuration) -> Vec<SocketAddr> {
let mut peers = config
.trusted_peers
.iter()
.filter_map(|peer| peer.address.to_socketaddr())
.map(|peer| peer.address.to_socketaddr().into_iter())
.flatten()
.collect::<Vec<_>>();
let mut rng = rand::thread_rng();
peers.shuffle(&mut rng);
Expand Down
112 changes: 108 additions & 4 deletions jormungandr/src/settings/start/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand All @@ -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);

Expand Down Expand Up @@ -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::<poldercast::Address>()
.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());
Expand All @@ -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<Vec<Address>, 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -226,6 +292,16 @@ impl Serialize for Address {
serializer.serialize_str(&format!("{}", self.0))
}
}

impl Serialize for TrustedAddress {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&format!("{}", self.0))
}
}

impl Serialize for Topic {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -282,6 +358,34 @@ impl<'de> Deserialize<'de> for Address {
}
}

impl<'de> Deserialize<'de> for TrustedAddress {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<Self::Value, E>
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<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
13 changes: 12 additions & 1 deletion jormungandr/src/settings/start/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(),
Expand Down
9 changes: 0 additions & 9 deletions jormungandr/src/settings/start/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,6 @@ pub struct TrustedPeer {
pub id: Id,
}

impl From<super::config::TrustedPeer> 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 {
Expand Down

0 comments on commit caac50d

Please sign in to comment.