mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-26 00:01:33 +00:00
Switch to stable futures (#1196)
* Switch to stable futures * Remove from_fn * Fix secio * Fix core --lib tests
This commit is contained in:
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user