Split ConnectionUpgrade. (#642)

Introduce `InboundUpgrade` and `OutboundUpgrade`.
This commit is contained in:
Toralf Wittner
2018-11-15 17:41:11 +01:00
committed by Pierre Krieger
parent 466385a58a
commit 2e549884ef
52 changed files with 2010 additions and 1658 deletions

View File

@ -19,8 +19,9 @@
// DEALINGS IN THE SOFTWARE.
use bytes::{BufMut, Bytes, BytesMut};
use futures::{prelude::*, future::FutureResult, future::IntoFuture};
use libp2p_core::{ConnectionUpgrade, Endpoint};
use futures::{prelude::*, future::{self, FutureResult}, try_ready};
use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use log::debug;
use rand::{distributions::Standard, prelude::*, rngs::EntropyRng};
use std::collections::VecDeque;
use std::io::Error as IoError;
@ -42,71 +43,53 @@ impl<TUserData> Default for Ping<TUserData> {
}
}
/// Output of a `Ping` upgrade.
pub enum PingOutput<TSocket, TUserData> {
/// We are on the dialing side.
Pinger(PingDialer<TSocket, TUserData>),
/// We are on the listening side.
Ponger(PingListener<TSocket>),
}
impl<TUserData> UpgradeInfo for Ping<TUserData> {
type UpgradeId = ();
type NamesIter = iter::Once<(Bytes, Self::UpgradeId)>;
impl<TSocket, TUserData> ConnectionUpgrade<TSocket> for Ping<TUserData>
where
TSocket: AsyncRead + AsyncWrite,
{
type NamesIter = iter::Once<(Bytes, Self::UpgradeIdentifier)>;
type UpgradeIdentifier = ();
#[inline]
fn protocol_names(&self) -> Self::NamesIter {
iter::once(("/ipfs/ping/1.0.0".into(), ()))
}
}
type Output = PingOutput<TSocket, TUserData>;
type Future = FutureResult<Self::Output, IoError>;
impl<TSocket, TUserData> InboundUpgrade<TSocket> for Ping<TUserData>
where
TSocket: AsyncRead + AsyncWrite,
{
type Output = PingListener<TSocket>;
type Error = IoError;
type Future = FutureResult<Self::Output, Self::Error>;
#[inline]
fn upgrade(
self,
socket: TSocket,
_: Self::UpgradeIdentifier,
endpoint: Endpoint,
) -> Self::Future {
let out = match endpoint {
Endpoint::Dialer => upgrade_as_dialer(socket),
Endpoint::Listener => upgrade_as_listener(socket),
fn upgrade_inbound(self, socket: TSocket, _: Self::UpgradeId) -> Self::Future {
let listener = PingListener {
inner: Framed::new(socket, Codec),
state: PingListenerState::Listening,
};
Ok(out).into_future()
future::ok(listener)
}
}
/// Upgrades a connection from the dialer side.
fn upgrade_as_dialer<TSocket, TUserData>(socket: TSocket) -> PingOutput<TSocket, TUserData>
where TSocket: AsyncRead + AsyncWrite,
impl<TSocket, TUserData> OutboundUpgrade<TSocket> for Ping<TUserData>
where
TSocket: AsyncRead + AsyncWrite,
{
let dialer = PingDialer {
inner: Framed::new(socket, Codec),
need_writer_flush: false,
needs_close: false,
sent_pings: VecDeque::with_capacity(4),
rng: EntropyRng::default(),
pings_to_send: VecDeque::with_capacity(4),
};
type Output = PingDialer<TSocket, TUserData>;
type Error = IoError;
type Future = FutureResult<Self::Output, Self::Error>;
PingOutput::Pinger(dialer)
}
/// Upgrades a connection from the listener side.
fn upgrade_as_listener<TSocket, TUserData>(socket: TSocket) -> PingOutput<TSocket, TUserData>
where TSocket: AsyncRead + AsyncWrite,
{
let listener = PingListener {
inner: Framed::new(socket, Codec),
state: PingListenerState::Listening,
};
PingOutput::Ponger(listener)
#[inline]
fn upgrade_outbound(self, socket: TSocket, _: Self::UpgradeId) -> Self::Future {
let dialer = PingDialer {
inner: Framed::new(socket, Codec),
need_writer_flush: false,
needs_close: false,
sent_pings: VecDeque::with_capacity(4),
rng: EntropyRng::default(),
pings_to_send: VecDeque::with_capacity(4),
};
future::ok(dialer)
}
}
/// Sends pings and receives the pongs.
@ -342,9 +325,9 @@ mod tests {
use self::tokio_tcp::TcpListener;
use self::tokio_tcp::TcpStream;
use super::{Ping, PingOutput};
use super::Ping;
use futures::{Future, Stream};
use libp2p_core::{ConnectionUpgrade, Endpoint};
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade};
// TODO: rewrite tests with the MemoryTransport
@ -358,32 +341,18 @@ mod tests {
.into_future()
.map_err(|(e, _)| e.into())
.and_then(|(c, _)| {
Ping::<()>::default().upgrade(
c.unwrap(),
(),
Endpoint::Listener,
)
Ping::<()>::default().upgrade_inbound(c.unwrap(), ())
})
.and_then(|out| match out {
PingOutput::Ponger(service) => service,
_ => unreachable!(),
});
.flatten();
let client = TcpStream::connect(&listener_addr)
.map_err(|e| e.into())
.and_then(|c| {
Ping::<()>::default().upgrade(
c,
(),
Endpoint::Dialer,
)
Ping::<()>::default().upgrade_outbound(c, ())
})
.and_then(|out| match out {
PingOutput::Pinger(mut pinger) => {
pinger.ping(());
pinger.into_future().map(|_| ()).map_err(|_| panic!())
},
_ => unreachable!(),
.and_then(|mut pinger| {
pinger.ping(());
pinger.into_future().map(|_| ()).map_err(|_| panic!())
})
.map(|_| ());
@ -402,39 +371,23 @@ mod tests {
.into_future()
.map_err(|(e, _)| e.into())
.and_then(|(c, _)| {
Ping::<u32>::default().upgrade(
c.unwrap(),
(),
Endpoint::Listener,
)
Ping::<u32>::default().upgrade_inbound(c.unwrap(), ())
})
.and_then(|out| match out {
PingOutput::Ponger(service) => service,
_ => unreachable!(),
});
.flatten();
let client = TcpStream::connect(&listener_addr)
.map_err(|e| e.into())
.and_then(|c| {
Ping::<u32>::default().upgrade(
c,
(),
Endpoint::Dialer,
)
Ping::<u32>::default().upgrade_outbound(c, ())
})
.and_then(|out| match out {
PingOutput::Pinger(mut pinger) => {
for n in 0..20 {
pinger.ping(n);
}
pinger
.take(20)
.collect()
.map(|val| { assert_eq!(val, (0..20).collect::<Vec<_>>()); })
.map_err(|_| panic!())
},
_ => unreachable!(),
.and_then(|mut pinger| {
for n in 0..20 {
pinger.ping(n);
}
pinger.take(20)
.collect()
.map(|val| { assert_eq!(val, (0..20).collect::<Vec<_>>()); })
.map_err(|_| panic!())
});
let mut runtime = tokio::runtime::Runtime::new().unwrap();