Skip to content

Commit

Permalink
chore: use Serde desrialize to resolve DNS names into PeerAddrs
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephGoulden committed Nov 25, 2019
1 parent e00ea4c commit 77703e8
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 72 deletions.
4 changes: 2 additions & 2 deletions p2p/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ impl Readable for GetPeerAddrs {

/// Peer addresses we know of that are fresh enough, in response to
/// GetPeerAddrs.
#[derive(Debug)]
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct PeerAddrs {
pub peers: Vec<PeerAddr>,
}
Expand All @@ -495,7 +495,7 @@ impl Readable for PeerAddrs {
for _ in 0..peer_count {
peers.push(PeerAddr::read(reader)?);
}
Ok(PeerAddrs { peers: peers })
Ok(PeerAddrs { peers })
}
}

Expand Down
53 changes: 2 additions & 51 deletions p2p/src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl Peer {

pub fn is_denied(config: &P2PConfig, peer_addr: PeerAddr) -> bool {
if let Some(ref denied) = config.peers_deny {
if denied.contains(&peer_addr.as_key()) {
if denied.peers.contains(&peer_addr) {
debug!(
"checking peer allowed/denied: {:?} explicitly denied",
peer_addr
Expand All @@ -161,7 +161,7 @@ impl Peer {
}
}
if let Some(ref allowed) = config.peers_allow {
if allowed.contains(&peer_addr.as_key()) {
if allowed.peers.contains(&peer_addr) {
debug!(
"checking peer allowed/denied: {:?} explicitly allowed",
peer_addr
Expand Down Expand Up @@ -617,52 +617,3 @@ impl NetAdapter for TrackingAdapter {
self.adapter.is_banned(addr)
}
}

#[cfg(test)]
mod test {
use crate::{P2PConfig, Peer, PeerAddr};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

#[test]
fn test_peer_is_allowed_by_default() {
let config = P2PConfig::default();
let peer = PeerAddr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
3414,
));
assert!(!Peer::is_denied(&config, peer));
}

#[test]
fn test_peer_is_denied() {
let mut config = P2PConfig::default();
config.peers_deny = Some(vec!["127.0.0.1:3414".to_string()]);
let peer = PeerAddr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
3414,
));
assert!(Peer::is_denied(&config, peer));
}

#[test]
fn test_peer_with_different_port_is_not_denied() {
let mut config = P2PConfig::default();
config.peers_deny = Some(vec!["127.0.0.1:3414".to_string()]);
let peer = PeerAddr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
3415,
));
assert!(!Peer::is_denied(&config, peer));
}

#[test]
fn test_peer_is_allowed() {
let mut config = P2PConfig::default();
config.peers_allow = Some(vec!["127.0.0.1:3414".to_string()]);
let peer = PeerAddr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
3414,
));
assert!(!Peer::is_denied(&config, peer));
}
}
60 changes: 52 additions & 8 deletions p2p/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::util::RwLock;
use std::convert::From;
use std::fmt;
use std::fs::File;
use std::io::{self, Read};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
use std::path::PathBuf;

use std::str::FromStr;
use std::sync::mpsc;
use std::sync::Arc;

use chrono::prelude::*;
use serde::de::{SeqAccess, Visitor};
use serde::{Deserialize, Deserializer};

use grin_store;

use crate::chain;
use crate::core::core;
use crate::core::core::hash::Hash;
use crate::core::global;
use crate::core::pow::Difficulty;
use crate::core::ser::{self, ProtocolVersion, Readable, Reader, Writeable, Writer};
use grin_store;
use crate::msg::PeerAddrs;
use crate::util::RwLock;

/// Maximum number of block headers a peer should ever send
pub const MAX_BLOCK_HEADERS: u32 = 512;
Expand Down Expand Up @@ -161,6 +166,45 @@ impl Readable for PeerAddr {
}
}

impl<'de> Visitor<'de> for PeerAddrs {
type Value = PeerAddrs;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an array of dns names or IP addresses")
}

fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
let mut peers = Vec::with_capacity(access.size_hint().unwrap_or(0));

while let Some(entry) = access.next_element::<&str>()? {
match SocketAddr::from_str(entry) {
// Try to parse IP address first
Ok(ip) => peers.push(PeerAddr(ip)),
// If that fails it's probably a DNS record
Err(_) => {
let socket_addrs = entry
.to_socket_addrs()
.expect(format!("Unable to resolve DNS: {}", entry).as_str());
peers.append(&mut socket_addrs.map(|addr| PeerAddr(addr)).collect());
}
}
}
Ok(PeerAddrs { peers })
}
}

impl<'de> Deserialize<'de> for PeerAddrs {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(PeerAddrs { peers: vec![] })
}
}

impl std::hash::Hash for PeerAddr {
/// If loopback address then we care about ip and port.
/// If regular address then we only care about the ip and ignore the port.
Expand Down Expand Up @@ -223,18 +267,18 @@ pub struct P2PConfig {
pub seeding_type: Seeding,

/// The list of seed nodes, if using Seeding as a seed type
pub seeds: Option<Vec<String>>,
pub seeds: Option<PeerAddrs>,

/// Capabilities expose by this node, also conditions which other peers this
/// node will have an affinity toward when connection.
pub capabilities: Capabilities,

pub peers_allow: Option<Vec<String>>,
pub peers_allow: Option<PeerAddrs>,

pub peers_deny: Option<Vec<String>>,
pub peers_deny: Option<PeerAddrs>,

/// The list of preferred peers that we will try to connect to
pub peers_preferred: Option<Vec<String>>,
pub peers_preferred: Option<PeerAddrs>,

pub ban_window: Option<i64>,

Expand Down
11 changes: 2 additions & 9 deletions servers/src/grin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,7 @@ impl Server {
seed::predefined_seeds(vec![])
}
p2p::Seeding::List => match &config.p2p_config.seeds {
Some(seeds) => {
let seed_addrs = seed::resolve_dns_to_addrs(seeds);
seed::predefined_seeds(seed_addrs)
}
Some(seeds) => seed::predefined_seeds(seeds.peers.clone()),
None => {
return Err(Error::Configuration(
"Seeds must be configured for seeding type List".to_owned(),
Expand All @@ -245,11 +242,7 @@ impl Server {
_ => unreachable!(),
};

let preferred_peers = config
.p2p_config
.peers_preferred
.clone()
.map(|p| seed::resolve_dns_to_addrs(&p));
let preferred_peers = config.p2p_config.peers_preferred.clone().map(|p| p.peers);

connect_thread = Some(seed::connect_and_monitor(
p2p_server.clone(),
Expand Down
9 changes: 7 additions & 2 deletions src/bin/cmd/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::core::global;
use crate::p2p::Seeding;
use crate::servers;
use crate::tui::ui;
use grin_p2p::msg::PeerAddrs;
use grin_p2p::PeerAddr;
use grin_util::logger::LogEntry;
use std::sync::mpsc;

Expand Down Expand Up @@ -119,9 +121,12 @@ pub fn server_command(
}

if let Some(seeds) = a.values_of("seed") {
let seed_addrs = seeds.filter_map(|s| s.parse().ok()).collect();
let peer = seeds
.filter_map(|s| s.parse().ok())
.map(|sa| PeerAddr(sa))
.collect();
server_config.p2p_config.seeding_type = Seeding::List;
server_config.p2p_config.seeds = Some(seed_addrs);
server_config.p2p_config.seeds = Some(PeerAddrs { peers });
}
}

Expand Down

0 comments on commit 77703e8

Please sign in to comment.