Skip to content

Commit

Permalink
Merge pull request #273 from c410-f3r/misc
Browse files Browse the repository at this point in the history
Fix #260
  • Loading branch information
c410-f3r authored Nov 23, 2024
2 parents cf0db03 + 21ab2f0 commit 1e2e572
Show file tree
Hide file tree
Showing 76 changed files with 1,019 additions and 571 deletions.
392 changes: 354 additions & 38 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion wtx-docs/src/web-socket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Implementation of [RFC6455](https://datatracker.ietf.org/doc/html/rfc6455) and [RFC7692](https://datatracker.ietf.org/doc/html/rfc7692). WebSocket is a communication protocol that enables full-duplex communication between a client (typically a web browser) and a server over a single TCP connection. Unlike traditional HTTP, which is request-response based, WebSocket allows real-time data exchange without the need for polling.

In-house benchmarks are available at <https://c410-f3r.github.io/wtx-bench>. If you are aware of other benchmark tools, please open an discussion in the GitHub project.

To use this functionality, it is necessary to activate the `web-socket` feature.

![WebSocket Benchmark](https://i.imgur.com/Iv2WzJV.jpg)
Expand All @@ -21,7 +23,7 @@ To get the most performance possible, try compiling your program with `RUSTFLAGS

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 thing is not desirable, please make sure to check the handshake parameters to avoid accidental scenarios.

To make everything work as intended both partys, client and server, need to implement this feature. For example, web browser won't stop masking frames.
To make everything work as intended both parties, client and server, need to implement this feature. For example, web browser won't stop masking frames.

## Client Example

Expand Down
2 changes: 1 addition & 1 deletion wtx-instances/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ required-features = ["wtx/http-server-framework"]
[[example]]
name = "http-server-framework-session"
path = "http-server-framework-examples/http-server-framework-session.rs"
required-features = ["argon2", "rand_chacha", "rand_core", "serde", "serde_json", "wtx/argon2", "wtx/http-server-framework", "wtx/http-session", "wtx/pool", "wtx/postgres", "wtx/rand_chacha"]
required-features = ["argon2", "rand_chacha", "rand_core", "serde", "serde_json", "wtx/argon2", "wtx/http-server-framework", "wtx/http-session", "wtx/pool", "wtx/postgres", "wtx/rand_chacha", "wtx-macros"]

# HTTP/2 Examples

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,48 +27,54 @@ use wtx::{
database::{Executor, Record},
http::{
server_framework::{get, post, Router, ServerFrameworkBuilder, State, StateClean},
ReqResBuffer, ReqResData, SessionDecoder, SessionEnforcer, SessionTokio, StatusCode,
ReqResBuffer, ReqResData, SessionDecoder, SessionEnforcer, SessionManagerTokio, SessionState,
StatusCode,
},
misc::{argon2_pwd, Vector},
pool::{PostgresRM, SimplePoolTokio},
};

type ConnAux = (Session, ChaCha20Rng);
type Pool = SimplePoolTokio<PostgresRM<wtx::Error, TcpStream>>;
type Session = SessionTokio<u32, wtx::Error, Pool>;
type SessionManager = SessionManagerTokio<u32, wtx::Error>;

#[tokio::main]
async fn main() -> wtx::Result<()> {
let pool = Pool::new(4, PostgresRM::tokio("postgres://USER:PASSWORD@localhost/DB_NAME".into()));
let uri = "postgres://USER:PASSWORD@localhost/DB_NAME";
let mut pool = Pool::new(4, PostgresRM::tokio(uri.into()));
let mut rng = ChaCha20Rng::from_entropy();
let (expired_sessions, session) = Session::builder(pool).build_generating_key(&mut rng);
let (expired, sm) = SessionManager::builder().build_generating_key(&mut rng, &mut pool);
let router = Router::new(
wtx::paths!(("/login", post(login)), ("/logout", get(logout)),),
(SessionDecoder::new(session.clone()), SessionEnforcer::new(["/admin"], session.clone())),
(SessionDecoder::new(sm.clone(), pool.clone()), SessionEnforcer::new(["/admin"])),
)?;
tokio::spawn(async move {
if let Err(err) = expired_sessions.await {
if let Err(err) = expired.await {
eprintln!("{err}");
}
});
let rng_clone = rng.clone();
ServerFrameworkBuilder::new(router)
.with_conn_aux(move || (session.clone(), rng_clone.clone()))
.with_conn_aux(move || ConnAux {
pool: pool.clone(),
rng: rng_clone.clone(),
session_manager: sm.clone(),
session_state: None,
})
.tokio("0.0.0.0:9000", rng, |err| eprintln!("{err:?}"), |_| Ok(()))
.await?;
Ok(())
}

#[inline]
async fn login(state: State<'_, ConnAux, (), ReqResBuffer>) -> wtx::Result<StatusCode> {
let (Session { manager, store }, rng) = state.conn_aux;
if manager.inner.lock().await.state().is_some() {
manager.delete_session_cookie(&mut state.req.rrd, store).await?;
let ConnAux { pool, rng, session_manager, session_state } = state.conn_aux;
if session_state.is_some() {
session_manager.delete_session_cookie(&mut state.req.rrd, session_state, pool).await?;
return Ok(StatusCode::Forbidden);
}
let user: UserLoginReq<'_> = serde_json::from_slice(state.req.rrd.body())?;
let mut guard = store.get().await?;
let record = guard
let mut pool_guard = pool.get().await?;
let record = pool_guard
.fetch_with_stmt("SELECT id,first_name,password,salt FROM user WHERE email = $1", (user.email,))
.await?;
let id = record.decode::<_, u32>(0)?;
Expand All @@ -81,18 +87,26 @@ async fn login(state: State<'_, ConnAux, (), ReqResBuffer>) -> wtx::Result<Statu
return Ok(StatusCode::Unauthorized);
}
serde_json::to_writer(&mut state.req.rrd.body, &UserLoginRes { id, name: first_name })?;
drop(guard);
manager.set_session_cookie(id, rng, &mut state.req.rrd, store).await?;
drop(pool_guard);
session_manager.set_session_cookie(id, rng, &mut state.req.rrd, pool).await?;
Ok(StatusCode::Ok)
}

#[inline]
async fn logout(state: StateClean<'_, ConnAux, (), ReqResBuffer>) -> wtx::Result<StatusCode> {
let (Session { manager, store }, _) = state.conn_aux;
manager.delete_session_cookie(&mut state.req.rrd, store).await?;
let ConnAux { pool, rng: _, session_manager, session_state } = state.conn_aux;
session_manager.delete_session_cookie(&mut state.req.rrd, session_state, pool).await?;
Ok(StatusCode::Ok)
}

#[derive(Clone, Debug, wtx_macros::ConnAux)]
struct ConnAux {
pool: Pool,
rng: ChaCha20Rng,
session_manager: SessionManager,
session_state: Option<SessionState<u32>>,
}

#[derive(Debug, serde::Deserialize)]
struct UserLoginReq<'req> {
email: &'req str,
Expand Down
2 changes: 0 additions & 2 deletions wtx-instances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ pub static ROOT_CA: &[u8] = include_bytes!("../../.certs/root-ca.crt");
pub async fn executor_postgres(
uri_str: &str,
) -> wtx::Result<Executor<wtx::Error, ExecutorBuffer, TcpStream>> {
use std::usize;

let uri = Uri::new(uri_str);
let mut rng = Xorshift64::from(simple_seed());
Executor::connect(
Expand Down
2 changes: 1 addition & 1 deletion wtx-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[dependencies]
proc-macro2 = { default-features = false, version = "1.0" }
quote = { default-features = false, features = ["proc-macro"], version = "1.0" }
syn = { default-features = false, features = ["extra-traits", "full", "parsing", "printing", "proc-macro"], version = "1.0" }
syn = { default-features = false, features = ["derive", "extra-traits", "full", "parsing", "printing", "proc-macro"], version = "1.0" }

[dev-dependencies]
trybuild = { default-features = false, version = "1.0" }
Expand Down
6 changes: 6 additions & 0 deletions wtx-macros/src/client_api_framework.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub(crate) mod api_params;
pub(crate) mod contained_attrs;
pub(crate) mod item_with_attr_span;
pub(crate) mod owned_or_ref;
pub(crate) mod pkg;
pub(crate) mod transport_group;
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
mod attrs;

use crate::{misc::create_ident, owned_or_ref::OwnedOrRef, transport_group::TransportGroup};
use crate::{
client_api_framework::{owned_or_ref::OwnedOrRef, transport_group::TransportGroup},
misc::create_ident,
};
use proc_macro2::{Ident, Span};
use quote::ToTokens;
use syn::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::transport_group::TransportGroup;
use crate::client_api_framework::transport_group::TransportGroup;
use syn::{Meta, MetaList, NestedMeta, Path};

#[derive(Debug)]
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ use syn::{
};

use crate::{
item_with_attr_span::ItemWithAttrSpan,
client_api_framework::{
item_with_attr_span::ItemWithAttrSpan,
pkg::{fir::fir_after_sending_item_values::FirAfterSendingItemValues, misc::unit_type},
},
misc::push_doc,
pkg::{fir::fir_after_sending_item_values::FirAfterSendingItemValues, misc::unit_type},
};

pub(crate) fn pkg(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{pkg::data_format_elems::DataFormatElems, transport_group::TransportGroup};
use crate::client_api_framework::{
pkg::data_format_elems::DataFormatElems, transport_group::TransportGroup,
};
use proc_macro2::{Ident, Span, TokenStream};
use syn::{Lit, Meta, NestedMeta};

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::keywords;
use crate::client_api_framework::pkg::keywords;
use syn::{
parse::{Parse, ParseStream},
spanned::Spanned,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{
use crate::client_api_framework::{
item_with_attr_span::ItemWithAttrSpan,
pkg::{
fir::fir_aux_field_attr::FirAuxFieldAttr,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::pkg::{fir::fir_custom_field_field_attr::FirCustomFieldFieldAttr, keywords};
use crate::client_api_framework::pkg::{
fir::fir_custom_field_field_attr::FirCustomFieldFieldAttr, keywords,
};
use syn::{
parse::{Parse, ParseStream},
spanned::Spanned,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::keywords;
use crate::client_api_framework::pkg::keywords;
use proc_macro2::Ident;
use syn::{
parse::{Parse, ParseStream},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::{
use crate::client_api_framework::pkg::{
enum_struct_or_type::EnumStructOrType, fir::fir_custom_field_field_attr::FirCustomFieldFieldAttr,
};
use syn::{punctuated::Punctuated, GenericParam, Ident, Token, Type, WherePredicate};
Expand Down Expand Up @@ -26,9 +26,9 @@ macro_rules! create_fir_custom_item_values {
$($cb:expr)?,
) => {
use crate::{
item_with_attr_span::ItemWithAttrSpan,
client_api_framework::item_with_attr_span::ItemWithAttrSpan,
misc::push_doc_if_inexistent,
pkg::{
client_api_framework::pkg::{
enum_struct_or_type::EnumStructOrType,
fir::{
fir_custom_field_attr::FirCustomFieldAttr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ macro_rules! create_fir_hook_item_values {
$fn_args_idents:expr,
$error:ident,
) => {
use crate::item_with_attr_span::ItemWithAttrSpan;
use crate::client_api_framework::item_with_attr_span::ItemWithAttrSpan;
use proc_macro2::TokenStream;
use syn::{punctuated::Punctuated, FnArg, Item, ItemFn, Pat, Token};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::keywords;
use crate::client_api_framework::pkg::keywords;
use proc_macro2::Span;
use syn::{
parse::{Parse, ParseBuffer, ParseStream},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{
use crate::client_api_framework::{
contained_attrs::ContainedAttrs,
item_with_attr_span::ItemWithAttrSpan,
pkg::{
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{item_with_attr_span::ItemWithAttrSpan, misc::push_doc_if_inexistent};
use crate::{
client_api_framework::item_with_attr_span::ItemWithAttrSpan, misc::push_doc_if_inexistent,
};
use proc_macro2::Ident;
use syn::Item;

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ mod sir_items_values_creators;
mod sir_items_values_pushers;

use crate::{
misc::{create_ident, extend_with_tmp_suffix},
pkg::{
client_api_framework::pkg::{
fir::{
fir_aux_item_values::FirAuxItemValues, fir_custom_item_values::FirCustomItemValuesRef,
fir_params_items_values::FirParamsItemValues, fir_req_item_values::FirReqItemValues,
},
misc::{from_camel_case_to_snake_case, split_params, EMPTY_GEN_PARAMS},
sir::sir_pkg_attr::SirPkaAttr,
},
misc::{create_ident, extend_with_tmp_suffix},
};
use proc_macro2::{Ident, Span, TokenStream};
use syn::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::{
use crate::client_api_framework::pkg::{
enum_struct_or_type::EnumStructOrType,
fir::{fir_aux_item_values::FirAuxItemValues, fir_custom_item_values::FirCustomItemValuesRef},
misc::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkg::{
use crate::client_api_framework::pkg::{
data_format::DataFormat,
fir::{
fir_aux_item_values::FirAuxItemValues, fir_params_items_values::FirParamsItemValues,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{
use crate::client_api_framework::{
pkg::{
data_format_elems::DataFormatElems,
fir::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{
use crate::client_api_framework::{
pkg::{data_format::DataFormat, fir::fir_pkg_attr::FirPkgAttr},
transport_group::TransportGroup,
};
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions wtx-macros/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub(crate) enum Error {
Syn(syn::Error),
UnknownDataFormat,
UnknownTransport(Span),
UnsupportedStructure,
}

impl From<syn::Error> for Error {
Expand Down Expand Up @@ -98,6 +99,7 @@ impl From<Error> for syn::Error {
Error::Syn(error) => error,
Error::UnknownDataFormat => syn::Error::new(Span::call_site(), "Unknown data format."),
Error::UnknownTransport(span) => syn::Error::new(span, "Unknown transport."),
Error::UnsupportedStructure => syn::Error::new(Span::call_site(), "Unsupported structure."),
}
}
}
48 changes: 48 additions & 0 deletions wtx-macros/src/http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};

pub(crate) fn conn_aux(item: proc_macro::TokenStream) -> crate::Result<proc_macro::TokenStream> {
let input = parse_macro_input::parse::<DeriveInput>(item)?;
let name = input.ident;
let mut field_names = Vec::new();
let mut field_tys = Vec::new();
match input.data {
Data::Struct(data) => match data.fields {
Fields::Named(fields) => {
for elem in fields.named {
field_names.push(elem.ident);
field_tys.push(elem.ty);
}
}
_ => return Err(crate::Error::UnsupportedStructure),
},
_ => return Err(crate::Error::UnsupportedStructure),
}
let expanded = quote! {
impl wtx::http::server_framework::ConnAux for #name {
type Init = Self;

#[inline]
fn conn_aux(init: Self::Init) -> wtx::Result<Self> {
Ok(init)
}
}

#(
impl wtx::misc::Lease<#field_tys> for #name {
#[inline]
fn lease(&self) -> &#field_tys {
&self.#field_names
}
}

impl wtx::misc::LeaseMut<#field_tys> for #name {
#[inline]
fn lease_mut(&mut self) -> &mut #field_tys {
&mut self.#field_names
}
}
)*
};
Ok(proc_macro::TokenStream::from(expanded))
}
Loading

0 comments on commit 1e2e572

Please sign in to comment.