From 0035f38c3c383b72f2ef9d220e3d5478f1b6938b Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 12 Apr 2021 16:01:09 +0100 Subject: [PATCH] rework stream to (for now) use two different streams with distinct types for reading + writing --- src/lib.rs | 11 ++--------- src/stream.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6cecaf6..950f8f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,10 +5,6 @@ #[macro_use] mod ext; #[allow(unused_imports)] use ext::*; -use std::sync::Arc; -use tokio::io::{AsyncWrite, AsyncRead}; -use openssl::symm::Crypter; - // Wrapper for plain/symm-enc stream swapping mod dual; // Crypto shit @@ -16,12 +12,9 @@ mod crypt; // Stream impls mod stream; - -/// A type that implements both `AsyncWrite` and `AsyncRead` -pub trait AsyncStream: AsyncRead + AsyncWrite{} -impl AsyncStream for T{} - pub use stream::{ + AsyncStream, + EncryptedStream, WriteHalf, ReadHalf, diff --git a/src/stream.rs b/src/stream.rs index 647414a..9e5d3f4 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,9 +1,18 @@ use super::*; + +use tokio::io::{AsyncWrite, AsyncRead}; +use std::sync::Arc; +use openssl::symm::Crypter; + use crypt::{ RsaPublicKey, RsaPrivateKey, }; +/// A type that implements both `AsyncWrite` and `AsyncRead` +pub trait AsyncStream: AsyncRead + AsyncWrite{} +impl AsyncStream for T{} + /// Inner rsa data for encrypted stream read+write halves struct EncryptedStreamMeta { @@ -42,20 +51,55 @@ struct ReadWriteCombined } /// RSA/chacha20 encrypted stream -pub struct EncryptedStream -where S: AsyncStream +pub struct EncryptedStream +where R: AsyncRead, + W: AsyncWrite, { meta: EncryptedStreamMeta, // Keep the streams on the heap to keep this type not hueg. - backing: Box>, + backing: Box>, } -impl EncryptedStream +//TODO: How do we use this with a single AsyncStream instead of requiring 2? Will we need to make our own Arc wrapper?? Ugh,, for now let's ignore this I guess... Most read+write thingies have a Read/WriteHalf split mechanism. +impl EncryptedStream { /// Has this stream done its RSA key exchange? pub fn has_exchanged(&self) -> bool { self.meta.them.is_some() } + + /// Split this stream into a read and writeable half. + pub fn split(self) -> (WriteHalf, ReadHalf) + { + let meta = Arc::new(self.meta); + let (read, write) = { + let ReadWriteCombined { cipher_read, backing_read, backing_write } = *self.backing; + + ((cipher_read, backing_read), backing_write) + }; + + (WriteHalf { + meta: Arc::clone(&meta), + backing_write: Box::new(write), + }, ReadHalf { + meta, + cipher: read.0, + backing_read: Box::new(read.1), + }) + } + + /// Join a split `EncryptedStream` from halves. + /// + /// # Panics + /// If the read and write half are not from the same split. + pub fn from_split((write, read): (WriteHalf, ReadHalf)) -> Self + { + if !Arc::ptr_eq(&write.meta, &read.meta) { + panic!("Read and Write halves are not from the same split"); + } + + todo!("Drop write's `meta`, consume read's `meta`. Move the streams into `ReadWriteCombined`") + } }