From 1c321301fd9f42eb4d78bf93600a89d2af4c3494 Mon Sep 17 00:00:00 2001 From: Donald Knuth Date: Sat, 3 Sep 2022 15:34:14 -0400 Subject: [PATCH] Cleanup --- README.md | 23 ++++++++++++++++------- src/client.rs | 19 +++++++++++++------ src/connection.rs | 18 +++++++++++------- src/file.rs | 25 ++++++++++++++++++------- src/handshake.rs | 2 +- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 97d7408..843f9c6 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,22 @@ `ruck` is a command line tool used for hosting relay servers and sending end-to-end encrypted files between clients. It was heavily inspired by [croc](https://github.com/schollz/croc), one of the easiest ways to send files between peers. This document describes the protocol `ruck` uses to support this functionality. -### Version +## Usage -This document refers to version `0.1.0` of `ruck` as defined by the `Cargo.toml` file. +```bash +## tab 1 +cargo run relay # this starts the server -## Server +## tab 2 +cargo run send /path/to/file1.md /path/to/file2.md supersecretpassword + +## tab 3 +cargo run receive supersecretpassword +``` + +## Protocol + +### Server The server in `ruck` exposes a TCP port. Its only functions are to staple connections and shuttle bytes between stapled connections. @@ -19,7 +30,7 @@ The time out is set to remove idle connections. The server does nothing else with the bytes, so the clients are free to end-to-end encrypt their messages. For this reason, updates to the `ruck` protocol do not typically necessitate server redeployments. -## Client +### Client There are two types of clients - `send` and `receive` clients. Out of band, the clients agree on a relay server and password, from which they can derive the 32 byte identifier used by the server to staple their connections. @@ -29,7 +40,5 @@ Once the handshake is complete, `send` and `receive` negotiate and exchange file - `send` offers a list of files and waits. - `receive` specifies which bytes it wants from these files. -- `send` sends the specified bytes and waits. -- `receive` sends heartbeats with progress updates. -- `send` hangs up once the heartbeats stop or received a successful heartbeat. +- `send` sends the specified bytes, then a completion message and hangs up. - `receive` hangs up once the downloads are complete. diff --git a/src/client.rs b/src/client.rs index 8a023c5..461c530 100644 --- a/src/client.rs +++ b/src/client.rs @@ -96,8 +96,8 @@ pub async fn request_specific_files(conn: &mut Connection) -> Result) -> Result> { let mut v = Vec::new(); for desired_file in desired_files { - let mut filename = desired_file.path; - filename.push_str(".part"); + let filename = desired_file.path; + // filename.push_str(".part"); let file = match File::open(filename.clone()).await { Ok(file) => { println!( @@ -106,16 +106,23 @@ pub async fn create_or_find_files(desired_files: Vec) -> Result File::create(filename).await?, + Err(_) => File::create(&filename).await?, }; let metadata = file.metadata().await?; println!( - "Current len: {:?}, Full Size: {:?}", + "File: {:?}. Current len: {:?}, Full Size: {:?}", + filename.clone(), metadata.len(), desired_file.size ); - let std_file_handle = - StdFileHandle::new(desired_file.id, file, metadata.len(), desired_file.size).await?; + let std_file_handle = StdFileHandle::new( + desired_file.id, + filename, + file, + metadata.len(), + desired_file.size, + ) + .await?; v.push(std_file_handle) } return Ok(v); diff --git a/src/connection.rs b/src/connection.rs index 6b91c36..a02caa4 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -81,12 +81,13 @@ impl Connection { let elapsed = before.elapsed(); let mb_sent = bytes_sent / 1_048_576; println!( - "{:?} mb sent, {:?} iterations. {:?} total time, {:?} avg per iteration, {:?} avg mb/sec", + "{:?}: {:?} mb sent (compressed), {:?} iterations. {:?} total time, {:?} avg per iteration, {:?} avg mb/sec", + handle.name, mb_sent, count, elapsed, elapsed / count, - mb_sent / elapsed.as_secs() + 1000 * mb_sent as u128 / elapsed.as_millis() ); Ok(()) } @@ -112,7 +113,6 @@ impl Connection { let msg = self.await_msg().await?; match msg { Message::FileTransfer(payload) => { - println!("In download"); if payload.chunk_header.id != handle.id { return Err(anyhow!("Wrong file")); } @@ -125,15 +125,19 @@ impl Connection { } } decoder.finish()?; - println!("Done downloading file."); - Connection::check_and_finish_download(clone, handle.size).await?; + println!("Done downloading {:?}.", handle.name); + Connection::check_and_finish_download(clone, handle.name, handle.size).await?; Ok(()) } - pub async fn check_and_finish_download(file: std::fs::File, size: u64) -> Result<()> { + pub async fn check_and_finish_download( + file: std::fs::File, + filename: String, + size: u64, + ) -> Result<()> { let metadata = file.metadata()?; if metadata.len() == size { - println!("File looks good."); + println!("OK: downloaded {:?} matches advertised size.", filename); return Ok(()); } return Err(anyhow!( diff --git a/src/file.rs b/src/file.rs index 43ed94f..ba47a6f 100644 --- a/src/file.rs +++ b/src/file.rs @@ -24,20 +24,25 @@ pub struct FileOffer { pub struct StdFileHandle { pub id: u8, + pub name: String, pub file: std::fs::File, pub start: u64, pub size: u64, } impl StdFileHandle { - pub async fn new(id: u8, file: File, start: u64, size: u64) -> Result { + pub async fn new( + id: u8, + name: String, + file: File, + start: u64, + size: u64, + ) -> Result { let mut file = file.into_std().await; file.seek(SeekFrom::Start(start))?; - if start != 0 { - println!("Seeking to {:?}", start); - } Ok(StdFileHandle { id, + name, file, start, size, @@ -85,8 +90,14 @@ impl FileHandle { } async fn to_std(self, chunk_header: &ChunkHeader) -> Result { - println!("{:?} requested start?", chunk_header.start); - StdFileHandle::new(self.id, self.file, chunk_header.start, self.md.len()).await + StdFileHandle::new( + self.id, + pathbuf_to_string(&self.path)?, + self.file, + chunk_header.start, + self.md.len(), + ) + .await } pub fn to_file_offer(&self) -> Result { @@ -130,6 +141,6 @@ pub fn pathbuf_to_string(path: &PathBuf) -> Result { let filename = filename.to_os_string(); match filename.into_string() { Ok(s) => Ok(s), - Err(e) => Err(anyhow!("Error converting {:?} to String", path)), + Err(_) => Err(anyhow!("Error converting {:?} to String", path)), } } diff --git a/src/handshake.rs b/src/handshake.rs index 1b1b409..c695d29 100644 --- a/src/handshake.rs +++ b/src/handshake.rs @@ -49,7 +49,7 @@ impl Handshake { ) -> Result<(TcpStream, Vec)> { let mut socket = socket; let bytes = &self.to_bytes(); - println!("client - sending handshake msg= {:?}", &bytes); + // println!("client - sending handshake msg= {:?}", &bytes); socket.write_all(&bytes).await?; let mut buffer = [0; HANDSHAKE_MSG_SIZE]; let n = socket.read_exact(&mut buffer).await?;