diff --git a/src/main.rs b/src/main.rs index 5b0e21e..691e668 100755 --- a/src/main.rs +++ b/src/main.rs @@ -2,73 +2,96 @@ use std::{error::Error, net::SocketAddr, path::PathBuf}; use clap::{command, ArgGroup, Parser, Subcommand}; -use contego::parser::{addr_parser, dirpath_parser, filepath_parser}; +use contego::{ + client::Client, + parser::{addr_parser, dirpath_parser, filepath_parser}, + server::Server, + util::{filepaths, metadata, Ip}, +}; +use env_logger::Env; +use tokio::sync::mpsc; #[derive(Debug, Parser)] #[command(about, version)] struct Cli { #[command(subcommand)] command: Commands, - /// Suspend all output expect errors - #[clap(long, default_value_t = false)] - quiet: bool, } #[derive(Debug, Subcommand)] enum Commands { - /// Host fileserver instance by providing JSON file with paths or list of paths #[clap(group(ArgGroup::new("input").required(true).args(&["infile", "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")] + source: Option, + /// Paths to shareable files (alternative to --source) + #[clap(short = 'f', long, num_args = 1.., value_parser = filepath_parser, conflicts_with = "infile", group = "input")] + files: Option>, /// Host port #[clap(short = 'p', long, default_value_t = 8080)] port: u16, - /// Use IPv6 instead of IPv4 + /// IPv6 instead of IPv4 #[clap(short = '6', long, default_value_t = false)] ipv6: bool, - /// Path to the inputfile - #[clap(short = 'i', long, value_parser = filepath_parser, conflicts_with = "files", group = "input")] - infile: Option, - /// Paths to the files - #[clap(short = 'f', long, num_args = 1.., value_parser = filepath_parser, conflicts_with = "infile", group = "input")] - files: Option>, - /// Outgoing traffic chunksize in bytes + /// Transmit chunksize in bytes #[clap(short = 'c', long, default_value_t = 8192)] chunksize: usize, - /// Host the files locally + /// Host locally #[clap(short = 'l', long, default_value_t = false)] local: bool, }, - /// Connect to hosted server by providing address, output folder and access key Connect { - /// IP address of the server (IPv4 or IPv6) + /// IP address of the instance #[clap(short = 'a', long, value_parser = addr_parser)] addr: SocketAddr, - /// Path to the output folder + /// Path to an output folder #[clap(short = 'o', long, value_parser = dirpath_parser)] out: PathBuf, - /// Access key for the fileserver + /// Access key #[clap(short = 'k', long)] key: String, }, } #[tokio::main] -async fn main() -> Result<(), Box> { - // TODO: init logger with default level set to 'info' +async fn main() -> Result<(), Box> { + env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); - let _cli = Cli::parse(); + let cli = Cli::parse(); - //match cli.command { - // Commands::Host { - // port, - // ipv6, - // infile, - // files, - // chunksize, - // local, - // } => {} - // Commands::Connect { addr, out, key } => {} - //}; + match cli.command { + Commands::Host { + port, + ipv6, + source, + files, + chunksize, + local, + key, + } => { + let files = filepaths(source, files)?; + let (metadata, index) = metadata(&files).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?; + } + Commands::Connect { addr, out, key } => { + let client = Client::new(addr, key, out); + client.connection().await?; + } + }; Ok(()) } diff --git a/src/util.rs b/src/util.rs index fd1ecc6..3e43330 100644 --- a/src/util.rs +++ b/src/util.rs @@ -50,10 +50,10 @@ impl FileInfo { } } -fn filepaths( +pub fn filepaths( infile: Option, files: Option>, -) -> Result, Box> { +) -> Result, Box> { info!("Collecting filepaths"); let mut filepaths = Vec::new();