expect byte test

This commit is contained in:
nora 2023-09-26 07:50:20 +02:00
parent 57f6feb70a
commit 800ff88a6d
3 changed files with 84 additions and 14 deletions

View file

@ -2,30 +2,31 @@ pub mod proto;
use std::{ use std::{
fmt::Debug, fmt::Debug,
io::{self, BufWriter, Read, Write}, io::{self, Read, Write},
net::TcpStream,
}; };
use crate::proto::TLSPlaintext; use crate::proto::TLSPlaintext;
type Result<T, E = Error> = std::result::Result<T, E>; type Result<T, E = Error> = std::result::Result<T, E>;
pub struct ClientConnection {} pub struct ClientConnection<W> {
_w: W,
}
impl ClientConnection { impl<W: Read + Write> ClientConnection<W> {
pub fn establish(host: &str, port: u16) -> Result<Self> { pub fn establish(w: W, host: &str) -> Result<Self> {
let _setup = ClientSetupConnection::establish(host, port)?; let _setup = ClientSetupConnection::establish(w, host)?;
todo!() todo!()
} }
} }
struct ClientSetupConnection {} struct ClientSetupConnection<W> {
_w: W,
impl ClientSetupConnection { }
fn establish(host: &str, port: u16) -> Result<Self> {
let mut stream = BufWriter::new(LoggingWriter(TcpStream::connect((host, port))?));
impl<W: Read + Write> ClientSetupConnection<W> {
fn establish(mut stream: W, host: &str) -> Result<Self> {
let secret = x25519_dalek::EphemeralSecret::random_from_rng(rand::thread_rng()); let secret = x25519_dalek::EphemeralSecret::random_from_rng(rand::thread_rng());
let public = x25519_dalek::PublicKey::from(&secret); let public = x25519_dalek::PublicKey::from(&secret);
@ -82,7 +83,7 @@ impl ClientSetupConnection {
plaintext.write(&mut stream)?; plaintext.write(&mut stream)?;
stream.flush()?; stream.flush()?;
let out = proto::TLSPlaintext::read(stream.get_mut())?; let out = proto::TLSPlaintext::read(&mut stream)?;
dbg!(&out); dbg!(&out);
if matches!(out, TLSPlaintext::Handshake { handshake } if handshake.is_hello_retry_request()) if matches!(out, TLSPlaintext::Handshake { handshake } if handshake.is_hello_retry_request())
@ -125,7 +126,7 @@ impl From<ErrorKind> for Error {
} }
#[derive(Debug)] #[derive(Debug)]
struct LoggingWriter<W>(W); pub struct LoggingWriter<W>(pub W);
impl<W: io::Write> io::Write for LoggingWriter<W> { impl<W: io::Write> io::Write for LoggingWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {

View file

@ -1,4 +1,7 @@
use std::net::TcpStream;
// An example program that makes a shitty HTTP/1.1 request. // An example program that makes a shitty HTTP/1.1 request.
fn main() { fn main() {
tls::ClientConnection::establish("nilstrieb.dev", 443).unwrap(); let conn = tls::LoggingWriter(TcpStream::connect(("nilstrieb.dev", 443)).unwrap());
tls::ClientConnection::establish(conn, "nilstrieb.dev").unwrap();
} }

66
tests/expect.rs Normal file
View file

@ -0,0 +1,66 @@
use std::io::{Read, Write};
struct ExpectServer {
expect: Vec<Expect>,
}
impl ExpectServer {
fn new(expect: Vec<Expect>) -> Self {
ExpectServer { expect }
}
}
impl Read for ExpectServer {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let Some(Expect::Server(server)) = self.expect.first_mut() else {
panic!("Reading from server, but client input is expected");
};
let len = std::cmp::min(buf.len(), server.len());
buf[..len].copy_from_slice(&mut server[..len]);
server.rotate_left(len);
server.truncate(server.len() - len);
if server.is_empty() {
self.expect.remove(0);
}
Ok(len)
}
}
impl Write for ExpectServer {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let Some(Expect::Client(client)) = self.expect.first_mut() else {
panic!("Writing as client, but should read instead");
};
let to_write = client
.get(..buf.len())
.expect("writing more bytes than expected");
assert_eq!(to_write, buf);
client.rotate_left(buf.len());
client.truncate(client.len() - buf.len());
if client.is_empty() {
self.expect.remove(0);
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
enum Expect {
Server(Vec<u8>),
Client(Vec<u8>),
}
#[test]
#[ignore]
fn connect() {
let mut expect = ExpectServer::new(vec![
Expect::Client(vec![0]), // TODO: do this
]);
let conn = tls::ClientConnection::establish(&mut expect, "example.com").unwrap();
}