mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-04-25 11:02:12 +00:00
Various fixes and improvements (#166)
This commit is contained in:
parent
342a9f69d3
commit
2445d9e9ee
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use futures::{stream, Future, IntoFuture, Stream};
|
use futures::{future, stream, Future, IntoFuture, Stream};
|
||||||
use libp2p_peerstore::{PeerAccess, PeerId, Peerstore};
|
use libp2p_peerstore::{PeerAccess, PeerId, Peerstore};
|
||||||
use libp2p_swarm::{MuxedTransport, Transport};
|
use libp2p_swarm::{MuxedTransport, Transport};
|
||||||
use multiaddr::{AddrComponent, Multiaddr};
|
use multiaddr::{AddrComponent, Multiaddr};
|
||||||
@ -91,37 +91,62 @@ where
|
|||||||
let listener = listener.map(move |connec| {
|
let listener = listener.map(move |connec| {
|
||||||
let peerstore = peerstore.clone();
|
let peerstore = peerstore.clone();
|
||||||
let identify_upgrade = identify_upgrade.clone();
|
let identify_upgrade = identify_upgrade.clone();
|
||||||
let fut = connec
|
let fut = connec.and_then(move |(connec, client_addr)| {
|
||||||
.and_then(move |(connec, client_addr)| {
|
for peer_id in peerstore.peers() {
|
||||||
// Dial the address that connected to us and try upgrade with the
|
let peer = match peerstore.peer(&peer_id) {
|
||||||
// identify protocol.
|
Some(p) => p,
|
||||||
identify_upgrade
|
None => continue,
|
||||||
.clone()
|
|
||||||
.dial(client_addr.clone())
|
|
||||||
.map_err(|_| {
|
|
||||||
IoError::new(IoErrorKind::Other, "couldn't dial back incoming node")
|
|
||||||
})
|
|
||||||
.map(move |id| (id, connec))
|
|
||||||
})
|
|
||||||
.and_then(move |(dial, connec)| dial.map(move |dial| (dial, connec)))
|
|
||||||
.and_then(move |((identify, original_addr), connec)| {
|
|
||||||
// Compute the "real" address of the node (in the form `/p2p/...`) and add
|
|
||||||
// it to the peerstore.
|
|
||||||
let real_addr = match identify {
|
|
||||||
IdentifyOutput::RemoteInfo { info, .. } => process_identify_info(
|
|
||||||
&info,
|
|
||||||
&*peerstore.clone(),
|
|
||||||
original_addr,
|
|
||||||
addr_ttl,
|
|
||||||
)?,
|
|
||||||
_ => unreachable!(
|
|
||||||
"the identify protocol guarantees that we receive \
|
|
||||||
remote information when we dial a node"
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((connec, real_addr))
|
if peer.addrs().any(|addr| addr == client_addr) {
|
||||||
});
|
debug!(target: "libp2p-identify", "Incoming substream from {} \
|
||||||
|
identified as {:?}", client_addr,
|
||||||
|
peer_id);
|
||||||
|
let ret = (connec, AddrComponent::P2P(peer_id.into_bytes()).into());
|
||||||
|
return future::Either::A(future::ok(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(target: "libp2p-identify", "Incoming connection from {}, dialing back \
|
||||||
|
in order to identify", client_addr);
|
||||||
|
// Dial the address that connected to us and try upgrade with the
|
||||||
|
// identify protocol.
|
||||||
|
let future = identify_upgrade
|
||||||
|
.clone()
|
||||||
|
.dial(client_addr.clone())
|
||||||
|
.map_err(move |_| {
|
||||||
|
IoError::new(IoErrorKind::Other, "couldn't dial back incoming node")
|
||||||
|
})
|
||||||
|
.map(move |id| (id, connec))
|
||||||
|
.into_future()
|
||||||
|
.and_then(move |(dial, connec)| dial.map(move |dial| (dial, connec)))
|
||||||
|
.and_then(move |((identify, original_addr), connec)| {
|
||||||
|
// Compute the "real" address of the node (in the form `/p2p/...`) and
|
||||||
|
// add it to the peerstore.
|
||||||
|
let real_addr = match identify {
|
||||||
|
IdentifyOutput::RemoteInfo { info, .. } => process_identify_info(
|
||||||
|
&info,
|
||||||
|
&*peerstore.clone(),
|
||||||
|
original_addr.clone(),
|
||||||
|
addr_ttl,
|
||||||
|
)?,
|
||||||
|
_ => unreachable!(
|
||||||
|
"the identify protocol guarantees that we receive \
|
||||||
|
remote information when we dial a node"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!(target: "libp2p-identify", "Identified {} as {}", original_addr,
|
||||||
|
real_addr);
|
||||||
|
Ok((connec, real_addr))
|
||||||
|
})
|
||||||
|
.map_err(move |err| {
|
||||||
|
warn!(target: "libp2p-identify", "Failed to identify incoming {}",
|
||||||
|
client_addr);
|
||||||
|
err
|
||||||
|
});
|
||||||
|
future::Either::B(future)
|
||||||
|
});
|
||||||
|
|
||||||
Box::new(fut) as Box<Future<Item = _, Error = _>>
|
Box::new(fut) as Box<Future<Item = _, Error = _>>
|
||||||
});
|
});
|
||||||
@ -143,17 +168,45 @@ where
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter();
|
.into_iter();
|
||||||
|
|
||||||
|
trace!(target: "libp2p-identify", "Try dialing peer ID {:?} ; {} multiaddrs \
|
||||||
|
loaded from peerstore", peer_id, addrs.len());
|
||||||
|
|
||||||
let transport = self.transport;
|
let transport = self.transport;
|
||||||
let future = stream::iter_ok(addrs)
|
let future = stream::iter_ok(addrs)
|
||||||
// Try to dial each address through the transport.
|
// Try to dial each address through the transport.
|
||||||
.filter_map(move |addr| transport.clone().dial(addr).ok())
|
.filter_map(move |addr| {
|
||||||
|
match transport.clone().dial(addr) {
|
||||||
|
Ok(dial) => Some(dial),
|
||||||
|
Err((_, addr)) => {
|
||||||
|
warn!(target: "libp2p-identify", "Address {} not supported by \
|
||||||
|
underlying transport", addr);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
.and_then(move |dial| dial)
|
.and_then(move |dial| dial)
|
||||||
// Pick the first non-failing dial result.
|
// Pick the first non-failing dial result by filtering out the ones which fail.
|
||||||
.then(|res| Ok(res))
|
.then(|res| Ok(res))
|
||||||
.filter_map(|res| res.ok())
|
.filter_map(|res| res.ok())
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.and_then(|(val, _)| val.ok_or(IoErrorKind::InvalidData.into())) // TODO: wrong error
|
.and_then(move |(val, _)| {
|
||||||
|
match val {
|
||||||
|
Some((connec, inner_addr)) => {
|
||||||
|
debug!(target: "libp2p-identify", "Successfully dialed peer {:?} \
|
||||||
|
through {}", peer_id,
|
||||||
|
inner_addr);
|
||||||
|
Ok((connec, inner_addr))
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
debug!(target: "libp2p-identify", "All multiaddresses failed when \
|
||||||
|
dialing peer {:?}", peer_id);
|
||||||
|
// TODO: wrong error
|
||||||
|
Err(IoErrorKind::InvalidData.into())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Replace the multiaddress with the one of the form `/p2p/...` or `/ipfs/...`.
|
||||||
.map(move |(socket, _inner_client_addr)| (socket, addr));
|
.map(move |(socket, _inner_client_addr)| (socket, addr));
|
||||||
|
|
||||||
Ok(Box::new(future) as Box<_>)
|
Ok(Box::new(future) as Box<_>)
|
||||||
@ -165,6 +218,8 @@ where
|
|||||||
let transport = self.transport;
|
let transport = self.transport;
|
||||||
let identify_upgrade = transport.clone().with_upgrade(IdentifyProtocolConfig);
|
let identify_upgrade = transport.clone().with_upgrade(IdentifyProtocolConfig);
|
||||||
|
|
||||||
|
trace!(target: "libp2p-identify", "Pass through when dialing {}", addr);
|
||||||
|
|
||||||
// We dial a first time the node and upgrade it to identify.
|
// We dial a first time the node and upgrade it to identify.
|
||||||
let dial = match identify_upgrade.dial(addr) {
|
let dial = match identify_upgrade.dial(addr) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
@ -233,34 +288,51 @@ where
|
|||||||
let addr_ttl = self.addr_ttl;
|
let addr_ttl = self.addr_ttl;
|
||||||
|
|
||||||
let future = self.transport.next_incoming().map(move |incoming| {
|
let future = self.transport.next_incoming().map(move |incoming| {
|
||||||
let future = incoming
|
let peerstore = peerstore.clone();
|
||||||
.and_then(move |(connec, client_addr)| {
|
let future = incoming.and_then(move |(connec, client_addr)| {
|
||||||
// On an incoming connection, dial back the node and upgrade to the identify
|
for peer_id in peerstore.peers() {
|
||||||
// protocol.
|
let peer = match peerstore.peer(&peer_id) {
|
||||||
identify_upgrade
|
Some(p) => p,
|
||||||
.clone()
|
None => continue,
|
||||||
.dial(client_addr.clone())
|
|
||||||
.map_err(|_| {
|
|
||||||
IoError::new(IoErrorKind::Other, "couldn't dial back incoming node")
|
|
||||||
})
|
|
||||||
.map(move |id| (id, connec))
|
|
||||||
})
|
|
||||||
.and_then(move |(dial, connec)| dial.map(move |dial| (dial, connec)))
|
|
||||||
.and_then(move |(identify, connec)| {
|
|
||||||
// Add the info to the peerstore and compute the "real" address of the node (in
|
|
||||||
// the form `/p2p/...`).
|
|
||||||
let real_addr = match identify {
|
|
||||||
(IdentifyOutput::RemoteInfo { info, .. }, old_addr) => {
|
|
||||||
process_identify_info(&info, &*peerstore, old_addr, addr_ttl)?
|
|
||||||
}
|
|
||||||
_ => unreachable!(
|
|
||||||
"the identify protocol guarantees that we receive remote \
|
|
||||||
information when we dial a node"
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((connec, real_addr))
|
if peer.addrs().any(|addr| addr == client_addr) {
|
||||||
});
|
debug!(target: "libp2p-identify", "Incoming substream from {} \
|
||||||
|
identified as {:?}", client_addr,
|
||||||
|
peer_id);
|
||||||
|
let ret = (connec, AddrComponent::P2P(peer_id.into_bytes()).into());
|
||||||
|
return future::Either::A(future::ok(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On an incoming connection, dial back the node and upgrade to the identify
|
||||||
|
// protocol.
|
||||||
|
let future = identify_upgrade
|
||||||
|
.clone()
|
||||||
|
.dial(client_addr.clone())
|
||||||
|
.map_err(|_| {
|
||||||
|
IoError::new(IoErrorKind::Other, "couldn't dial back incoming node")
|
||||||
|
})
|
||||||
|
.into_future()
|
||||||
|
.and_then(move |dial| dial)
|
||||||
|
.map(move |dial| (dial, connec))
|
||||||
|
.and_then(move |(identify, connec)| {
|
||||||
|
// Add the info to the peerstore and compute the "real" address of the
|
||||||
|
// node (in the form `/p2p/...`).
|
||||||
|
let real_addr = match identify {
|
||||||
|
(IdentifyOutput::RemoteInfo { info, .. }, old_addr) => {
|
||||||
|
process_identify_info(&info, &*peerstore, old_addr, addr_ttl)?
|
||||||
|
}
|
||||||
|
_ => unreachable!(
|
||||||
|
"the identify protocol guarantees that we receive remote \
|
||||||
|
information when we dial a node"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((connec, real_addr))
|
||||||
|
});
|
||||||
|
future::Either::B(future)
|
||||||
|
});
|
||||||
|
|
||||||
Box::new(future) as Box<Future<Item = _, Error = _>>
|
Box::new(future) as Box<Future<Item = _, Error = _>>
|
||||||
});
|
});
|
||||||
|
@ -15,6 +15,7 @@ libp2p-identify = { path = "../identify" }
|
|||||||
libp2p-peerstore = { path = "../peerstore" }
|
libp2p-peerstore = { path = "../peerstore" }
|
||||||
libp2p-ping = { path = "../ping" }
|
libp2p-ping = { path = "../ping" }
|
||||||
libp2p-swarm = { path = "../swarm" }
|
libp2p-swarm = { path = "../swarm" }
|
||||||
|
log = "0.4"
|
||||||
multiaddr = "0.3"
|
multiaddr = "0.3"
|
||||||
parking_lot = "0.5.1"
|
parking_lot = "0.5.1"
|
||||||
protobuf = "1.4.2"
|
protobuf = "1.4.2"
|
||||||
|
@ -27,12 +27,13 @@ use fnv::FnvHashMap;
|
|||||||
use futures::{self, future, Future};
|
use futures::{self, future, Future};
|
||||||
use futures::sync::oneshot;
|
use futures::sync::oneshot;
|
||||||
use kad_server::{KadServerInterface, KademliaServerConfig, KademliaServerController};
|
use kad_server::{KadServerInterface, KademliaServerConfig, KademliaServerController};
|
||||||
use kbucket::{KBucketsTable, UpdateOutcome};
|
use kbucket::{KBucketsPeerId, KBucketsTable, UpdateOutcome};
|
||||||
use libp2p_peerstore::{PeerAccess, PeerId, Peerstore};
|
use libp2p_peerstore::{PeerAccess, PeerId, Peerstore};
|
||||||
use libp2p_swarm::{Endpoint, MuxedTransport, SwarmController};
|
use libp2p_swarm::{Endpoint, MuxedTransport, SwarmController};
|
||||||
use libp2p_swarm::ConnectionUpgrade;
|
use libp2p_swarm::ConnectionUpgrade;
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use protocol::ConnectionType;
|
||||||
use query;
|
use query;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -364,6 +365,15 @@ where
|
|||||||
self.kbuckets.my_id()
|
self.kbuckets.my_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn peer_info(&self, peer_id: &PeerId) -> (Vec<Multiaddr>, ConnectionType) {
|
||||||
|
let addrs = self.peer_store
|
||||||
|
.peer(peer_id)
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|p| p.addrs())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
(addrs, ConnectionType::Connected) // ConnectionType meh :-/
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn kbuckets_update(&self, peer: &PeerId) {
|
fn kbuckets_update(&self, peer: &PeerId) {
|
||||||
// TODO: is this the right place for this check?
|
// TODO: is this the right place for this check?
|
||||||
@ -382,7 +392,19 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn kbuckets_find_closest(&self, addr: &PeerId) -> Vec<PeerId> {
|
fn kbuckets_find_closest(&self, addr: &PeerId) -> Vec<PeerId> {
|
||||||
self.kbuckets.find_closest(addr).collect()
|
let mut intermediate: Vec<_> = self.kbuckets.find_closest(addr).collect();
|
||||||
|
let my_id = self.kbuckets.my_id().clone();
|
||||||
|
if let Some(pos) = intermediate
|
||||||
|
.iter()
|
||||||
|
.position(|e| e.distance_with(&addr) >= my_id.distance_with(&addr))
|
||||||
|
{
|
||||||
|
if intermediate[pos] != my_id {
|
||||||
|
intermediate.insert(pos, my_id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
intermediate.push(my_id);
|
||||||
|
}
|
||||||
|
intermediate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,10 @@ pub trait KadServerInterface: Clone {
|
|||||||
/// Returns the peer ID of the local node.
|
/// Returns the peer ID of the local node.
|
||||||
fn local_id(&self) -> &PeerId;
|
fn local_id(&self) -> &PeerId;
|
||||||
|
|
||||||
|
/// Returns known information about the peer. Not atomic/thread-safe in the sense that
|
||||||
|
/// information can change immediately after being returned and before they are processed.
|
||||||
|
fn peer_info(&self, _: &PeerId) -> (Vec<Multiaddr>, protocol::ConnectionType);
|
||||||
|
|
||||||
/// Updates an entry in the K-Buckets. Called whenever that peer sends us a message.
|
/// Updates an entry in the K-Buckets. Called whenever that peer sends us a message.
|
||||||
fn kbuckets_update(&self, peer: &PeerId);
|
fn kbuckets_update(&self, peer: &PeerId);
|
||||||
|
|
||||||
@ -408,19 +412,34 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Builds a `KadMsg` that handles a `FIND_NODE` request received from the remote.
|
// Builds a `KadMsg` that handles a `FIND_NODE` request received from the remote.
|
||||||
fn handle_find_node_req<I>(interface: &I, _requested_key: &[u8]) -> KadMsg
|
fn handle_find_node_req<I>(interface: &I, requested_key: &[u8]) -> KadMsg
|
||||||
where
|
where
|
||||||
I: ?Sized + KadServerInterface,
|
I: ?Sized + KadServerInterface,
|
||||||
{
|
{
|
||||||
KadMsg::FindNodeRes {
|
let peer_id = match PeerId::from_bytes(requested_key.to_vec()) {
|
||||||
closer_peers: vec![
|
// TODO: suboptimal
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(_) => {
|
||||||
|
return KadMsg::FindNodeRes {
|
||||||
|
closer_peers: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let closer_peers = interface
|
||||||
|
.kbuckets_find_closest(&peer_id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|peer| {
|
||||||
|
let (multiaddrs, connection_ty) = interface.peer_info(&peer);
|
||||||
protocol::Peer {
|
protocol::Peer {
|
||||||
node_id: interface.local_id().clone(),
|
node_id: peer,
|
||||||
multiaddrs: vec![],
|
multiaddrs: multiaddrs,
|
||||||
connection_ty: protocol::ConnectionType::Connected,
|
connection_ty: connection_ty,
|
||||||
},
|
}
|
||||||
], // TODO: fill the multiaddresses from the peer store
|
})
|
||||||
}
|
.collect();
|
||||||
|
|
||||||
|
KadMsg::FindNodeRes { closer_peers }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds a `KadMsg` that handles a `FIND_VALUE` request received from the remote.
|
// Builds a `KadMsg` that handles a `FIND_VALUE` request received from the remote.
|
||||||
|
@ -72,6 +72,8 @@ extern crate libp2p_identify;
|
|||||||
extern crate libp2p_peerstore;
|
extern crate libp2p_peerstore;
|
||||||
extern crate libp2p_ping;
|
extern crate libp2p_ping;
|
||||||
extern crate libp2p_swarm;
|
extern crate libp2p_swarm;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
extern crate multiaddr;
|
extern crate multiaddr;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate protobuf;
|
extern crate protobuf;
|
||||||
@ -82,7 +84,7 @@ extern crate tokio_timer;
|
|||||||
extern crate varint;
|
extern crate varint;
|
||||||
|
|
||||||
pub use self::high_level::{KademliaConfig, KademliaController, KademliaControllerPrototype};
|
pub use self::high_level::{KademliaConfig, KademliaController, KademliaControllerPrototype};
|
||||||
pub use self::high_level::KademliaUpgrade;
|
pub use self::high_level::{KademliaProcessingFuture, KademliaUpgrade};
|
||||||
|
|
||||||
mod high_level;
|
mod high_level;
|
||||||
mod kad_server;
|
mod kad_server;
|
||||||
|
@ -142,6 +142,9 @@ fn query<'a, I>(
|
|||||||
where
|
where
|
||||||
I: QueryInterface + 'a,
|
I: QueryInterface + 'a,
|
||||||
{
|
{
|
||||||
|
debug!(target: "libp2p-kad", "Start query for {:?} ; num results = {}", searched_key,
|
||||||
|
num_results);
|
||||||
|
|
||||||
// State of the current iterative process.
|
// State of the current iterative process.
|
||||||
struct State<'a> {
|
struct State<'a> {
|
||||||
// If true, we are still in the first step of the algorithm where we try to find the
|
// If true, we are still in the first step of the algorithm where we try to find the
|
||||||
@ -206,6 +209,10 @@ where
|
|||||||
to_contact
|
to_contact
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!(target: "libp2p-kad", "New query round ; {} queries in progress ; contacting \
|
||||||
|
{} new peers", state.current_attempts_fut.len(),
|
||||||
|
to_contact.len());
|
||||||
|
|
||||||
// For each node in `to_contact`, start an RPC query and a corresponding entry in the two
|
// For each node in `to_contact`, start an RPC query and a corresponding entry in the two
|
||||||
// `state.current_attempts_*` fields.
|
// `state.current_attempts_*` fields.
|
||||||
for peer in to_contact {
|
for peer in to_contact {
|
||||||
@ -229,7 +236,7 @@ where
|
|||||||
// values back when inside the loop.
|
// values back when inside the loop.
|
||||||
let current_attempts_fut = mem::replace(&mut state.current_attempts_fut, Vec::new());
|
let current_attempts_fut = mem::replace(&mut state.current_attempts_fut, Vec::new());
|
||||||
if current_attempts_fut.is_empty() {
|
if current_attempts_fut.is_empty() {
|
||||||
// If `current_attempts_fut` is empty, then `select_all` would panic. It attempts
|
// If `current_attempts_fut` is empty, then `select_all` would panic. It happens
|
||||||
// when we have no additional node to query.
|
// when we have no additional node to query.
|
||||||
let future = future::ok(future::Loop::Break(state));
|
let future = future::ok(future::Loop::Break(state));
|
||||||
return future::Either::A(future);
|
return future::Either::A(future);
|
||||||
@ -254,18 +261,23 @@ where
|
|||||||
// `message` contains the reason why the current future was woken up.
|
// `message` contains the reason why the current future was woken up.
|
||||||
let closer_peers = match message {
|
let closer_peers = match message {
|
||||||
Ok(msg) => msg,
|
Ok(msg) => msg,
|
||||||
Err(_) => {
|
Err(err) => {
|
||||||
|
trace!(target: "libp2p-kad", "RPC query failed for {:?}: {:?}", remote_id, err);
|
||||||
state.failed_to_contact.insert(remote_id);
|
state.failed_to_contact.insert(remote_id);
|
||||||
return Ok(future::Loop::Continue(state));
|
return Ok(future::Loop::Continue(state));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update `state.result` with the fact that we received a valid message from a node.
|
// Inserting the node we received a response from into `state.result`.
|
||||||
|
// The code is non-trivial because `state.result` is ordered by distance and is limited
|
||||||
|
// by `num_results` elements.
|
||||||
if let Some(insert_pos) = state.result.iter().position(|e| {
|
if let Some(insert_pos) = state.result.iter().position(|e| {
|
||||||
e.distance_with(&searched_key) >= remote_id.distance_with(&searched_key)
|
e.distance_with(&searched_key) >= remote_id.distance_with(&searched_key)
|
||||||
}) {
|
}) {
|
||||||
if state.result[insert_pos] != remote_id {
|
if state.result[insert_pos] != remote_id {
|
||||||
state.result.pop();
|
if state.result.len() >= num_results {
|
||||||
|
state.result.pop();
|
||||||
|
}
|
||||||
state.result.insert(insert_pos, remote_id);
|
state.result.insert(insert_pos, remote_id);
|
||||||
}
|
}
|
||||||
} else if state.result.len() < num_results {
|
} else if state.result.len() < num_results {
|
||||||
@ -282,6 +294,8 @@ where
|
|||||||
// the remote.
|
// the remote.
|
||||||
{
|
{
|
||||||
let valid_multiaddrs = peer.multiaddrs.drain(..);
|
let valid_multiaddrs = peer.multiaddrs.drain(..);
|
||||||
|
trace!(target: "libp2p-kad", "Adding multiaddresses to {:?}: {:?}",
|
||||||
|
peer.node_id, valid_multiaddrs);
|
||||||
query_interface2.peer_add_addrs(
|
query_interface2.peer_add_addrs(
|
||||||
&peer.node_id,
|
&peer.node_id,
|
||||||
valid_multiaddrs,
|
valid_multiaddrs,
|
||||||
@ -317,10 +331,10 @@ where
|
|||||||
{
|
{
|
||||||
// Check that our `Vec::with_capacity` is correct.
|
// Check that our `Vec::with_capacity` is correct.
|
||||||
debug_assert_eq!(state.result.capacity(), num_results);
|
debug_assert_eq!(state.result.capacity(), num_results);
|
||||||
|
|
||||||
Ok(future::Loop::Break(state))
|
Ok(future::Loop::Break(state))
|
||||||
} else {
|
} else {
|
||||||
if !local_nearest_node_updated {
|
if !local_nearest_node_updated {
|
||||||
|
trace!(target: "libp2p-kad", "Loop didn't update closer node ; jumping to step 2");
|
||||||
state.looking_for_closer = false;
|
state.looking_for_closer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,6 +345,10 @@ where
|
|||||||
future::Either::B(future)
|
future::Either::B(future)
|
||||||
});
|
});
|
||||||
|
|
||||||
let stream = stream.map(|state| state.result);
|
let stream = stream.map(|state| {
|
||||||
|
debug!(target: "libp2p-kad", "Query finished with {} results", state.result.len());
|
||||||
|
state.result
|
||||||
|
});
|
||||||
|
|
||||||
Box::new(stream) as Box<_>
|
Box::new(stream) as Box<_>
|
||||||
}
|
}
|
||||||
|
@ -156,14 +156,12 @@ where
|
|||||||
.get(&addr)
|
.get(&addr)
|
||||||
.map(|c| c.clone())
|
.map(|c| c.clone())
|
||||||
{
|
{
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: Reusing multiplexed connection to {} \
|
debug!(target: "libp2p-swarm", "Using existing multiplexed connection to {}", addr);
|
||||||
instead of dialing", addr);
|
|
||||||
let future = connec.outbound().map(|s| (s, addr));
|
let future = connec.outbound().map(|s| (s, addr));
|
||||||
return Ok(Box::new(future) as Box<_>);
|
return Ok(Box::new(future) as Box<_>);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: No existing connection to {} ; dialing",
|
debug!(target: "libp2p-swarm", "No existing connection to {} ; dialing", addr);
|
||||||
addr);
|
|
||||||
|
|
||||||
// TODO: handle if we're already in the middle in dialing that same node?
|
// TODO: handle if we're already in the middle in dialing that same node?
|
||||||
// TODO: try dialing again if the existing connection has dropped
|
// TODO: try dialing again if the existing connection has dropped
|
||||||
@ -171,6 +169,8 @@ where
|
|||||||
let dial = match self.inner.dial(addr) {
|
let dial = match self.inner.dial(addr) {
|
||||||
Ok(l) => l,
|
Ok(l) => l,
|
||||||
Err((inner, addr)) => {
|
Err((inner, addr)) => {
|
||||||
|
warn!(target: "libp2p-swarm", "Failed to dial {} because the underlying \
|
||||||
|
transport doesn't support this address", addr);
|
||||||
return Err((
|
return Err((
|
||||||
ConnectionReuse {
|
ConnectionReuse {
|
||||||
inner: inner,
|
inner: inner,
|
||||||
@ -259,14 +259,13 @@ where
|
|||||||
}
|
}
|
||||||
Ok(Async::NotReady) => {}
|
Ok(Async::NotReady) => {}
|
||||||
Ok(Async::Ready(None)) => {
|
Ok(Async::Ready(None)) => {
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: listener has been closed");
|
debug!(target: "libp2p-swarm", "listener has been closed");
|
||||||
if self.connections.is_empty() && self.current_upgrades.is_empty() {
|
if self.connections.is_empty() && self.current_upgrades.is_empty() {
|
||||||
return Ok(Async::Ready(None));
|
return Ok(Async::Ready(None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: error while polling \
|
debug!(target: "libp2p-swarm", "error while polling listener: {:?}", err);
|
||||||
listener: {:?}", err);
|
|
||||||
if self.connections.is_empty() && self.current_upgrades.is_empty() {
|
if self.connections.is_empty() && self.current_upgrades.is_empty() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
@ -295,8 +294,8 @@ where
|
|||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// Insert the rest of the pending upgrades, but not the current one.
|
// Insert the rest of the pending upgrades, but not the current one.
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: error while upgrading \
|
debug!(target: "libp2p-swarm", "error while upgrading listener connection: \
|
||||||
listener connection: {:?}", err);
|
{:?}", err);
|
||||||
return Ok(Async::Ready(Some(future::err(err))));
|
return Ok(Async::Ready(Some(future::err(err))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,7 +318,7 @@ where
|
|||||||
self.connections.push((muxer, next_incoming, client_addr));
|
self.connections.push((muxer, next_incoming, client_addr));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!(target: "libp2p-swarm", "ConnectionReuse: error while upgrading the \
|
debug!(target: "libp2p-swarm", "error while upgrading the \
|
||||||
multiplexed incoming connection: {:?}", err);
|
multiplexed incoming connection: {:?}", err);
|
||||||
// Insert the rest of the pending connections, but not the current one.
|
// Insert the rest of the pending connections, but not the current one.
|
||||||
return Ok(Async::Ready(Some(future::err(err))));
|
return Ok(Async::Ready(Some(future::err(err))));
|
||||||
@ -374,6 +373,7 @@ where
|
|||||||
Ok(Async::Ready(value)) => {
|
Ok(Async::Ready(value)) => {
|
||||||
// A substream is ready ; push back the muxer for the next time this function
|
// A substream is ready ; push back the muxer for the next time this function
|
||||||
// is called, then return.
|
// is called, then return.
|
||||||
|
debug!(target: "libp2p-swarm", "New incoming substream");
|
||||||
let next = muxer.clone().inbound();
|
let next = muxer.clone().inbound();
|
||||||
lock.next_incoming.push((muxer, next, addr.clone()));
|
lock.next_incoming.push((muxer, next, addr.clone()));
|
||||||
return Ok(Async::Ready(future::ok((value, addr))));
|
return Ok(Async::Ready(future::ok((value, addr))));
|
||||||
|
@ -222,7 +222,7 @@ pub mod muxing;
|
|||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
pub use self::connection_reuse::ConnectionReuse;
|
pub use self::connection_reuse::ConnectionReuse;
|
||||||
pub use self::multiaddr::Multiaddr;
|
pub use self::multiaddr::{AddrComponent, Multiaddr};
|
||||||
pub use self::muxing::StreamMuxer;
|
pub use self::muxing::StreamMuxer;
|
||||||
pub use self::swarm::{swarm, SwarmController, SwarmFuture};
|
pub use self::swarm::{swarm, SwarmController, SwarmFuture};
|
||||||
pub use self::transport::{ConnectionUpgrade, OrUpgrade, PlainTextConfig, Transport, UpgradedNode};
|
pub use self::transport::{ConnectionUpgrade, OrUpgrade, PlainTextConfig, Transport, UpgradedNode};
|
||||||
|
@ -255,13 +255,12 @@ where
|
|||||||
|
|
||||||
match self.next_incoming.poll() {
|
match self.next_incoming.poll() {
|
||||||
Ok(Async::Ready(connec)) => {
|
Ok(Async::Ready(connec)) => {
|
||||||
trace!(target: "libp2p-swarm", "Swarm received new multiplexed \
|
debug!(target: "libp2p-swarm", "Swarm received new multiplexed \
|
||||||
incoming connection");
|
incoming connection");
|
||||||
self.next_incoming = self.upgraded.clone().next_incoming();
|
self.next_incoming = self.upgraded.clone().next_incoming();
|
||||||
self.listeners_upgrade.push(connec);
|
self.listeners_upgrade.push(connec);
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => {}
|
Ok(Async::NotReady) => {}
|
||||||
// TODO: may not be the best idea because we're killing the whole server
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!(target: "libp2p-swarm", "Error in multiplexed incoming \
|
debug!(target: "libp2p-swarm", "Error in multiplexed incoming \
|
||||||
connection: {:?}", err);
|
connection: {:?}", err);
|
||||||
@ -323,7 +322,7 @@ where
|
|||||||
match upgrade.poll() {
|
match upgrade.poll() {
|
||||||
Ok(Async::Ready((output, client_addr))) => {
|
Ok(Async::Ready((output, client_addr))) => {
|
||||||
debug!(
|
debug!(
|
||||||
"Successfully upgraded listened connection with {}",
|
"Successfully upgraded incoming connection with {}",
|
||||||
client_addr
|
client_addr
|
||||||
);
|
);
|
||||||
self.to_process.push(future::Either::A(
|
self.to_process.push(future::Either::A(
|
||||||
|
@ -927,6 +927,7 @@ where
|
|||||||
.and_then(move |(connection, client_addr)| {
|
.and_then(move |(connection, client_addr)| {
|
||||||
let iter = upgrade.protocol_names()
|
let iter = upgrade.protocol_names()
|
||||||
.map(|(name, id)| (name, <Bytes as PartialEq>::eq, id));
|
.map(|(name, id)| (name, <Bytes as PartialEq>::eq, id));
|
||||||
|
debug!(target: "libp2p-swarm", "Starting protocol negotiation (dialer)");
|
||||||
let negotiated = multistream_select::dialer_select_proto(connection, iter)
|
let negotiated = multistream_select::dialer_select_proto(connection, iter)
|
||||||
.map_err(|err| IoError::new(IoErrorKind::Other, err));
|
.map_err(|err| IoError::new(IoErrorKind::Other, err));
|
||||||
negotiated.map(|(upgrade_id, conn)| (upgrade_id, conn, upgrade, client_addr))
|
negotiated.map(|(upgrade_id, conn)| (upgrade_id, conn, upgrade, client_addr))
|
||||||
@ -949,6 +950,14 @@ where
|
|||||||
debug!(target: "libp2p-swarm", "Trying to apply negotiated protocol with {}",
|
debug!(target: "libp2p-swarm", "Trying to apply negotiated protocol with {}",
|
||||||
client_addr);
|
client_addr);
|
||||||
f.map(|v| (v, client_addr))
|
f.map(|v| (v, client_addr))
|
||||||
|
})
|
||||||
|
.then(|val| {
|
||||||
|
match val {
|
||||||
|
Ok(_) => debug!(target: "libp2p-swarm", "Successfully applied negotiated \
|
||||||
|
protocol"),
|
||||||
|
Err(_) => debug!(target: "libp2p-swarm", "Failed to apply negotiated protocol"),
|
||||||
|
}
|
||||||
|
val
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Box::new(future))
|
Ok(Box::new(future))
|
||||||
@ -982,6 +991,7 @@ where
|
|||||||
let iter = upgrade
|
let iter = upgrade
|
||||||
.protocol_names()
|
.protocol_names()
|
||||||
.map::<_, fn(_) -> _>(|(name, id)| (name, <Bytes as PartialEq>::eq, id));
|
.map::<_, fn(_) -> _>(|(name, id)| (name, <Bytes as PartialEq>::eq, id));
|
||||||
|
debug!(target: "libp2p-swarm", "Starting protocol negotiation (incoming)");
|
||||||
let negotiated = multistream_select::listener_select_proto(connection, iter)
|
let negotiated = multistream_select::listener_select_proto(connection, iter)
|
||||||
.map_err(|err| IoError::new(IoErrorKind::Other, err));
|
.map_err(|err| IoError::new(IoErrorKind::Other, err));
|
||||||
negotiated.map(move |(upgrade_id, conn)| (upgrade_id, conn, upgrade, addr))
|
negotiated.map(move |(upgrade_id, conn)| (upgrade_id, conn, upgrade, addr))
|
||||||
@ -1000,10 +1010,19 @@ where
|
|||||||
negotiated
|
negotiated
|
||||||
})
|
})
|
||||||
.and_then(move |(upgrade_id, connection, upgrade, addr)| {
|
.and_then(move |(upgrade_id, connection, upgrade, addr)| {
|
||||||
let upg = upgrade.upgrade(connection, upgrade_id, Endpoint::Dialer, &addr);
|
let upg = upgrade.upgrade(connection, upgrade_id, Endpoint::Listener, &addr);
|
||||||
debug!(target: "libp2p-swarm", "Trying to apply negotiated protocol with {}",
|
debug!(target: "libp2p-swarm", "Trying to apply negotiated protocol with {}",
|
||||||
addr);
|
addr);
|
||||||
upg.map(|u| (u, addr))
|
upg.map(|u| (u, addr))
|
||||||
|
})
|
||||||
|
.then(|val| {
|
||||||
|
match val {
|
||||||
|
Ok(_) => debug!(target: "libp2p-swarm", "Successfully applied negotiated \
|
||||||
|
protocol"),
|
||||||
|
Err(_) => debug!(target: "libp2p-swarm", "Failed to apply negotiated \
|
||||||
|
protocol"),
|
||||||
|
}
|
||||||
|
val
|
||||||
});
|
});
|
||||||
|
|
||||||
Box::new(future) as Box<Future<Item = _, Error = _>>
|
Box::new(future) as Box<Future<Item = _, Error = _>>
|
||||||
@ -1064,6 +1083,7 @@ where
|
|||||||
let iter = upgrade.protocol_names()
|
let iter = upgrade.protocol_names()
|
||||||
.map::<_, fn(_) -> _>(|(n, t)| (n, <Bytes as PartialEq>::eq, t));
|
.map::<_, fn(_) -> _>(|(n, t)| (n, <Bytes as PartialEq>::eq, t));
|
||||||
let remote_addr2 = remote_addr.clone();
|
let remote_addr2 = remote_addr.clone();
|
||||||
|
debug!(target: "libp2p-swarm", "Starting protocol negotiation (listener)");
|
||||||
multistream_select::listener_select_proto(connection, iter)
|
multistream_select::listener_select_proto(connection, iter)
|
||||||
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
||||||
.then(move |negotiated| {
|
.then(move |negotiated| {
|
||||||
|
@ -150,14 +150,21 @@ where
|
|||||||
let is_wss = match inner_addr.pop() {
|
let is_wss = match inner_addr.pop() {
|
||||||
Some(AddrComponent::WS) => false,
|
Some(AddrComponent::WS) => false,
|
||||||
Some(AddrComponent::WSS) => true,
|
Some(AddrComponent::WSS) => true,
|
||||||
_ => return Err((self, original_addr)),
|
_ => {
|
||||||
|
trace!(target: "libp2p-websocket", "Ignoring dial attempt for {} because it is \
|
||||||
|
not a websocket multiaddr", original_addr);
|
||||||
|
return Err((self, original_addr));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(target: "libp2p-websocket", "Dialing {} through inner transport", inner_addr);
|
debug!(target: "libp2p-websocket", "Dialing {} through inner transport", inner_addr);
|
||||||
|
|
||||||
let inner_dial = match self.transport.dial(inner_addr) {
|
let inner_dial = match self.transport.dial(inner_addr) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err((transport, _)) => {
|
Err((transport, old_addr)) => {
|
||||||
|
warn!(target: "libp2p-websocket", "Failed to dial {} because {} is not supported \
|
||||||
|
by the underlying transport", original_addr,
|
||||||
|
old_addr);
|
||||||
return Err((
|
return Err((
|
||||||
WsConfig {
|
WsConfig {
|
||||||
transport: transport,
|
transport: transport,
|
||||||
@ -201,7 +208,15 @@ where
|
|||||||
let read_write = RwStreamSink::new(framed_data);
|
let read_write = RwStreamSink::new(framed_data);
|
||||||
Box::new(read_write) as Box<AsyncStream>
|
Box::new(read_write) as Box<AsyncStream>
|
||||||
})
|
})
|
||||||
.map(|c| (c, client_addr))
|
.map(move |c| {
|
||||||
|
let mut actual_addr = client_addr;
|
||||||
|
if is_wss {
|
||||||
|
actual_addr.append(AddrComponent::WSS);
|
||||||
|
} else {
|
||||||
|
actual_addr.append(AddrComponent::WS);
|
||||||
|
};
|
||||||
|
(c, actual_addr)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Box::new(dial) as Box<_>)
|
Ok(Box::new(dial) as Box<_>)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user