feat: added upload file capability

This commit is contained in:
Andrew Rioux
2023-09-06 14:56:21 -04:00
parent 231108f2c3
commit 50b5c1a921
9 changed files with 277 additions and 5 deletions

View File

@@ -0,0 +1,93 @@
use std::{path::PathBuf, sync::Arc};
use tokio::{
fs,
io::{self, AsyncReadExt},
};
use sparse_05_common::messages::{
Command, Response, FILE_BUFFER_BUFFER_SIZE, FILE_TRANSFER_PACKET_SIZE,
};
use crate::commands::connect::Connection;
pub async fn download_file(
conn: Arc<Connection>,
remote_file: PathBuf,
local_path: PathBuf,
) -> anyhow::Result<()> {
let mut file = fs::OpenOptions::new().read(true).open(&local_path).await?;
let file_size = file.metadata().await?.len();
let command = Command::StartUploadFile(
remote_path,
(file_size / FILE_TRANSFER_PACKET_SIZE as u64) + 1,
);
conn.send_command(command).await?;
let id = loop {
let resp = conn.get_response().await?;
if let Response::UploadFileID(id) = resp {
break id;
}
};
loop {
let mut file_data: Vec<Vec<u8>> = Vec::with_capacity(FILE_BUFFER_BUFFER_SIZE);
let mut buffer = [0u8; FILE_TRANSFER_PACKET_SIZE];
let mut done = false;
for _ in 0..FILE_BUFFER_BUFFER_SIZE {
let amount = file.read(&mut buffer).await?;
if amount == 0 {
done = true;
break;
}
file_data.push(buffer[..amount].to_vec());
}
for (i, buffer) in file_data.iter().enumerate() {
let comm = Command::SendFileSegment(id, i as u64, buffer.clone());
conn.send_command(comm).await?;
}
loop {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
conn.send_command(Command::GetUploadStatus(id, file_data.len() as u64))
.await?;
let buffers_needed = loop {
let resp = conn.get_response().await?;
if let Response::UploadFileStatus(iid, buffers) = resp {
if id == iid {
break buffers;
}
}
};
if buffers_needed.len() == 0 {
break;
}
for buffer_needed in &buffers_needed {
let comm = Command::SendFileSegment(
id,
*buffer_needed,
file_data[*buffer_needed as usize].clone(),
);
conn.send_command(comm).await?;
}
}
if done {
break;
}
}
Ok(())
}

View File

@@ -1,5 +1,14 @@
use std::{path::PathBuf, sync::Arc};
use tokio::{
fs,
io::{self, AsyncReadExt},
};
use sparse_05_common::messages::{
Command, Response, FILE_BUFFER_BUFFER_SIZE, FILE_TRANSFER_PACKET_SIZE,
};
use crate::commands::connect::Connection;
pub async fn upload_file(
@@ -7,5 +16,78 @@ pub async fn upload_file(
local_path: PathBuf,
remote_path: PathBuf,
) -> anyhow::Result<()> {
let mut file = fs::OpenOptions::new().read(true).open(&local_path).await?;
let file_size = file.metadata().await?.len();
let command = Command::StartUploadFile(
remote_path,
(file_size / FILE_TRANSFER_PACKET_SIZE as u64) + 1,
);
conn.send_command(command).await?;
let id = loop {
let resp = conn.get_response().await?;
if let Response::UploadFileID(id) = resp {
break id;
}
};
loop {
let mut file_data: Vec<Vec<u8>> = Vec::with_capacity(FILE_BUFFER_BUFFER_SIZE);
let mut buffer = [0u8; FILE_TRANSFER_PACKET_SIZE];
let mut done = false;
for _ in 0..FILE_BUFFER_BUFFER_SIZE {
let amount = file.read(&mut buffer).await?;
if amount == 0 {
done = true;
break;
}
file_data.push(buffer[..amount].to_vec());
}
for (i, buffer) in file_data.iter().enumerate() {
let comm = Command::SendFileSegment(id, i as u64, buffer.clone());
conn.send_command(comm).await?;
}
loop {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
conn.send_command(Command::GetUploadStatus(id, file_data.len() as u64))
.await?;
let buffers_needed = loop {
let resp = conn.get_response().await?;
if let Response::UploadFileStatus(iid, buffers) = resp {
if id == iid {
break buffers;
}
}
};
if buffers_needed.len() == 0 {
break;
}
for buffer_needed in &buffers_needed {
let comm = Command::SendFileSegment(
id,
*buffer_needed,
file_data[*buffer_needed as usize].clone(),
);
conn.send_command(comm).await?;
}
}
if done {
break;
}
}
Ok(())
}

View File

@@ -171,6 +171,7 @@ pub(super) async fn shell(
let Ok(input) = std::str::from_utf8(&cmd) else {
continue;
};
let input = input.trim();
let (args, help) = if input.starts_with("#help") {
(input.split(" ").collect::<Vec<_>>(), true)
@@ -207,6 +208,20 @@ pub(super) async fn shell(
eprintln!("{e:?}")
}
}
(
Ok(SparseCommands::DownloadFile {
local_path,
remote_file,
}),
_,
) => {
if let Err(e) =
commands::download::download(Arc::clone(&connection), remote_file, local_path)
.await
{
eprintln!("{e:?}")
}
}
_ => {
if let Err(e) = run_command(
&mut stdin_receiver,