Skip to content

Commit

Permalink
Add the "no-masking" parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
c410-f3r committed Oct 28, 2024
1 parent b2a6d93 commit cae1705
Show file tree
Hide file tree
Showing 43 changed files with 830 additions and 505 deletions.
42 changes: 19 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions wtx-docs/src/web-socket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ The "permessage-deflate" extension is the only supported compression format and

To get the most performance possible, try compiling your program with `RUSTFLAGS='-C target-cpu=native'` to allow `zlib-rs` to use more efficient SIMD instructions.

## No masking

Although not officially endorsed, the `no-masking` parameter described at https://datatracker.ietf.org/doc/html/draft-damjanovic-websockets-nomasking-02 is supported to increase performance. If such a feature is not desirable, please make sure to check the handshake parameters to avoid accidental scenarios.

## Client Example

```rust,edition2021,no_run
Expand Down
1 change: 1 addition & 0 deletions wtx-instances/generic-examples/client-api-framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ async fn main() -> wtx::Result<()> {
let web_socket = WebSocketClient::connect(
(),
[],
false,
Xorshift64::from(simple_seed()),
TcpStream::connect(uri.hostname_with_implied_port()).await?,
&uri,
Expand Down
1 change: 1 addition & 0 deletions wtx-instances/generic-examples/web-socket-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ async fn main() -> wtx::Result<()> {
let mut ws = WebSocketClient::connect(
(),
[],
false,
Xorshift64::from(simple_seed()),
TcpStream::connect(uri.hostname_with_implied_port()).await?,
&uri.to_ref(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@
//! password BYTEA NOT NULL,
//! salt BYTEA NOT NULL
//! );
//! ALTER TABLE "user" ADD CONSTRAINT user__email__uq UNIQUE (email);
//!
//! CREATE TABLE session (
//! id BYTEA NOT NULL PRIMARY KEY,
//! user_id INT NOT NULL,
//! expires_at TIMESTAMPTZ NOT NULL
//! );
//!
//! 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::{
Expand All @@ -29,21 +28,10 @@ use wtx::{
server_framework::{get, post, Router, ServerFrameworkBuilder, State, StateClean},
ReqResBuffer, ReqResData, SessionDecoder, SessionEnforcer, SessionTokio, StatusCode,
},
misc::argon2_pwd,
pool::{PostgresRM, SimplePoolTokio},
};

const ARGON2_OUTPUT_LEN: usize = 32;
const ARGON2_PARAMS: Params = {
let Ok(elem) = Params::new(
Params::DEFAULT_M_COST,
Params::DEFAULT_T_COST,
Params::DEFAULT_P_COST,
Some(ARGON2_OUTPUT_LEN),
) else {
panic!();
};
elem
};
type ConnAux = (Session, ChaCha20Rng);
type Pool = SimplePoolTokio<PostgresRM<wtx::Error, TcpStream>>;
type Session = SessionTokio<u32, wtx::Error, Pool>;
Expand Down Expand Up @@ -71,40 +59,29 @@ async fn main() -> wtx::Result<()> {
Ok(())
}

#[derive(Debug, serde::Deserialize)]
struct User<'req> {
email: &'req str,
password: &'req str,
}

#[inline]
async fn login(state: State<'_, ConnAux, (), ReqResBuffer>) -> wtx::Result<StatusCode> {
let (session, rng) = state.ca;
if session.content.lock().await.state().is_some() {
session.delete_session_cookie(&mut state.req.rrd).await?;
return Ok(StatusCode::Forbidden);
}
let user: User<'_> = serde_json::from_slice(state.req.rrd.body())?;
let user: UserLoginReq<'_> = serde_json::from_slice(state.req.rrd.body())?;
let mut executor_guard = session.store.get().await?;
let record = executor_guard
.fetch_with_stmt("SELECT id,password,salt FROM user WHERE email = $1", (user.email,))
.await?;
let id = record.decode::<_, u32>(0)?;
let password_db = record.decode::<_, &[u8]>(1)?;
let salt = record.decode::<_, &[u8]>(2)?;
let mut password_req = [0; ARGON2_OUTPUT_LEN];
Argon2::new(Algorithm::Argon2id, Version::V0x13, ARGON2_PARAMS).hash_password_into_with_memory(
user.password.as_bytes(),
salt,
&mut password_req,
&mut [Block::new(); ARGON2_PARAMS.block_count()],
)?;
let password_req = argon2_pwd(user.password.as_bytes(), salt)?;
state.req.rrd.clear();
if password_db != &password_req {
return Ok(StatusCode::Unauthorized);
}
drop(executor_guard);
session.set_session_cookie(id, rng, &mut state.req.rrd).await?;
serde_json::to_writer(&mut state.req.rrd.body, &UserLoginRes { id })?;
Ok(StatusCode::Ok)
}

Expand All @@ -113,3 +90,14 @@ async fn logout(state: StateClean<'_, ConnAux, (), ReqResBuffer>) -> wtx::Result
state.ca.0.delete_session_cookie(&mut state.req.rrd).await?;
Ok(StatusCode::Ok)
}

#[derive(Debug, serde::Deserialize)]
struct UserLoginReq<'req> {
email: &'req str,
password: &'req str,
}

#[derive(Debug, serde::Serialize)]
struct UserLoginRes {
id: u32,
}
36 changes: 20 additions & 16 deletions wtx-instances/http2-examples/http2-server.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Serves requests using low-level HTTP/2 resources along side self-made certificates.
//! HTTP/2 server that uses optioned parameters.
extern crate tokio;
extern crate tokio_rustls;
Expand All @@ -8,8 +8,11 @@ extern crate wtx_instances;
use tokio::{io::WriteHalf, net::TcpStream};
use tokio_rustls::server::TlsStream;
use wtx::{
http::{Headers, OptionedServer, ReqResBuffer, Request, Response, StatusCode},
http2::{Http2Buffer, Http2Params, ServerStreamTokio, WebSocketOverStream},
http::{
AutoStream, ManualServerStreamTokio, OptionedServer, ReqResBuffer, Response, StatusCode,
StreamMode,
},
http2::{is_web_socket_handshake, Http2Buffer, Http2Params, WebSocketOverStream},
misc::{simple_seed, TokioRustlsAcceptor, Vector, Xorshift64},
web_socket::{Frame, OpCode},
};
Expand All @@ -31,6 +34,13 @@ async fn main() -> wtx::Result<()> {
|error| eprintln!("{error}"),
manual,
|| Ok((Vector::new(), ReqResBuffer::empty())),
|headers, method, protocol| {
Ok(if is_web_socket_handshake(headers, method, protocol) {
StreamMode::Manual
} else {
StreamMode::Auto
})
},
(
|| {
TokioRustlsAcceptor::without_client_auth()
Expand All @@ -44,25 +54,19 @@ async fn main() -> wtx::Result<()> {
.await
}

async fn auto(
_: (),
_: Vector<u8>,
mut req: Request<ReqResBuffer>,
) -> Result<Response<ReqResBuffer>, wtx::Error> {
req.rrd.clear();
Ok(req.into_response(StatusCode::Ok))
async fn auto(mut ha: AutoStream<(), Vector<u8>>) -> Result<Response<ReqResBuffer>, wtx::Error> {
ha.req.rrd.clear();
Ok(ha.req.into_response(StatusCode::Ok))
}

async fn manual(
_: (),
mut buffer: Vector<u8>,
_: Headers,
stream: ServerStreamTokio<Http2Buffer, WriteHalf<TlsStream<TcpStream>>, false>,
mut hm: ManualServerStreamTokio<(), Vector<u8>, Http2Buffer, WriteHalf<TlsStream<TcpStream>>>,
) -> Result<(), wtx::Error> {
let rng = Xorshift64::from(simple_seed());
let mut wos = WebSocketOverStream::new(&Headers::new(), rng, stream).await?;
hm.headers.clear();
let mut wos = WebSocketOverStream::new(&hm.headers, false, rng, hm.stream).await?;
loop {
let mut frame = wos.read_frame(&mut buffer).await?;
let mut frame = wos.read_frame(&mut hm.sa).await?;
match (frame.op_code(), frame.text_payload()) {
(_, Some(elem)) => println!("{elem}"),
(OpCode::Close, _) => break,
Expand Down
3 changes: 1 addition & 2 deletions wtx-instances/http2-examples/http2-web-socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ extern crate wtx;
extern crate wtx_instances;

use core::mem;

use tokio::net::TcpListener;
use wtx::{
http::{Headers, ReqResBuffer},
Expand Down Expand Up @@ -47,7 +46,7 @@ async fn main() -> wtx::Result<()> {
return Ok(());
};
let mut buffer = Vector::new();
let mut wos = WebSocketOverStream::new(&Headers::new(), rng, &mut stream).await?;
let mut wos = WebSocketOverStream::new(&Headers::new(), false, rng, &mut stream).await?;
loop {
let mut frame = wos.read_frame(&mut buffer).await?;
match (frame.op_code(), frame.text_payload()) {
Expand Down
3 changes: 3 additions & 0 deletions wtx-instances/src/bin/autobahn-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async fn main() -> wtx::Result<()> {
let mut ws = WebSocketClient::connect(
Flate2::default(),
[],
false,
Xorshift64::from(simple_seed()),
TcpStream::connect(host).await?,
&UriRef::new(&format!("http://{host}/runCase?case={case}&agent=wtx")),
Expand All @@ -40,6 +41,7 @@ async fn main() -> wtx::Result<()> {
WebSocketClient::connect(
(),
[],
false,
Xorshift64::from(simple_seed()),
TcpStream::connect(host).await?,
&UriRef::new(&format!("http://{host}/updateReports?agent=wtx")),
Expand All @@ -55,6 +57,7 @@ async fn get_case_count(host: &str, wsb: &mut WebSocketBuffer) -> wtx::Result<u3
let mut ws = WebSocketClient::connect(
(),
[],
false,
Xorshift64::from(simple_seed()),
TcpStream::connect(host).await?,
&UriRef::new(&format!("http://{host}/getCaseCount")),
Expand Down
25 changes: 10 additions & 15 deletions wtx-instances/src/bin/h2load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
#![expect(clippy::print_stderr, reason = "internal")]

use std::u32;

use tokio::net::tcp::OwnedWriteHalf;
use wtx::{
http::{Headers, OptionedServer, ReqResBuffer, Request, Response, StatusCode},
http2::{Http2Buffer, Http2Params, ServerStreamTokio},
http::{
AutoStream, ManualServerStreamTokio, OptionedServer, ReqResBuffer, Response, StatusCode,
StreamMode,
},
http2::{Http2Buffer, Http2Params},
misc::{simple_seed, Xorshift64},
};

Expand All @@ -28,24 +29,18 @@ async fn main() -> wtx::Result<()> {
|error| eprintln!("{error}"),
manual,
|| Ok(((), ReqResBuffer::empty())),
|_, _, _| Ok(StreamMode::Auto),
(|| Ok(()), |_| {}, |_, stream| async move { Ok(stream.into_split()) }),
)
.await
}
async fn auto(
_: (),
_: (),
mut req: Request<ReqResBuffer>,
) -> Result<Response<ReqResBuffer>, wtx::Error> {
req.rrd.clear();
Ok(req.into_response(StatusCode::Ok))
async fn auto(mut ha: AutoStream<(), ()>) -> Result<Response<ReqResBuffer>, wtx::Error> {
ha.req.rrd.clear();
Ok(ha.req.into_response(StatusCode::Ok))
}

async fn manual(
_: (),
_: (),
_: Headers,
_: ServerStreamTokio<Http2Buffer, OwnedWriteHalf, false>,
_: ManualServerStreamTokio<(), (), Http2Buffer, OwnedWriteHalf>,
) -> Result<(), wtx::Error> {
Ok(())
}
Loading

0 comments on commit cae1705

Please sign in to comment.