Prevent duplicate incoming connections (#4180)

This commit is contained in:
Arkadiy Paronyan 2017-01-17 16:02:29 +01:00 committed by GitHub
parent e95d66832c
commit 8852a05301

View File

@ -683,8 +683,7 @@ impl Host {
#[cfg_attr(feature="dev", allow(single_match))] #[cfg_attr(feature="dev", allow(single_match))]
fn connect_peer(&self, id: &NodeId, io: &IoContext<NetworkIoMessage>) { fn connect_peer(&self, id: &NodeId, io: &IoContext<NetworkIoMessage>) {
if self.have_session(id) if self.have_session(id) {
{
trace!(target: "network", "Aborted connect. Node already connected."); trace!(target: "network", "Aborted connect. Node already connected.");
return; return;
} }
@ -788,7 +787,9 @@ impl Host {
let mut packet_data: Vec<(ProtocolId, PacketId, Vec<u8>)> = Vec::new(); let mut packet_data: Vec<(ProtocolId, PacketId, Vec<u8>)> = Vec::new();
let mut kill = false; let mut kill = false;
let session = { self.sessions.read().get(token).cloned() }; let session = { self.sessions.read().get(token).cloned() };
let mut ready_id = None;
if let Some(session) = session.clone() { if let Some(session) = session.clone() {
{
let mut s = session.lock(); let mut s = session.lock();
loop { loop {
let session_result = s.readable(io, &self.info.read()); let session_result = s.readable(io, &self.info.read());
@ -820,21 +821,24 @@ impl Host {
(info.config.min_peers as usize, max_peers as usize, info.config.non_reserved_mode == NonReservedPeerMode::Deny) (info.config.min_peers as usize, max_peers as usize, info.config.non_reserved_mode == NonReservedPeerMode::Deny)
}; };
let id = s.id().expect("Ready session always has id").clone();
// Check for the session limit. session_counts accounts for the new session. // Check for the session limit. session_counts accounts for the new session.
if reserved_only || if reserved_only ||
(s.info.originated && session_count > min_peers) || (s.info.originated && session_count > min_peers) ||
(!s.info.originated && session_count > max_peers) { (!s.info.originated && session_count > max_peers) {
// only proceed if the connecting peer is reserved. // only proceed if the connecting peer is reserved.
if !self.reserved_nodes.read().contains(s.id().expect("Ready session always has id")) { if !self.reserved_nodes.read().contains(&id) {
s.disconnect(io, DisconnectReason::TooManyPeers); s.disconnect(io, DisconnectReason::TooManyPeers);
return; return;
} }
} }
ready_id = Some(id);
// Add it to the node table // Add it to the node table
if !s.info.originated { if !s.info.originated {
if let Ok(address) = s.remote_addr() { if let Ok(address) = s.remote_addr() {
let entry = NodeEntry { id: s.id().expect("Ready session always has id").clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; let entry = NodeEntry { id: id, endpoint: NodeEndpoint { address: address, udp_port: address.port() } };
self.nodes.write().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); self.nodes.write().add_node(Node::new(entry.id.clone(), entry.endpoint.clone()));
let mut discovery = self.discovery.lock(); let mut discovery = self.discovery.lock();
if let Some(ref mut discovery) = *discovery { if let Some(ref mut discovery) = *discovery {
@ -863,27 +867,39 @@ impl Host {
} }
} }
} }
if kill { if kill {
self.kill_connection(token, io, true); self.kill_connection(token, io, true);
} }
let handlers = self.handlers.read(); let handlers = self.handlers.read();
if !ready_data.is_empty() {
let duplicate = self.sessions.read().iter().any(|e| {
let session = e.lock();
session.token() != token && session.info.id == ready_id
});
if duplicate {
trace!(target: "network", "Rejected duplicate connection: {}", token);
session.lock().disconnect(io, DisconnectReason::DuplicatePeer);
return;
}
for p in ready_data { for p in ready_data {
self.stats.inc_sessions(); self.stats.inc_sessions();
let reserved = self.reserved_nodes.read(); let reserved = self.reserved_nodes.read();
if let Some(h) = handlers.get(&p).clone() { if let Some(h) = handlers.get(&p).clone() {
h.connected(&NetworkContext::new(io, p, session.clone(), self.sessions.clone(), &reserved), &token); h.connected(&NetworkContext::new(io, p, Some(session.clone()), self.sessions.clone(), &reserved), &token);
// accumulate pending packets. // accumulate pending packets.
if let Some(session) = session.as_ref() {
let mut session = session.lock(); let mut session = session.lock();
packet_data.extend(session.mark_connected(p)); packet_data.extend(session.mark_connected(p));
} }
} }
} }
for (p, packet_id, data) in packet_data { for (p, packet_id, data) in packet_data {
let reserved = self.reserved_nodes.read(); let reserved = self.reserved_nodes.read();
if let Some(h) = handlers.get(&p).clone() { if let Some(h) = handlers.get(&p).clone() {
h.read(&NetworkContext::new(io, p, session.clone(), self.sessions.clone(), &reserved), &token, packet_id, &data[1..]); h.read(&NetworkContext::new(io, p, Some(session.clone()), self.sessions.clone(), &reserved), &token, packet_id, &data[1..]);
}
} }
} }
} }