use deon_protocol::{
DeonProtocol, transport::TcpTransport,
};
use clap::{Parser, Subcommand};
use tokio::net::TcpListener;
use tokio::io::AsyncReadExt;
use log::info;
#[derive(Parser)]
#[command(name = "deon-protocol")]
#[command(version = "1.3.0")]
#[command(about = "Deon Protocol Secure File Transfer CLI", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Send {
#[arg(short, long)]
file: String,
#[arg(short, long)]
address: String,
#[arg(short, long)]
password: String,
},
Receive {
#[arg(short, long, default_value_t = 8080)]
port: u16,
#[arg(short, long)]
password: String,
},
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let cli = Cli::parse();
match cli.command {
Commands::Send { file, address, password } => {
run_sender(&file, &address, &password).await?;
}
Commands::Receive { port, password } => {
run_receiver(port, &password).await?;
}
}
Ok(())
}
async fn run_sender(file_path: &str, address: &str, password: &str) -> Result<(), Box<dyn std::error::Error>> {
info!("Starting Deon Protocol Sender...");
let path = std::path::Path::new(file_path);
let filename = path.file_name().ok_or("Invalid filename")?.to_str().ok_or("Invalid filename")?;
let mut file = tokio::fs::File::open(path).await?;
let mut data = Vec::new();
file.read_to_end(&mut data).await?;
info!("Read file '{}' ({} bytes)", filename, data.len());
info!("Connecting to {}...", address);
let transport = deon_protocol::transport::connect_tcp(address).await?;
let mut deon = DeonProtocol::new(transport);
info!("Performing Secure Handshake...");
deon.handshake(password).await?;
info!("Handshake Successful!");
info!("Sending File...");
deon.send_file(filename, &data).await?;
info!("File Sent Successfully!");
Ok(())
}
async fn run_receiver(port: u16, password: &str) -> Result<(), Box<dyn std::error::Error>> {
info!("Starting Deon Protocol Receiver on port {}...", port);
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
info!("Listening for connections...");
let (socket, addr) = listener.accept().await?;
info!("Accepted connection from: {}", addr);
let transport = Box::new(TcpTransport::new(socket));
let mut deon = DeonProtocol::new(transport);
info!("Waiting for Secure Handshake...");
deon.accept_handshake(password).await?;
info!("Handshake Successful!");
info!("Waiting for File...");
deon.receive_file().await?;
info!("File Received Successfully!");
Ok(())
}