Skip connecting PeerWithSelf by checking ip address (#2253)

* skip the connecting to self
This commit is contained in:
Gary Yu 2018-12-31 07:15:58 +08:00 committed by GitHub
parent 9c98b798ee
commit ea7eea3f84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 8 deletions

View file

@ -14,7 +14,7 @@
use crate::util::RwLock; use crate::util::RwLock;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::net::{SocketAddr, TcpStream}; use std::net::{Shutdown, SocketAddr, TcpStream};
use std::sync::Arc; use std::sync::Arc;
use chrono::prelude::*; use chrono::prelude::*;
@ -29,6 +29,7 @@ use crate::peer::Peer;
use crate::types::{Capabilities, Direction, Error, P2PConfig, PeerInfo, PeerLiveInfo}; use crate::types::{Capabilities, Direction, Error, P2PConfig, PeerInfo, PeerLiveInfo};
const NONCES_CAP: usize = 100; const NONCES_CAP: usize = 100;
const ADDRS_CAP: usize = 10;
/// Handles the handshake negotiation when two peers connect and decides on /// Handles the handshake negotiation when two peers connect and decides on
/// protocol. /// protocol.
@ -36,6 +37,8 @@ pub struct Handshake {
/// Ring buffer of nonces sent to detect self connections without requiring /// Ring buffer of nonces sent to detect self connections without requiring
/// a node id. /// a node id.
nonces: Arc<RwLock<VecDeque<u64>>>, nonces: Arc<RwLock<VecDeque<u64>>>,
/// Ring buffer of self addr(s) collected from PeerWithSelf detection (by nonce).
pub addrs: Arc<RwLock<VecDeque<SocketAddr>>>,
/// The genesis block header of the chain seen by this node. /// The genesis block header of the chain seen by this node.
/// We only want to connect to other nodes seeing the same chain (forks are /// We only want to connect to other nodes seeing the same chain (forks are
/// ok). /// ok).
@ -48,6 +51,7 @@ impl Handshake {
pub fn new(genesis: Hash, config: P2PConfig) -> Handshake { pub fn new(genesis: Hash, config: P2PConfig) -> Handshake {
Handshake { Handshake {
nonces: Arc::new(RwLock::new(VecDeque::with_capacity(NONCES_CAP))), nonces: Arc::new(RwLock::new(VecDeque::with_capacity(NONCES_CAP))),
addrs: Arc::new(RwLock::new(VecDeque::with_capacity(ADDRS_CAP))),
genesis, genesis,
config, config,
} }
@ -145,7 +149,17 @@ impl Handshake {
} else { } else {
// check the nonce to see if we are trying to connect to ourselves // check the nonce to see if we are trying to connect to ourselves
let nonces = self.nonces.read(); let nonces = self.nonces.read();
let addr = extract_ip(&hand.sender_addr.0, &conn);
if nonces.contains(&hand.nonce) { if nonces.contains(&hand.nonce) {
// save ip addresses of ourselves
let mut addrs = self.addrs.write();
addrs.push_back(addr);
if addrs.len() >= ADDRS_CAP {
addrs.pop_front();
}
if let Err(e) = conn.shutdown(Shutdown::Both) {
debug!("Error shutting down conn: {:?}", e);
}
return Err(Error::PeerWithSelf); return Err(Error::PeerWithSelf);
} }
} }

View file

@ -22,6 +22,7 @@ use crate::lmdb;
use crate::core::core; use crate::core::core;
use crate::core::core::hash::Hash; use crate::core::core::hash::Hash;
use crate::core::global;
use crate::core::pow::Difficulty; use crate::core::pow::Difficulty;
use crate::handshake::Handshake; use crate::handshake::Handshake;
use crate::peer::Peer; use crate::peer::Peer;
@ -108,13 +109,16 @@ impl Server {
return Err(Error::ConnectionClose); return Err(Error::ConnectionClose);
} }
// check ip and port to see if we are trying to connect to ourselves if global::is_production_mode() {
// todo: this can't detect all cases of PeerWithSelf, for example config.host is '0.0.0.0' let hs = self.handshake.clone();
// let addrs = hs.addrs.read();
if self.config.port == addr.port() if addrs.contains(&addr) {
&& (addr.ip().is_loopback() || addr.ip() == self.config.host) debug!(
{ "connect: ignore the connecting to PeerWithSelf, addr: {}",
return Err(Error::PeerWithSelf); addr
);
return Err(Error::PeerWithSelf);
}
} }
if let Some(p) = self.peers.get_connected_peer(addr) { if let Some(p) = self.peers.get_connected_peer(addr) {