From f430787fb715bd5f0b7087d3c05c2d1cde646e0f Mon Sep 17 00:00:00 2001 From: daxpedda Date: Fri, 25 Aug 2023 14:52:11 +0200 Subject: [PATCH] Fix CI --- .cargo/config.toml | 90 ++++++++++++ .github/workflows/rust.yml | 13 +- Cargo.toml | 5 +- examples/basic.rs | 6 +- examples/onestream.rs | 100 +++++++++++++ examples/twostream.rs | 115 +++++++++++++++ lints.txt | 216 ++++++++++++++++++++++++++++ src/error.rs | 17 +-- src/lib.rs | 59 +------- src/quic/connection/incoming.rs | 15 +- src/quic/connection/mod.rs | 22 +-- src/quic/connection/receiver.rs | 6 +- src/quic/connection/sender.rs | 1 - src/quic/endpoint/builder/config.rs | 15 +- src/quic/endpoint/builder/mod.rs | 39 ++--- src/quic/endpoint/mod.rs | 18 +-- src/quic/task.rs | 4 - src/x509/mod.rs | 5 +- src/x509/private_key.rs | 7 +- 19 files changed, 602 insertions(+), 151 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 examples/onestream.rs create mode 100644 examples/twostream.rs create mode 100644 lints.txt diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..53685b6f --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,90 @@ +[target.'cfg(all())'] +rustflags = [ + # Deny `unsafe`. + "-Dunsafe_code", + # Clippy groups. + "-Wclippy::pedantic", + "-Wclippy::cargo", + # Clippy lints. + "-Wclippy::allow_attributes_without_reason", + "-Wclippy::as_conversions", + "-Wclippy::as_underscore", + "-Wclippy::assertions_on_result_states", + "-Wclippy::clone_on_ref_ptr", + "-Wclippy::create_dir", + "-Wclippy::dbg_macro", + "-Wclippy::decimal_literal_representation", + "-Wclippy::default_numeric_fallback", + "-Wclippy::deref_by_slicing", + "-Wclippy::empty_drop", + "-Wclippy::empty_structs_with_brackets", + "-Wclippy::filetype_is_file", + "-Wclippy::format_push_string", + "-Wclippy::get_unwrap", + "-Wclippy::if_then_some_else_none", + "-Wclippy::impl_trait_in_params", + "-Wclippy::inline_asm_x86_att_syntax", + "-Wclippy::large_include_file", + "-Wclippy::lossy_float_literal", + "-Wclippy::min_ident_chars", + "-Wclippy::missing_docs_in_private_items", + "-Wclippy::mixed_read_write_in_expression", + "-Wclippy::multiple_inherent_impl", + "-Wclippy::multiple_unsafe_ops_per_block", + "-Wclippy::mutex_atomic", + "-Wclippy::needless_raw_strings", + "-Wclippy::partial_pub_fields", + "-Wclippy::pub_without_shorthand", + "-Wclippy::rc_mutex", + "-Wclippy::redundant_type_annotations", + "-Wclippy::ref_patterns", + "-Wclippy::rest_pat_in_fully_bound_structs", + "-Wclippy::same_name_method", + "-Wclippy::self_named_module_files", + "-Wclippy::single_char_lifetime_names", + "-Wclippy::str_to_string", + "-Wclippy::string_add", + "-Wclippy::string_slice", + "-Wclippy::string_to_string", + "-Wclippy::suspicious_xor_used_as_pow", + "-Wclippy::todo", + "-Wclippy::try_err", + "-Wclippy::undocumented_unsafe_blocks", + "-Wclippy::unimplemented", + "-Wclippy::unnecessary_safety_doc", + "-Wclippy::unnecessary_self_imports", + "-Wclippy::unneeded_field_pattern", + "-Wclippy::unseparated_literal_suffix", + "-Wclippy::verbose_file_reads", + # Allowed Clippy lints. + "-Aclippy::tabs_in_doc_comments", + # Rustdoc group. + "-Wrustdoc::all", + # Rust groups. + "-Wfuture_incompatible", + "-Wrust_2018_compatibility", + "-Wrust_2018_idioms", + "-Wrust_2021_compatibility", + "-Wunused", + # Rust lints. + "-Wdeprecated_in_future", + "-Wffi_unwind_calls", + "-Winvalid-reference_casting", + "-Wmacro_use_extern_crate", + "-Wmeta_variable_misuse", + "-Wmissing_abi", + "-Wmissing_copy_implementations", + "-Wmissing_debug_implementations", + "-Wmissing_docs", + "-Wnon_ascii_idents", + "-Wnoop_method_call", + "-Wsingle_use_lifetimes", + "-Wtrivial_casts", + "-Wtrivial_numeric_casts", + "-Wunreachable_pub", + "-Wunsafe_op_in_unsafe_fn", + "-Wunused_import_braces", + "-Wunused_lifetimes", + "-Wunused_qualifications", + "-Wunused_tuple_struct_fields", +] diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 501a252d..2fdef367 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,8 +30,7 @@ jobs: - name: Run doc tests run: | - rustup toolchain install nightly --profile minimal --allow-downgrade - cargo +nightly test --workspace --doc --all-features + cargo test --workspace --doc --all-features msrv: runs-on: ubuntu-latest @@ -43,7 +42,7 @@ jobs: - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.68.2" + toolchain: "1.72" - name: Run unit tests run: | @@ -63,6 +62,12 @@ jobs: run: | cargo clippy --workspace --all-targets --all-features -- -D warnings + - name: Run Rustdoc + run: | + cargo doc --no-deps --workspace --all-features + env: + RUSTDOCFLAGS: -D warnings + docs: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' @@ -79,7 +84,7 @@ jobs: rustup install nightly --profile minimal cargo +nightly doc --no-deps --workspace --all-features env: - RUSTDOCFLAGS: -D warnings + RUSTDOCFLAGS: --cfg docsrs - name: Deploy Docs uses: JamesIves/github-pages-deploy-action@releases/v4 diff --git a/Cargo.toml b/Cargo.toml index b14c6f4b..4e5ba512 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/khonsulabs/fabruic" keywords = ["quic"] categories = ["network-programming"] edition = "2021" -rust-version = "1.68.2" +rust-version = "1.72" [features] dangerous = [] @@ -24,12 +24,10 @@ flume = { version = "0.11" } futures-channel = "0.3" futures-executor = "0.3" futures-util = "0.3" -if_chain = "1" parking_lot = { version = "0.12", features = ["send_guard"] } pin-project = "1" quinn = "0.10.1" rcgen = { version = "0.11.0", default-features = false, optional = true } -ring = "0.16" rustls = { version = "0.21.1", default-features = false, features = [ "dangerous_configuration", ] } @@ -65,4 +63,5 @@ lto = true [package.metadata.docs.rs] features = ["dangerous", "rcgen", "trust-dns"] +rustdoc-args = ["--cfg", "docsrs"] targets = [] diff --git a/examples/basic.rs b/examples/basic.rs index c22dea85..c1f7191b 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,10 +1,14 @@ +//! TODO + use anyhow::{Error, Result}; use fabruic::{Endpoint, KeyPair}; use futures_util::{future, StreamExt, TryFutureExt}; +/// Used in the certificate. const SERVER_NAME: &str = "test"; /// Some random port. const SERVER_PORT: u16 = 34857; +/// Number of clients to simulate. const CLIENTS: usize = 100; #[tokio::main] @@ -55,7 +59,7 @@ async fn main() -> Result<()> { ); // send message - sender.send(&format!("hello from client {}", index))?; + sender.send(&format!("hello from client {index}"))?; // start listening to new incoming messages // in this example we know there is only 1 incoming message, so we will diff --git a/examples/onestream.rs b/examples/onestream.rs new file mode 100644 index 00000000..96a0a53b --- /dev/null +++ b/examples/onestream.rs @@ -0,0 +1,100 @@ +//! TODO + +#![allow(clippy::missing_docs_in_private_items)] + +use anyhow::{Error, Result}; +use fabruic::{Endpoint, KeyPair}; +use futures_util::StreamExt; + +const SERVER_NAME: &str = "test"; +const SERVER_PORT: u16 = 5001; +const CLIENTS: usize = 100; + +#[tokio::main] +#[cfg_attr(test, test)] +async fn main() -> Result<()> { + // generate a certificate pair + let key_pair = KeyPair::new_self_signed(SERVER_NAME); + + // start the server + let server = Endpoint::new_server(SERVER_PORT, key_pair.clone())?; + let address = format!("quic://{}", server.local_address()?); + println!("[server] Listening on {address}"); + tokio::spawn(run_server(server)); + + // build a client + let client = Endpoint::new_client()?; + + let connection = client + .connect_pinned(address, key_pair.end_entity_certificate(), None) + .await? + .accept::<()>() + .await?; + connection.close_incoming().await?; + + // initiate a stream + let (sender, receiver) = connection.open_stream::(&()).await?; + + let tasks = (0..CLIENTS) + .map(|_| { + let sender = sender.clone(); + let mut receiver = receiver.clone(); + async move { + sender.send(&String::from("test"))?; + let value = receiver.next().await.expect("didn't get a response")?; + assert_eq!(value, "test"); + Ok(()) + } + }) + .collect::>(); + + futures_util::future::join_all(tasks) + .await + .into_iter() + .collect::, Error>>()?; + + // wait for client to finish cleanly + client.wait_idle().await; + + Ok(()) +} + +async fn run_server(mut server: Endpoint) -> Result<(), Error> { + // start listening to new incoming connections + // in this example we know there is `CLIENTS` number of clients, so we will not + // wait for more + let mut connection = server + .next() + .await + .expect("connection failed") + .accept::<()>() + .await?; + println!("[server] New Connection: {}", connection.remote_address()); + + // start listening to new incoming streams + // in this example we know there is only 1 incoming stream, so we will not wait + // for more + let incoming = connection.next().await.expect("no stream found")?; + connection.close_incoming().await?; + println!( + "[server] New incoming stream from: {}", + connection.remote_address() + ); + + // accept stream + let (sender, mut receiver) = incoming.accept::().await?; + + // start listening to new incoming messages + // in this example we know there is only 1 incoming message, so we will not wait + // for more + while let Some(message) = receiver.next().await { + let message = message?; + sender.send(&message)?; + } + + // wait for stream to finish + sender.finish().await?; + receiver.finish().await?; + + Ok(()) +} diff --git a/examples/twostream.rs b/examples/twostream.rs new file mode 100644 index 00000000..ee2e5c7e --- /dev/null +++ b/examples/twostream.rs @@ -0,0 +1,115 @@ +//! TODO + +#![allow(clippy::missing_docs_in_private_items)] + +use anyhow::{Error, Result}; +use fabruic::{Endpoint, Incoming, KeyPair}; +use futures_util::StreamExt; + +const SERVER_NAME: &str = "test"; +const SERVER_PORT: u16 = 5002; +const REQUESTS_PER_STREAM: usize = 10; +const STREAMS: usize = 1000; + +#[tokio::main(worker_threads = 16)] +#[cfg_attr(test, test)] +async fn main() -> Result<()> { + // generate a certificate pair + let key_pair = KeyPair::new_self_signed(SERVER_NAME); + + // start the server + let server = Endpoint::new_server(SERVER_PORT, key_pair.clone())?; + let address = format!("quic://{}", server.local_address()?); + println!("[server] Listening on {address}"); + tokio::spawn(run_server(server)); + + // build a client + let client = Endpoint::new_client()?; + + let connection = client + .connect_pinned(address, key_pair.end_entity_certificate(), None) + .await? + .accept::<()>() + .await?; + connection.close_incoming().await?; + + // initiate a stream + + let tasks = (0..STREAMS) + .map(|_| async { + let (sender, receiver) = connection.open_stream::(&()).await.unwrap(); + (0..REQUESTS_PER_STREAM).for_each(|_| { + let sender = sender.clone(); + let mut receiver = receiver.clone(); + tokio::task::spawn(async move { + sender.send(&String::from("test"))?; + let value = receiver.next().await.expect("didn't get a response")?; + assert_eq!(value, "test"); + Result::<(), Error>::Ok(()) + }); + }); + Ok(()) + }) + .collect::>(); + + futures_util::future::join_all(tasks) + .await + .into_iter() + .collect::, Error>>() + .unwrap(); + + // wait for client to finish cleanly + client.wait_idle().await; + + Ok(()) +} + +async fn run_server(mut server: Endpoint) -> Result<(), Error> { + // start listening to new incoming connections + // in this example we know there is `CLIENTS` number of clients, so we will not + // wait for more + while let Some(connection) = server.next().await { + let connection = connection.accept::<()>().await?; + println!("[server] New Connection: {}", connection.remote_address()); + + // every new incoming connections is handled in it's own task + tokio::spawn(run_connection(connection)); + } + + Ok(()) +} + +async fn run_connection(mut connection: fabruic::Connection<()>) -> Result<(), Error> { + // start listening to new incoming streams + // in this example we know there is only 1 incoming stream, so we will not wait + // for more + while let Some(incoming) = connection.next().await { + // connection.close_incoming().await?; + /*println!( + "[server] New incoming stream from: {}", + connection.remote_address() + );*/ + + tokio::spawn(run_stream(incoming?)); + } + + Ok(()) +} + +async fn run_stream(incoming: Incoming<()>) -> Result<(), Error> { + let (sender, mut receiver) = incoming.accept::().await?; + + // start listening to new incoming messages + // in this example we know there is only 1 incoming message, so we will not wait + // for more + while let Some(message) = receiver.next().await { + let message = message?; + sender.send(&message)?; + } + + // wait for stream to finish + sender.finish().await?; + receiver.finish().await?; + + Ok(()) +} diff --git a/lints.txt b/lints.txt new file mode 100644 index 00000000..426b2da3 --- /dev/null +++ b/lints.txt @@ -0,0 +1,216 @@ + +Available lint options: + -W Warn about + -A Allow + -D Deny + -F Forbid (deny and all attempts to override) + + +Lint checks provided by rustc: + + name default meaning + ---- ------- ------- + absolute-paths-not-starting-with-crate allow fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name + box-pointers allow use of owned (Box type) heap memory + deprecated-in-future allow detects use of items that will be deprecated in a future version + elided-lifetimes-in-paths allow hidden lifetime parameters in types are deprecated + explicit-outlives-requirements allow outlives requirements can be inferred + ffi-unwind-calls allow call to foreign functions or function pointers with FFI-unwind ABI + fuzzy-provenance-casts allow a fuzzy integer to pointer cast is used + invalid-reference-casting allow casts of `&T` to `&mut T` without interior mutability + keyword-idents allow detects edition keywords being used as an identifier + let-underscore-drop allow non-binding let on a type that implements `Drop` + lossy-provenance-casts allow a lossy pointer to integer cast is used + macro-use-extern-crate allow the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system + meta-variable-misuse allow possible meta-variable misuse at macro definition + missing-abi allow No declared ABI for extern declaration + missing-copy-implementations allow detects potentially-forgotten implementations of `Copy` + missing-debug-implementations allow detects missing implementations of Debug + missing-docs allow detects missing documentation for public members + multiple-supertrait-upcastable allow detect when an object-safe trait has multiple supertraits + must-not-suspend allow use of a `#[must_not_suspend]` value across a yield point + non-ascii-idents allow detects non-ASCII identifiers + non-exhaustive-omitted-patterns allow detect when patterns of types marked `non_exhaustive` are missed + noop-method-call allow detects the use of well-known noop methods + pointer-structural-match allow pointers are not structural-match + private-bounds allow private type in secondary interface of an item + private-interfaces allow private type in primary interface of an item + rust-2021-incompatible-closure-captures allow detects closures affected by Rust 2021 changes + rust-2021-incompatible-or-patterns allow detects usage of old versions of or-patterns + rust-2021-prefixes-incompatible-syntax allow identifiers that will be parsed as a prefix in Rust 2021 + rust-2021-prelude-collisions allow detects the usage of trait methods which are ambiguous with traits added to the prelude in future editions + single-use-lifetimes allow detects lifetime parameters that are only used once + trivial-casts allow detects trivial casts which could be removed + trivial-numeric-casts allow detects trivial casts of numeric types which could be removed + unnameable-types allow effective visibility of a type is larger than the area in which it can be named + unreachable-pub allow `pub` items not reachable from crate root + unsafe-code allow usage of `unsafe` code and other potentially unsound constructs + unsafe-op-in-unsafe-fn allow unsafe operations in unsafe functions without an explicit unsafe block are deprecated + unstable-features allow enabling unstable features (deprecated. do not use) + unused-crate-dependencies allow crate dependencies that are never used + unused-extern-crates allow extern crates that are never used + unused-import-braces allow unnecessary braces around an imported item + unused-lifetimes allow detects lifetime parameters that are never used + unused-macro-rules allow detects macro rules that were not used + unused-qualifications allow detects unnecessarily qualified names + unused-results allow unused result of an expression in a statement + unused-tuple-struct-fields allow detects tuple struct fields that are never read + variant-size-differences allow detects enums with widely varying variant sizes + ambiguous-glob-reexports warn ambiguous glob re-exports + anonymous-parameters warn detects anonymous parameters + array-into-iter warn detects calling `into_iter` on arrays in Rust 2015 and 2018 + asm-sub-register warn using only a subset of a register for inline asm inputs + bad-asm-style warn incorrect use of inline assembly + bare-trait-objects warn suggest using `dyn Trait` for trait objects + break-with-label-and-loop warn `break` expression with label and unlabeled loop as value expression + byte-slice-in-packed-struct-with-derive warn `[u8]` or `str` used in a packed struct with `derive` + clashing-extern-declarations warn detects when an extern fn has been declared with the same name but different types + coherence-leak-check warn distinct impls distinguished only by the leak-check code + confusable-idents warn detects visually confusable pairs between identifiers + const-evaluatable-unchecked warn detects a generic constant is used in a type without a emitting a warning + const-item-mutation warn detects attempts to mutate a `const` item + dead-code warn detect unused, unexported items + deprecated warn detects use of deprecated items + deprecated-where-clause-location warn deprecated where clause location + deref-into-dyn-supertrait warn `Deref` implementation usage with a supertrait trait object for output might be shadowed in the future + deref-nullptr warn detects when an null pointer is dereferenced + dropping-copy-types warn calls to `std::mem::drop` with a value that implements Copy + dropping-references warn calls to `std::mem::drop` with a reference instead of an owned value + drop-bounds warn bounds of the form `T: Drop` are most likely incorrect + duplicate-macro-attributes warn duplicated attribute + dyn-drop warn trait objects of the form `dyn Drop` are useless + ellipsis-inclusive-range-patterns warn `...` range patterns are deprecated + exported-private-dependencies warn public interface leaks type from a private dependency + forbidden-lint-groups warn applying forbid to lint-groups + forgetting-copy-types warn calls to `std::mem::forget` with a value that implements Copy + forgetting-references warn calls to `std::mem::forget` with a reference instead of an owned value + for-loops-over-fallibles warn for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let` + function-item-references warn suggest casting to a function pointer when attempting to take references to function items + hidden-glob-reexports warn name introduced by a private item shadows a name introduced by a public glob re-export + illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns + improper-ctypes warn proper use of libc types in foreign modules + improper-ctypes-definitions warn proper use of libc types in foreign item definitions + incomplete-features warn incomplete features that may function improperly in some or all cases + indirect-structural-match warn constant used in pattern contains value of non-structural-match type in a field or a variant + inline-no-sanitize warn detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]` + invalid-doc-attributes warn detects invalid `#[doc(...)]` attributes + invalid-from-utf8 warn using a non UTF-8 literal in `std::str::from_utf8` + invalid-macro-export-arguments warn "invalid_parameter" isn't a valid argument for `#[macro_export]` + invalid-nan-comparisons warn detects invalid floating point NaN comparisons + invalid-value warn an invalid value is being created (such as a null reference) + irrefutable-let-patterns warn detects irrefutable patterns in `if let` and `while let` statements + large-assignments warn detects large moves or copies + late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters + legacy-derive-helpers warn detects derive helper attributes that are used before they are introduced + map-unit-fn warn `Iterator::map` call that discard the iterator's values + mixed-script-confusables warn detects Unicode scripts whose mixed script confusables codepoints are solely used + named-arguments-used-positionally warn named arguments in format used positionally + nontrivial-structural-match warn constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types + non-camel-case-types warn types, variants, traits and type parameters should have camel case names + non-fmt-panics warn detect single-argument panic!() invocations in which the argument is not a format string + non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern + non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names + non-upper-case-globals warn static constants should have uppercase identifiers + no-mangle-generic-items warn generic items must be mangled + opaque-hidden-inferred-bound warn detects the use of nested `impl Trait` types in associated type bounds that are not general enough + overlapping-range-endpoints warn detects range patterns with overlapping endpoints + path-statements warn path statements with no effect + private-in-public warn detect private items in public interfaces not caught by the old implementation + redundant-semicolons warn detects unnecessary trailing semicolons + renamed-and-removed-lints warn lints that have been renamed or removed + repr-transparent-external-private-fields warn transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields + semicolon-in-expressions-from-macros warn trailing semicolon in macro body used as expression + special-module-name warn module declarations for files with a special meaning + stable-features warn stable features found in `#[feature]` directive + suspicious-auto-trait-impls warn the rules governing auto traits will change in the future + suspicious-double-ref-op warn suspicious call of trait method on `&&T` + temporary-cstring-as-ptr warn detects getting the inner pointer of a temporary `CString` + trivial-bounds warn these bounds don't depend on an type parameters + type-alias-bounds warn bounds in type aliases are not enforced + tyvar-behind-raw-pointer warn raw pointer to an inference variable + uncommon-codepoints warn detects uncommon Unicode codepoints in identifiers + unconditional-recursion warn functions that cannot return without calling themselves + undefined-naked-function-abi warn undefined naked function ABI + unexpected-cfgs warn detects unexpected names and values in `#[cfg]` conditions + unfulfilled-lint-expectations warn unfulfilled lint expectation + ungated-async-fn-track-caller warn enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled + uninhabited-static warn uninhabited static + unknown-lints warn unrecognized lint attribute + unnameable-test-items warn detects an item that cannot be named being marked as `#[test_case]` + unreachable-code warn detects unreachable code paths + unreachable-patterns warn detects unreachable patterns + unstable-name-collisions warn detects name collision with an existing but unstable method + unstable-syntax-pre-expansion warn unstable syntax can change at any point in the future, causing a hard error! + unsupported-calling-conventions warn use of unsupported calling convention + unused-allocation warn detects unnecessary allocations that can be eliminated + unused-assignments warn detect assignments that will never be read + unused-associated-type-bounds warn detects unused `Foo = Bar` bounds in `dyn Trait` + unused-attributes warn detects attributes that were not used by the compiler + unused-braces warn unnecessary braces around an expression + unused-comparisons warn comparisons made useless by limits of the types involved + unused-doc-comments warn detects doc comments that aren't used by rustdoc + unused-features warn unused features found in crate-level `#[feature]` directives + unused-imports warn imports that are never used + unused-labels warn detects labels that are never used + unused-macros warn detects macros that were not used + unused-must-use warn unused result of a type flagged as `#[must_use]` + unused-mut warn detect mut variables which don't need to be mutable + unused-parens warn `if`, `match`, `while` and `return` do not need parentheses + unused-unsafe warn unnecessary use of an `unsafe` block + unused-variables warn detect variables which are not used in any way + warnings warn mass-change the level for lints which produce warnings + where-clauses-object-safety warn checks the object safety of where clauses + while-true warn suggest using `loop { }` instead of `while true { }` + ambiguous-associated-items deny ambiguous associated items + arithmetic-overflow deny arithmetic operation overflows + bindings-with-variant-name deny detects pattern bindings with the same name as one of the matched variants + cenum-impl-drop-cast deny a C-like enum implementing Drop is cast + conflicting-repr-hints deny conflicts between `#[repr(..)]` hints that were previously accepted and used in practice + deprecated-cfg-attr-crate-type-name deny detects usage of `#![cfg_attr(..., crate_type/crate_name = "...")]` + enum-intrinsics-non-enums deny detects calls to `core::mem::discriminant` and `core::mem::variant_count` with non-enum types + ill-formed-attribute-input deny ill-formed attribute inputs that were previously accepted and used in practice + implied-bounds-entailment deny impl method assumes more implied bounds than its corresponding trait method + incomplete-include deny trailing content in included file + ineffective-unstable-trait-impl deny detects `#[unstable]` on stable trait implementations for stable types + invalid-alignment deny raw pointers must be aligned before dereferencing + invalid-atomic-ordering deny usage of invalid atomic ordering in atomic operations and memory fences + invalid-from-utf8-unchecked deny using a non UTF-8 literal in `std::str::from_utf8_unchecked` + invalid-type-param-default deny type parameter default erroneously allowed in invalid location + let-underscore-lock deny non-binding let on a synchronization lock + long-running-const-eval deny detects long const eval operations + macro-expanded-macro-exports-accessed-by-absolute-paths deny macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths + missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns + mutable-transmutes deny transmuting &T to &mut T is undefined behavior, even if the reference is unused + named-asm-labels deny named labels in inline assembly + no-mangle-const-items deny const items will not have their symbols exported + order-dependent-trait-objects deny trait-object types were treated as different depending on marker-trait order + overflowing-literals deny literal out of range for its type + patterns-in-fns-without-body deny patterns in functions without body were erroneously allowed + proc-macro-back-compat deny detects usage of old versions of certain proc-macro crates + proc-macro-derive-resolution-fallback deny detects proc macro derives using inaccessible names from parent modules + pub-use-of-private-extern-crate deny detect public re-exports of private extern crates + soft-unstable deny a feature gate that doesn't break dependent crates + test-unstable-lint deny this unstable lint is only for testing + text-direction-codepoint-in-comment deny invisible directionality-changing codepoints in comment + text-direction-codepoint-in-literal deny detect special Unicode codepoints that affect the visual representation of text on screen, changing the direction in which text flows + unconditional-panic deny operation will cause a panic at runtime + undropped-manually-drops deny calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value + unknown-crate-types deny unknown crate type found in `#[crate_type]` directive + useless-deprecated deny detects deprecation attributes with no effect + + +Lint groups provided by rustc: + + name sub-lints + ---- --------- + warnings all lints that are set to issue warnings + future-incompatible deref-into-dyn-supertrait, ambiguous-associated-items, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, private-in-public, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety + let-underscore let-underscore-drop, let-underscore-lock + nonstandard-style non-camel-case-types, non-snake-case, non-upper-case-globals + rust-2018-compatibility keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer + rust-2018-idioms bare-trait-objects, unused-extern-crates, ellipsis-inclusive-range-patterns, elided-lifetimes-in-paths, explicit-outlives-requirements + rust-2021-compatibility ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics + unused unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn + + +Lint tools like Clippy can provide additional lints and lint groups. diff --git a/src/error.rs b/src/error.rs index c3668b76..bbb9126a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,8 +1,4 @@ -#![allow( - box_pointers, - clippy::module_name_repetitions, - clippy::exhaustive_structs -)] +#![allow(clippy::module_name_repetitions)] //! [`Error`](std::error::Error) for this [`crate`]. // TODO: error type is becoming too big, split it up @@ -17,7 +13,6 @@ use quinn::ConnectionClose; pub use quinn::{ConnectError, ConnectionError, ReadError, WriteError}; use thiserror::Error; #[cfg(feature = "trust-dns")] -#[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub use trust_dns_resolver::error::ResolveError; pub use url::ParseError; pub use webpki::Error; @@ -38,7 +33,6 @@ pub struct Certificate { /// Error constructing [`Certificate`](crate::Certificate) with /// [`Certificate::from_der`](crate::Certificate::from_der). -#[allow(clippy::module_name_repetitions)] #[derive(Clone, Debug, Error, PartialEq)] pub enum CertificateError { /// [`Error`](std::error::Error) returned by [`webpki`]. @@ -66,8 +60,11 @@ pub enum CertificateError { pub struct PrivateKey(pub Vec); impl Debug for PrivateKey { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_tuple("PrivateKey").field(&"[[redacted]]").finish() + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_tuple("PrivateKey") + .field(&"[[redacted]]") + .finish() } } @@ -125,7 +122,6 @@ pub enum Config { /// Error aquiring or parsing root certs from OS. #[derive(Debug, Error)] -#[allow(variant_size_differences)] pub enum OsStore { /// Failed to aquire root certs from OS. #[error("Error aquiring root certificates from the OS: {0}")] @@ -161,7 +157,6 @@ pub enum Connect { ParseDomain(ParseError), /// Failed to resolve domain with [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] #[error("Error resolving domain with trust-dns: {0}")] TrustDns(#[from] Box), /// Failed to resolve domain with diff --git a/src/lib.rs b/src/lib.rs index cd57c40b..af36a77d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,65 +1,12 @@ #![deny(unsafe_code)] -#![warn(clippy::cargo, clippy::pedantic, future_incompatible, rust_2018_idioms)] -#![warn( - macro_use_extern_crate, - meta_variable_misuse, - missing_copy_implementations, - missing_debug_implementations, - missing_docs, - non_ascii_idents, - single_use_lifetimes, - trivial_casts, - trivial_numeric_casts, - unreachable_pub, - unused_import_braces, - unused_lifetimes, - unused_qualifications, - unused_results, - variant_size_differences -)] -#![allow( - clippy::blanket_clippy_restriction_lints, - clippy::else_if_without_else, - clippy::exhaustive_enums, - clippy::expect_used, - clippy::future_not_send, - clippy::implicit_return, - clippy::missing_inline_in_public_items, - clippy::multiple_crate_versions, - clippy::non_ascii_literal, - clippy::pattern_type_mismatch, - clippy::redundant_pub_crate, - clippy::separated_literal_suffix, - clippy::shadow_reuse, - // Currently breaks async - clippy::shadow_same, - clippy::shadow_unrelated, - clippy::tabs_in_doc_comments, - clippy::unreachable, - clippy::wildcard_enum_match_arm, - // See: https://github.com/rust-lang/rust/issues/64762 - unreachable_pub, -)] -#![cfg_attr( - doc, - feature(doc_cfg), - warn(rustdoc::all), - allow(rustdoc::missing_doc_code_examples, rustdoc::private_doc_tests) -)] -#![cfg_attr( - test, - allow( - clippy::arithmetic_side_effects, - clippy::panic, - clippy::panic_in_result_fn - ) -)] +#![allow(clippy::missing_docs_in_private_items)] +#![allow(clippy::multiple_crate_versions)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] //! TODO mod x509; #[cfg(feature = "dangerous")] -#[cfg_attr(doc, doc(cfg(feature = "dangerous")))] pub mod dangerous { //! Security-sensitive settings are hidden behind these traits. Be careful! diff --git a/src/quic/connection/incoming.rs b/src/quic/connection/incoming.rs index 839e4335..9b3ca578 100644 --- a/src/quic/connection/incoming.rs +++ b/src/quic/connection/incoming.rs @@ -22,8 +22,9 @@ pub struct Incoming { } impl Debug for Incoming { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Incoming") + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Incoming") .field("sender", &self.sender) .field("receiver", &"ReceiverStream") .field("type", &"Option>") @@ -47,12 +48,11 @@ impl Incoming { /// - [`error::Incoming::Receiver`] if receiving the type information to the /// peer failed, see [`error::Receiver`] for more details /// - [`error::Incoming::Closed`] if the stream was closed - // TODO: fix lint - #[allow(unused_lifetimes)] // TODO: return different state, because error can't be cloned and state is // unusable anyway #[allow(clippy::missing_panics_doc)] pub async fn r#type(&mut self) -> Result<&T, &error::Incoming> { + #[allow(clippy::ref_patterns)] if let Some(ref r#type) = self.r#type { r#type.as_ref() } else { @@ -63,12 +63,7 @@ impl Incoming { .map_or(Err(error::Incoming::Closed), |result| { result.map_err(error::Incoming::Receiver) }); - // TODO: replace with `Option::insert` - self.r#type = Some(r#type); - self.r#type - .as_ref() - .expect("`type` just inserted missing") - .as_ref() + self.r#type.insert(r#type).as_ref() } } diff --git a/src/quic/connection/mod.rs b/src/quic/connection/mod.rs index a83f0cb4..16d5bc7c 100644 --- a/src/quic/connection/mod.rs +++ b/src/quic/connection/mod.rs @@ -16,6 +16,7 @@ mod sender; use std::{ fmt::{self, Debug, Formatter}, + future::Future, marker::PhantomData, net::SocketAddr, pin::{pin, Pin}, @@ -23,7 +24,6 @@ use std::{ }; pub use connecting::Connecting; -use flume::r#async::RecvStream; use futures_channel::oneshot; use futures_util::{ stream::{self, FusedStream}, @@ -31,7 +31,7 @@ use futures_util::{ }; pub use incoming::Incoming; use pin_project::pin_project; -use quinn::{crypto::rustls::HandshakeData, AcceptBi, VarInt}; +use quinn::{crypto::rustls::HandshakeData, AcceptBi, RecvStream, SendStream, VarInt}; pub use receiver::Receiver; use receiver_stream::ReceiverStream; pub use sender::Sender; @@ -49,7 +49,7 @@ pub struct Connection { connection: quinn::Connection, /// Receive incoming streams. receiver: - RecvStream<'static, Result<(quinn::SendStream, quinn::RecvStream), error::Connection>>, + flume::r#async::RecvStream<'static, Result<(SendStream, RecvStream), error::Connection>>, /// [`Task`] handling new incoming streams. task: Task<()>, /// Type for type negotiation for new streams. @@ -57,8 +57,9 @@ pub struct Connection { } impl Debug for Connection { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Connection") + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Connection") .field("connection", &self.connection) .field("receiver", &"RecvStream") .field("task", &self.task) @@ -69,7 +70,6 @@ impl Debug for Connection { impl Connection { /// Builds a new [`Connection`] from raw [`quinn`] types. - #[allow(clippy::mut_mut)] // futures_util::select_biased internal usage pub(super) fn new(connection: quinn::Connection) -> Self { // channels for passing down new `Incoming` `Connection`s let (sender, receiver) = flume::unbounded(); @@ -193,15 +193,15 @@ impl FusedStream for Connectio } } -struct IncomingStreams<'a> { - connection: &'a quinn::Connection, - accept: Option>>>, +struct IncomingStreams<'connection> { + connection: &'connection quinn::Connection, + accept: Option>>>, shutdown: oneshot::Receiver<()>, - sender: flume::Sender>, + sender: flume::Sender>, complete: bool, } -impl std::future::Future for IncomingStreams<'_> { +impl Future for IncomingStreams<'_> { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { diff --git a/src/quic/connection/receiver.rs b/src/quic/connection/receiver.rs index 9cbccdda..723dae22 100644 --- a/src/quic/connection/receiver.rs +++ b/src/quic/connection/receiver.rs @@ -23,8 +23,9 @@ pub struct Receiver { } impl Debug for Receiver { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Receiver") + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Receiver") .field("receiver", &"RecvStream") .field("task", &self.task) .finish() @@ -34,7 +35,6 @@ impl Debug for Receiver { impl Receiver { /// Builds a new [`Receiver`] from a raw [`quinn`] type. Spawns a task that /// receives data from the stream. - #[allow(clippy::mut_mut)] // futures_util::select_biased internal usage pub(super) fn new(mut stream: ReceiverStream) -> Self where T: DeserializeOwned + Send, diff --git a/src/quic/connection/sender.rs b/src/quic/connection/sender.rs index 80e248d1..c4acd098 100644 --- a/src/quic/connection/sender.rs +++ b/src/quic/connection/sender.rs @@ -92,7 +92,6 @@ impl Sender { /// - [`error::Sender::Write`] if the [`Sender`] failed to to write to the /// stream /// - [`error::Sender::Closed`] if the [`Sender`] is closed - #[allow(clippy::panic_in_result_fn, clippy::unwrap_in_result)] pub(super) fn send_any(&self, data: &A) -> Result<(), error::Sender> { let mut bytes = BytesMut::new(); diff --git a/src/quic/endpoint/builder/config.rs b/src/quic/endpoint/builder/config.rs index bdb1d634..cc7da488 100644 --- a/src/quic/endpoint/builder/config.rs +++ b/src/quic/endpoint/builder/config.rs @@ -33,15 +33,12 @@ pub(in crate::quic::endpoint) struct Config { max_idle_timeout: Option, /// Enable [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] trust_dns: bool, /// Enables DNSSEC validation for [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] dnssec: bool, /// Enables `/etc/hosts` file support for [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] hosts_file: bool, } @@ -96,7 +93,6 @@ impl Config { /// Controls the use of [`trust-dns`](trust_dns_resolver) for /// [`Endpoint::connect`](crate::Endpoint::connect). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub(super) fn set_trust_dns(&mut self, enable: bool) { self.trust_dns = enable; } @@ -104,10 +100,7 @@ impl Config { /// Disables the use of [`trust-dns`](trust_dns_resolver) for /// [`Endpoint::connect`](crate::Endpoint::connect) despite the activates /// crate features. - #[cfg_attr( - not(feature = "trust-dns"), - allow(clippy::unused_self, unused_variables) - )] + #[cfg_attr(not(feature = "trust-dns"), allow(clippy::unused_self))] pub(super) fn disable_trust_dns(&mut self) { #[cfg(feature = "trust-dns")] { @@ -126,14 +119,12 @@ impl Config { /// Controls DNSSEC validation for [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub(super) fn set_dnssec(&mut self, enable: bool) { self.dnssec = enable; } /// Returns if DNSSEC is enabled for [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub(in crate::quic::endpoint) const fn dnssec(&self) -> bool { self.dnssec } @@ -141,7 +132,6 @@ impl Config { /// Controls `/etc/hosts` file support for /// [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub(super) fn set_hosts_file(&mut self, enable: bool) { self.hosts_file = enable; } @@ -149,7 +139,6 @@ impl Config { /// Returns if `/etc/hosts` file support is enabled for /// [`trust-dns`](trust_dns_resolver). #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub(in crate::quic::endpoint) const fn hosts_file(&self) -> bool { self.hosts_file } @@ -189,7 +178,6 @@ impl Config { /// Panics if the given [`KeyPair`] or [`Certificate`]s are invalid. Can't /// happen if they were properly validated through [`KeyPair::from_parts`] /// or [`Certificate::from_der`]. - #[allow(clippy::unwrap_in_result)] pub(in crate::quic::endpoint) fn new_client( &self, certificates: &[Certificate], @@ -259,7 +247,6 @@ impl Config { ct_logs::LOGS, // Add one year to last release. PrimitiveDateTime::new( - #[allow(clippy::arithmetic_side_effects)] Date::from_calendar_date(2021 + 1, Month::April, 10).expect("invalid date"), Time::MIDNIGHT, ) diff --git a/src/quic/endpoint/builder/mod.rs b/src/quic/endpoint/builder/mod.rs index 3179f98d..a0f2266c 100644 --- a/src/quic/endpoint/builder/mod.rs +++ b/src/quic/endpoint/builder/mod.rs @@ -272,7 +272,6 @@ impl Builder { /// builder.set_trust_dns(false); /// ``` #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub fn set_trust_dns(&mut self, enable: bool) { self.config.set_trust_dns(enable); } @@ -334,7 +333,6 @@ impl Builder { /// builder.set_dnssec(false); /// ``` #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub fn set_dnssec(&mut self, enable: bool) { self.config.set_dnssec(enable); } @@ -354,7 +352,6 @@ impl Builder { /// ``` #[must_use] #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub const fn dnssec(&self) -> bool { self.config.dnssec() } @@ -374,7 +371,6 @@ impl Builder { /// builder.set_hosts_file(false); /// ``` #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub fn set_hosts_file(&mut self, enable: bool) { self.config.set_hosts_file(enable); } @@ -395,7 +391,6 @@ impl Builder { /// ``` #[must_use] #[cfg(feature = "trust-dns")] - #[cfg_attr(doc, doc(cfg(feature = "trust-dns")))] pub const fn hosts_file(&self) -> bool { self.config.hosts_file() } @@ -461,7 +456,6 @@ impl Builder { /// # Errors /// [`Config::MaxIdleTimeout`](error::Config::MaxIdleTimeout) if time /// exceeds 2^62 ms. - #[allow(clippy::unwrap_in_result)] pub fn set_max_idle_timeout(&mut self, time: Option) -> Result<(), error::Config> { self.config.set_max_idle_timeout(time) } @@ -689,8 +683,6 @@ mod test { use futures_util::StreamExt; use quinn::ConnectionError; use quinn_proto::TransportError; - use trust_dns_proto::error::ProtoErrorKind; - use trust_dns_resolver::error::ResolveErrorKind; use super::*; @@ -907,6 +899,7 @@ mod test { } #[test] + #[cfg(feature = "trust-dns")] fn trust_dns() { let mut builder = Builder::new(); @@ -930,7 +923,7 @@ mod test { let endpoint = builder.build()?; // TODO: find a better target without DNSSEC support then Google - assert!(endpoint.connect("https://google.com").await.is_ok()); + let _ = endpoint.connect("https://google.com").await.unwrap(); Ok(()) } @@ -942,13 +935,17 @@ mod test { let endpoint = builder.build()?; // TODO: find a better target with DNSSEC support then Cloudflare - assert!(endpoint.connect("https://cloudflare.com").await.is_ok()); + let _ = endpoint.connect("https://cloudflare.com").await.unwrap(); Ok(()) } #[tokio::test] + #[cfg(feature = "trust-dns")] async fn trust_dns_fail() -> Result<()> { + use trust_dns_proto::error::ProtoErrorKind; + use trust_dns_resolver::error::ResolveErrorKind; + let endpoint = Builder::new().build()?; // TODO: find a better target without DNSSEC support then Google @@ -968,6 +965,7 @@ mod test { } #[test] + #[cfg(feature = "trust-dns")] fn dnssec() { let mut builder = Builder::new(); @@ -982,18 +980,20 @@ mod test { } #[tokio::test] + #[cfg(feature = "trust-dns")] async fn dnssec_disabled() -> Result<()> { let mut builder = Builder::new(); builder.set_dnssec(false); let endpoint = builder.build()?; // TODO: find a better target without DNSSEC support then Google - assert!(endpoint.connect("https://google.com").await.is_ok()); + let _ = endpoint.connect("https://google.com").await.unwrap(); Ok(()) } #[test] + #[cfg(feature = "trust-dns")] fn hosts_file() { let mut builder = Builder::new(); @@ -1014,8 +1014,9 @@ mod test { // connection, for some reason IPv6 `[::]` doesn't work on GitHub Actions builder.set_address(([0, 0, 0, 0], 0).into()); // QUIC is comptaible with HTTP/3 to establish a connection only - builder.set_protocols([b"h3-29".to_vec()]); + builder.set_protocols([b"h3".to_vec()]); // `cloudflare-quic` doesn't support DNSSEC + #[cfg(feature = "trust-dns")] builder.set_dnssec(false); // default @@ -1027,12 +1028,12 @@ mod test { let endpoint = builder.build()?; // TODO: find a better target to test our root certificate store against - assert!(endpoint + let _ = endpoint .connect("https://cloudflare-quic.com:443") .await? .accept::<()>() .await - .is_ok()); + .unwrap(); Ok(()) } @@ -1044,8 +1045,9 @@ mod test { // connection, for some reason IPv6 `[::]` doesn't work on GitHub Actions builder.set_address(([0, 0, 0, 0], 0).into()); // QUIC is comptaible with HTTP/3 to establish a connection only - builder.set_protocols([b"h3-29".to_vec()]); + builder.set_protocols([b"h3".to_vec()]); // `cloudflare-quic` doesn't support DNSSEC + #[cfg(feature = "trust-dns")] builder.set_dnssec(false); builder.set_store(Store::Os); @@ -1054,12 +1056,12 @@ mod test { let endpoint = builder.build()?; // TODO: find a better target to test our root certificate store against - assert!(endpoint + let _ = endpoint .connect("https://cloudflare-quic.com:443") .await? .accept::<()>() .await - .is_ok()); + .unwrap(); Ok(()) } @@ -1071,8 +1073,9 @@ mod test { // connection, for some reason IPv6 `[::]` doesn't work on GitHub Actions builder.set_address(([0, 0, 0, 0], 0).into()); // QUIC is comptaible with HTTP/3 to establish a connection only - builder.set_protocols([b"h3-29".to_vec()]); + builder.set_protocols([b"h3".to_vec()]); // `cloudflare-quic` doesn't support DNSSEC + #[cfg(feature = "trust-dns")] builder.set_dnssec(false); builder.set_store(Store::Empty); diff --git a/src/quic/endpoint/mod.rs b/src/quic/endpoint/mod.rs index f6fc0aa9..239e70a1 100644 --- a/src/quic/endpoint/mod.rs +++ b/src/quic/endpoint/mod.rs @@ -9,7 +9,7 @@ use std::{ pin::Pin, slice, sync::Arc, - task::{Context, Poll}, + task::{Context, Poll}, future::Future, }; use async_trait::async_trait; @@ -50,8 +50,9 @@ pub struct Endpoint { } impl Debug for Endpoint { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Server") + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Server") .field("endpoint", &self.endpoint) .field("receiver", &"RecvStream") .field("task", &self.task) @@ -321,7 +322,6 @@ impl Endpoint { /// .await?; /// # Ok(()) } /// ``` - #[allow(clippy::unwrap_in_result)] pub async fn connect_pinned>( &self, url: U, @@ -530,15 +530,15 @@ impl Endpoint { } } -struct IncomingConnections<'a> { - endpoint: &'a quinn::Endpoint, - accept: Option>>>, +struct IncomingConnections<'connection> { + endpoint: &'connection quinn::Endpoint, + accept: Option>>>, shutdown: Receiver<()>, sender: Sender, complete: bool, } -impl std::future::Future for IncomingConnections<'_> { +impl Future for IncomingConnections<'_> { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -700,7 +700,7 @@ mod test { #[test] fn builder() { - let _builder: Builder = Endpoint::builder(); + let _builder = Endpoint::builder(); } #[tokio::test] diff --git a/src/quic/task.rs b/src/quic/task.rs index 97ab0074..f2de2b29 100644 --- a/src/quic/task.rs +++ b/src/quic/task.rs @@ -192,8 +192,6 @@ mod test { #[tokio::test] #[should_panic = "test"] - // TODO: fix lint (https://github.com/rust-lang/rust-clippy/issues/7438) - #[allow(clippy::semicolon_if_nothing_returned)] async fn panic_await() { let task: Task<()> = Task::new(|_| async move { panic!("test"); @@ -204,8 +202,6 @@ mod test { #[tokio::test] #[should_panic = "test"] - // TODO: fix lint (https://github.com/rust-lang/rust-clippy/issues/7438) - #[allow(clippy::semicolon_if_nothing_returned)] async fn panic_close() { let task = Task::new(|_| async move { panic!("test"); diff --git a/src/x509/mod.rs b/src/x509/mod.rs index 77ef9293..d09064f2 100644 --- a/src/x509/mod.rs +++ b/src/x509/mod.rs @@ -2,7 +2,7 @@ mod certificate; mod certificate_chain; -pub mod private_key; +pub(crate) mod private_key; pub use certificate::Certificate; pub use certificate_chain::CertificateChain; @@ -35,7 +35,6 @@ impl TryFrom<(CertificateChain, PrivateKey)> for KeyPair { impl KeyPair { /// Generate a self signed certificate. #[cfg(feature = "rcgen")] - #[cfg_attr(doc, doc(cfg(feature = "rcgen")))] #[allow(clippy::missing_panics_doc)] pub fn new_self_signed>(domain: S) -> Self { let key_pair = rcgen::generate_simple_self_signed([domain.into()]) @@ -115,7 +114,6 @@ impl KeyPair { /// Destructure [`KeyPair`] into it's owned parts. #[must_use] - #[allow(clippy::missing_const_for_fn)] pub fn into_parts(self) -> (CertificateChain, PrivateKey) { (self.certificate_chain, self.private_key) } @@ -171,7 +169,6 @@ impl Dangerous for KeyPair { /// /// We [`Serialize`](serde::Serialize) [`PrivateKey`] in [`KeyPair`] not /// directly, we have to correspondingly do the same when [`Deserialize`]ing. -#[allow(single_use_lifetimes)] fn deserialize_private_key<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, diff --git a/src/x509/private_key.rs b/src/x509/private_key.rs index 83a710cb..39d949f7 100644 --- a/src/x509/private_key.rs +++ b/src/x509/private_key.rs @@ -20,8 +20,11 @@ use crate::error; pub struct PrivateKey(Option>); impl Debug for PrivateKey { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_tuple("PrivateKey").field(&"[[redacted]]").finish() + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter + .debug_tuple("PrivateKey") + .field(&"[[redacted]]") + .finish() } }