From f80a081e699b89a93569c003c1f5921961fd2307 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 22 Sep 2024 20:06:13 -0300 Subject: [PATCH] Update RNG --- Cargo.lock | 53 +++--- wtx-instances/Cargo.toml | 2 + .../generic-examples/client-api-framework.rs | 6 +- wtx-instances/generic-examples/grpc-server.rs | 2 + .../generic-examples/http2-client.rs | 4 +- .../generic-examples/http2-server.rs | 4 +- .../generic-examples/web-socket-client.rs | 4 +- .../generic-examples/web-socket-server.rs | 4 +- .../http-server-framework-cors.rs | 9 +- .../http-server-framework-redirect.rs | 13 +- .../http-server-framework-session.rs | 13 +- .../http-server-framework.rs | 6 +- wtx-instances/src/bin/autobahn-client.rs | 8 +- wtx-instances/src/bin/autobahn-server.rs | 4 +- wtx-instances/src/bin/h2spec-server.rs | 4 +- wtx-instances/src/lib.rs | 4 +- wtx-ui/src/schema_manager.rs | 4 +- wtx-ui/src/web_socket.rs | 6 +- wtx/Cargo.toml | 5 +- .../client/postgres/integration_tests.rs | 6 +- .../database/client/postgres/statements.rs | 6 +- .../schema_manager/integration_tests.rs | 4 +- .../http/low_level_server/tokio_web_socket.rs | 8 +- wtx/src/http/server_framework.rs | 22 ++- wtx/src/http2/hpack_decoder.rs | 4 +- wtx/src/http2/hpack_encoder.rs | 4 +- wtx/src/http2/http2_buffer.rs | 5 +- wtx/src/http2/tests/connections.rs | 6 +- wtx/src/http2/tests/hpack.rs | 4 +- wtx/src/misc/rng.rs | 68 +------ wtx/src/misc/rng/no_std_rng.rs | 63 ------- wtx/src/misc/rng/rand.rs | 30 --- wtx/src/misc/rng/rand_chacha.rs | 45 +++++ wtx/src/misc/rng/seed.rs | 41 +++++ wtx/src/misc/rng/std_rng.rs | 117 ------------ wtx/src/misc/rng/xorshift.rs | 171 ++++++++++++++++++ wtx/src/pool/resource_manager.rs | 12 +- wtx/src/web_socket/handshake/tests.rs | 88 +++++++-- 38 files changed, 465 insertions(+), 394 deletions(-) delete mode 100644 wtx/src/misc/rng/no_std_rng.rs delete mode 100644 wtx/src/misc/rng/rand.rs create mode 100644 wtx/src/misc/rng/rand_chacha.rs create mode 100644 wtx/src/misc/rng/seed.rs delete mode 100644 wtx/src/misc/rng/std_rng.rs create mode 100644 wtx/src/misc/rng/xorshift.rs diff --git a/Cargo.lock b/Cargo.lock index 816f18ab..ed27aefb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,15 +231,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.19" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "jobserver", "libc", @@ -293,9 +293,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", "clap_derive", @@ -303,9 +303,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstyle", "clap_lex", @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -527,9 +527,9 @@ checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -723,9 +723,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -1106,9 +1106,9 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "smallvec" @@ -1228,18 +1228,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1332,9 +1332,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "serde", @@ -1524,9 +1524,9 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -1663,7 +1663,8 @@ dependencies = [ "memchr", "proptest", "quick-protobuf", - "rand", + "rand_chacha", + "rand_core", "ring", "rust_decimal", "rustls-pemfile", @@ -1700,6 +1701,8 @@ dependencies = [ "argon2", "pb-rs", "quick-protobuf", + "rand_chacha", + "rand_core", "serde", "serde_json", "tokio", diff --git a/wtx-instances/Cargo.toml b/wtx-instances/Cargo.toml index 0d0bc873..24824880 100644 --- a/wtx-instances/Cargo.toml +++ b/wtx-instances/Cargo.toml @@ -107,6 +107,8 @@ pb-rs = { default-features = false, version = "0.10" } [dependencies] argon2 = { default-features = false, version = "0.5" } quick-protobuf = { default-features = false, version = "0.8" } +rand_chacha = { default-features = false, version = "0.3" } +rand_core = { default-features = false, feature = ["getrandom"], version = "0.6" } serde = { default-features = false, version = "1.0" } serde_json = { default-features = false, features = ["alloc"], version = "1.0" } tokio = { default-features = false, features = ["macros", "rt-multi-thread"], version = "1.0" } diff --git a/wtx-instances/generic-examples/client-api-framework.rs b/wtx-instances/generic-examples/client-api-framework.rs index 2cd0631a..3abf9186 100644 --- a/wtx-instances/generic-examples/client-api-framework.rs +++ b/wtx-instances/generic-examples/client-api-framework.rs @@ -21,7 +21,7 @@ use wtx::{ }, data_transformation::dnsn::SerdeJson, http::client_framework::ClientFrameworkTokio, - misc::{NoStdRng, Uri}, + misc::{simple_seed, Uri, Xorshift64}, web_socket::{FrameBufferVec, HeadersBuffer, WebSocketBuffer, WebSocketClient}, }; @@ -97,7 +97,7 @@ async fn http_pair( async fn web_socket_pair() -> wtx::Result< Pair< PkgsAux, - (FrameBufferVec, WebSocketClient<(), NoStdRng, TcpStream, WebSocketBuffer>), + (FrameBufferVec, WebSocketClient<(), Xorshift64, TcpStream, WebSocketBuffer>), >, > { let mut fb = FrameBufferVec::default(); @@ -107,7 +107,7 @@ async fn web_socket_pair() -> wtx::Result< &mut fb, [], &mut HeadersBuffer::default(), - NoStdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(uri.hostname_with_implied_port()).await?, &uri, WebSocketBuffer::default(), diff --git a/wtx-instances/generic-examples/grpc-server.rs b/wtx-instances/generic-examples/grpc-server.rs index b3bad32d..05d14ef3 100644 --- a/wtx-instances/generic-examples/grpc-server.rs +++ b/wtx-instances/generic-examples/grpc-server.rs @@ -13,6 +13,7 @@ use wtx::{ server_framework::{post, Router, ServerFrameworkBuilder, State}, ReqResBuffer, StatusCode, }, + misc::{simple_seed, Xorshift64}, }; use wtx_instances::grpc_bindings::wtx::{GenericRequest, GenericResponse}; @@ -28,6 +29,7 @@ async fn main() -> wtx::Result<()> { .listen_tls( (wtx_instances::CERT, wtx_instances::KEY), &wtx_instances::host_from_args(), + Xorshift64::from(simple_seed()), |error| eprintln!("{error}"), ) .await diff --git a/wtx-instances/generic-examples/http2-client.rs b/wtx-instances/generic-examples/http2-client.rs index 81fc7131..5ff5e9ae 100644 --- a/wtx-instances/generic-examples/http2-client.rs +++ b/wtx-instances/generic-examples/http2-client.rs @@ -10,14 +10,14 @@ use tokio::net::TcpStream; use wtx::{ http::{Method, ReqResBuffer, Request}, http2::{Http2Buffer, Http2ErrorCode, Http2Params, Http2Tokio}, - misc::{from_utf8_basic, NoStdRng, Uri}, + misc::{from_utf8_basic, simple_seed, Uri, Xorshift64}, }; #[tokio::main] async fn main() -> wtx::Result<()> { let uri = Uri::new("http://www.example.com"); let (frame_reader, mut http2) = Http2Tokio::connect( - Http2Buffer::new(NoStdRng::default()), + Http2Buffer::new(Xorshift64::from(simple_seed())), Http2Params::default(), TcpStream::connect(uri.hostname_with_implied_port()).await?.into_split(), ) diff --git a/wtx-instances/generic-examples/http2-server.rs b/wtx-instances/generic-examples/http2-server.rs index 6b4b9920..2c764e16 100644 --- a/wtx-instances/generic-examples/http2-server.rs +++ b/wtx-instances/generic-examples/http2-server.rs @@ -7,14 +7,14 @@ extern crate wtx_instances; use wtx::{ http::{LowLevelServer, ReqResBuffer, Request, Response, StatusCode}, http2::{Http2Buffer, Http2Params}, - misc::{StdRng, TokioRustlsAcceptor}, + misc::{simple_seed, TokioRustlsAcceptor, Xorshift64}, }; #[tokio::main] async fn main() -> wtx::Result<()> { LowLevelServer::tokio_http2( &wtx_instances::host_from_args(), - || Ok(((), Http2Buffer::new(StdRng::default()), Http2Params::default())), + || Ok(((), Http2Buffer::new(Xorshift64::from(simple_seed())), Http2Params::default())), |error| eprintln!("{error}"), handle, || Ok(((), ReqResBuffer::empty())), diff --git a/wtx-instances/generic-examples/web-socket-client.rs b/wtx-instances/generic-examples/web-socket-client.rs index 3494ca89..b1c8c1be 100644 --- a/wtx-instances/generic-examples/web-socket-client.rs +++ b/wtx-instances/generic-examples/web-socket-client.rs @@ -12,7 +12,7 @@ use tokio::{ net::TcpStream, }; use wtx::{ - misc::{StdRng, Uri}, + misc::{simple_seed, Uri, Xorshift64}, web_socket::{ FrameBufferVec, FrameMutVec, HeadersBuffer, OpCode, WebSocketBuffer, WebSocketClient, }, @@ -27,7 +27,7 @@ async fn main() -> wtx::Result<()> { fb, [], &mut HeadersBuffer::default(), - StdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(uri.hostname_with_implied_port()).await?, &uri.to_ref(), WebSocketBuffer::default(), diff --git a/wtx-instances/generic-examples/web-socket-server.rs b/wtx-instances/generic-examples/web-socket-server.rs index 0aa2830f..93ea5be1 100644 --- a/wtx-instances/generic-examples/web-socket-server.rs +++ b/wtx-instances/generic-examples/web-socket-server.rs @@ -9,7 +9,7 @@ use tokio::net::TcpStream; use tokio_rustls::server::TlsStream; use wtx::{ http::LowLevelServer, - misc::{StdRng, TokioRustlsAcceptor}, + misc::{TokioRustlsAcceptor, Xorshift64}, web_socket::{FrameBufferVec, OpCode, WebSocketBuffer, WebSocketServer}, }; @@ -35,7 +35,7 @@ async fn main() -> wtx::Result<()> { async fn handle( fb: &mut FrameBufferVec, - mut ws: WebSocketServer<(), StdRng, TlsStream, &mut WebSocketBuffer>, + mut ws: WebSocketServer<(), Xorshift64, TlsStream, &mut WebSocketBuffer>, ) -> wtx::Result<()> { loop { let mut frame = ws.read_frame(fb).await?; diff --git a/wtx-instances/http-server-framework-examples/http-server-framework-cors.rs b/wtx-instances/http-server-framework-examples/http-server-framework-cors.rs index 1da72bc6..69d61dc3 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework-cors.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework-cors.rs @@ -1,13 +1,18 @@ //! The `CorsMiddleware` middleware inserts permissive CORS headers in every response. -use wtx::http::server_framework::{get, CorsMiddleware, Router, ServerFrameworkBuilder}; +use wtx::{ + http::server_framework::{get, CorsMiddleware, Router, ServerFrameworkBuilder}, + misc::{simple_seed, Xorshift64}, +}; #[tokio::main] async fn main() -> wtx::Result<()> { let router = Router::new(wtx::paths!(("/hello", get(hello))), (), CorsMiddleware::permissive())?; ServerFrameworkBuilder::new(router) .without_aux() - .listen("0.0.0.0:9000", |error: wtx::Error| eprintln!("{error:?}")) + .listen("0.0.0.0:9000", Xorshift64::from(simple_seed()), |error: wtx::Error| { + eprintln!("{error:?}") + }) .await?; Ok(()) } diff --git a/wtx-instances/http-server-framework-examples/http-server-framework-redirect.rs b/wtx-instances/http-server-framework-examples/http-server-framework-redirect.rs index 36fa04ab..c0f9d009 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework-redirect.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework-redirect.rs @@ -1,8 +1,11 @@ //! Different types of redirects. -use wtx::http::{ - server_framework::{get, Redirect, Router, ServerFrameworkBuilder, StateClean}, - ReqResBuffer, StatusCode, +use wtx::{ + http::{ + server_framework::{get, Redirect, Router, ServerFrameworkBuilder, StateClean}, + ReqResBuffer, StatusCode, + }, + misc::{simple_seed, Xorshift64}, }; #[tokio::main] @@ -11,7 +14,9 @@ async fn main() -> wtx::Result<()> { Router::paths(wtx::paths!(("/permanent", get(permanent)), ("/temporary", get(temporary))))?; ServerFrameworkBuilder::new(router) .without_aux() - .listen(&wtx_instances::host_from_args(), |error| eprintln!("{error}")) + .listen(&wtx_instances::host_from_args(), Xorshift64::from(simple_seed()), |error| { + eprintln!("{error}") + }) .await } diff --git a/wtx-instances/http-server-framework-examples/http-server-framework-session.rs b/wtx-instances/http-server-framework-examples/http-server-framework-session.rs index 8957cd5d..15703e9b 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework-session.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework-session.rs @@ -19,8 +19,10 @@ //! //! ALTER TABLE session ADD CONSTRAINT session__user__fk FOREIGN KEY (user_id) REFERENCES "user" (id); //! ``` +//! use argon2::{Algorithm, Argon2, Block, Params, Version}; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use tokio::net::TcpStream; use wtx::{ database::{Executor, Record}, @@ -28,7 +30,7 @@ use wtx::{ server_framework::{get, post, Router, ServerFrameworkBuilder, State, StateClean}, ReqResBuffer, ReqResData, SessionDecoder, SessionEnforcer, SessionTokio, StatusCode, }, - misc::{Rng, StdRng}, + misc::Rng, pool::{PostgresRM, SimplePoolTokio}, }; @@ -47,7 +49,7 @@ const ARGON2_PARAMS: Params = { const LOGIN: &str = "/login"; const LOGOUT: &str = "/logout"; -type ConnAux = (Session, StdRng); +type ConnAux = (Session, ChaCha20Rng); type Pool = SimplePoolTokio>; type Session = SessionTokio; @@ -59,7 +61,7 @@ async fn main() -> wtx::Result<()> { (), )?; let pool = Pool::new(4, PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME".into())); - let mut rng = StdRng::default(); + let mut rng = ChaCha20Rng::from_entropy(); let mut key = [0; 16]; rng.fill_slice(&mut key); let (expired_sessions, session) = Session::builder(key, pool).build(); @@ -68,9 +70,10 @@ async fn main() -> wtx::Result<()> { eprintln!("{err}"); } }); + let rng_clone = rng.clone(); ServerFrameworkBuilder::new(router) - .with_conn_aux(move || (session.clone(), rng)) - .listen("0.0.0.0:9000", |error: wtx::Error| eprintln!("{error:?}")) + .with_conn_aux(move || (session.clone(), rng_clone.clone())) + .listen("0.0.0.0:9000", rng, |error: wtx::Error| eprintln!("{error:?}")) .await?; Ok(()) } diff --git a/wtx-instances/http-server-framework-examples/http-server-framework.rs b/wtx-instances/http-server-framework-examples/http-server-framework.rs index a698dcfb..1774fbb8 100644 --- a/wtx-instances/http-server-framework-examples/http-server-framework.rs +++ b/wtx-instances/http-server-framework-examples/http-server-framework.rs @@ -21,7 +21,7 @@ use wtx::{ }, ReqResBuffer, Request, Response, StatusCode, }, - misc::FnFutWrapper, + misc::{simple_seed, FnFutWrapper, Xorshift64}, pool::{PostgresRM, SimplePoolTokio}, }; @@ -45,7 +45,9 @@ async fn main() -> wtx::Result<()> { let pool = Pool::new(4, rm); ServerFrameworkBuilder::new(router) .with_req_aux(move || pool.clone()) - .listen(&wtx_instances::host_from_args(), |error| eprintln!("{error:?}")) + .listen(&wtx_instances::host_from_args(), Xorshift64::from(simple_seed()), |error| { + eprintln!("{error:?}") + }) .await } diff --git a/wtx-instances/src/bin/autobahn-client.rs b/wtx-instances/src/bin/autobahn-client.rs index 2eed1514..c31bdc72 100644 --- a/wtx-instances/src/bin/autobahn-client.rs +++ b/wtx-instances/src/bin/autobahn-client.rs @@ -2,7 +2,7 @@ use tokio::net::TcpStream; use wtx::{ - misc::{StdRng, UriRef}, + misc::{simple_seed, UriRef, Xorshift64}, web_socket::{ compression::Flate2, CloseCode, FrameBufferVec, FrameMutVec, HeadersBuffer, OpCode, WebSocketBuffer, WebSocketClient, @@ -20,7 +20,7 @@ async fn main() -> wtx::Result<()> { fb, [], &mut HeadersBuffer::default(), - StdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(host).await?, &UriRef::new(&format!("http://{host}/runCase?case={case}&agent=wtx")), &mut wsb, @@ -47,7 +47,7 @@ async fn main() -> wtx::Result<()> { fb, [], &mut HeadersBuffer::default(), - StdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(host).await?, &UriRef::new(&format!("http://{host}/updateReports?agent=wtx")), wsb, @@ -68,7 +68,7 @@ async fn get_case_count( fb, [], &mut HeadersBuffer::default(), - StdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(host).await?, &UriRef::new(&format!("http://{host}/getCaseCount")), wsb, diff --git a/wtx-instances/src/bin/autobahn-server.rs b/wtx-instances/src/bin/autobahn-server.rs index 91dfba09..230289d4 100644 --- a/wtx-instances/src/bin/autobahn-server.rs +++ b/wtx-instances/src/bin/autobahn-server.rs @@ -5,7 +5,7 @@ use tokio::net::TcpStream; use wtx::{ http::LowLevelServer, - misc::StdRng, + misc::Xorshift64, web_socket::{ compression::{Flate2, NegotiatedFlate2}, FrameBufferVec, OpCode, WebSocketBuffer, WebSocketServer, @@ -27,7 +27,7 @@ async fn main() -> wtx::Result<()> { async fn handle( fb: &mut FrameBufferVec, - mut ws: WebSocketServer, StdRng, TcpStream, &mut WebSocketBuffer>, + mut ws: WebSocketServer, Xorshift64, TcpStream, &mut WebSocketBuffer>, ) -> wtx::Result<()> { loop { let mut frame = ws.read_frame(fb).await?; diff --git a/wtx-instances/src/bin/h2spec-server.rs b/wtx-instances/src/bin/h2spec-server.rs index 8f6b0e09..4f47b14d 100644 --- a/wtx-instances/src/bin/h2spec-server.rs +++ b/wtx-instances/src/bin/h2spec-server.rs @@ -5,7 +5,7 @@ use wtx::{ http::{LowLevelServer, ReqResBuffer, Request, Response, StatusCode}, http2::{Http2Buffer, Http2Params}, - misc::StdRng, + misc::{simple_seed, Xorshift64}, }; #[tokio::main] @@ -14,7 +14,7 @@ async fn main() -> wtx::Result<()> { let _rslt = wtx::misc::tracing_tree_init(None); LowLevelServer::tokio_http2( "127.0.0.1:9000", - || Ok(((), Http2Buffer::new(StdRng::default()), Http2Params::default())), + || Ok(((), Http2Buffer::new(Xorshift64::from(simple_seed())), Http2Params::default())), |error| eprintln!("{error}"), handle, || Ok(((), ReqResBuffer::empty())), diff --git a/wtx-instances/src/lib.rs b/wtx-instances/src/lib.rs index bfc68e19..b38fd2ec 100644 --- a/wtx-instances/src/lib.rs +++ b/wtx-instances/src/lib.rs @@ -20,7 +20,7 @@ pub mod grpc_bindings; use tokio::net::TcpStream; use wtx::{ database::client::postgres::{Config, Executor, ExecutorBuffer}, - misc::{NoStdRng, Uri}, + misc::{simple_seed, Uri, Xorshift64}, }; /// Certificate @@ -35,7 +35,7 @@ pub async fn executor( uri_str: &str, ) -> wtx::Result> { let uri = Uri::new(uri_str); - let mut rng = NoStdRng::default(); + let mut rng = Xorshift64::from(simple_seed()); Executor::connect( &Config::from_uri(&uri)?, ExecutorBuffer::with_default_params(&mut rng)?, diff --git a/wtx-ui/src/schema_manager.rs b/wtx-ui/src/schema_manager.rs index 2905bc94..7ecbb2db 100644 --- a/wtx-ui/src/schema_manager.rs +++ b/wtx-ui/src/schema_manager.rs @@ -7,7 +7,7 @@ use wtx::{ schema_manager::{Commands, DbMigration, SchemaManagement, DEFAULT_CFG_FILE_NAME}, Identifier, DEFAULT_URI_VAR, }, - misc::{StdRng, UriRef, Vector}, + misc::{simple_seed, UriRef, Vector, Xorshift64}, }; pub(crate) async fn schema_manager(sm: SchemaManager) -> wtx::Result<()> { @@ -21,7 +21,7 @@ pub(crate) async fn schema_manager(sm: SchemaManager) -> wtx::Result<()> { let uri = UriRef::new(&var); match uri.scheme() { "postgres" | "postgresql" => { - let mut rng = StdRng::default(); + let mut rng = Xorshift64::from(simple_seed()); let executor = Executor::connect( &Config::from_uri(&uri)?, ExecutorBuffer::with_default_params(&mut rng)?, diff --git a/wtx-ui/src/web_socket.rs b/wtx-ui/src/web_socket.rs index 226c720c..0124c632 100644 --- a/wtx-ui/src/web_socket.rs +++ b/wtx-ui/src/web_socket.rs @@ -3,7 +3,7 @@ use tokio::{ net::{TcpListener, TcpStream}, }; use wtx::{ - misc::{StdRng, UriRef}, + misc::{simple_seed, UriRef, Xorshift64}, web_socket::{ FrameBufferVec, FrameMutVec, HeadersBuffer, OpCode, WebSocketBuffer, WebSocketClient, WebSocketServer, @@ -19,7 +19,7 @@ pub(crate) async fn connect(uri: &str, cb: impl Fn(&str)) -> wtx::Result<()> { fb, [], &mut HeadersBuffer::default(), - StdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(uri.hostname_with_implied_port()).await?, &uri, wsb, @@ -60,7 +60,7 @@ pub(crate) async fn serve( let sun = || async move { let mut ws = WebSocketServer::accept( (), - StdRng::default(), + Xorshift64::from(simple_seed()), stream, WebSocketBuffer::default(), |_| true, diff --git a/wtx/Cargo.toml b/wtx/Cargo.toml index 0db5b2f9..5d2dd91d 100644 --- a/wtx/Cargo.toml +++ b/wtx/Cargo.toml @@ -18,7 +18,8 @@ matchit = { default-features = false, optional = true, version = "0.8" } memchr = { default-features = false, optional = true, version = "2.0" } proptest = { default-features = false, features = ["alloc"], optional = true, version = "1.0" } quick-protobuf = { default-features = false, optional = true, version = "0.8" } -rand = { default-features = false, features = ["small_rng"], optional = true, version = "0.8" } +rand_chacha = { default-features = false, optional = true, version = "0.3" } +rand_core = { default-features = false, optional = true, version = "0.6" } ring = { default-features = false, optional = true, version = "0.17" } rust_decimal = { default-features = false, features = ["maths"], optional = true, version = "1.0" } rustls-pemfile = { default-features = false, features = ["std"], optional = true, version = "2.0" } @@ -73,7 +74,7 @@ pool = [] postgres = ["ahash", "base64", "crypto-common", "database", "digest", "hashbrown", "hmac", "sha2"] proptest = ["dep:proptest"] quick-protobuf = ["dep:quick-protobuf", "std"] -rand = ["dep:rand"] +rand_chacha = ["dep:rand_chacha", "dep:rand_core"] ring = ["dep:ring"] rust_decimal = ["dep:rust_decimal"] schema-manager = ["database", "chrono"] diff --git a/wtx/src/database/client/postgres/integration_tests.rs b/wtx/src/database/client/postgres/integration_tests.rs index 8d6baa2a..49f32e23 100644 --- a/wtx/src/database/client/postgres/integration_tests.rs +++ b/wtx/src/database/client/postgres/integration_tests.rs @@ -6,7 +6,7 @@ use crate::{ }, Decode, Encode, Executor as _, Record, Records as _, }, - misc::{NoStdRng, UriRef}, + misc::{simple_seed, UriRef, Xorshift64}, }; use alloc::string::String; use tokio::net::TcpStream; @@ -17,7 +17,7 @@ const SCRAM: &str = "postgres://wtx_scram:wtx@localhost/wtx"; #[tokio::test] async fn conn_scram_tls() { let uri = UriRef::new(SCRAM); - let mut rng = NoStdRng::default(); + let mut rng = Xorshift64::from(simple_seed()); let _executor = Executor::::connect_encrypted( &Config::from_uri(&uri).unwrap(), ExecutorBuffer::with_default_params(&mut rng).unwrap(), @@ -433,7 +433,7 @@ async fn serde_json() { async fn executor() -> Executor { let uri = UriRef::new(SCRAM); - let mut rng = NoStdRng::default(); + let mut rng = Xorshift64::from(simple_seed()); Executor::connect( &Config::from_uri(&uri).unwrap(), ExecutorBuffer::with_default_params(&mut rng).unwrap(), diff --git a/wtx/src/database/client/postgres/statements.rs b/wtx/src/database/client/postgres/statements.rs index d0e4f28d..c20285b1 100644 --- a/wtx/src/database/client/postgres/statements.rs +++ b/wtx/src/database/client/postgres/statements.rs @@ -246,13 +246,13 @@ mod tests { ty::Ty, Statements, }, - misc::{NoStdRng, Vector}, + misc::{simple_seed, Vector, Xorshift64}, }; #[test] fn stmt_if_duplicated() { let stmt_hash = 123; - let mut stmts = Statements::new(100, &mut NoStdRng::default()); + let mut stmts = Statements::new(100, &mut Xorshift64::from(simple_seed())); let PushRslt::Builder(builder) = stmts.push(stmt_hash) else { panic!() }; let _ = builder.finish(); let PushRslt::Stmt(_) = stmts.push(stmt_hash) else { panic!() }; @@ -260,7 +260,7 @@ mod tests { #[test] fn two_statements() { - let mut stmts = Statements::new(2, &mut NoStdRng::default()); + let mut stmts = Statements::new(2, &mut Xorshift64::from(simple_seed())); stmts.num_of_elements_to_remove_when_full = 1; let stmt_id0 = 123; diff --git a/wtx/src/database/schema_manager/integration_tests.rs b/wtx/src/database/schema_manager/integration_tests.rs index 4851a88d..d2d05cd7 100644 --- a/wtx/src/database/schema_manager/integration_tests.rs +++ b/wtx/src/database/schema_manager/integration_tests.rs @@ -11,7 +11,7 @@ use crate::{ }, Identifier, DEFAULT_URI_VAR, }, - misc::{NoStdRng, Vector}, + misc::{Vector, Xorshift64}, }; use alloc::string::String; use core::fmt::Write; @@ -44,7 +44,7 @@ macro_rules! create_integration_tests { let uri = crate::misc::UriRef::new(&uri); let config = crate::database::client::postgres::Config::from_uri(&uri).unwrap(); let stream = TcpStream::connect(uri.hostname_with_implied_port()).await.unwrap(); - let mut rng = NoStdRng::default(); + let mut rng = Xorshift64::from(crate::misc::simple_seed()); crate::database::client::postgres::Executor::connect( &config, crate::database::client::postgres::ExecutorBuffer::with_default_params(&mut rng).unwrap(), diff --git a/wtx/src/http/low_level_server/tokio_web_socket.rs b/wtx/src/http/low_level_server/tokio_web_socket.rs index 38b4e27d..2d815d39 100644 --- a/wtx/src/http/low_level_server/tokio_web_socket.rs +++ b/wtx/src/http/low_level_server/tokio_web_socket.rs @@ -1,6 +1,6 @@ use crate::{ http::LowLevelServer, - misc::{FnFut, StdRng, Stream, Vector, _number_or_available_parallelism}, + misc::{FnFut, Stream, Vector, Xorshift64, _number_or_available_parallelism, simple_seed}, pool::{SimplePoolGetElem, SimplePoolResource, SimplePoolTokio, WebSocketRM}, web_socket::{Compression, FrameBuffer, FrameBufferVec, WebSocketBuffer, WebSocketServer}, }; @@ -35,7 +35,7 @@ impl LowLevelServer { + FnFut< ( &'fb mut FrameBufferVec, - WebSocketServer, + WebSocketServer, ), Result = Result<(), E>, > + Send @@ -44,7 +44,7 @@ impl LowLevelServer { SF: Send + Future>, for<'fb, 'wsb> , + WebSocketServer, )>>::Future: Send, for<'handle> &'handle F: Send, { @@ -69,7 +69,7 @@ impl LowLevelServer { fb, WebSocketServer::accept( local_compression_cb(), - StdRng::default(), + Xorshift64::from(simple_seed()), stream, wsb, |_| true, diff --git a/wtx/src/http/server_framework.rs b/wtx/src/http/server_framework.rs index 9349dceb..e266f69a 100644 --- a/wtx/src/http/server_framework.rs +++ b/wtx/src/http/server_framework.rs @@ -21,7 +21,7 @@ mod state; use crate::{ http::{ConnParams, LowLevelServer, ReqResBuffer, Request, Response}, http2::Http2Buffer, - misc::StdRng, + misc::Rng, }; use alloc::sync::Arc; pub use conn_aux::ConnAux; @@ -64,15 +64,19 @@ where { /// Starts listening to incoming requests based on the given `host`. #[inline] - pub async fn listen( + pub async fn listen( self, host: &str, + rng: RNG, err_cb: impl Clone + Fn(E) + Send + 'static, - ) -> crate::Result<()> { + ) -> crate::Result<()> + where + RNG: Clone + Rng + Send + 'static, + { let Self { ca_cb, cp, ra_cb, router } = self; LowLevelServer::tokio_http2( host, - move || Ok((CA::conn_aux(ca_cb())?, Http2Buffer::new(StdRng::default()), cp.to_hp())), + move || Ok((CA::conn_aux(ca_cb())?, Http2Buffer::new(rng.clone()), cp.to_hp())), err_cb, Self::handle, move || Ok(((ra_cb.clone(), Arc::clone(&router)), ReqResBuffer::empty())), @@ -84,16 +88,20 @@ where /// Starts listening to incoming encrypted requests based on the given `host`. #[cfg(feature = "tokio-rustls")] #[inline] - pub async fn listen_tls( + pub async fn listen_tls( self, (cert_chain, priv_key): (&'static [u8], &'static [u8]), host: &str, + rng: RNG, err_cb: impl Clone + Fn(E) + Send + 'static, - ) -> crate::Result<()> { + ) -> crate::Result<()> + where + RNG: Clone + Rng + Send + 'static, + { let Self { ca_cb, cp, ra_cb, router } = self; LowLevelServer::tokio_http2( host, - move || Ok((CA::conn_aux(ca_cb())?, Http2Buffer::new(StdRng::default()), cp.to_hp())), + move || Ok((CA::conn_aux(ca_cb())?, Http2Buffer::new(rng.clone()), cp.to_hp())), err_cb, Self::handle, move || Ok(((ra_cb.clone(), Arc::clone(&router)), ReqResBuffer::empty())), diff --git a/wtx/src/http2/hpack_decoder.rs b/wtx/src/http2/hpack_decoder.rs index cb5e6a21..0b349cc0 100644 --- a/wtx/src/http2/hpack_decoder.rs +++ b/wtx/src/http2/hpack_decoder.rs @@ -415,7 +415,7 @@ mod bench { use crate::{ http::Header, http2::{HpackDecoder, HpackEncoder}, - misc::{NoStdRng, Usize, Vector}, + misc::{simple_seed, Usize, Vector, Xorshift64}, }; #[bench] @@ -429,7 +429,7 @@ mod bench { rslt }; let mut buffer = Vector::with_capacity(*Usize::from(N)).unwrap(); - let mut he = HpackEncoder::new(NoStdRng::default()); + let mut he = HpackEncoder::new(Xorshift64::from(simple_seed())); he.set_max_dyn_super_bytes(N); he.encode(&mut buffer, [].into_iter(), { data.chunks_exact(128).map(|el| Header::from_name_and_value(&el[..64], &el[64..])) diff --git a/wtx/src/http2/hpack_encoder.rs b/wtx/src/http2/hpack_encoder.rs index 0a95c14d..487facba 100644 --- a/wtx/src/http2/hpack_encoder.rs +++ b/wtx/src/http2/hpack_encoder.rs @@ -647,14 +647,14 @@ mod bench { use crate::{ http::Header, http2::HpackEncoder, - misc::{NoStdRng, Usize, Vector}, + misc::{simple_seed, Usize, Vector, Xorshift64}, }; #[bench] fn encode(b: &mut test::Bencher) { const N: u32 = 1024 * 1024 * 4; let data = crate::bench::_data(*Usize::from(N)); - let mut he = HpackEncoder::new(NoStdRng::default()); + let mut he = HpackEncoder::new(Xorshift64::from(simple_seed())); he.set_max_dyn_super_bytes(N); let mut buffer = Vector::new(); b.iter(|| { diff --git a/wtx/src/http2/http2_buffer.rs b/wtx/src/http2/http2_buffer.rs index c0edf992..b331b252 100644 --- a/wtx/src/http2/http2_buffer.rs +++ b/wtx/src/http2/http2_buffer.rs @@ -1,7 +1,7 @@ use crate::{ http::Method, http2::{HpackDecoder, HpackEncoder, Scrp, Sorp, UriBuffer, U31}, - misc::{AtomicWaker, Lease, LeaseMut, PartitionedFilledBuffer, Rng, Vector}, + misc::{simple_seed, AtomicWaker, Lease, LeaseMut, PartitionedFilledBuffer, Rng, Vector}, }; use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; use core::{ @@ -77,11 +77,10 @@ impl Http2Buffer { } } -#[cfg(feature = "std")] impl Default for Http2Buffer { #[inline] fn default() -> Self { - Self::new(crate::misc::StdRng::default()) + Self::new(crate::misc::Xorshift64::from(simple_seed())) } } diff --git a/wtx/src/http2/tests/connections.rs b/wtx/src/http2/tests/connections.rs index 9a275e07..943cf35b 100644 --- a/wtx/src/http2/tests/connections.rs +++ b/wtx/src/http2/tests/connections.rs @@ -1,7 +1,7 @@ use crate::{ http::{Header, Headers, Method, ReqResBuffer, ReqResData, Request, StatusCode}, http2::{Http2Buffer, Http2ErrorCode, Http2Params, Http2Tokio}, - misc::{Either, NoStdRng, UriRef, UriString}, + misc::{simple_seed, Either, UriRef, UriString, Xorshift64}, tests::_uri, }; use core::time::Duration; @@ -20,7 +20,7 @@ async fn client(uri: &UriString) { let mut rrb = ReqResBuffer::empty(); rrb.headers.reserve(6, 1).unwrap(); let (frame_header, mut http2) = Http2Tokio::connect( - Http2Buffer::new(NoStdRng::default()), + Http2Buffer::new(Xorshift64::from(simple_seed())), Http2Params::default(), TcpStream::connect(uri.hostname_with_implied_port()).await.unwrap().into_split(), ) @@ -60,7 +60,7 @@ async fn server(uri: &UriString) { let (stream, _) = listener.accept().await.unwrap(); let mut rrb = ReqResBuffer::empty(); let (frame_header, mut http2) = Http2Tokio::accept( - Http2Buffer::new(NoStdRng::default()), + Http2Buffer::new(Xorshift64::from(simple_seed())), Http2Params::default(), stream.into_split(), ) diff --git a/wtx/src/http2/tests/hpack.rs b/wtx/src/http2/tests/hpack.rs index a648823f..c069cbc9 100644 --- a/wtx/src/http2/tests/hpack.rs +++ b/wtx/src/http2/tests/hpack.rs @@ -1,7 +1,7 @@ use crate::{ http::{Header, StatusCode}, http2::{HpackDecoder, HpackEncoder, HpackHeaderBasic, MAX_HPACK_LEN}, - misc::{from_utf8_basic, NoStdRng, Vector}, + misc::{from_utf8_basic, simple_seed, Vector, Xorshift64}, }; use alloc::string::String; use core::{fmt::Formatter, marker::PhantomData}; @@ -24,7 +24,7 @@ fn hpack_test_cases() { fetch_project(); let mut buffer = Vector::new(); let mut decoder = HpackDecoder::new(); - let mut encoder = HpackEncoder::new(NoStdRng::default()); + let mut encoder = HpackEncoder::new(Xorshift64::from(simple_seed())); decoder.set_max_bytes(MAX_HEADER_LEN); encoder.set_max_dyn_super_bytes(MAX_HEADER_LEN); let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("hpack-test-case"); diff --git a/wtx/src/misc/rng.rs b/wtx/src/misc/rng.rs index 94dfbf4b..d4bf9ba9 100644 --- a/wtx/src/misc/rng.rs +++ b/wtx/src/misc/rng.rs @@ -2,20 +2,18 @@ #[cfg(feature = "fastrand")] mod fastrand; -mod no_std_rng; -#[cfg(feature = "rand")] -mod rand; -#[cfg(feature = "std")] -mod std_rng; +#[cfg(feature = "rand_chacha")] +mod rand_chacha; +mod seed; +mod xorshift; -#[cfg(feature = "std")] -pub use self::std_rng::{StdRng, StdRngSync}; use crate::misc::Usize; use core::{ cell::Cell, ops::{Bound, RangeBounds}, }; -pub use no_std_rng::NoStdRng; +pub use seed::*; +pub use xorshift::*; /// Allows the creation of random instances. pub trait FromRng @@ -32,7 +30,7 @@ where { #[inline] fn from_rng(rng: &mut RNG) -> Self { - rng.u8_8()[0] + rng.u8() } } @@ -207,55 +205,3 @@ where (*self).u8_16() } } - -#[inline] -fn u8(n: u64) -> u8 { - let [a, ..] = n.to_be_bytes(); - a -} - -#[inline] -fn u8_4(n: u64) -> [u8; 4] { - let [a, b, c, d, ..] = n.to_be_bytes(); - [a, b, c, d] -} - -#[inline] -fn u8_8(n: u64) -> [u8; 8] { - n.to_be_bytes() -} - -#[inline] -fn u8_16(first: u64, second: u64) -> [u8; 16] { - let [a, b, c, d, e, f, g, h] = first.to_be_bytes(); - let [i, j, k, l, m, n, o, p] = second.to_be_bytes(); - [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] -} - -#[inline] -fn xor_numbers(seed: &mut u64) -> u64 { - *seed ^= *seed << 13; - *seed ^= *seed >> 17; - *seed ^= *seed << 5; - *seed -} - -#[inline] -fn xor_u8(seed: &mut u64) -> u8 { - u8(xor_numbers(seed)) -} - -#[inline] -fn xor_u8_4(seed: &mut u64) -> [u8; 4] { - u8_4(xor_numbers(seed)) -} - -#[inline] -fn xor_u8_8(seed: &mut u64) -> [u8; 8] { - u8_8(xor_numbers(seed)) -} - -#[inline] -fn xor_u8_16(seed: &mut u64) -> [u8; 16] { - u8_16(xor_numbers(seed), xor_numbers(seed)) -} diff --git a/wtx/src/misc/rng/no_std_rng.rs b/wtx/src/misc/rng/no_std_rng.rs deleted file mode 100644 index c7d34445..00000000 --- a/wtx/src/misc/rng/no_std_rng.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::misc::{ - rng::{xor_u8, xor_u8_16, xor_u8_4, xor_u8_8}, - Rng, Usize, -}; -use alloc::boxed::Box; -use core::{ - panic::Location, - ptr, - sync::atomic::{AtomicU64, Ordering}, -}; - -static COUNTER: AtomicU64 = AtomicU64::new(0); - -/// Uses a combination of weak strategies that will likely result in poor results. -/// -/// 1. The address of a heap allocation. -/// 2. A large fixed number. -/// 3. The value of an ever increasing static counter. -/// 4. The line and column of the caller location. -#[derive(Clone, Copy, Debug)] -pub struct NoStdRng(u64); - -impl Rng for NoStdRng { - #[inline] - fn u8(&mut self) -> u8 { - xor_u8(&mut self.0) - } - - #[inline] - fn u8_4(&mut self) -> [u8; 4] { - xor_u8_4(&mut self.0) - } - - #[inline] - fn u8_8(&mut self) -> [u8; 8] { - xor_u8_8(&mut self.0) - } - - #[inline] - fn u8_16(&mut self) -> [u8; 16] { - xor_u8_16(&mut self.0) - } -} - -impl Default for NoStdRng { - #[inline] - #[track_caller] - fn default() -> Self { - let elem = Box::new(Foo { _bar: 1, _baz: 2 }); - let ref_ptr = ptr::addr_of!(elem); - let mut n = Usize::from_usize(ref_ptr.addr()).into_u64(); - n = n.wrapping_add(11_400_714_819_323_198_485); - n = n.wrapping_add(COUNTER.fetch_add(3, Ordering::Release)); - let location = Location::caller(); - n ^= n << (u64::from(location.column().wrapping_add(location.line())) % 17); - Self(n) - } -} - -struct Foo { - _bar: usize, - _baz: usize, -} diff --git a/wtx/src/misc/rng/rand.rs b/wtx/src/misc/rng/rand.rs deleted file mode 100644 index a9ae8298..00000000 --- a/wtx/src/misc/rng/rand.rs +++ /dev/null @@ -1,30 +0,0 @@ -use rand::Rng; - -macro_rules! implement { - ($struct:ty) => { - impl crate::misc::rng::Rng for $struct { - #[inline] - fn u8(&mut self) -> u8 { - self.r#gen() - } - - #[inline] - fn u8_4(&mut self) -> [u8; 4] { - self.r#gen() - } - - #[inline] - fn u8_8(&mut self) -> [u8; 8] { - self.r#gen() - } - - #[inline] - fn u8_16(&mut self) -> [u8; 16] { - self.r#gen() - } - } - }; -} - -implement!(rand::rngs::mock::StepRng); -implement!(rand::rngs::SmallRng); diff --git a/wtx/src/misc/rng/rand_chacha.rs b/wtx/src/misc/rng/rand_chacha.rs new file mode 100644 index 00000000..c18c4a49 --- /dev/null +++ b/wtx/src/misc/rng/rand_chacha.rs @@ -0,0 +1,45 @@ +use rand_core::RngCore; + +macro_rules! implement { + ($struct:ty) => { + #[cfg(feature = "http-server-framework")] + impl crate::http::server_framework::ConnAux for $struct { + type Init = Self; + + #[inline] + fn conn_aux(init: Self::Init) -> crate::Result { + Ok(init) + } + } + + impl crate::misc::rng::Rng for $struct { + #[inline] + fn u8(&mut self) -> u8 { + let [a, ..] = self.next_u32().to_be_bytes(); + a + } + + #[inline] + fn u8_4(&mut self) -> [u8; 4] { + self.next_u32().to_be_bytes() + } + + #[inline] + fn u8_8(&mut self) -> [u8; 8] { + let [a, b, c, d, e, f, g, h] = self.next_u64().to_be_bytes(); + [a, b, c, d, e, f, g, h] + } + + #[inline] + fn u8_16(&mut self) -> [u8; 16] { + let [a, b, c, d, e, f, g, h] = self.next_u64().to_be_bytes(); + let [i, j, k, l, m, n, o, p] = self.next_u64().to_be_bytes(); + [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] + } + } + }; +} + +implement!(rand_chacha::ChaCha8Rng); +implement!(rand_chacha::ChaCha12Rng); +implement!(rand_chacha::ChaCha20Rng); diff --git a/wtx/src/misc/rng/seed.rs b/wtx/src/misc/rng/seed.rs new file mode 100644 index 00000000..eed29a0d --- /dev/null +++ b/wtx/src/misc/rng/seed.rs @@ -0,0 +1,41 @@ +use crate::misc::Usize; +use alloc::boxed::Box; +use core::{ + panic::Location, + ptr, + sync::atomic::{AtomicU64, Ordering}, +}; + +/// Uses a combination of weak strategies that will likely result in poor results. +/// +/// 1. The address of a heap allocation. +/// 2. A large fixed number. +/// 3. The value of an ever increasing static counter. +/// 4. The line and column of the caller location. +#[inline] +pub fn simple_seed() -> u64 { + static COUNTER: AtomicU64 = AtomicU64::new(0); + + struct Foo { + _bar: usize, + _baz: usize, + } + + let elem = Box::new(Foo { _bar: 1, _baz: 2 }); + let ptr_addr = ptr::addr_of!(elem).addr(); + let mut rslt = Usize::from_usize(ptr_addr).into_u64(); + rslt = rslt.wrapping_add(11_400_714_819_323_198_485); + rslt = rslt.wrapping_add(COUNTER.fetch_add(3, Ordering::Release)); + let location = Location::caller(); + rslt = rslt.wrapping_add(u64::from(location.column().wrapping_add(location.line()))); + rslt +} + +/// Seed retrieved from the machinery of the standard library. +#[cfg(feature = "std")] +#[inline] +pub fn std_seed() -> u64 { + use core::hash::{BuildHasher, Hasher}; + use std::hash::RandomState; + Hasher::finish(&BuildHasher::build_hasher(&RandomState::new())) +} diff --git a/wtx/src/misc/rng/std_rng.rs b/wtx/src/misc/rng/std_rng.rs deleted file mode 100644 index abe74227..00000000 --- a/wtx/src/misc/rng/std_rng.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::misc::rng::{xor_numbers, xor_u8, xor_u8_16, xor_u8_4, xor_u8_8, Rng}; -use core::{ - hash::{BuildHasher, Hasher}, - sync::atomic::{AtomicU64, Ordering}, -}; -use std::collections::hash_map::RandomState; - -/// Derived from the tools provided by the standard library, uses a simple XOR strategy. -#[derive(Clone, Copy, Debug)] -pub struct StdRng(u64); - -impl Rng for StdRng { - #[inline] - fn u8(&mut self) -> u8 { - xor_u8(&mut self.0) - } - - #[inline] - fn u8_4(&mut self) -> [u8; 4] { - xor_u8_4(&mut self.0) - } - - #[inline] - fn u8_8(&mut self) -> [u8; 8] { - xor_u8_8(&mut self.0) - } - - #[inline] - fn u8_16(&mut self) -> [u8; 16] { - xor_u8_16(&mut self.0) - } -} - -#[cfg(feature = "http-server-framework")] -impl crate::http::server_framework::ConnAux for StdRng { - type Init = Self; - - #[inline] - fn conn_aux(init: Self::Init) -> crate::Result { - Ok(init) - } -} - -impl Default for StdRng { - #[inline] - fn default() -> Self { - Self(Hasher::finish(&BuildHasher::build_hasher(&RandomState::new()))) - } -} - -/// Synchronous version of [`StdRng`]. -#[derive(Debug)] -pub struct StdRngSync(AtomicU64); - -impl StdRngSync { - #[inline] - fn modify(&self) -> u64 { - self - .0 - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut el| { - let _ = xor_numbers(&mut el); - Some(el) - }) - .unwrap_or_else(|el| el) - } -} - -impl Rng for StdRngSync { - #[inline] - fn u8(&mut self) -> u8 { - crate::misc::rng::u8(self.modify()) - } - - #[inline] - fn u8_4(&mut self) -> [u8; 4] { - crate::misc::rng::u8_4(self.modify()) - } - - #[inline] - fn u8_8(&mut self) -> [u8; 8] { - crate::misc::rng::u8_8(self.modify()) - } - - #[inline] - fn u8_16(&mut self) -> [u8; 16] { - crate::misc::rng::u8_16(self.modify(), self.modify()) - } -} - -impl Rng for &StdRngSync { - #[inline] - fn u8(&mut self) -> u8 { - crate::misc::rng::u8(self.modify()) - } - - #[inline] - fn u8_4(&mut self) -> [u8; 4] { - crate::misc::rng::u8_4(self.modify()) - } - - #[inline] - fn u8_8(&mut self) -> [u8; 8] { - crate::misc::rng::u8_8(self.modify()) - } - - #[inline] - fn u8_16(&mut self) -> [u8; 16] { - crate::misc::rng::u8_16(self.modify(), self.modify()) - } -} - -impl Default for StdRngSync { - #[inline] - fn default() -> Self { - Self(AtomicU64::new(Hasher::finish(&BuildHasher::build_hasher(&RandomState::new())))) - } -} diff --git a/wtx/src/misc/rng/xorshift.rs b/wtx/src/misc/rng/xorshift.rs new file mode 100644 index 00000000..71082b91 --- /dev/null +++ b/wtx/src/misc/rng/xorshift.rs @@ -0,0 +1,171 @@ +use crate::misc::Rng; +use core::sync::atomic::{AtomicU64, Ordering}; + +/// Xorshift that deals with 64 bits numbers. +#[derive(Clone, Copy, Debug)] +pub struct Xorshift64 { + value: u64, +} + +#[cfg(feature = "http-server-framework")] +impl crate::http::server_framework::ConnAux for Xorshift64 { + type Init = Self; + + #[inline] + fn conn_aux(init: Self::Init) -> crate::Result { + Ok(init) + } +} + +impl Rng for Xorshift64 { + #[inline] + fn u8(&mut self) -> u8 { + xor_u8(&mut self.value) + } + + #[inline] + fn u8_4(&mut self) -> [u8; 4] { + xor_u8_4(&mut self.value) + } + + #[inline] + fn u8_8(&mut self) -> [u8; 8] { + xor_u8_8(&mut self.value) + } + + #[inline] + fn u8_16(&mut self) -> [u8; 16] { + xor_u8_16(&mut self.value) + } +} + +impl From for Xorshift64 { + #[inline] + fn from(value: u64) -> Self { + Self { value } + } +} + +/// Xorshift that deals with 64 bits numbers. +/// +/// Suitable for multi-thread environments. +#[derive(Debug)] +pub struct Xorshift64Sync { + value: AtomicU64, +} + +impl Xorshift64Sync { + #[inline] + fn modify(&self) -> u64 { + self + .value + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut el| { + let _ = xor_numbers(&mut el); + Some(el) + }) + .unwrap_or_else(|el| el) + } +} + +impl Rng for Xorshift64Sync { + #[inline] + fn u8(&mut self) -> u8 { + u8(self.modify()) + } + + #[inline] + fn u8_4(&mut self) -> [u8; 4] { + u8_4(self.modify()) + } + + #[inline] + fn u8_8(&mut self) -> [u8; 8] { + u8_8(self.modify()) + } + + #[inline] + fn u8_16(&mut self) -> [u8; 16] { + u8_16(self.modify(), self.modify()) + } +} + +impl Rng for &Xorshift64Sync { + #[inline] + fn u8(&mut self) -> u8 { + u8(self.modify()) + } + + #[inline] + fn u8_4(&mut self) -> [u8; 4] { + u8_4(self.modify()) + } + + #[inline] + fn u8_8(&mut self) -> [u8; 8] { + u8_8(self.modify()) + } + + #[inline] + fn u8_16(&mut self) -> [u8; 16] { + u8_16(self.modify(), self.modify()) + } +} + +impl From for Xorshift64Sync { + #[inline] + fn from(value: u64) -> Self { + Self { value: AtomicU64::new(value) } + } +} + +#[inline] +fn u8(n: u64) -> u8 { + let [a, ..] = n.to_be_bytes(); + a +} + +#[inline] +fn u8_4(n: u64) -> [u8; 4] { + let [a, b, c, d, ..] = n.to_be_bytes(); + [a, b, c, d] +} + +#[inline] +fn u8_8(n: u64) -> [u8; 8] { + n.to_be_bytes() +} + +#[inline] +fn u8_16(first: u64, second: u64) -> [u8; 16] { + let [a, b, c, d, e, f, g, h] = first.to_be_bytes(); + let [i, j, k, l, m, n, o, p] = second.to_be_bytes(); + [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] +} + +#[inline] +fn xor_numbers(seed: &mut u64) -> u64 { + *seed ^= *seed << 13; + *seed ^= *seed >> 17; + *seed ^= *seed << 5; + *seed +} + +#[inline] +fn xor_u8(seed: &mut u64) -> u8 { + u8(xor_numbers(seed)) +} + +#[inline] +fn xor_u8_4(seed: &mut u64) -> [u8; 4] { + u8_4(xor_numbers(seed)) +} + +#[inline] +fn xor_u8_8(seed: &mut u64) -> [u8; 8] { + u8_8(xor_numbers(seed)) +} + +#[inline] +fn xor_u8_16(seed: &mut u64) -> [u8; 16] { + u8_16(xor_numbers(seed), xor_numbers(seed)) +} diff --git a/wtx/src/pool/resource_manager.rs b/wtx/src/pool/resource_manager.rs index 40161d4b..db078ed4 100644 --- a/wtx/src/pool/resource_manager.rs +++ b/wtx/src/pool/resource_manager.rs @@ -93,7 +93,7 @@ where #[cfg(feature = "postgres")] pub(crate) mod database { - use crate::misc::StdRngSync; + use crate::misc::Xorshift64Sync; use alloc::string::String; use core::marker::PhantomData; @@ -102,7 +102,7 @@ pub(crate) mod database { pub struct PostgresRM { _certs: Option<&'static [u8]>, error: PhantomData E>, - rng: StdRngSync, + rng: Xorshift64Sync, stream: PhantomData, uri: String, } @@ -123,7 +123,7 @@ pub(crate) mod database { client::postgres::{Executor, ExecutorBuffer}, Executor as _, }, - misc::StdRngSync, + misc::{simple_seed, Xorshift64Sync}, pool::{PostgresRM, ResourceManager}, }; use alloc::string::String; @@ -137,7 +137,7 @@ pub(crate) mod database { Self { _certs: None, error: PhantomData, - rng: StdRngSync::default(), + rng: Xorshift64Sync::from(simple_seed()), stream: PhantomData, uri, } @@ -196,7 +196,7 @@ pub(crate) mod database { client::postgres::{Executor, ExecutorBuffer}, Executor as _, }, - misc::{StdRngSync, TokioRustlsConnector}, + misc::{simple_seed, TokioRustlsConnector, Xorshift64Sync}, pool::{PostgresRM, ResourceManager}, }; use alloc::string::String; @@ -211,7 +211,7 @@ pub(crate) mod database { Self { _certs: certs, error: PhantomData, - rng: StdRngSync::default(), + rng: Xorshift64Sync::from(simple_seed()), stream: PhantomData, uri, } diff --git a/wtx/src/web_socket/handshake/tests.rs b/wtx/src/web_socket/handshake/tests.rs index 651e2043..84b67dd6 100644 --- a/wtx/src/web_socket/handshake/tests.rs +++ b/wtx/src/web_socket/handshake/tests.rs @@ -8,7 +8,7 @@ macro_rules! call_tests { } use crate::{ - misc::NoStdRng, + misc::{simple_seed, Xorshift64}, tests::_uri, web_socket::{ compression::NegotiatedCompression, frame::FrameMutVec, handshake::HeadersBuffer, Compression, @@ -61,7 +61,7 @@ where let mut fb = FrameBufferVec::with_capacity(0); let mut ws = WebSocketServer::accept( server_compression, - NoStdRng::default(), + Xorshift64::from(simple_seed()), stream, WebSocketBuffer::with_capacity(0, 0), |_| true, @@ -88,7 +88,7 @@ where &mut fb, [], &mut HeadersBuffer::default(), - NoStdRng::default(), + Xorshift64::from(simple_seed()), TcpStream::connect(uri.hostname_with_implied_port()).await.unwrap(), &uri.to_ref(), WebSocketBuffer::with_capacity(0, 0), @@ -122,9 +122,15 @@ where } trait Test { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned); + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ); - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned); + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ); } struct FragmentedText; @@ -132,12 +138,18 @@ impl Test for FragmentedText where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { write(FrameMutVec::new_unfin(fb, OpCode::Text, b"1").unwrap(), ws).await; write(FrameMutVec::new_fin(fb, OpCode::Continuation, b"23").unwrap(), ws).await; } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { let text = ws.read_frame(fb).await.unwrap(); assert_eq!(OpCode::Text, text.op_code()); assert_eq!(b"123", text.fb().payload()); @@ -149,7 +161,10 @@ impl Test for HelloAndGoodbye where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { let hello = ws.read_frame(fb).await.unwrap(); assert_eq!(OpCode::Text, hello.op_code()); assert_eq!(b"Hello!", hello.fb().payload()); @@ -157,7 +172,10 @@ where assert_eq!(OpCode::Close, ws.read_frame(fb).await.unwrap().op_code()); } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { write(FrameMutVec::new_fin(fb, OpCode::Text, b"Hello!").unwrap(), ws).await; assert_eq!(ws.read_frame(&mut *fb).await.unwrap().fb().payload(), b"Goodbye!"); write(FrameMutVec::new_fin(fb, OpCode::Close, &[]).unwrap(), ws).await; @@ -169,7 +187,10 @@ impl Test for LargeFragmentedText where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { let bytes = vec![51; 256 * 1024]; write(FrameMutVec::new_unfin(fb, OpCode::Text, &bytes).unwrap(), ws).await; write(FrameMutVec::new_unfin(fb, OpCode::Continuation, &bytes).unwrap(), ws).await; @@ -183,7 +204,10 @@ where write(FrameMutVec::new_fin(fb, OpCode::Continuation, &bytes).unwrap(), ws).await; } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { let text = ws.read_frame(fb).await.unwrap(); assert_eq!(OpCode::Text, text.op_code()); assert_eq!(&vec![51; 10 * 256 * 1024], text.fb().payload()); @@ -195,13 +219,19 @@ impl Test for PingAndText where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { write(FrameMutVec::new_fin(fb, OpCode::Ping, b"123").unwrap(), ws).await; write(FrameMutVec::new_fin(fb, OpCode::Text, b"ipat").unwrap(), ws).await; assert_eq!(OpCode::Pong, ws.read_frame(fb).await.unwrap().op_code()); } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { assert_eq!(b"ipat", ws.read_frame(fb).await.unwrap().fb().payload()); } } @@ -211,14 +241,20 @@ impl Test for PingBetweenFragmentedText where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { write(FrameMutVec::new_unfin(fb, OpCode::Text, b"1").unwrap(), ws).await; write(FrameMutVec::new_fin(fb, OpCode::Ping, b"9").unwrap(), ws).await; write(FrameMutVec::new_fin(fb, OpCode::Continuation, b"23").unwrap(), ws).await; assert_eq!(OpCode::Pong, ws.read_frame(fb).await.unwrap().op_code()); } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { assert_eq!(OpCode::Text, ws.read_frame(fb).await.unwrap().op_code()); } } @@ -228,7 +264,10 @@ impl Test for SeveralBytes where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { write(FrameMutVec::new_unfin(fb, OpCode::Text, &[206]).unwrap(), ws).await; write(FrameMutVec::new_unfin(fb, OpCode::Continuation, &[186]).unwrap(), ws).await; write(FrameMutVec::new_unfin(fb, OpCode::Continuation, &[225]).unwrap(), ws).await; @@ -243,7 +282,10 @@ where write(FrameMutVec::new_fin(fb, OpCode::Continuation, &[]).unwrap(), ws).await; } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { let text = ws.read_frame(fb).await.unwrap(); assert_eq!(OpCode::Text, text.op_code()); assert_eq!("κόσμε".as_bytes(), text.fb().payload()); @@ -255,7 +297,10 @@ impl Test for TwoPings where NC: NegotiatedCompression, { - async fn client(fb: &mut FrameBufferVec, ws: &mut WebSocketClientOwned) { + async fn client( + fb: &mut FrameBufferVec, + ws: &mut WebSocketClientOwned, + ) { write(FrameMutVec::new_fin(fb, OpCode::Ping, b"0").unwrap(), ws).await; write(FrameMutVec::new_fin(fb, OpCode::Ping, b"1").unwrap(), ws).await; let _0 = ws.read_frame(fb).await.unwrap(); @@ -267,7 +312,10 @@ where write(FrameMutVec::new_fin(fb, OpCode::Text, b"").unwrap(), ws).await; } - async fn server(fb: &mut FrameBufferVec, ws: &mut WebSocketServerOwned) { + async fn server( + fb: &mut FrameBufferVec, + ws: &mut WebSocketServerOwned, + ) { let _0 = ws.read_frame(fb).await.unwrap(); assert_eq!(OpCode::Text, _0.op_code()); assert_eq!(b"", _0.fb().payload()); @@ -276,7 +324,7 @@ where async fn write( mut frame: FrameMutVec<'_, IS_CLIENT>, - ws: &mut WebSocket, + ws: &mut WebSocket, ) where NC: NegotiatedCompression, {