1
0
Fork 0
forked from zesterer/babble

Added persistent counts, faster RNG, stats in page

This commit is contained in:
Joshua Barretto 2025-04-28 22:55:12 +01:00
parent d602984fbd
commit f40478a58d
4 changed files with 63 additions and 37 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
/target
count.txt

32
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
version = 3
[[package]]
name = "addr2line"
@ -127,9 +127,9 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
version = "0.28.1"
version = "0.28.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ddeb19ee86cb16ecfc871e5b0660aff6285760957aaedda6284cf0e790d3769"
checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1"
dependencies = [
"bindgen",
"cc",
@ -287,9 +287,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
version = "1.2.19"
version = "1.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
dependencies = [
"jobserver",
"libc",
@ -503,9 +503,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
@ -992,7 +992,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.15",
"getrandom 0.2.16",
"libc",
"untrusted",
"windows-sys 0.52.0",
@ -1175,9 +1175,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.100"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
@ -1229,9 +1229,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.14"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
dependencies = [
"bytes",
"futures-core",
@ -1543,18 +1543,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.24"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.24"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",

View file

@ -1,7 +1,8 @@
[package]
name = "babble"
version = "0.1.0"
edition = "2024"
# edition = "2024"
edition = "2021"
[dependencies]
axum = "0.8.3"

View file

@ -1,18 +1,18 @@
mod generator;
use axum::{Router, extract::Path, response::Html, routing::get};
use axum::{extract::Path, response::Html, routing::get, Router};
use axum_server::{bind_rustls, tls_rustls::RustlsConfig};
use clap::Parser;
use hashbrown::HashMap;
use itertools::Itertools;
use rand::{Rng as _, prelude::*, random_range};
use rand_chacha::{ChaCha8Rng, rand_core::SeedableRng};
use rand::{prelude::*, Rng as _};
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use std::{
borrow::Cow,
path::PathBuf,
sync::{
Arc,
atomic::{AtomicU64, Ordering},
Arc,
},
time::Duration,
};
@ -32,6 +32,17 @@ pub struct Args {
key: Option<PathBuf>,
}
#[inline]
fn create_rng(seed_bytes: impl IntoIterator<Item = u8>) -> Rng {
let mut seed = [0; 32];
for (i, b) in seed_bytes.into_iter().take(seed.len()).enumerate() {
seed[i] = b;
}
Rng::from_seed(seed)
}
const COUNT_FILE: &str = "count.txt";
#[tokio::main]
async fn main() {
let args = Args::parse();
@ -41,43 +52,54 @@ async fn main() {
Arc::new(generator::Ast::new()),
];
let counter = Arc::new(AtomicU64::new(0));
let counter = Arc::new(AtomicU64::new(
if let Some(prev_count) = std::fs::read_to_string(COUNT_FILE)
.ok()
.and_then(|s| s.parse().ok())
{
prev_count
} else {
0
},
));
let app = {
let counter = counter.clone();
Router::new().route(
"/{id}",
get(|Path(id): Path<String>| async move {
tokio::time::sleep(Duration::from_millis(random_range(200..1000))).await;
counter.fetch_add(1, Ordering::Relaxed);
// Create a RNG for this path (deterministic, to simulate static pages)
let mut rng = create_rng(id.bytes());
let mut seed = [0; 32];
for (i, b) in id
.bytes()
.chain(core::iter::repeat(0))
.take(seed.len())
.enumerate()
{
seed[i] = b;
}
let mut rng = Rng::from_seed(seed);
// Count the request. Also doubles as the non-deterministic seed
let count = counter.fetch_add(1, Ordering::Relaxed);
// Create a RNG for this session (non-deterministic)
let mut session_rng = create_rng(count.to_le_bytes());
// Artificially slow down connections as rudimentary DDoS protection, and to use up client resources
tokio::time::sleep(Duration::from_millis(session_rng.random_range(200..1000)))
.await;
// Choose a bullshit generator from our collection for this page
let generator = generators.choose(&mut rng).unwrap();
let title = generator
.word_stream(rng.random_range(2..10), &mut rng.clone())
.join(" ");
let stats = format!("Served rubbish to {count} clients so far");
let content = generator
.word_stream(rng.random_range(50..5_000), &mut rng.clone())
.fold(String::new(), |mut content, word| {
// Small chance of every word becoming a link back into the void
if rng.random_bool(0.05) {
let url = generator.word_stream(3, &mut rng.clone()).join("-");
content += &format!(" <a href=\"{}\">{}</a>", url, word);
} else if rng.random_bool(0.01) {
content += ".<br>";
} else {
content += " ";
// Also, a chance for every word to end with a newline. This should probably be controlled by the generator.
content += if rng.random_bool(0.01) { ".<br>" } else { " " };
content += &word
}
content
@ -92,6 +114,7 @@ async fn main() {
<body>
<h1>{title}</h1>
<p>{stats}</p>
<p>{content}</p>
</body>
@ -116,6 +139,7 @@ async fn main() {
chrono::offset::Local::now(),
count,
);
let _ = std::fs::write(COUNT_FILE, &format!("{count}"));
}
}
});