feat: added upload file capability
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user