Merge pull request #95 from tomaka/identify-correct-report

Correctly report the address of the dialer in the identify protocol
This commit is contained in:
Pierre Krieger 2018-01-15 13:08:32 +01:00 committed by GitHub
commit 047e33023d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 51 deletions

View File

@ -49,17 +49,17 @@ mod structs_proto;
/// Prototype for an upgrade to the identity protocol.
#[derive(Debug, Clone)]
pub struct IdentifyProtocol {
pub information: IdentifyInfo,
}
impl IdentifyProtocol {
/// Builds a new `IdentifyProtocol`.
#[inline]
pub fn new(information: IdentifyInfo) -> IdentifyProtocol {
IdentifyProtocol {
information
}
}
/// Our public key to report to the remote.
pub public_key: Vec<u8>,
/// Version of the "global" protocol, eg. `ipfs/1.0.0` or `polkadot/1.0.0`.
pub protocol_version: String,
/// Name and version of the client. Can be thought as similar to the `User-Agent` header
/// of HTTP.
pub agent_version: String,
/// Addresses that we are listening on.
pub listen_addrs: Vec<Multiaddr>,
/// Protocols supported by us.
pub protocols: Vec<String>,
}
/// Information sent from the listener to the dialer.
@ -67,13 +67,14 @@ impl IdentifyProtocol {
pub struct IdentifyInfo {
/// Public key of the node.
pub public_key: Vec<u8>,
/// Version of the "global" protocol, eg. `ipfs/1.0.0`.
/// Version of the "global" protocol, eg. `ipfs/1.0.0` or `polkadot/1.0.0`.
pub protocol_version: String,
/// Name and version. Can be thought as similar to the `User-Agent` header of HTTP.
/// Name and version of the client. Can be thought as similar to the `User-Agent` header
/// of HTTP.
pub agent_version: String,
/// Addresses that are listened on.
/// Addresses that the remote is listening on.
pub listen_addrs: Vec<Multiaddr>,
/// Address that the server uses to communicate with the dialer.
/// Our own address as reported by the remote.
pub observed_addr: Multiaddr,
/// Protocols supported by the remote.
pub protocols: Vec<String>,
@ -92,7 +93,7 @@ impl<C> ConnectionUpgrade<C> for IdentifyProtocol
iter::once((Bytes::from("/ipfs/id/1.0.0"), ()))
}
fn upgrade(self, socket: C, _: (), ty: Endpoint) -> Self::Future {
fn upgrade(self, socket: C, _: (), ty: Endpoint, remote_addr: &Multiaddr) -> Self::Future {
// TODO: use jack's varint library instead
let socket = length_delimited::Builder::new().length_field_length(1).new_framed(socket);
@ -111,20 +112,18 @@ impl<C> ConnectionUpgrade<C> for IdentifyProtocol
}
Endpoint::Listener => {
let info = self.information;
let listen_addrs = info.listen_addrs
let listen_addrs = self.listen_addrs
.into_iter()
.map(|addr| addr.to_string().into_bytes())
.collect();
let mut message = structs_proto::Identify::new();
message.set_agentVersion(info.agent_version);
message.set_protocolVersion(info.protocol_version);
message.set_publicKey(info.public_key);
message.set_agentVersion(self.agent_version);
message.set_protocolVersion(self.protocol_version);
message.set_publicKey(self.public_key);
message.set_listenAddrs(listen_addrs);
message.set_observedAddr(info.observed_addr.to_string().into_bytes());
message.set_protocols(RepeatedField::from_vec(info.protocols));
message.set_observedAddr(remote_addr.to_string().into_bytes());
message.set_protocols(RepeatedField::from_vec(self.protocols));
let bytes = message.write_to_bytes()
.expect("writing protobuf failed ; should never happen");
@ -189,7 +188,6 @@ mod tests {
use self::libp2p_tcp_transport::TcpConfig;
use self::tokio_core::reactor::Core;
use IdentifyInfo;
use IdentifyProtocol;
use futures::{IntoFuture, Future, Stream};
use libp2p_swarm::Transport;
@ -198,14 +196,13 @@ mod tests {
fn basic() {
let mut core = Core::new().unwrap();
let tcp = TcpConfig::new(core.handle());
let with_proto = tcp.with_upgrade(IdentifyProtocol::new(IdentifyInfo {
let with_proto = tcp.with_upgrade(IdentifyProtocol {
public_key: vec![1, 2, 3, 4],
protocol_version: "ipfs/1.0.0".to_owned(),
agent_version: "agent/version".to_owned(),
listen_addrs: vec!["/ip4/5.6.7.8/tcp/12345".parse().unwrap()],
observed_addr: "/ip4/1.2.3.4/tcp/9876".parse().unwrap(),
protocols: vec!["ping".to_owned(), "kad".to_owned()],
}));
});
let (server, addr) = with_proto.clone()
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())

View File

@ -90,6 +90,7 @@ use bytes::{Bytes, BytesMut, BufMut};
use futures::{Future, Sink, Stream};
use futures::future::{FutureResult, IntoFuture, loop_fn, Loop};
use futures::sync::{mpsc, oneshot};
use libp2p_swarm::Multiaddr;
use libp2p_swarm::transport::{ConnectionUpgrade, Endpoint};
use parking_lot::Mutex;
use rand::Rand;
@ -124,7 +125,7 @@ impl<C> ConnectionUpgrade<C> for Ping
type Future = FutureResult<Self::Output, IoError>;
#[inline]
fn upgrade(self, socket: C, _: Self::UpgradeIdentifier, _: Endpoint)
fn upgrade(self, socket: C, _: Self::UpgradeIdentifier, _: Endpoint, _: &Multiaddr)
-> Self::Future
{
// # How does it work?
@ -277,15 +278,19 @@ mod tests {
let server = listener.incoming()
.into_future()
.map_err(|(e, _)| e.into())
.and_then(|(c, _)| Ping.upgrade(c.unwrap().0, (),
Endpoint::Listener))
.and_then(|(c, _)| {
Ping.upgrade(c.unwrap().0, (), Endpoint::Listener,
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap())
})
.and_then(|(mut pinger, service)| {
pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!())
});
let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into())
.and_then(|c| Ping.upgrade(c, (), Endpoint::Dialer))
.and_then(|c| {
Ping.upgrade(c, (), Endpoint::Dialer, &"/ip4/127.0.0.1/tcp/10000".parse().unwrap())
})
.and_then(|(mut pinger, service)| {
pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!())
});
@ -304,13 +309,16 @@ mod tests {
let server = listener.incoming()
.into_future()
.map_err(|(e, _)| e.into())
.and_then(|(c, _)| Ping.upgrade(c.unwrap().0, (),
Endpoint::Listener))
.and_then(|(c, _)| {
Ping.upgrade(c.unwrap().0, (), Endpoint::Listener,
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap())
})
.and_then(|(_, service)| service.map_err(|_| panic!()));
let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into())
.and_then(|c| Ping.upgrade(c, (), Endpoint::Dialer))
.and_then(|c| Ping.upgrade(c, (), Endpoint::Dialer,
&"/ip4/127.0.0.1/tcp/1000".parse().unwrap()))
.and_then(|(mut pinger, service)| {
let pings = (0 .. 20).map(move |_| {
pinger.ping().map_err(|_| ())

View File

@ -95,6 +95,7 @@ pub use self::error::SecioError;
use bytes::{Bytes, BytesMut};
use futures::{Future, Poll, StartSend, Sink, Stream};
use futures::stream::MapErr as StreamMapErr;
use libp2p_swarm::Multiaddr;
use ring::signature::RSAKeyPair;
use rw_stream_sink::RwStreamSink;
use std::error::Error;
@ -197,7 +198,7 @@ impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConfig
}
#[inline]
fn upgrade(self, incoming: S, _: (), _: libp2p_swarm::Endpoint) -> Self::Future {
fn upgrade(self, incoming: S, _: (), _: libp2p_swarm::Endpoint, _: &Multiaddr) -> Self::Future {
let fut = SecioMiddleware::handshake(
incoming,
self.key,

View File

@ -297,7 +297,7 @@ where
type Future = FromErr<O::Future, IoError>;
#[inline]
fn upgrade(self, socket: C, _: (), _: Endpoint) -> Self::Future {
fn upgrade(self, socket: C, _: (), _: Endpoint, _: &Multiaddr) -> Self::Future {
let upgrade = &self.upgrade;
upgrade(socket).into_future().from_err()
}
@ -522,7 +522,8 @@ pub trait ConnectionUpgrade<C: AsyncRead + AsyncWrite> {
///
/// Because performing the upgrade may not be instantaneous (eg. it may require a handshake),
/// this function returns a future instead of the direct output.
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint) -> Self::Future;
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint,
remote_addr: &Multiaddr) -> Self::Future;
}
/// Type of connection for the upgrade.
@ -552,7 +553,7 @@ impl<C> ConnectionUpgrade<C> for DeniedConnectionUpgrade
}
#[inline]
fn upgrade(self, _: C, _: Self::UpgradeIdentifier, _: Endpoint) -> Self::Future {
fn upgrade(self, _: C, _: Self::UpgradeIdentifier, _: Endpoint, _: &Multiaddr) -> Self::Future {
unreachable!("the denied connection upgrade always fails to negotiate")
}
}
@ -597,13 +598,15 @@ where
type Future = EitherConnUpgrFuture<A::Future, B::Future>;
#[inline]
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint) -> Self::Future {
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint,
remote_addr: &Multiaddr) -> Self::Future
{
match id {
EitherUpgradeIdentifier::First(id) => {
EitherConnUpgrFuture::First(self.0.upgrade(socket, id, ty))
EitherConnUpgrFuture::First(self.0.upgrade(socket, id, ty, remote_addr))
}
EitherUpgradeIdentifier::Second(id) => {
EitherConnUpgrFuture::Second(self.1.upgrade(socket, id, ty))
EitherConnUpgrFuture::Second(self.1.upgrade(socket, id, ty, remote_addr))
}
}
}
@ -709,7 +712,7 @@ where
type NamesIter = iter::Once<(Bytes, ())>;
#[inline]
fn upgrade(self, i: C, _: (), _: Endpoint) -> Self::Future {
fn upgrade(self, i: C, _: (), _: Endpoint, _: &Multiaddr) -> Self::Future {
future::ok(i)
}
@ -800,7 +803,7 @@ where
) -> Result<Box<Future<Item = C::Output, Error = IoError> + 'a>, (Self, Multiaddr)> {
let upgrade = self.upgrade;
let dialed_fut = match self.transports.dial(addr) {
let dialed_fut = match self.transports.dial(addr.clone()) {
Ok(f) => f.into_future(),
Err((trans, addr)) => {
let builder = UpgradedNode {
@ -821,8 +824,8 @@ where
.map_err(|err| IoError::new(IoErrorKind::Other, err));
negotiated.map(|(upgrade_id, conn)| (upgrade_id, conn, upgrade))
})
.and_then(|(upgrade_id, connection, upgrade)| {
upgrade.upgrade(connection, upgrade_id, Endpoint::Dialer)
.and_then(move |(upgrade_id, connection, upgrade)| {
upgrade.upgrade(connection, upgrade_id, Endpoint::Dialer, &addr)
});
Ok(Box::new(future))
@ -850,7 +853,7 @@ where
negotiated.map(|(upgrade_id, conn)| (upgrade_id, conn, upgrade, addr))
})
.and_then(|(upgrade_id, connection, upgrade, addr)| {
upgrade.upgrade(connection, upgrade_id, Endpoint::Dialer)
upgrade.upgrade(connection, upgrade_id, Endpoint::Dialer, &addr)
.map(|u| (u, addr))
});
@ -895,6 +898,7 @@ where
let stream = listening_stream
.map(move |(connection, client_addr)| {
let upgrade = upgrade.clone();
let remote_addr = client_addr.clone();
let connection = connection
// Try to negotiate the protocol
.and_then(move |connection| {
@ -902,8 +906,9 @@ where
.map::<_, fn(_) -> _>(|(n, t)| (n, <Bytes as PartialEq>::eq, t));
multistream_select::listener_select_proto(connection, iter)
.map_err(|err| IoError::new(IoErrorKind::Other, err))
.and_then(|(upgrade_id, connection)| {
upgrade.upgrade(connection, upgrade_id, Endpoint::Listener)
.and_then(move |(upgrade_id, connection)| {
upgrade.upgrade(connection, upgrade_id, Endpoint::Listener,
&remote_addr)
})
.into_future()
});

View File

@ -42,7 +42,7 @@ use futures::{Async, Future, Poll};
use futures::future::{self, FutureResult};
use header::MultiplexHeader;
use swarm::muxing::StreamMuxer;
use swarm::{ConnectionUpgrade, Endpoint};
use swarm::{ConnectionUpgrade, Endpoint, Multiaddr};
use futures_mutex::Mutex;
use read::{read_stream, MultiplexReadState};
use shared::{buf_from_slice, ByteBuf, MultiplexShared};
@ -348,7 +348,7 @@ where
type NamesIter = iter::Once<(Bytes, ())>;
#[inline]
fn upgrade(self, i: C, _: (), end: Endpoint) -> Self::Future {
fn upgrade(self, i: C, _: (), end: Endpoint, _: &Multiaddr) -> Self::Future {
future::ok(Multiplex::new(i, end))
}