replace '~' with absolute path & removed unnecessary return traits
This commit is contained in:
parent
ba0678c149
commit
91f1a6d69f
@ -130,7 +130,7 @@ impl Client {
|
||||
debug!("File '{}': {} bytes remaining", file.hash, remaining);
|
||||
}
|
||||
|
||||
let check_hash = crypto::try_hash(&path)?;
|
||||
let check_hash = crypto::try_hash(&path).unwrap();
|
||||
let msg = check_hash.as_bytes().to_vec();
|
||||
handler.send(&msg).await?;
|
||||
|
||||
|
@ -102,7 +102,7 @@ impl Crypto {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_hash(path: &Path) -> Result<String, Box<dyn Error + Send + Sync>> {
|
||||
pub fn try_hash(path: &Path) -> Result<String, Box<dyn Error>> {
|
||||
debug!("Calculating SHA hash");
|
||||
|
||||
let hash = sha256::try_digest(path)?;
|
||||
|
36
src/main.rs
36
src/main.rs
@ -6,9 +6,10 @@ use contego::{
|
||||
client::Client,
|
||||
parser::{addr_parser, dirpath_parser, filepath_parser},
|
||||
server::Server,
|
||||
util::{filepaths, metadata, Ip},
|
||||
util::{filepaths, handle_exit, metadata, Ip},
|
||||
};
|
||||
use env_logger::Env;
|
||||
use log::error;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@ -20,16 +21,16 @@ struct Cli {
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Commands {
|
||||
#[clap(group(ArgGroup::new("input").required(true).args(&["infile", "files"])))]
|
||||
#[clap(group(ArgGroup::new("input").required(true).args(&["source", "files"])))]
|
||||
Host {
|
||||
/// Access key
|
||||
#[clap(short = 'k', long)]
|
||||
key: String,
|
||||
/// Path to a source file (alternative to --files)
|
||||
#[clap(short = 'i', long, value_parser = filepath_parser, conflicts_with = "files", group = "input")]
|
||||
#[clap(short = 's', long, value_parser = filepath_parser, conflicts_with = "files", group = "input")]
|
||||
source: Option<PathBuf>,
|
||||
/// Paths to shareable files (alternative to --source)
|
||||
#[clap(short = 'f', long, num_args = 1.., value_parser = filepath_parser, conflicts_with = "infile", group = "input")]
|
||||
#[clap(short = 'f', long, num_args = 1.., value_parser = filepath_parser, conflicts_with = "source", group = "input")]
|
||||
files: Option<Vec<PathBuf>>,
|
||||
/// Host port
|
||||
#[clap(short = 'p', long, default_value_t = 8080)]
|
||||
@ -58,9 +59,8 @@ enum Commands {
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
@ -73,23 +73,33 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
local,
|
||||
key,
|
||||
} => {
|
||||
let files = filepaths(source, files)?;
|
||||
let (metadata, index) = metadata(&files).await?;
|
||||
let (tx, rx) = mpsc::channel::<()>(1);
|
||||
|
||||
let paths = filepaths(source, files)?;
|
||||
let (metadata, index) = metadata(&paths).await?;
|
||||
let addr = match (local, ipv6) {
|
||||
(true, _) => Ip::Local.fetch(port)?,
|
||||
(false, true) => Ip::V6.fetch(port)?,
|
||||
(false, false) => Ip::V4.fetch(port)?,
|
||||
};
|
||||
|
||||
// TODO: handle shutdown signal
|
||||
let (_tx, rx) = mpsc::channel::<()>(1);
|
||||
|
||||
let server = Server::new(addr, key, chunksize, metadata, index);
|
||||
server.start(rx).await?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
match server.start(rx).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error during server execution: {}", e),
|
||||
};
|
||||
});
|
||||
|
||||
handle_exit(tx).await?;
|
||||
}
|
||||
Commands::Connect { addr, out, key } => {
|
||||
let client = Client::new(addr, key, out);
|
||||
client.connection().await?;
|
||||
match client.connection().await {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("Error during client execution: {}", e),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
use std::{
|
||||
env,
|
||||
io::{Error, ErrorKind::NotFound},
|
||||
net::{AddrParseError, SocketAddr},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use log::debug;
|
||||
|
||||
pub fn addr_parser(addr: &str) -> Result<SocketAddr, AddrParseError> {
|
||||
let addr = addr
|
||||
.parse::<SocketAddr>()
|
||||
@ -13,7 +16,13 @@ pub fn addr_parser(addr: &str) -> Result<SocketAddr, AddrParseError> {
|
||||
}
|
||||
|
||||
pub fn filepath_parser(path: &str) -> Result<PathBuf, Error> {
|
||||
let path = path.parse::<PathBuf>().expect("Failed to parse path");
|
||||
debug!("Validating filepath '{}'", path);
|
||||
|
||||
let home = env::var("HOME").unwrap();
|
||||
let path = path
|
||||
.replace('~', &home)
|
||||
.parse::<PathBuf>()
|
||||
.expect("Failed to parse path");
|
||||
|
||||
if path.exists() && path.is_file() {
|
||||
Ok(path)
|
||||
@ -23,6 +32,8 @@ pub fn filepath_parser(path: &str) -> Result<PathBuf, Error> {
|
||||
}
|
||||
|
||||
pub fn dirpath_parser(path: &str) -> Result<PathBuf, Error> {
|
||||
debug!("Validating dirpath '{}'", path);
|
||||
|
||||
let path = path.parse::<PathBuf>().expect("Failed to parse path");
|
||||
|
||||
if path.exists() && path.is_dir() {
|
||||
|
69
src/util.rs
69
src/util.rs
@ -1,7 +1,15 @@
|
||||
use std::{collections::HashMap, error::Error, fs, net::SocketAddr, path::PathBuf};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
error::Error,
|
||||
fs,
|
||||
io::{stdin, Read},
|
||||
net::SocketAddr,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use log::{debug, info};
|
||||
use tokio::{fs::File, io::BufWriter};
|
||||
use tokio::{fs::File, io::BufWriter, sync::mpsc::Sender};
|
||||
|
||||
use crate::crypto;
|
||||
|
||||
@ -16,9 +24,7 @@ pub enum Ip {
|
||||
}
|
||||
|
||||
impl Ip {
|
||||
pub fn fetch(self, port: u16) -> Result<SocketAddr, Box<dyn Error + Send + Sync>> {
|
||||
debug!("Fetching IP information");
|
||||
|
||||
pub fn fetch(self, port: u16) -> Result<SocketAddr, Box<dyn Error>> {
|
||||
let addr = match self {
|
||||
Ip::V4 => PUBLIC_IPV4,
|
||||
Ip::V6 => PUBLIC_IPV6,
|
||||
@ -28,6 +34,8 @@ impl Ip {
|
||||
}
|
||||
};
|
||||
|
||||
info!("Fetching IP information from {}", addr);
|
||||
|
||||
let res = format!("{}:{}", ureq::get(addr).call()?.into_string()?.trim(), port);
|
||||
let addr = res.parse::<SocketAddr>()?;
|
||||
|
||||
@ -51,38 +59,41 @@ impl FileInfo {
|
||||
}
|
||||
|
||||
pub fn filepaths(
|
||||
infile: Option<PathBuf>,
|
||||
source: Option<PathBuf>,
|
||||
files: Option<Vec<PathBuf>>,
|
||||
) -> Result<Vec<PathBuf>, Box<dyn Error + Send + Sync>> {
|
||||
) -> Result<Vec<PathBuf>, Box<dyn Error>> {
|
||||
info!("Collecting filepaths");
|
||||
|
||||
let mut filepaths = Vec::new();
|
||||
let mut paths = Vec::new();
|
||||
|
||||
if let Some(infile) = infile {
|
||||
let paths = fs::read_to_string(infile)?;
|
||||
for path in paths.lines() {
|
||||
filepaths.push(PathBuf::from(path));
|
||||
}
|
||||
if let Some(source) = source {
|
||||
let home = env::var("HOME")?;
|
||||
let content = fs::read_to_string(source)?;
|
||||
paths = content
|
||||
.lines()
|
||||
.into_iter()
|
||||
.map(|p| PathBuf::from(p.replace('~', &home)))
|
||||
.collect();
|
||||
} else if let Some(files) = files {
|
||||
for file in files {
|
||||
filepaths.push(file);
|
||||
}
|
||||
paths = files;
|
||||
}
|
||||
|
||||
debug!("Filepaths collection finished (total: {})", filepaths.len());
|
||||
debug!("Filepaths collection finished (total: {})", paths.len());
|
||||
|
||||
Ok(filepaths)
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
pub async fn metadata(
|
||||
files: &Vec<PathBuf>,
|
||||
) -> Result<(Vec<FileInfo>, HashMap<String, PathBuf>), Box<dyn Error + Send + Sync>> {
|
||||
) -> Result<(Vec<FileInfo>, HashMap<String, PathBuf>), Box<dyn Error>> {
|
||||
info!("Collecting metadata");
|
||||
|
||||
let mut metadata = Vec::new();
|
||||
let mut index = HashMap::new();
|
||||
|
||||
for path in files {
|
||||
debug!("Collecting '{}' metadata", path.to_str().unwrap());
|
||||
|
||||
let split = path.to_str().unwrap().split('/').collect::<Vec<&str>>();
|
||||
let name = split[split.len() - 1].to_string();
|
||||
let handle = File::open(path).await?;
|
||||
@ -90,8 +101,6 @@ pub async fn metadata(
|
||||
let hash = crypto::try_hash(path)?;
|
||||
|
||||
if size > 0 {
|
||||
debug!("Collecting '{}' metadata", name);
|
||||
|
||||
let info = FileInfo::new(name, size, hash.clone());
|
||||
metadata.push(info);
|
||||
index.insert(hash, path.clone());
|
||||
@ -117,3 +126,21 @@ pub async fn new_file(
|
||||
|
||||
Ok((BufWriter::new(handle), path))
|
||||
}
|
||||
|
||||
pub async fn handle_exit(tx: Sender<()>) -> Result<(), Box<dyn Error>> {
|
||||
let mut stdin = stdin().lock().bytes();
|
||||
|
||||
loop {
|
||||
let k = match stdin.next() {
|
||||
None => continue,
|
||||
Some(k) => k?,
|
||||
};
|
||||
|
||||
if k == b'q' {
|
||||
tx.send(()).await?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user