Merge branch 'us-enable-connection-between-clients' into development
* us-enable-connection-between-clients: add seperate file for http_server functionality changed from reqwest to hyper and added own httpclient file caesar: change repo structure and rebuild
This commit is contained in:
commit
d7a1a46db8
18 changed files with 1626 additions and 154 deletions
1405
Cargo.lock
generated
Normal file
1405
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
21
Cargo.toml
21
Cargo.toml
|
|
@ -1,6 +1,17 @@
|
||||||
[workspace]
|
[package]
|
||||||
members = [
|
name = "caesar"
|
||||||
"caesar_cli", "caesar_core", "caesar_server",
|
version = "0.0.1"
|
||||||
]
|
edition = "2021"
|
||||||
|
authors = ["Manuel Keidel", "Patryk Hegenberg", "Krzysztof Stankiewicz"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
|
reqwest = { version = "0.12.3", features = ["blocking", "json"] }
|
||||||
|
hyper = { version = "1", features = ["full"] }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
http-body-util = "0.1"
|
||||||
|
hyper-util = { version = "0.1", features = ["full"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "caesar_cli"
|
|
||||||
version = "0.0.1"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
[[bin]]
|
|
||||||
name = "caesar"
|
|
||||||
path = "src/main.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
clap = { version = "4.5.4", features = ["derive"] }
|
|
||||||
reqwest = { version = "0.12.3", features = ["blocking", "json"] }
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
use clap::{Parser, Subcommand};
|
|
||||||
use reqwest::blocking::Client;
|
|
||||||
|
|
||||||
use crate::command;
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(version, about, long_about = None)]
|
|
||||||
pub struct Cli {
|
|
||||||
/// Sets a custom config file
|
|
||||||
#[arg(short, long, value_name = "FILE")]
|
|
||||||
pub config: Option<String>,
|
|
||||||
|
|
||||||
/// Turn debugging information on
|
|
||||||
#[arg(short, long, action = clap::ArgAction::Count)]
|
|
||||||
pub debug: u8,
|
|
||||||
|
|
||||||
/// Name of Transfer to download files
|
|
||||||
#[arg(short, long, value_name = "Transfer_Name")]
|
|
||||||
pub name: Option<String>,
|
|
||||||
|
|
||||||
#[command(subcommand)]
|
|
||||||
pub command: Option<Commands>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
pub enum Commands {
|
|
||||||
/// Files to Send
|
|
||||||
Send {
|
|
||||||
/// Path to file(s)
|
|
||||||
#[arg(short, long, value_name = "FILE")]
|
|
||||||
file: Option<String>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Cli {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::parse()
|
|
||||||
}
|
|
||||||
pub fn handle_cli_args(&self, client: Client) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
if let Some(config_path) = self.config.as_deref() {
|
|
||||||
println!("Value for config: {}", config_path);
|
|
||||||
}
|
|
||||||
match self.debug {
|
|
||||||
0 => println!("Debug mode is off"),
|
|
||||||
1 => println!("Debug mode is kind of on"),
|
|
||||||
2 => println!("Debug mode is on"),
|
|
||||||
_ => println!("Don't be crazy"),
|
|
||||||
}
|
|
||||||
|
|
||||||
match &self.command {
|
|
||||||
Some(Commands::Send { file }) => {
|
|
||||||
command::send_info(client, file.as_deref().unwrap_or("test.txt"))?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let filename = self.name.as_deref().unwrap_or("None");
|
|
||||||
command::download_info(client, filename)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Cli {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
use reqwest::{blocking::Client, StatusCode};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
pub fn send_info(client: Client, file: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
map.insert("keyword", "test");
|
|
||||||
map.insert("files", file);
|
|
||||||
|
|
||||||
let res = client
|
|
||||||
.post("http://192.168.178.43:1323/upload")
|
|
||||||
.json(&map)
|
|
||||||
.send()?;
|
|
||||||
|
|
||||||
if res.status() == StatusCode::OK {
|
|
||||||
let json: HashMap<String, String> = res.json()?;
|
|
||||||
println!("JSON Response: {:?}", json);
|
|
||||||
} else {
|
|
||||||
println!("Error: Failed to send request");
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn download_info(client: Client, filename: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let res = client
|
|
||||||
.get(format!("http://192.168.178.43:1323/download/{}", filename))
|
|
||||||
.send()?;
|
|
||||||
|
|
||||||
if res.status() == StatusCode::OK {
|
|
||||||
let json: HashMap<String, String> = res.json()?;
|
|
||||||
println!("JSON Response: {:?}", json);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
mod cli;
|
|
||||||
mod command;
|
|
||||||
use reqwest::blocking::Client;
|
|
||||||
|
|
||||||
pub use crate::cli::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let client = Client::new();
|
|
||||||
let cli = cli::Cli::new();
|
|
||||||
|
|
||||||
if let Err(e) = cli.handle_cli_args(client) {
|
|
||||||
eprintln!("Error: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "caesar_core"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "caesar_server"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
||||||
93
src/args.rs
Normal file
93
src/args.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
use crate::receiver;
|
||||||
|
use crate::sender;
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
// use reqwest::blocking::Client;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
pub struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: Option<Commands>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Commands {
|
||||||
|
Send {
|
||||||
|
/// Address of the relay server. Accepted formats are: 127.0.0.1:8080, [::1]:8080, example.com
|
||||||
|
#[arg(short, long)]
|
||||||
|
relay: bool,
|
||||||
|
/// Path to file(s)
|
||||||
|
#[arg(short, long, value_name = "FILE")]
|
||||||
|
file: Option<String>,
|
||||||
|
},
|
||||||
|
/// Receives Files from the sender with the matching password
|
||||||
|
Receive {
|
||||||
|
/// Address of the relay server. Accepted formats are: 127.0.0.1:8080, [::1]:8080, example.com
|
||||||
|
#[arg(short, long)]
|
||||||
|
relay: bool,
|
||||||
|
|
||||||
|
/// Overwrite existing Files
|
||||||
|
#[arg(short, long)]
|
||||||
|
overwrite: bool,
|
||||||
|
|
||||||
|
/// Name of Transfer to download files
|
||||||
|
#[arg(short, long, value_name = "Transfer_Name")]
|
||||||
|
name: Option<String>,
|
||||||
|
},
|
||||||
|
Serve {
|
||||||
|
/// Port to run the relay server on
|
||||||
|
#[arg(short, long)]
|
||||||
|
port: bool,
|
||||||
|
},
|
||||||
|
Config {
|
||||||
|
/// Show path to config file
|
||||||
|
#[arg(short, long)]
|
||||||
|
path: bool,
|
||||||
|
|
||||||
|
/// View configured Options
|
||||||
|
#[arg(short, long)]
|
||||||
|
show: bool,
|
||||||
|
|
||||||
|
/// Edit the config file
|
||||||
|
#[arg(short, long)]
|
||||||
|
edit: bool,
|
||||||
|
|
||||||
|
/// Reset changed config
|
||||||
|
#[arg(short, long)]
|
||||||
|
reset: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Args {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::parse()
|
||||||
|
}
|
||||||
|
pub async fn run(
|
||||||
|
&self,
|
||||||
|
// client: Client,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
match &self.command {
|
||||||
|
Some(Commands::Send { relay, file }) => {
|
||||||
|
println!("Stuff");
|
||||||
|
sender::send_info(file.as_deref().unwrap_or("test.txt")).await?;
|
||||||
|
}
|
||||||
|
Some(Commands::Receive {
|
||||||
|
relay,
|
||||||
|
overwrite,
|
||||||
|
name,
|
||||||
|
}) => {
|
||||||
|
let transfer_name = name.as_deref().unwrap_or("None");
|
||||||
|
receiver::download_info(transfer_name).await?
|
||||||
|
}
|
||||||
|
Some(Commands::Serve { port }) => {}
|
||||||
|
Some(Commands::Config {
|
||||||
|
path,
|
||||||
|
show,
|
||||||
|
edit,
|
||||||
|
reset,
|
||||||
|
}) => {}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/http_client.rs
Normal file
54
src/http_client.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
use http_body_util::{BodyExt, Empty, Full};
|
||||||
|
use hyper::{body::Bytes, Request, StatusCode};
|
||||||
|
use hyper_util::rt::TokioIo;
|
||||||
|
use tokio::{
|
||||||
|
io::{self, AsyncWriteExt},
|
||||||
|
net::TcpStream,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn send_request(
|
||||||
|
url: &str,
|
||||||
|
method: &str,
|
||||||
|
body: Option<String>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
let url = url.parse::<hyper::Uri>()?;
|
||||||
|
let host = url.host().expect("uri has no host");
|
||||||
|
let port = url.port_u16().unwrap_or(80);
|
||||||
|
let address = format!("{}:{}", host, port);
|
||||||
|
let stream = TcpStream::connect(address).await?;
|
||||||
|
let io = TokioIo::new(stream);
|
||||||
|
let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
if let Err(err) = conn.await {
|
||||||
|
eprintln!("Connection failed: {:?}", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let authority = url.authority().unwrap().clone();
|
||||||
|
let send_body = match body {
|
||||||
|
Some(body_str) => Full::<Bytes>::from(Bytes::from(body_str)),
|
||||||
|
None => Full::<Bytes>::from(Bytes::from("")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let req = Request::builder()
|
||||||
|
.method(method)
|
||||||
|
.uri(url)
|
||||||
|
.header(hyper::header::HOST, authority.as_str())
|
||||||
|
.header(hyper::header::CONTENT_TYPE, "application/json")
|
||||||
|
.body(send_body)?;
|
||||||
|
|
||||||
|
let mut res = sender.send_request(req).await?;
|
||||||
|
|
||||||
|
println!("Response status: {}", res.status());
|
||||||
|
|
||||||
|
if res.status() == StatusCode::OK {
|
||||||
|
while let Some(next) = res.frame().await {
|
||||||
|
let frame = next?;
|
||||||
|
if let Some(chunk) = frame.data_ref() {
|
||||||
|
io::stdout().write_all(chunk).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
0
src/http_server.rs
Normal file
0
src/http_server.rs
Normal file
14
src/main.rs
Normal file
14
src/main.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
pub mod args;
|
||||||
|
pub mod http_client;
|
||||||
|
pub mod http_server;
|
||||||
|
pub mod receiver;
|
||||||
|
pub mod sender;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
let args = args::Args::new();
|
||||||
|
if let Err(e) = args.run().await {
|
||||||
|
eprintln!("Error {e}");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
0
src/password.rs
Normal file
0
src/password.rs
Normal file
13
src/receiver.rs
Normal file
13
src/receiver.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
use crate::http_client;
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
|
pub async fn download_info(filename: &str) -> Result<()> {
|
||||||
|
http_client::send_request(
|
||||||
|
format!("http://192.168.178.43:1323/download/{}", filename).trim(),
|
||||||
|
"GET",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
21
src/sender.rs
Normal file
21
src/sender.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
use crate::http_client;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
|
pub async fn send_info(file: &str) -> Result<()> {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert("keyword", "test");
|
||||||
|
map.insert("files", file);
|
||||||
|
|
||||||
|
let json_data = serde_json::to_string(&map)?;
|
||||||
|
|
||||||
|
http_client::send_request(
|
||||||
|
"http://192.168.178.43:1323/upload".trim(),
|
||||||
|
"POST",
|
||||||
|
Some(json_data),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
10
src/server.rs
Normal file
10
src/server.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
use std::convert::Infallible;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use http_body_util::Full;
|
||||||
|
use hyper::body::Bytes;
|
||||||
|
use hyper::server::conn::http1;
|
||||||
|
use hyper::service::service_fn;
|
||||||
|
use hyper::{Request, Response};
|
||||||
|
use hyper_util::rt::TokioIo;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue