rework stream to (for now) use two different streams with distinct types for reading + writing

no-dual
Avril 3 years ago
parent 0b9af0ee18
commit 0035f38c3c
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -5,10 +5,6 @@
#[macro_use] mod ext; #[macro_use] mod ext;
#[allow(unused_imports)] use 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 // Wrapper for plain/symm-enc stream swapping
mod dual; mod dual;
// Crypto shit // Crypto shit
@ -16,12 +12,9 @@ mod crypt;
// Stream impls // Stream impls
mod stream; mod stream;
/// A type that implements both `AsyncWrite` and `AsyncRead`
pub trait AsyncStream: AsyncRead + AsyncWrite{}
impl<T: AsyncRead + AsyncWrite + ?Sized> AsyncStream for T{}
pub use stream::{ pub use stream::{
AsyncStream,
EncryptedStream, EncryptedStream,
WriteHalf, WriteHalf,
ReadHalf, ReadHalf,

@ -1,9 +1,18 @@
use super::*; use super::*;
use tokio::io::{AsyncWrite, AsyncRead};
use std::sync::Arc;
use openssl::symm::Crypter;
use crypt::{ use crypt::{
RsaPublicKey, RsaPublicKey,
RsaPrivateKey, RsaPrivateKey,
}; };
/// A type that implements both `AsyncWrite` and `AsyncRead`
pub trait AsyncStream: AsyncRead + AsyncWrite{}
impl<T: AsyncRead + AsyncWrite + ?Sized> AsyncStream for T{}
/// Inner rsa data for encrypted stream read+write halves /// Inner rsa data for encrypted stream read+write halves
struct EncryptedStreamMeta struct EncryptedStreamMeta
{ {
@ -42,20 +51,55 @@ struct ReadWriteCombined<R, W>
} }
/// RSA/chacha20 encrypted stream /// RSA/chacha20 encrypted stream
pub struct EncryptedStream<S> pub struct EncryptedStream<R, W>
where S: AsyncStream where R: AsyncRead,
W: AsyncWrite,
{ {
meta: EncryptedStreamMeta, meta: EncryptedStreamMeta,
// Keep the streams on the heap to keep this type not hueg. // Keep the streams on the heap to keep this type not hueg.
backing: Box<ReadWriteCombined<S, S>>, backing: Box<ReadWriteCombined<R, W>>,
} }
impl<S: AsyncStream> EncryptedStream<S> //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<R: AsyncRead, W: AsyncWrite> EncryptedStream<R, W>
{ {
/// Has this stream done its RSA key exchange? /// Has this stream done its RSA key exchange?
pub fn has_exchanged(&self) -> bool pub fn has_exchanged(&self) -> bool
{ {
self.meta.them.is_some() self.meta.them.is_some()
} }
/// Split this stream into a read and writeable half.
pub fn split(self) -> (WriteHalf<W>, ReadHalf<R>)
{
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<W>, ReadHalf<R>)) -> 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`")
}
} }

Loading…
Cancel
Save