Switch to stable futures (#1196)

* Switch to stable futures

* Remove from_fn

* Fix secio

* Fix core --lib tests
This commit is contained in:
Pierre Krieger
2019-09-16 11:08:44 +02:00
committed by GitHub
parent 8c119269d6
commit 170d2d268f
105 changed files with 3193 additions and 5594 deletions

View File

@ -25,30 +25,12 @@ mod payload;
use crate::error::NoiseError;
use crate::protocol::{Protocol, PublicKey, KeypairIdentity};
use libp2p_core::identity;
use futures::{future, Async, Future, future::FutureResult, Poll};
use std::{mem, io};
use tokio_io::{io as nio, AsyncWrite, AsyncRead};
use futures::prelude::*;
use std::{mem, io, task::Poll};
use protobuf::Message;
use super::NoiseOutput;
/// A future performing a Noise handshake pattern.
pub struct Handshake<T, C>(
Box<dyn Future<
Item = <Handshake<T, C> as Future>::Item,
Error = <Handshake<T, C> as Future>::Error
> + Send>
);
impl<T, C> Future for Handshake<T, C> {
type Error = NoiseError;
type Item = (RemoteIdentity<C>, NoiseOutput<T>);
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.0.poll()
}
}
/// The identity of the remote established during a handshake.
pub enum RemoteIdentity<C> {
/// The remote provided no identifying information.
@ -131,12 +113,11 @@ where
session: Result<snow::Session, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
) -> Handshake<T, C> {
Handshake(Box::new(
State::new(io, session, identity, identity_x)
.and_then(State::send_identity)
.and_then(State::recv_identity)
.and_then(State::finish)))
) -> Result<(RemoteIdentity<C>, NoiseOutput<T>), NoiseError> {
let mut state = State::new(io, session, identity, identity_x);
send_identity(&mut state).await?;
recv_identity(&mut state).await?;
state.finish.await
}
/// Creates an authenticated Noise handshake for the responder of a
@ -160,12 +141,11 @@ where
session: Result<snow::Session, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange,
) -> Handshake<T, C> {
Handshake(Box::new(
State::new(io, session, identity, identity_x)
.and_then(State::recv_identity)
.and_then(State::send_identity)
.and_then(State::finish)))
) -> Result<(RemoteIdentity<C>, NoiseOutput<T>), NoiseError> {
let mut state = State::new(io, session, identity, identity_x);
recv_identity(&mut state).await?;
send_identity(&mut state).await?;
state.finish.await
}
/// Creates an authenticated Noise handshake for the initiator of a
@ -191,13 +171,12 @@ where
session: Result<snow::Session, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
) -> Handshake<T, C> {
Handshake(Box::new(
State::new(io, session, identity, identity_x)
.and_then(State::send_empty)
.and_then(State::recv_identity)
.and_then(State::send_identity)
.and_then(State::finish)))
) -> Result<(RemoteIdentity<C>, NoiseOutput<T>), NoiseError> {
let mut state = State::new(io, session, identity, identity_x);
send_empty(&mut state).await?;
send_identity(&mut state).await?;
recv_identity(&mut state).await?;
state.finish.await
}
/// Creates an authenticated Noise handshake for the responder of a
@ -218,18 +197,17 @@ where
/// initiator <-{id}- responder
/// initiator -{id}-> responder
/// ```
pub fn rt15_responder(
pub async fn rt15_responder(
io: T,
session: Result<snow::Session, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
) -> Handshake<T, C> {
Handshake(Box::new(
State::new(io, session, identity, identity_x)
.and_then(State::recv_empty)
.and_then(State::send_identity)
.and_then(State::recv_identity)
.and_then(State::finish)))
) -> Result<(RemoteIdentity<C>, NoiseOutput<T>), NoiseError> {
let mut state = State::new(io, session, identity, identity_x);
recv_empty(&mut state).await?;
send_identity(&mut state).await?;
recv_identity(&mut state).await?;
state.finish().await
}
}
@ -251,36 +229,6 @@ struct State<T> {
send_identity: bool,
}
impl<T: io::Read> io::Read for State<T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.io.read(buf)
}
}
impl<T: io::Write> io::Write for State<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.io.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.io.flush()
}
}
impl<T: AsyncRead> AsyncRead for State<T> {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.io.prepare_uninitialized_buffer(buf)
}
fn read_buf<B: bytes::BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
self.io.read_buf(buf)
}
}
impl<T: AsyncWrite> AsyncWrite for State<T> {
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.io.shutdown()
}
}
impl<T> State<T> {
/// Initializes the state for a new Noise handshake, using the given local
/// identity keypair and local DH static public key. The handshake messages
@ -346,30 +294,6 @@ impl<T> State<T>
}
}
impl<T> State<T> {
/// Creates a future that sends a Noise handshake message with an empty payload.
fn send_empty(self) -> SendEmpty<T> {
SendEmpty { state: SendState::Write(self) }
}
/// Creates a future that expects to receive a Noise handshake message with an empty payload.
fn recv_empty(self) -> RecvEmpty<T> {
RecvEmpty { state: RecvState::Read(self) }
}
/// Creates a future that sends a Noise handshake message with a payload identifying
/// the local node to the remote.
fn send_identity(self) -> SendIdentity<T> {
SendIdentity { state: SendIdentityState::Init(self) }
}
/// Creates a future that expects to receive a Noise handshake message with a
/// payload identifying the remote.
fn recv_identity(self) -> RecvIdentity<T> {
RecvIdentity { state: RecvIdentityState::Init(self) }
}
}
//////////////////////////////////////////////////////////////////////////////
// Handshake Message Futures
@ -378,34 +302,12 @@ impl<T> State<T> {
/// A future for receiving a Noise handshake message with an empty payload.
///
/// Obtained from [`Handshake::recv_empty`].
struct RecvEmpty<T> {
state: RecvState<T>
}
enum RecvState<T> {
Read(State<T>),
Done
}
impl<T> Future for RecvEmpty<T>
async fn recv_empty<T>(state: &mut State<T>) -> Result<(), NoiseError>
where
T: AsyncRead
{
type Error = NoiseError;
type Item = State<T>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match mem::replace(&mut self.state, RecvState::Done) {
RecvState::Read(mut st) => {
if !st.io.poll_read(&mut [])?.is_ready() {
self.state = RecvState::Read(st);
return Ok(Async::NotReady)
}
Ok(Async::Ready(st))
},
RecvState::Done => panic!("RecvEmpty polled after completion")
}
}
state.io.read(&mut []).await?;
Ok(())
}
// SendEmpty -----------------------------------------------------------------
@ -413,44 +315,13 @@ where
/// A future for sending a Noise handshake message with an empty payload.
///
/// Obtained from [`Handshake::send_empty`].
struct SendEmpty<T> {
state: SendState<T>
}
enum SendState<T> {
Write(State<T>),
Flush(State<T>),
Done
}
impl<T> Future for SendEmpty<T>
async fn send_empty<T>(state: &mut State<T>) -> Result<(), NoiseError>
where
T: AsyncWrite
{
type Error = NoiseError;
type Item = State<T>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
match mem::replace(&mut self.state, SendState::Done) {
SendState::Write(mut st) => {
if !st.io.poll_write(&mut [])?.is_ready() {
self.state = SendState::Write(st);
return Ok(Async::NotReady)
}
self.state = SendState::Flush(st);
},
SendState::Flush(mut st) => {
if !st.io.poll_flush()?.is_ready() {
self.state = SendState::Flush(st);
return Ok(Async::NotReady)
}
return Ok(Async::Ready(st))
}
SendState::Done => panic!("SendEmpty polled after completion")
}
}
}
state.write(&[]).await?;
state.flush().await?;
Ok(())
}
// RecvIdentity --------------------------------------------------------------
@ -523,71 +394,24 @@ where
// SendIdentity --------------------------------------------------------------
/// A future for sending a Noise handshake message with a payload
/// identifying the local node to the remote.
/// Send a Noise handshake message with a payload identifying the local node to the remote.
///
/// Obtained from [`Handshake::send_identity`].
struct SendIdentity<T> {
state: SendIdentityState<T>
}
enum SendIdentityState<T> {
Init(State<T>),
WritePayloadLen(nio::WriteAll<State<T>, [u8; 2]>, Vec<u8>),
WritePayload(nio::WriteAll<State<T>, Vec<u8>>),
Flush(State<T>),
Done
}
impl<T> Future for SendIdentity<T>
async fn send_identity<T>(state: &mut State<T>) -> Result<(), NoiseError>
where
T: AsyncWrite,
T: AsyncWrite
{
type Error = NoiseError;
type Item = State<T>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
match mem::replace(&mut self.state, SendIdentityState::Done) {
SendIdentityState::Init(st) => {
let mut pb = payload::Identity::new();
if st.send_identity {
pb.set_pubkey(st.identity.public.clone().into_protobuf_encoding());
}
if let Some(ref sig) = st.identity.signature {
pb.set_signature(sig.clone());
}
let pb_bytes = pb.write_to_bytes()?;
let len = (pb_bytes.len() as u16).to_be_bytes();
let write_len = nio::write_all(st, len);
self.state = SendIdentityState::WritePayloadLen(write_len, pb_bytes);
},
SendIdentityState::WritePayloadLen(mut write_len, payload) => {
if let Async::Ready((st, _)) = write_len.poll()? {
self.state = SendIdentityState::WritePayload(nio::write_all(st, payload));
} else {
self.state = SendIdentityState::WritePayloadLen(write_len, payload);
return Ok(Async::NotReady)
}
},
SendIdentityState::WritePayload(mut write_payload) => {
if let Async::Ready((st, _)) = write_payload.poll()? {
self.state = SendIdentityState::Flush(st);
} else {
self.state = SendIdentityState::WritePayload(write_payload);
return Ok(Async::NotReady)
}
},
SendIdentityState::Flush(mut st) => {
if !st.poll_flush()?.is_ready() {
self.state = SendIdentityState::Flush(st);
return Ok(Async::NotReady)
}
return Ok(Async::Ready(st))
},
SendIdentityState::Done => panic!("SendIdentity polled after completion")
}
}
let mut pb = payload::Identity::new();
if st.send_identity {
pb.set_pubkey(st.identity.public.clone().into_protobuf_encoding());
}
if let Some(ref sig) = st.identity.signature {
pb.set_signature(sig.clone());
}
let pb_bytes = pb.write_to_bytes()?;
let len = (pb_bytes.len() as u16).to_be_bytes();
st.write_all(&len).await?;
st.write_all(&pb_bytes).await?;
st.flush().await?;
Ok(())
}

View File

@ -57,11 +57,10 @@ mod protocol;
pub use error::NoiseError;
pub use io::NoiseOutput;
pub use io::handshake::{Handshake, RemoteIdentity, IdentityExchange};
pub use io::handshake::{RemoteIdentity, IdentityExchange};
pub use protocol::{Keypair, AuthenticKeypair, KeypairIdentity, PublicKey, SecretKey};
pub use protocol::{Protocol, ProtocolParams, x25519::X25519, IX, IK, XX};
use futures::{future::{self, FutureResult}, Future};
use libp2p_core::{identity, PeerId, UpgradeInfo, InboundUpgrade, OutboundUpgrade, Negotiated};
use tokio_io::{AsyncRead, AsyncWrite};
use zeroize::Zeroize;