2019-10-28 18:04:01 +01:00
|
|
|
// Copyright 2019 Parity Technologies (UK) Ltd.
|
2018-05-02 11:50:48 +02:00
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2019-10-28 18:04:01 +01:00
|
|
|
use crate::error::PlainTextError;
|
|
|
|
use crate::handshake::Remote;
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
use bytes::BytesMut;
|
|
|
|
use futures::future::{self, Ready};
|
|
|
|
use futures::prelude::*;
|
|
|
|
use futures::{future::BoxFuture, Sink, Stream};
|
|
|
|
use futures_codec::Framed;
|
|
|
|
use libp2p_core::{
|
|
|
|
identity,
|
|
|
|
InboundUpgrade,
|
|
|
|
OutboundUpgrade,
|
|
|
|
UpgradeInfo,
|
|
|
|
upgrade::Negotiated,
|
|
|
|
PeerId,
|
|
|
|
PublicKey,
|
|
|
|
};
|
|
|
|
use log::debug;
|
|
|
|
use rw_stream_sink::RwStreamSink;
|
|
|
|
use std::{io, iter, pin::Pin, task::{Context, Poll}};
|
|
|
|
use unsigned_varint::codec::UviBytes;
|
|
|
|
use void::Void;
|
|
|
|
|
2019-10-28 18:04:01 +01:00
|
|
|
mod error;
|
|
|
|
mod handshake;
|
2020-01-09 14:12:43 +01:00
|
|
|
mod structs_proto;
|
2018-11-15 17:41:11 +01:00
|
|
|
|
2019-11-06 16:09:15 +01:00
|
|
|
/// `PlainText1Config` is an insecure connection handshake for testing purposes only.
|
|
|
|
///
|
|
|
|
/// > **Note**: Given that `PlainText1Config` has no notion of exchanging peer identity information it is not compatible
|
|
|
|
/// > with the `libp2p_core::transport::upgrade::Builder` pattern. See
|
|
|
|
/// > [`PlainText2Config`](struct.PlainText2Config.html) if compatibility is needed. Even though not compatible with the
|
|
|
|
/// > Builder pattern one can still do an upgrade *manually*:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use libp2p_core::transport::{ Transport, memory::MemoryTransport };
|
|
|
|
/// # use libp2p_plaintext::PlainText1Config;
|
|
|
|
/// #
|
|
|
|
/// MemoryTransport::default()
|
|
|
|
/// .and_then(move |io, endpoint| {
|
|
|
|
/// libp2p_core::upgrade::apply(
|
|
|
|
/// io,
|
|
|
|
/// PlainText1Config{},
|
|
|
|
/// endpoint,
|
|
|
|
/// libp2p_core::transport::upgrade::Version::V1,
|
|
|
|
/// )
|
|
|
|
/// })
|
|
|
|
/// .map(|plaintext, _endpoint| {
|
|
|
|
/// unimplemented!();
|
|
|
|
/// // let peer_id = somehow_derive_peer_id();
|
|
|
|
/// // return (peer_id, plaintext);
|
|
|
|
/// });
|
|
|
|
/// ```
|
2018-05-02 11:50:48 +02:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
2019-10-28 18:04:01 +01:00
|
|
|
pub struct PlainText1Config;
|
2018-05-02 11:50:48 +02:00
|
|
|
|
2019-10-28 18:04:01 +01:00
|
|
|
impl UpgradeInfo for PlainText1Config {
|
2018-12-11 15:13:10 +01:00
|
|
|
type Info = &'static [u8];
|
|
|
|
type InfoIter = iter::Once<Self::Info>;
|
2018-11-15 17:41:11 +01:00
|
|
|
|
2018-12-11 15:13:10 +01:00
|
|
|
fn protocol_info(&self) -> Self::InfoIter {
|
|
|
|
iter::once(b"/plaintext/1.0.0")
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-28 18:04:01 +01:00
|
|
|
impl<C> InboundUpgrade<C> for PlainText1Config {
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = Negotiated<C>;
|
2018-11-15 17:41:11 +01:00
|
|
|
type Error = Void;
|
2019-09-16 11:08:44 +02:00
|
|
|
type Future = Ready<Result<Negotiated<C>, Self::Error>>;
|
2018-05-02 11:50:48 +02:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_inbound(self, i: Negotiated<C>, _: Self::Info) -> Self::Future {
|
2019-09-16 11:08:44 +02:00
|
|
|
future::ready(Ok(i))
|
2018-05-02 11:50:48 +02:00
|
|
|
}
|
2018-11-15 17:41:11 +01:00
|
|
|
}
|
2018-05-02 11:50:48 +02:00
|
|
|
|
2019-10-28 18:04:01 +01:00
|
|
|
impl<C> OutboundUpgrade<C> for PlainText1Config {
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = Negotiated<C>;
|
2018-11-15 17:41:11 +01:00
|
|
|
type Error = Void;
|
2019-09-16 11:08:44 +02:00
|
|
|
type Future = Ready<Result<Negotiated<C>, Self::Error>>;
|
2018-11-15 17:41:11 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_outbound(self, i: Negotiated<C>, _: Self::Info) -> Self::Future {
|
2019-09-16 11:08:44 +02:00
|
|
|
future::ready(Ok(i))
|
2018-05-02 11:50:48 +02:00
|
|
|
}
|
|
|
|
}
|
2018-11-15 17:41:11 +01:00
|
|
|
|
2019-11-06 16:09:15 +01:00
|
|
|
/// `PlainText2Config` is an insecure connection handshake for testing purposes only, implementing
|
|
|
|
/// the libp2p plaintext connection handshake specification.
|
2019-10-28 18:04:01 +01:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct PlainText2Config {
|
|
|
|
pub local_public_key: identity::PublicKey,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UpgradeInfo for PlainText2Config {
|
|
|
|
type Info = &'static [u8];
|
|
|
|
type InfoIter = iter::Once<Self::Info>;
|
|
|
|
|
|
|
|
fn protocol_info(&self) -> Self::InfoIter {
|
|
|
|
iter::once(b"/plaintext/2.0.0")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C> InboundUpgrade<C> for PlainText2Config
|
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
C: AsyncRead + AsyncWrite + Send + Unpin + 'static
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
|
|
|
type Output = (PeerId, PlainTextOutput<Negotiated<C>>);
|
|
|
|
type Error = PlainTextError;
|
2019-11-19 11:15:35 +01:00
|
|
|
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
2019-10-28 18:04:01 +01:00
|
|
|
|
|
|
|
fn upgrade_inbound(self, socket: Negotiated<C>, _: Self::Info) -> Self::Future {
|
2019-11-19 11:15:35 +01:00
|
|
|
Box::pin(self.handshake(socket))
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C> OutboundUpgrade<C> for PlainText2Config
|
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
C: AsyncRead + AsyncWrite + Send + Unpin + 'static
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
|
|
|
type Output = (PeerId, PlainTextOutput<Negotiated<C>>);
|
|
|
|
type Error = PlainTextError;
|
2019-11-19 11:15:35 +01:00
|
|
|
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
2019-10-28 18:04:01 +01:00
|
|
|
|
|
|
|
fn upgrade_outbound(self, socket: Negotiated<C>, _: Self::Info) -> Self::Future {
|
2019-11-19 11:15:35 +01:00
|
|
|
Box::pin(self.handshake(socket))
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PlainText2Config {
|
2019-11-19 11:15:35 +01:00
|
|
|
async fn handshake<T>(self, socket: T) -> Result<(PeerId, PlainTextOutput<T>), PlainTextError>
|
2019-10-28 18:04:01 +01:00
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
T: AsyncRead + AsyncWrite + Send + Unpin + 'static
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
|
|
|
debug!("Starting plaintext upgrade");
|
2019-11-19 11:15:35 +01:00
|
|
|
let (stream_sink, remote) = PlainTextMiddleware::handshake(socket, self).await?;
|
|
|
|
let mapped = stream_sink.map_err(map_err as fn(_) -> _);
|
|
|
|
Ok((
|
|
|
|
remote.peer_id,
|
|
|
|
PlainTextOutput {
|
|
|
|
stream: RwStreamSink::new(mapped),
|
|
|
|
remote_key: remote.public_key,
|
|
|
|
}
|
|
|
|
))
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn map_err(err: io::Error) -> io::Error {
|
|
|
|
debug!("error during plaintext handshake {:?}", err);
|
|
|
|
io::Error::new(io::ErrorKind::InvalidData, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PlainTextMiddleware<S> {
|
2019-11-19 11:15:35 +01:00
|
|
|
inner: Framed<S, UviBytes<BytesMut>>,
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S> PlainTextMiddleware<S>
|
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
S: AsyncRead + AsyncWrite + Send + Unpin,
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
2019-11-19 11:15:35 +01:00
|
|
|
async fn handshake(socket: S, config: PlainText2Config)
|
|
|
|
-> Result<(PlainTextMiddleware<S>, Remote), PlainTextError>
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
2019-11-19 11:15:35 +01:00
|
|
|
let (inner, remote) = handshake::handshake(socket, config).await?;
|
|
|
|
Ok((PlainTextMiddleware { inner }, remote))
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
impl<S> Sink<BytesMut> for PlainTextMiddleware<S>
|
2019-10-28 18:04:01 +01:00
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
2019-11-19 11:15:35 +01:00
|
|
|
type Error = io::Error;
|
|
|
|
|
|
|
|
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Sink::poll_ready(Pin::new(&mut self.inner), cx)
|
|
|
|
}
|
2019-10-28 18:04:01 +01:00
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn start_send(mut self: Pin<&mut Self>, item: BytesMut) -> Result<(), Self::Error> {
|
|
|
|
Sink::start_send(Pin::new(&mut self.inner), item)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Sink::poll_flush(Pin::new(&mut self.inner), cx)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Sink::poll_close(Pin::new(&mut self.inner), cx)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S> Stream for PlainTextMiddleware<S>
|
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
2019-11-19 11:15:35 +01:00
|
|
|
type Item = Result<BytesMut, io::Error>;
|
2019-10-28 18:04:01 +01:00
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
|
|
Stream::poll_next(Pin::new(&mut self.inner), cx)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Output of the plaintext protocol.
|
|
|
|
pub struct PlainTextOutput<S>
|
|
|
|
where
|
2019-11-19 11:15:35 +01:00
|
|
|
S: AsyncRead + AsyncWrite + Unpin,
|
2019-10-28 18:04:01 +01:00
|
|
|
{
|
|
|
|
/// The plaintext stream.
|
2019-11-19 11:15:35 +01:00
|
|
|
pub stream: RwStreamSink<futures::stream::MapErr<PlainTextMiddleware<S>, fn(io::Error) -> io::Error>>,
|
2019-10-28 18:04:01 +01:00
|
|
|
/// The public key of the remote.
|
|
|
|
pub remote_key: PublicKey,
|
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
impl<S: AsyncRead + AsyncWrite + Unpin> AsyncRead for PlainTextOutput<S> {
|
|
|
|
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut [u8])
|
|
|
|
-> Poll<Result<usize, io::Error>>
|
|
|
|
{
|
|
|
|
AsyncRead::poll_read(Pin::new(&mut self.stream), cx, buf)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for PlainTextOutput<S> {
|
|
|
|
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context, buf: &[u8])
|
|
|
|
-> Poll<Result<usize, io::Error>>
|
|
|
|
{
|
|
|
|
AsyncWrite::poll_write(Pin::new(&mut self.stream), cx, buf)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context)
|
|
|
|
-> Poll<Result<(), io::Error>>
|
|
|
|
{
|
|
|
|
AsyncWrite::poll_flush(Pin::new(&mut self.stream), cx)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
|
2019-11-19 11:15:35 +01:00
|
|
|
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context)
|
|
|
|
-> Poll<Result<(), io::Error>>
|
|
|
|
{
|
|
|
|
AsyncWrite::poll_close(Pin::new(&mut self.stream), cx)
|
2019-10-28 18:04:01 +01:00
|
|
|
}
|
|
|
|
}
|