chore: much better readable code
This commit is contained in:
62
Cargo.lock
generated
62
Cargo.lock
generated
@@ -52,6 +52,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.1"
|
version = "2.9.1"
|
||||||
@@ -172,6 +178,17 @@ version = "0.2.174"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.5"
|
version = "2.7.5"
|
||||||
@@ -196,6 +213,29 @@ version = "1.70.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.95"
|
version = "1.0.95"
|
||||||
@@ -214,6 +254,21 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
@@ -249,6 +304,12 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -315,6 +376,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"httparse",
|
"httparse",
|
||||||
|
"parking_lot",
|
||||||
"serde",
|
"serde",
|
||||||
"shlex",
|
"shlex",
|
||||||
"toml",
|
"toml",
|
||||||
|
@@ -8,6 +8,7 @@ anstyle = "1"
|
|||||||
clap = { version = "4", features = ["derive", "string"] }
|
clap = { version = "4", features = ["derive", "string"] }
|
||||||
ctrlc = "3"
|
ctrlc = "3"
|
||||||
httparse = "1"
|
httparse = "1"
|
||||||
|
parking_lot = { version = "0", features = ["arc_lock", "serde"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
shlex = "1"
|
shlex = "1"
|
||||||
toml = "0"
|
toml = "0"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
listen_at = "127.0.0.1:8080"
|
listen_at = "127.0.0.1:8080"
|
||||||
|
|
||||||
[hosts]
|
[hosts]
|
||||||
"git.tuxcord.net" = "127.0.0.1:3000"
|
"git.tuxcord.net" = [ "127.0.0.1:3000", "i_like_gitea", "_csrf" ]
|
||||||
|
@@ -19,7 +19,7 @@ pub struct Args {
|
|||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
/// Connects to the selected IPC
|
/// Connects to the selected IPC
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
Ipc,
|
Ipc, // TODO: add -c flag for an automatic command
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_clap_styles() -> clap::builder::Styles {
|
fn get_clap_styles() -> clap::builder::Styles {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
use std::{collections::HashMap, net::SocketAddr, path::PathBuf, sync::RwLock};
|
use std::{collections::HashMap, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@@ -7,5 +8,5 @@ pub struct Schema {
|
|||||||
pub listen_at: SocketAddr,
|
pub listen_at: SocketAddr,
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
pub ipc: Option<PathBuf>,
|
pub ipc: Option<PathBuf>,
|
||||||
pub hosts: RwLock<HashMap<String, SocketAddr>>,
|
pub hosts: RwLock<HashMap<String, (SocketAddr, String, String)>>,
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
use core::net;
|
use core::{net, str};
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
io::{self, BufRead, BufReader, Write, stdout},
|
io::{self, BufRead, BufReader, Write, stdout},
|
||||||
os::unix::net::{UnixListener, UnixStream},
|
os::unix::net::{UnixListener, UnixStream},
|
||||||
process,
|
process,
|
||||||
sync::{Arc, RwLockWriteGuard},
|
sync::Arc,
|
||||||
thread::{self, JoinHandle},
|
thread::{self, JoinHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use parking_lot::RwLockWriteGuard;
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
|
|
||||||
pub fn start_client(config: config::Schema) {
|
pub fn start_client(config: config::Schema) {
|
||||||
@@ -79,41 +81,38 @@ pub fn handle_daemon_client(mut stream: UnixStream, config: Arc<config::Schema>)
|
|||||||
"list" => {
|
"list" => {
|
||||||
_ = writeln!(stream, "aquiring read lock");
|
_ = writeln!(stream, "aquiring read lock");
|
||||||
let rlock = config.hosts.read();
|
let rlock = config.hosts.read();
|
||||||
match rlock {
|
_ = writeln!(stream, "{rlock:#?}");
|
||||||
Ok(lock) => {
|
|
||||||
_ = writeln!(stream, "{lock:#?}");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
_ = writeln!(stream, "err with read lock: {err:?}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
"create" => {
|
"create" => {
|
||||||
if let [name, value] = args {
|
if let [name, value] = args {
|
||||||
match value.parse::<net::SocketAddr>() {
|
if let Ok([value, id, csrf]) =
|
||||||
Ok(addr) => {
|
<_ as TryInto<[&str; 3]>>::try_into(
|
||||||
_ = writeln!(stream, "aquiring write lock");
|
value.split(',').take(3).collect::<Vec<_>>(),
|
||||||
let wlock = config.hosts.write();
|
)
|
||||||
match wlock {
|
{
|
||||||
Ok(mut lock) => {
|
match value.parse::<net::SocketAddr>() {
|
||||||
lock.insert(name.to_string(), addr);
|
Ok(addr) => {
|
||||||
let lock = RwLockWriteGuard::downgrade(lock);
|
_ = writeln!(stream, "aquiring write lock");
|
||||||
_ = writeln!(stream, "{lock:#?}");
|
let mut wlock = config.hosts.write();
|
||||||
}
|
wlock.insert(
|
||||||
Err(err) => {
|
name.to_string(),
|
||||||
_ = writeln!(
|
(addr, id.to_string(), csrf.to_string()),
|
||||||
stream,
|
);
|
||||||
"err with write lock: {err:?}"
|
let rlock = RwLockWriteGuard::downgrade(wlock);
|
||||||
);
|
_ = writeln!(stream, "{rlock:#?}");
|
||||||
}
|
}
|
||||||
};
|
Err(err) => {
|
||||||
}
|
_ = writeln!(
|
||||||
Err(err) => {
|
stream,
|
||||||
_ = writeln!(
|
"err: parsing value as socket addres {err:?}"
|
||||||
stream,
|
);
|
||||||
"err: parsing value as socket addres {err:?}"
|
}
|
||||||
);
|
};
|
||||||
}
|
} else {
|
||||||
|
_ = writeln!(
|
||||||
|
stream,
|
||||||
|
"err: value wasn't 3 comma separated values"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
_ = writeln!(
|
_ = writeln!(
|
||||||
@@ -125,17 +124,10 @@ pub fn handle_daemon_client(mut stream: UnixStream, config: Arc<config::Schema>)
|
|||||||
"delete" => {
|
"delete" => {
|
||||||
if let [name] = args {
|
if let [name] = args {
|
||||||
_ = writeln!(stream, "aquiring write lock");
|
_ = writeln!(stream, "aquiring write lock");
|
||||||
let wlock = config.hosts.write();
|
let mut wlock = config.hosts.write();
|
||||||
match wlock {
|
wlock.remove(name);
|
||||||
Ok(mut lock) => {
|
let lock = RwLockWriteGuard::downgrade(wlock);
|
||||||
lock.remove(name);
|
_ = writeln!(stream, "{lock:#?}");
|
||||||
let lock = RwLockWriteGuard::downgrade(lock);
|
|
||||||
_ = writeln!(stream, "{lock:#?}");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
_ = writeln!(stream, "err with write lock: {err:?}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
_ = writeln!(stream, "invalid arg count, expected a name");
|
_ = writeln!(stream, "invalid arg count, expected a name");
|
||||||
}
|
}
|
||||||
|
58
src/main.rs
58
src/main.rs
@@ -1,5 +1,10 @@
|
|||||||
//! # Tuxcord Reverse Proxy Header Authenthication
|
//! # Tuxcord Reverse Proxy Header Authenthication
|
||||||
#![feature(rwlock_downgrade, try_blocks)]
|
#![feature(
|
||||||
|
rwlock_downgrade,
|
||||||
|
try_blocks,
|
||||||
|
iterator_try_collect,
|
||||||
|
anonymous_lifetime_in_impl_trait
|
||||||
|
)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
@@ -11,10 +16,13 @@ use std::{
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
use crate::utils::headers::HeadersExt;
|
||||||
|
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
pub mod ipc;
|
pub mod ipc;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
use args::Args;
|
use args::Args;
|
||||||
|
|
||||||
@@ -78,54 +86,30 @@ fn handle_client(client: &mut TcpStream, config: &config::Schema) -> Result<(),
|
|||||||
let mut header_buf = [0u8; 1024 * 8];
|
let mut header_buf = [0u8; 1024 * 8];
|
||||||
let mut read_pos = 0usize;
|
let mut read_pos = 0usize;
|
||||||
|
|
||||||
let pos = loop {
|
let mut headers;
|
||||||
|
let (pos, req) = loop {
|
||||||
|
headers = [httparse::EMPTY_HEADER; 16];
|
||||||
|
let mut req = httparse::Request::new(&mut headers);
|
||||||
|
|
||||||
let Ok(n) = client.read(&mut header_buf[read_pos..]) else {
|
let Ok(n) = client.read(&mut header_buf[read_pos..]) else {
|
||||||
return Err("error reading stream");
|
return Err("error reading stream");
|
||||||
};
|
};
|
||||||
read_pos += n;
|
read_pos += n;
|
||||||
|
|
||||||
let pos = header_buf
|
if let Ok(httparse::Status::Complete(n)) = req.parse(&header_buf[0..read_pos]) {
|
||||||
.windows(b"\r\n\r\n".len())
|
break (n - b"\r\n\r\n".len(), req);
|
||||||
.position(|w| w == b"\r\n\r\n");
|
}
|
||||||
if let Some(pos) = pos {
|
|
||||||
break pos;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut headers = [httparse::EMPTY_HEADER; 16];
|
let theres_body = req.headers.has_any(["conten-length", "transfer-encoding"]);
|
||||||
let mut req = httparse::Request::new(&mut headers);
|
|
||||||
let Ok(httparse::Status::Complete(_)) =
|
|
||||||
httparse::Request::parse(&mut req, &header_buf[0..(pos + b"\r\n\r\n".len())])
|
|
||||||
else {
|
|
||||||
return Err("parsing request was not complete");
|
|
||||||
};
|
|
||||||
|
|
||||||
let theres_body = req
|
let Some(host_header) = req.headers.get("host") else {
|
||||||
.headers
|
|
||||||
.iter()
|
|
||||||
.any(|header| header.name.to_lowercase() == "content-length")
|
|
||||||
|| req
|
|
||||||
.headers
|
|
||||||
.iter()
|
|
||||||
.any(|header| header.name.to_lowercase() == "transfer-encoding");
|
|
||||||
|
|
||||||
let Some(header) = req
|
|
||||||
.headers
|
|
||||||
.iter()
|
|
||||||
.find(|header| header.name.to_lowercase() == "host")
|
|
||||||
else {
|
|
||||||
return Err("failed to find \"host\" header");
|
return Err("failed to find \"host\" header");
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(host_header) = String::from_utf8(header.value.to_vec()) else {
|
|
||||||
return Err("\"host\" header is not valid UTF-8");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Now find that header and pas everything
|
// Now find that header and pas everything
|
||||||
let Ok(read_hosts) = config.hosts.read() else {
|
let read_hosts = config.hosts.read();
|
||||||
return Err("poisoned RwLock");
|
let Some((addr, _, _)) = read_hosts.get(host_header.as_ref()) else {
|
||||||
};
|
|
||||||
let Some(addr) = read_hosts.get(&host_header) else {
|
|
||||||
return Err("host not in hashmap");
|
return Err("host not in hashmap");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
src/utils.rs
Normal file
26
src/utils.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
pub mod headers {
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
pub trait HeadersExt<'a> {
|
||||||
|
fn has_any(&self, headers: impl IntoIterator<Item = &'_ str>) -> bool {
|
||||||
|
headers.into_iter().any(|h| self.has(h))
|
||||||
|
}
|
||||||
|
fn has_all(&self, headers: impl IntoIterator<Item = &'_ str>) -> bool {
|
||||||
|
headers.into_iter().all(|h| self.has(h))
|
||||||
|
}
|
||||||
|
fn has(&self, header: &str) -> bool;
|
||||||
|
fn get(&self, header: &str) -> Option<Cow<'a, str>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HeadersExt<'a> for &mut [httparse::Header<'a>] {
|
||||||
|
fn has(&self, header: &str) -> bool {
|
||||||
|
self.iter().any(|h| h.name.eq_ignore_ascii_case(header))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, header: &str) -> Option<Cow<'a, str>> {
|
||||||
|
self.iter()
|
||||||
|
.find(|h| h.name.eq_ignore_ascii_case(header))
|
||||||
|
.map(|h| String::from_utf8_lossy(h.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user