2022-08-30 14:53:16 +01:00
|
|
|
use crate::connection::Connection;
|
2022-09-02 21:41:40 +01:00
|
|
|
use crate::file::{ChunkHeader, FileHandle, FileOffer, StdFileHandle};
|
2022-08-30 02:21:48 +01:00
|
|
|
use crate::handshake::Handshake;
|
2022-09-02 21:41:40 +01:00
|
|
|
use crate::message::{FileOfferPayload, FileRequestPayload, Message};
|
|
|
|
use crate::ui::prompt_user_for_file_confirmation;
|
2022-02-06 19:04:36 +00:00
|
|
|
|
2022-02-12 19:59:04 +00:00
|
|
|
use anyhow::{anyhow, Result};
|
2022-09-02 21:41:40 +01:00
|
|
|
|
2022-02-07 00:54:36 +00:00
|
|
|
use std::path::PathBuf;
|
2022-02-15 04:01:30 +00:00
|
|
|
use tokio::fs::File;
|
2022-09-02 21:41:40 +01:00
|
|
|
|
2022-02-06 19:04:36 +00:00
|
|
|
use tokio::net::TcpStream;
|
|
|
|
|
2022-02-10 19:52:28 +00:00
|
|
|
pub async fn send(file_paths: &Vec<PathBuf>, password: &String) -> Result<()> {
|
2022-02-12 19:59:04 +00:00
|
|
|
// Fail early if there are problems generating file handles
|
2022-08-31 19:05:58 +01:00
|
|
|
let handles = FileHandle::get_file_handles(file_paths).await?;
|
2022-02-12 17:18:24 +00:00
|
|
|
|
2022-02-12 19:59:04 +00:00
|
|
|
// Establish connection to server
|
2022-02-10 19:52:28 +00:00
|
|
|
let socket = TcpStream::connect("127.0.0.1:8080").await?;
|
2022-02-12 01:50:14 +00:00
|
|
|
|
2022-08-30 02:21:48 +01:00
|
|
|
let (handshake, s1) = Handshake::from_password(password);
|
2022-08-30 03:33:50 +01:00
|
|
|
// Complete handshake, returning key used for encryption
|
|
|
|
let (socket, key) = handshake.negotiate(socket, s1).await?;
|
2022-08-30 02:21:48 +01:00
|
|
|
|
2022-08-30 14:53:16 +01:00
|
|
|
let mut connection = Connection::new(socket, key);
|
2022-09-02 21:41:40 +01:00
|
|
|
// Offer files, wait for requested file response
|
|
|
|
let requested_chunks = offer_files(&mut connection, &handles).await?;
|
2022-02-12 19:59:04 +00:00
|
|
|
|
|
|
|
// Upload negotiated files
|
2022-09-02 21:41:40 +01:00
|
|
|
let std_file_handles = FileHandle::to_stds(handles, requested_chunks).await;
|
|
|
|
connection.upload_files(std_file_handles).await?;
|
2022-08-30 03:33:50 +01:00
|
|
|
println!("Done uploading.");
|
2022-02-12 19:59:04 +00:00
|
|
|
|
|
|
|
// Exit
|
|
|
|
Ok(())
|
2022-02-10 19:52:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn receive(password: &String) -> Result<()> {
|
2022-09-02 21:41:40 +01:00
|
|
|
// Establish connection to server
|
2022-02-10 19:52:28 +00:00
|
|
|
let socket = TcpStream::connect("127.0.0.1:8080").await?;
|
2022-08-30 02:21:48 +01:00
|
|
|
let (handshake, s1) = Handshake::from_password(password);
|
2022-09-02 21:41:40 +01:00
|
|
|
// Complete handshake, returning key used for encryption
|
2022-08-30 03:33:50 +01:00
|
|
|
let (socket, key) = handshake.negotiate(socket, s1).await?;
|
2022-08-30 14:53:16 +01:00
|
|
|
let mut connection = Connection::new(socket, key);
|
2022-09-02 21:41:40 +01:00
|
|
|
// Wait for offered files, respond with desired files
|
|
|
|
let desired_files = request_specific_files(&mut connection).await?;
|
|
|
|
// Create files
|
2022-09-03 19:58:48 +01:00
|
|
|
let std_file_handles = create_or_find_files(desired_files).await?;
|
2022-09-02 21:41:40 +01:00
|
|
|
// Download them
|
|
|
|
connection.download_files(std_file_handles).await?;
|
2022-02-10 19:52:28 +00:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2022-09-02 21:41:40 +01:00
|
|
|
pub async fn offer_files(
|
2022-08-30 14:53:16 +01:00
|
|
|
conn: &mut Connection,
|
2022-09-02 21:41:40 +01:00
|
|
|
file_handles: &Vec<FileHandle>,
|
|
|
|
) -> Result<Vec<ChunkHeader>> {
|
|
|
|
// Collect file offer
|
2022-09-03 19:58:48 +01:00
|
|
|
let mut files = vec![];
|
|
|
|
for handle in file_handles {
|
|
|
|
files.push(handle.to_file_offer()?);
|
|
|
|
}
|
2022-09-02 21:41:40 +01:00
|
|
|
let msg = Message::FileOffer(FileOfferPayload { files });
|
|
|
|
// Send file offer
|
2022-08-30 14:53:16 +01:00
|
|
|
conn.send_msg(msg).await?;
|
2022-09-02 21:41:40 +01:00
|
|
|
// Wait for reply
|
2022-08-30 14:53:16 +01:00
|
|
|
let reply = conn.await_msg().await?;
|
2022-09-02 21:41:40 +01:00
|
|
|
// Return requested chunks
|
|
|
|
match reply {
|
|
|
|
Message::FileRequest(file_request_payload) => Ok(file_request_payload.chunks),
|
|
|
|
_ => Err(anyhow!("Expecting file request message back")),
|
|
|
|
}
|
2022-02-12 19:59:04 +00:00
|
|
|
}
|
|
|
|
|
2022-09-02 21:41:40 +01:00
|
|
|
pub async fn request_specific_files(conn: &mut Connection) -> Result<Vec<FileOffer>> {
|
|
|
|
// Wait for offer message
|
|
|
|
let offer_message = conn.await_msg().await?;
|
|
|
|
let offered_files: Vec<FileOffer> = match offer_message {
|
|
|
|
Message::FileOffer(file_offer_payload) => file_offer_payload.files,
|
|
|
|
_ => return Err(anyhow!("Expecting file offer message")),
|
2022-02-12 19:59:04 +00:00
|
|
|
};
|
2022-09-02 21:41:40 +01:00
|
|
|
// Prompt user for confirmation of files
|
|
|
|
let desired_files = prompt_user_for_file_confirmation(offered_files).await;
|
|
|
|
let file_request_msg = Message::FileRequest(FileRequestPayload {
|
|
|
|
chunks: desired_files
|
|
|
|
.iter()
|
|
|
|
.map(|file| ChunkHeader {
|
|
|
|
id: file.id,
|
|
|
|
start: 0,
|
|
|
|
})
|
|
|
|
.collect(),
|
2022-02-15 04:01:30 +00:00
|
|
|
});
|
2022-09-02 21:41:40 +01:00
|
|
|
conn.send_msg(file_request_msg).await?;
|
|
|
|
Ok(desired_files)
|
2022-02-06 19:04:36 +00:00
|
|
|
}
|
2022-02-12 19:59:04 +00:00
|
|
|
|
2022-09-03 19:58:48 +01:00
|
|
|
pub async fn create_or_find_files(desired_files: Vec<FileOffer>) -> Result<Vec<StdFileHandle>> {
|
2022-09-02 21:41:40 +01:00
|
|
|
let mut v = Vec::new();
|
|
|
|
for desired_file in desired_files {
|
2022-09-03 19:58:48 +01:00
|
|
|
let mut filename = desired_file.path;
|
|
|
|
filename.push_str(".part");
|
|
|
|
let file = match File::open(filename.clone()).await {
|
|
|
|
Ok(file) => {
|
|
|
|
println!(
|
|
|
|
"File {:?} already exists. Attempting to resume download.",
|
|
|
|
filename
|
|
|
|
);
|
|
|
|
file
|
|
|
|
}
|
|
|
|
Err(_) => File::create(filename).await?,
|
|
|
|
};
|
|
|
|
let metadata = file.metadata().await?;
|
|
|
|
let std_file_handle =
|
|
|
|
StdFileHandle::new(desired_file.id, file, metadata.len(), desired_file.size).await?;
|
2022-09-02 21:41:40 +01:00
|
|
|
v.push(std_file_handle)
|
2022-02-16 01:55:33 +00:00
|
|
|
}
|
2022-09-02 21:41:40 +01:00
|
|
|
return Ok(v);
|
2022-02-15 04:01:30 +00:00
|
|
|
}
|