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:
Patryk Hegenberg 2024-04-11 22:42:01 +02:00
commit d7a1a46db8
18 changed files with 1626 additions and 154 deletions

1405
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -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"

View file

@ -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"] }

View file

@ -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()
}
}

View file

@ -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(())
}

View file

@ -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}");
}
}

View file

@ -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]

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

View file

@ -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]

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

93
src/args.rs Normal file
View 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
View 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
View file

14
src/main.rs Normal file
View 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
View file

13
src/receiver.rs Normal file
View 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
View 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
View 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;