diff --git a/Cargo.lock b/Cargo.lock index c70648e..67d6b9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,26 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.70" @@ -134,6 +154,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + [[package]] name = "bytemuck" version = "1.13.1" @@ -179,9 +205,12 @@ dependencies = [ "bytemuck", "color-eyre", "console-subscriber", + "css-minify", "eyre", "futures", "hyper", + "minify-html", + "minify-js 0.5.6", "once_cell", "serde", "serde_json", @@ -263,6 +292,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "crc32fast" version = "1.3.2" @@ -291,6 +326,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "css-minify" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd" +dependencies = [ + "derive_more", + "indexmap", + "nom", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "either" version = "1.8.1" @@ -430,6 +489,16 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "bumpalo", +] + [[package]] name = "hdrhistogram" version = "7.5.2" @@ -541,7 +610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -607,6 +676,40 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minify-html" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4d9147754a49e80557df835eb59e743eab1bf75410a134f55dc4b9dbb692ad" +dependencies = [ + "aho-corasick", + "css-minify", + "lazy_static", + "memchr", + "minify-js 0.4.3", + "rustc-hash", +] + +[[package]] +name = "minify-js" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c300f90ba1138b5c5daf5d9441dc9bdc67b808aac22cf638362a2647bc213be4" +dependencies = [ + "lazy_static", + "parse-js 0.10.3", +] + +[[package]] +name = "minify-js" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22d6c512a82abddbbc13b70609cb2beff01be2c7afff534d6e5e1c85e438fc8b" +dependencies = [ + "lazy_static", + "parse-js 0.17.0", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -709,6 +812,30 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "parse-js" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5" +dependencies = [ + "aho-corasick", + "lazy_static", + "memchr", +] + +[[package]] +name = "parse-js" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec3b11d443640ec35165ee8f6f0559f1c6f41878d70330fe9187012b5935f02" +dependencies = [ + "aho-corasick", + "bumpalo", + "hashbrown 0.13.2", + "lazy_static", + "memchr", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -863,6 +990,21 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -875,6 +1017,12 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.157" @@ -1238,6 +1386,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 2a418f3..1d2ceb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,8 +26,14 @@ color-eyre = "0.6.2" tracing-error = "0.2.0" zerocopy = "0.6.1" tokio-stream = { version = "0.1.14", features = ["sync"] } +minify-html = "0.11.1" + +[build-dependencies] +minify-js = { version = "0.5.6", optional = true } +minify-html = { version = "0.11.1", optional = true } +css-minify = { version = "0.3.1", optional = true } [features] default = ["debug_server"] -debug_server = ["dep:hyper"] +debug_server = ["dep:hyper", "minify-html", "dep:minify-js", "dep:css-minify"] tokio_console = ["dep:console-subscriber"] diff --git a/src/debug_server.rs b/src/debug_server.rs index 0fd3bc2..50024e2 100644 --- a/src/debug_server.rs +++ b/src/debug_server.rs @@ -46,35 +46,9 @@ pub async fn debug_server( let change_receiver = WatchStream::new(change_receiver.clone()); async move { match (req.method(), req.uri().path()) { - (&Method::GET, "/") => Ok(Response::new(Body::from( - r#" - - - - - "#, - ))), + (&Method::GET, "/") => Ok(Response::new(Body::from(include_str!( + concat!(env!("OUT_DIR"), "/minified.html") + )))), (&Method::GET, "/data") => { let res = Response::builder().header("Cache-Control", "no-store"); diff --git a/src/packets.rs b/src/packets.rs index 0738cfc..f82b56c 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -2,6 +2,7 @@ use std::{ffi::CStr, fmt::Debug}; use bytemuck::{Pod, Zeroable}; use eyre::eyre; +use serde::Serialize; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::tcp::{ReadHalf, WriteHalf}, @@ -68,14 +69,14 @@ impl PacketKind { } } -#[derive(Default, Clone, Copy, Pod, Zeroable)] +#[derive(Serialize, Default, Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct Header { pub kind: u8, pub length: u8, } -#[derive(Default, Clone)] +#[derive(Serialize, Default, Clone)] pub struct Packet { pub header: Header, pub data: Vec, diff --git a/src/ports.rs b/src/ports.rs index af1effd..633d822 100644 --- a/src/ports.rs +++ b/src/ports.rs @@ -10,7 +10,7 @@ use std::{ }; use eyre::eyre; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use tokio::{ net::TcpListener, sync::{watch::Receiver, Mutex}, @@ -27,19 +27,21 @@ use crate::{ #[derive(Default, Serialize, Deserialize)] pub struct PortHandler { - #[serde(skip)] + #[serde(skip_deserializing)] + #[serde(serialize_with = "serialize_last_update")] pub last_update: Option, #[serde(skip)] pub change_sender: Option>, - #[serde(skip)] + #[serde(skip_deserializing)] port_guards: HashMap, allowed_ports: AllowedList, #[serde(skip)] free_ports: HashSet, + errored_ports: BTreeSet<(UnixTimestamp, Port)>, allocated_ports: HashMap, @@ -50,6 +52,23 @@ pub struct PortHandler { pub names: HashMap, } +#[allow(clippy::missing_errors_doc)] +pub fn serialize_last_update( + last_update: &Option, + serializer: S, +) -> Result { + last_update + .and_then(|instant| { + Some( + (SystemTime::now() + instant.elapsed()) + .duration_since(UNIX_EPOCH) + .ok()? + .as_secs(), + ) + }) + .serialize(serializer) +} + #[instrument(skip(port_handler, change_receiver))] pub async fn cache_daemon( port_handler: Arc>, @@ -151,9 +170,16 @@ impl PortHandler { #[instrument(skip(self))] pub fn store(&self, cache: &Path) -> std::io::Result<()> { debug!("storing cache"); - let temp_file = cache.with_extension(".temp"); + let temp_file = cache.with_extension("temp"); - serde_json::to_writer(BufWriter::new(File::create(&temp_file)?), self)?; + let mut value = serde_json::to_value(self)?; + + let value_object = value.as_object_mut().unwrap(); + + value_object.remove("port_guards").unwrap(); + value_object.remove("last_update").unwrap(); + + serde_json::to_writer(BufWriter::new(File::create(&temp_file)?), &value)?; std::fs::rename(temp_file, cache)?; Ok(()) @@ -259,6 +285,15 @@ struct Rejector { handle: JoinHandle<()>, } +impl Serialize for Rejector { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.state.1.serialize(serializer) + } +} + impl Debug for Rejector { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Rejector")