1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-08-12 09:57:07 +02:00

Compare commits

..

11 Commits

Author SHA1 Message Date
Rob Ede
14272a1762 chore: force secure rustls-webpki 2023-08-29 18:45:11 +01:00
Rob Ede
7e043048a0 chore(actix-tls): prepare release 3.1.1 2023-08-29 18:41:48 +01:00
Rob Ede
45a7dcba90 chore(tls): fix min rustls version 2023-08-29 18:40:55 +01:00
Rob Ede
5029beb866 prepare actix-tls release 3.1.0 2023-08-26 18:05:39 +01:00
Rob Ede
910c181251 prepare actix-server release 2.3.0 2023-08-26 18:04:22 +01:00
Rob Ede
150d2c05d3 prepare actix-rt release 2.9.0 2023-08-26 18:02:48 +01:00
Alik Aslanyan
3b5716c23e Add getter methods for actix_rt::Runtime and tokio::runtime::Runtime (#484)
Co-authored-by: Alik Aslanyan <inline0@pm.me>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2023-08-26 15:04:08 +00:00
Rob Ede
0bc310a656 Rustls v0.21 support (#480) 2023-08-26 14:59:51 +01:00
Rob Ede
6ce8307060 remove num_cpus dependency (#488) 2023-08-24 00:56:31 +01:00
Rob Ede
9cb8a1fadc remove lint exception 2023-07-24 03:27:44 +01:00
Rob Ede
9017de439f ci: fix post-merge tool installs 2023-07-20 00:22:55 +01:00
31 changed files with 747 additions and 141 deletions

View File

@@ -15,9 +15,11 @@ ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
# tests avoiding io-uring feature
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
ci-test-rustls-020 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_21 test --lib --tests --no-fail-fast -- --nocapture"
ci-test-rustls-021 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
# tests avoiding io-uring feature on Windows
ci-test-win = "hack --feature-powerset --depth 2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
ci-test-win = "hack --feature-powerset --depth=2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
# test with io-uring feature
ci-test-linux = "hack --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
ci-test-linux = "hack --feature-powerset --exclude-features=rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"

View File

@@ -16,6 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# prettier-ignore
target:
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
@@ -37,6 +38,10 @@ jobs:
- uses: actions/checkout@v3
- name: Free Disk Space
if: matrix.target.os == 'ubuntu-latest'
run: ./scripts/free-disk-space.sh
- name: Install OpenSSL
if: matrix.target.os == 'windows-latest'
run: choco install openssl -y --forcex64 --no-progress
@@ -83,8 +88,15 @@ jobs:
run: cargo ci-test
- name: tests
if: matrix.target.os == 'ubuntu-latest'
run: |
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
run: >-
sudo bash -c "
ulimit -Sl 512
&& ulimit -Hl 512
&& PATH=$PATH:/usr/share/rust/.cargo/bin
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-020
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
"
- name: Clear the cargo caches
run: |
@@ -101,11 +113,13 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with: { toolchain: nightly }
- name: Install cargo-tarpaulin
uses: taiki-e/install-action@v1
with: { tool: cargo-tarpaulin }
- name: Generate coverage file
if: github.ref == 'refs/heads/master'
run: |
cargo install cargo-tarpaulin
cargo tarpaulin --out Xml --verbose
run: cargo tarpaulin --out Xml --verbose
- name: Upload to Codecov
if: github.ref == 'refs/heads/master'
uses: codecov/codecov-action@v3
@@ -121,8 +135,9 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with: { toolchain: nightly }
- uses: taiki-e/install-action@v1
with: { tool: cargo-hack, cargo-minimal-versions }
- name: Install cargo-hack & cargo-minimal-versions
uses: taiki-e/install-action@v1
with: { tool: 'cargo-hack,cargo-minimal-versions' }
- name: Check With Minimal Versions
run: cargo minimal-versions check
@@ -137,7 +152,8 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install cargo-nextest
run: cargo install cargo-nextest
uses: taiki-e/install-action@v1
with: { tool: cargo-nextest }
- name: Test with cargo-nextest
run: cargo nextest run

View File

@@ -1,6 +1,6 @@
name: CI
on:
on:
pull_request: {}
push: { branches: [master] }
@@ -16,6 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# prettier-ignore
target:
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
@@ -38,6 +39,10 @@ jobs:
- uses: actions/checkout@v3
- name: Free Disk Space
if: matrix.target.os == 'ubuntu-latest'
run: ./scripts/free-disk-space.sh
- name: Install OpenSSL
if: matrix.target.os == 'windows-latest'
run: choco install openssl -y --forcex64 --no-progress
@@ -95,8 +100,15 @@ jobs:
run: cargo ci-test-win
- name: tests
if: matrix.target.os == 'ubuntu-latest'
run: |
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
run: >-
sudo bash -c "
ulimit -Sl 512
&& ulimit -Hl 512
&& PATH=$PATH:/usr/share/rust/.cargo/bin
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-020
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
"
- name: Clear the cargo caches
run: |

View File

@@ -15,6 +15,7 @@ members = [
resolver = "2"
[workspace.package]
license = "MIT OR Apache-2.0"
edition = "2021"
rust-version = "1.65"

View File

@@ -28,8 +28,6 @@ type AttributeArgs = syn::punctuated::Punctuated<syn::Meta, syn::Token![,]>;
/// println!("Hello world");
/// }
/// ```
// #[allow(clippy::needless_doctest_main)]
// #[cfg(not(test))] // Work around for rust-lang/rust#62127
#[proc_macro_attribute]
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {

View File

@@ -2,6 +2,10 @@
## Unreleased - 2023-xx-xx
## 2.9.0
- Add `actix_rt::System::runtime()` method to retrieve the underlying `actix_rt::Runtime` runtime.
- Add `actix_rt::Runtime::tokio_runtime()` method to retrieve the underlying Tokio runtime.
- Minimum supported Rust version (MSRV) is now 1.65.
## 2.8.0 - 2022-12-21

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-rt"
version = "2.8.0"
version = "2.9.0"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",

View File

@@ -3,11 +3,11 @@
> Tokio-based single-threaded async runtime for the Actix ecosystem.
[![crates.io](https://img.shields.io/crates/v/actix-rt?label=latest)](https://crates.io/crates/actix-rt)
[![Documentation](https://docs.rs/actix-rt/badge.svg?version=2.8.0)](https://docs.rs/actix-rt/2.8.0)
[![Documentation](https://docs.rs/actix-rt/badge.svg?version=2.9.0)](https://docs.rs/actix-rt/2.9.0)
[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-rt.svg)
<br />
[![dependency status](https://deps.rs/crate/actix-rt/2.8.0/status.svg)](https://deps.rs/crate/actix-rt/2.8.0)
[![dependency status](https://deps.rs/crate/actix-rt/2.9.0/status.svg)](https://deps.rs/crate/actix-rt/2.9.0)
![Download](https://img.shields.io/crates/d/actix-rt.svg)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/WghFtEH6Hb)

View File

@@ -61,6 +61,62 @@ impl Runtime {
self.local.spawn_local(future)
}
/// Retrieves a reference to the underlying Tokio runtime associated with this instance.
///
/// The Tokio runtime is responsible for executing asynchronous tasks and managing
/// the event loop for an asynchronous Rust program. This method allows accessing
/// the runtime to interact with its features directly.
///
/// In a typical use case, you might need to share the same runtime between different
/// modules of your project. For example, a module might require a `tokio::runtime::Handle`
/// to spawn tasks on the same runtime, or the runtime itself to configure more complex
/// behaviours.
///
/// # Example
///
/// ```
/// use actix_rt::Runtime;
///
/// mod module_a {
/// pub fn do_something(handle: tokio::runtime::Handle) {
/// handle.spawn(async {
/// // Some asynchronous task here
/// });
/// }
/// }
///
/// mod module_b {
/// pub fn do_something_else(rt: &tokio::runtime::Runtime) {
/// rt.spawn(async {
/// // Another asynchronous task here
/// });
/// }
/// }
///
/// let actix_runtime = actix_rt::Runtime::new().unwrap();
/// let tokio_runtime = actix_runtime.tokio_runtime();
///
/// let handle = tokio_runtime.handle().clone();
///
/// module_a::do_something(handle);
/// module_b::do_something_else(tokio_runtime);
/// ```
///
/// # Returns
///
/// An immutable reference to the `tokio::runtime::Runtime` instance associated with this
/// `Runtime` instance.
///
/// # Note
///
/// While this method provides an immutable reference to the Tokio runtime, which is safe to share across threads,
/// be aware that spawning blocking tasks on the Tokio runtime could potentially impact the execution
/// of the Actix runtime. This is because Tokio is responsible for driving the Actix system,
/// and blocking tasks could delay or deadlock other tasks in run loop.
pub fn tokio_runtime(&self) -> &tokio::runtime::Runtime {
&self.rt
}
/// Runs the provided future, blocking the current thread until the future completes.
///
/// This function can be used to synchronously block the current thread until the provided

View File

@@ -203,6 +203,41 @@ impl SystemRunner {
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
}
/// Retrieves a reference to the underlying Actix runtime associated with this SystemRunner instance.
///
/// The Actix runtime is responsible for managing the event loop for an Actix system and executing asynchronous tasks.
/// This method provides access to the runtime, allowing direct interaction with its features.
///
/// In a typical use case, you might need to share the same runtime between different
/// parts of your project. For example, some components might require a [`actix_rt::Runtime`] to spawn tasks on
/// the same runtime.
///
/// # Example
///
/// ```
/// let system_runner = actix_rt::System::new();
/// let actix_runtime = system_runner.runtime();
///
/// // Use the runtime to spawn an async task or perform other operations
/// ```
///
/// Read more in the documentation for [`actix_rt::Runtime`]
///
/// # Returns
///
/// An immutable reference to the [`actix_rt::Runtime`] instance associated with this
/// [`actix_rt::SystemRunner`] instance.
///
/// # Note
///
/// While this method provides an immutable reference to the Actix runtime, which is safe to share across threads,
/// be aware that spawning blocking tasks on the Actix runtime could potentially impact system performance.
/// This is because the Actix runtime is responsible for driving the system,
/// and blocking tasks could delay other tasks in the run loop.
pub fn runtime(&self) -> &crate::runtime::Runtime {
&self.rt
}
/// Runs the provided future, blocking the current thread until the future completes.
#[track_caller]
#[inline]

View File

@@ -1,22 +1,24 @@
# Changes
## Unreleased - 2023-xx-xx
## Unreleased
## 2.3.0
- Add support for MultiPath TCP (MPTCP) with `MpTcp` enum and `ServerBuilder::mptcp()` method.
- Minimum supported Rust version (MSRV) is now 1.65.
## 2.2.0 - 2022-12-21
## 2.2.0
- Minimum supported Rust version (MSRV) is now 1.59.
- Update `tokio-uring` dependency to `0.4`. [#473]
[#473]: https://github.com/actix/actix-net/pull/473
## 2.1.1 - 2022-03-09
## 2.1.1
- No significant changes since `2.1.0`.
## 2.1.0 - 2022-03-08
## 2.1.0
- Update `tokio-uring` dependency to `0.3`. [#448]
- Logs emitted now use the `tracing` crate with `log` compatibility. [#448]
@@ -25,27 +27,27 @@
[#443]: https://github.com/actix/actix-net/pull/443
[#448]: https://github.com/actix/actix-net/pull/448
## 2.0.0 - 2022-01-19
## 2.0.0
- No significant changes since `2.0.0-rc.4`.
## 2.0.0-rc.4 - 2022-01-12
## 2.0.0-rc.4
- Update `tokio-uring` dependency to `0.2`. [#436]
[#436]: https://github.com/actix/actix-net/pull/436
## 2.0.0-rc.3 - 2021-12-31
## 2.0.0-rc.3
- No significant changes since `2.0.0-rc.2`.
## 2.0.0-rc.2 - 2021-12-27
## 2.0.0-rc.2
- Simplify `TestServer`. [#431]
[#431]: https://github.com/actix/actix-net/pull/431
## 2.0.0-rc.1 - 2021-12-05
## 2.0.0-rc.1
- Hide implementation details of `Server`. [#424]
- `Server` now runs only after awaiting it. [#425]
@@ -53,19 +55,19 @@
[#424]: https://github.com/actix/actix-net/pull/424
[#425]: https://github.com/actix/actix-net/pull/425
## 2.0.0-beta.9 - 2021-11-15
## 2.0.0-beta.9
- Restore `Arbiter` support lost in `beta.8`. [#417]
[#417]: https://github.com/actix/actix-net/pull/417
## 2.0.0-beta.8 - 2021-11-05 _(YANKED)_
## 2.0.0-beta.8
- Fix non-unix signal handler. [#410]
[#410]: https://github.com/actix/actix-net/pull/410
## 2.0.0-beta.7 - 2021-11-05 _(YANKED)_
## 2.0.0-beta.7
- Server can be started in regular Tokio runtime. [#408]
- Expose new `Server` type whose `Future` impl resolves when server stops. [#408]
@@ -78,7 +80,7 @@
[#407]: https://github.com/actix/actix-net/pull/407
[#408]: https://github.com/actix/actix-net/pull/408
## 2.0.0-beta.6 - 2021-10-11
## 2.0.0-beta.6
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block subsequent exit signals from working. [#389]
@@ -89,19 +91,19 @@
[#349]: https://github.com/actix/actix-net/pull/349
[#389]: https://github.com/actix/actix-net/pull/389
## 2.0.0-beta.5 - 2021-04-20
## 2.0.0-beta.5
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all workers to shutdown immediately in force shutdown case. [#333]
[#333]: https://github.com/actix/actix-net/pull/333
## 2.0.0-beta.4 - 2021-04-01
## 2.0.0-beta.4
- Prevent panic when `shutdown_timeout` is very large. [f9262db]
[f9262db]: https://github.com/actix/actix-net/commit/f9262db
## 2.0.0-beta.3 - 2021-02-06
## 2.0.0-beta.3
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`. [#246]
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop. [#264]
@@ -113,13 +115,13 @@
[#265]: https://github.com/actix/actix-net/pull/265
[#273]: https://github.com/actix/actix-net/pull/273
## 2.0.0-beta.2 - 2021-01-03
## 2.0.0-beta.2
- Merge `actix-testing` to `actix-server` as `test_server` mod. [#242]
[#242]: https://github.com/actix/actix-net/pull/242
## 2.0.0-beta.1 - 2020-12-28
## 2.0.0-beta.1
- Added explicit info log message on accept queue pause. [#215]
- Prevent double registration of sockets when back-pressure is resolved. [#223]
@@ -134,127 +136,127 @@
[#223]: https://github.com/actix/actix-net/pull/223
[#239]: https://github.com/actix/actix-net/pull/239
## 1.0.4 - 2020-09-12
## 1.0.4
- Update actix-codec to 0.3.0.
- Workers must be greater than 0. [#167]
[#167]: https://github.com/actix/actix-net/pull/167
## 1.0.3 - 2020-05-19
## 1.0.3
- Replace deprecated `net2` crate with `socket2` [#140]
[#140]: https://github.com/actix/actix-net/pull/140
## 1.0.2 - 2020-02-26
## 1.0.2
- Avoid error by calling `reregister()` on Windows [#103]
[#103]: https://github.com/actix/actix-net/pull/103
## 1.0.1 - 2019-12-29
## 1.0.1
- Rename `.start()` method to `.run()`
## 1.0.0 - 2019-12-11
## 1.0.0
- Use actix-net releases
## 1.0.0-alpha.4 - 2019-12-08
## 1.0.0-alpha.4
- Use actix-service 1.0.0-alpha.4
## 1.0.0-alpha.3 - 2019-12-07
## 1.0.0-alpha.3
- Migrate to tokio 0.2
- Fix compilation on non-unix platforms
- Better handling server configuration
## 1.0.0-alpha.2 - 2019-12-02
## 1.0.0-alpha.2
- Simplify server service (remove actix-server-config)
- Allow to wait on `Server` until server stops
## 0.8.0-alpha.1 - 2019-11-22
## 0.8.0-alpha.1
- Migrate to `std::future`
## 0.7.0 - 2019-10-04
## 0.7.0
- Update `rustls` to 0.16
- Minimum required Rust version upped to 1.37.0
## 0.6.1 - 2019-09-25
## 0.6.1
- Add UDS listening support to `ServerBuilder`
## 0.6.0 - 2019-07-18
## 0.6.0
- Support Unix domain sockets #3
## 0.5.1 - 2019-05-18
## 0.5.1
- ServerBuilder::shutdown_timeout() accepts u64
## 0.5.0 - 2019-05-12
## 0.5.0
- Add `Debug` impl for `SslError`
- Derive debug for `Server` and `ServerCommand`
- Upgrade to actix-service 0.4
## 0.4.3 - 2019-04-16
## 0.4.3
- Re-export `IoStream` trait
- Depend on `ssl` and `rust-tls` features from actix-server-config
## 0.4.2 - 2019-03-30
## 0.4.2
- Fix SIGINT force shutdown
## 0.4.1 - 2019-03-14
## 0.4.1
- `SystemRuntime::on_start()` - allow to run future before server service initialization
## 0.4.0 - 2019-03-12
## 0.4.0
- Use `ServerConfig` for service factory
- Wrap tcp socket to `Io` type
- Upgrade actix-service
## 0.3.1 - 2019-03-04
## 0.3.1
- Add `ServerBuilder::maxconnrate` sets the maximum per-worker number of concurrent connections
- Add helper ssl error `SslError`
- Rename `StreamServiceFactory` to `ServiceFactory`
- Deprecate `StreamServiceFactory`
## 0.3.0 - 2019-03-02
## 0.3.0
- Use new `NewService` trait
## 0.2.1 - 2019-02-09
## 0.2.1
- Drop service response
## 0.2.0 - 2019-02-01
## 0.2.0
- Migrate to actix-service 0.2
- Updated rustls dependency
## 0.1.3 - 2018-12-21
## 0.1.3
- Fix max concurrent connections handling
## 0.1.2 - 2018-12-12
## 0.1.2
- rename ServiceConfig::rt() to ServiceConfig::apply()
- Fix back-pressure for concurrent ssl handshakes
## 0.1.1 - 2018-12-11
## 0.1.1
- Fix signal handling on windows
## 0.1.0 - 2018-12-09
## 0.1.0
- Move server to separate crate

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-server"
version = "2.2.0"
version = "2.3.0"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@@ -27,7 +27,6 @@ actix-utils = "3"
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
mio = { version = "0.8", features = ["os-poll", "net"] }
num_cpus = "1.13"
socket2 = "0.5"
tokio = { version = "1.23.1", features = ["sync"] }
tracing = { version = "0.1.30", default-features = false, features = ["log"] }

View File

@@ -3,10 +3,10 @@
> General purpose TCP server built for the Actix ecosystem.
[![crates.io](https://img.shields.io/crates/v/actix-server?label=latest)](https://crates.io/crates/actix-server)
[![Documentation](https://docs.rs/actix-server/badge.svg?version=2.2.0)](https://docs.rs/actix-server/2.2.0)
[![Documentation](https://docs.rs/actix-server/badge.svg?version=2.3.0)](https://docs.rs/actix-server/2.3.0)
[![Version](https://img.shields.io/badge/rustc-1.52+-ab6000.svg)](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
![License](https://img.shields.io/crates/l/actix-server.svg)
[![Dependency Status](https://deps.rs/crate/actix-server/2.2.0/status.svg)](https://deps.rs/crate/actix-server/2.2.0)
[![Dependency Status](https://deps.rs/crate/actix-server/2.3.0/status.svg)](https://deps.rs/crate/actix-server/2.3.0)
![Download](https://img.shields.io/crates/d/actix-server.svg)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

View File

@@ -1,4 +1,4 @@
use std::{io, time::Duration};
use std::{io, num::NonZeroUsize, time::Duration};
use actix_rt::net::TcpStream;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
@@ -55,7 +55,7 @@ impl ServerBuilder {
let (cmd_tx, cmd_rx) = unbounded_channel();
ServerBuilder {
threads: num_cpus::get_physical(),
threads: std::thread::available_parallelism().map_or(2, NonZeroUsize::get),
token: 0,
factories: Vec::new(),
sockets: Vec::new(),
@@ -76,6 +76,12 @@ impl ServerBuilder {
/// The default worker count is the number of physical CPU cores available. If your benchmark
/// testing indicates that simultaneous multi-threading is beneficial to your app, you can use
/// the [`num_cpus`] crate to acquire the _logical_ core count instead.
///
/// # Panics
///
/// Panics if `num` is 0.
///
/// [`num_cpus`]: https://docs.rs/num_cpus
pub fn workers(mut self, num: usize) -> Self {
assert_ne!(num, 0, "workers must be greater than 0");
self.threads = num;

View File

@@ -1,6 +1,7 @@
use std::{
future::Future,
io, mem,
num::NonZeroUsize,
pin::Pin,
rc::Rc,
sync::{
@@ -249,8 +250,11 @@ pub(crate) struct ServerWorkerConfig {
impl Default for ServerWorkerConfig {
fn default() -> Self {
// 512 is the default max blocking thread count of tokio runtime.
let max_blocking_threads = std::cmp::max(512 / num_cpus::get_physical(), 1);
let parallelism = std::thread::available_parallelism().map_or(2, NonZeroUsize::get);
// 512 is the default max blocking thread count of a Tokio runtime.
let max_blocking_threads = std::cmp::max(512 / parallelism, 1);
Self {
shutdown_timeout: Duration::from_secs(30),
max_blocking_threads,
@@ -621,6 +625,7 @@ impl Future for ServerWorker {
self.poll(cx)
}
},
WorkerState::Restarting(ref mut restart) => {
let factory_id = restart.factory_id;
let token = restart.token;
@@ -645,6 +650,7 @@ impl Future for ServerWorker {
self.poll(cx)
}
WorkerState::Shutdown(ref mut shutdown) => {
// drop all pending connections in rx channel.
while let Poll::Ready(Some(conn)) = this.conn_rx.poll_recv(cx) {
@@ -678,6 +684,7 @@ impl Future for ServerWorker {
shutdown.timer.as_mut().poll(cx)
}
}
// actively poll stream and handle worker command
WorkerState::Available => loop {
match this.check_readiness(cx) {

View File

@@ -1,40 +1,49 @@
# Changes
## Unreleased - 2023-xx-xx
## Unreleased
## 3.1.1
- Fix `rustls` v0.21 version requirement.
## 3.1.0
- Support Rustls v0.21.
- Added `{accept, connect}::rustls_0_21` modules.
- Added `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
- Minimum supported Rust version (MSRV) is now 1.65.
## 3.0.4 - 2022-03-15
## 3.0.4
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
[#451]: https://github.com/actix/actix-net/pull/451
## 3.0.3 - 2022-02-15
## 3.0.3
- No significant changes since `3.0.2`.
## 3.0.2 - 2022-01-28
## 3.0.2
- Expose `connect::Connection::new`. [#439]
[#439]: https://github.com/actix/actix-net/pull/439
## 3.0.1 - 2022-01-11
## 3.0.1
- No significant changes since `3.0.0`.
## 3.0.0 - 2021-12-26
## 3.0.0
- No significant changes since `3.0.0-rc.2`.
## 3.0.0-rc.2 - 2021-12-10
## 3.0.0-rc.2
- Re-export `openssl::SslConnectorBuilder` in `connect::openssl::reexports`. [#429]
[#429]: https://github.com/actix/actix-net/pull/429
## 3.0.0-rc.1 - 2021-11-29
## 3.0.0-rc.1
### Added
@@ -72,7 +81,7 @@
[#422]: https://github.com/actix/actix-net/pull/422
[#423]: https://github.com/actix/actix-net/pull/423
## 3.0.0-beta.9 - 2021-11-22
## 3.0.0-beta.9
- Add configurable timeout for accepting TLS connection. [#393]
- Added `TlsError::Timeout` variant. [#393]
@@ -82,20 +91,20 @@
[#393]: https://github.com/actix/actix-net/pull/393
[#420]: https://github.com/actix/actix-net/pull/420
## 3.0.0-beta.8 - 2021-11-15
## 3.0.0-beta.8
- Add `Connect::request` for getting a reference to the connection request. [#415]
[#415]: https://github.com/actix/actix-net/pull/415
## 3.0.0-beta.7 - 2021-10-20
## 3.0.0-beta.7
- Add `webpki_roots_cert_store()` to get rustls compatible webpki roots cert store. [#401]
- Alias `connect::ssl` to `connect::tls`. [#401]
[#401]: https://github.com/actix/actix-net/pull/401
## 3.0.0-beta.6 - 2021-10-19
## 3.0.0-beta.6
- Update `tokio-rustls` to `0.23` which uses `rustls` `0.20`. [#396]
- Removed a re-export of `Session` from `rustls` as it no longer exist. [#396]
@@ -103,7 +112,7 @@
[#396]: https://github.com/actix/actix-net/pull/396
## 3.0.0-beta.5 - 2021-03-29
## 3.0.0-beta.5
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef` generation failed instead of panic. [#296]
- Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
@@ -117,7 +126,7 @@
[#297]: https://github.com/actix/actix-net/pull/297
[#299]: https://github.com/actix/actix-net/pull/299
## 3.0.0-beta.4 - 2021-02-24
## 3.0.0-beta.4
- Rename `accept::openssl::{SslStream => TlsStream}`.
- Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
@@ -125,7 +134,7 @@
[#282]: https://github.com/actix/actix-net/pull/282
## 3.0.0-beta.3 - 2021-02-06
## 3.0.0-beta.3
- Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
- Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
@@ -139,13 +148,13 @@
[#248]: https://github.com/actix/actix-net/pull/248
[#273]: https://github.com/actix/actix-net/pull/273
## 3.0.0-beta.2 - 2022-xx-xx
## 3.0.0-beta.2
- Depend on stable trust-dns packages. [#204]
[#204]: https://github.com/actix/actix-net/pull/204
## 3.0.0-beta.1 - 2020-12-29
## 3.0.0-beta.1
- Move acceptors under `accept` module. [#238]
- Merge `actix-connect` crate under `connect` module. [#238]
@@ -153,7 +162,7 @@
[#238]: https://github.com/actix/actix-net/pull/238
## 2.0.0 - 2020-09-03
## 2.0.0
- `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
- Where possible, "SSL" terminology is replaced with "TLS".
@@ -161,28 +170,28 @@
- `TlsError::Ssl` enum variant is renamed to `TlsError::Tls`.
- `max_concurrent_ssl_connect` is renamed to `max_concurrent_tls_connect`.
## 2.0.0-alpha.2 - 2020-08-17
## 2.0.0-alpha.2
- Update `rustls` dependency to 0.18
- Update `tokio-rustls` dependency to 0.14
- Update `webpki-roots` dependency to 0.20
## [2.0.0-alpha.1] - 2020-03-03
## [2.0.0-alpha.1]
- Update `rustls` dependency to 0.17
- Update `tokio-rustls` dependency to 0.13
- Update `webpki-roots` dependency to 0.19
## [1.0.0] - 2019-12-11
## [1.0.0]
- 1.0.0 release
## [1.0.0-alpha.3] - 2019-12-07
## [1.0.0-alpha.3]
- Migrate to tokio 0.2
- Enable rustls acceptor service
- Enable native-tls acceptor service
## [1.0.0-alpha.1] - 2019-12-02
## [1.0.0-alpha.1]
- Split openssl acceptor from actix-server package

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-tls"
version = "3.0.4"
version = "3.1.1"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@@ -9,7 +9,7 @@ description = "TLS acceptor and connector services for Actix ecosystem"
keywords = ["network", "tls", "ssl", "async", "transport"]
repository = "https://github.com/actix/actix-net.git"
categories = ["network-programming", "asynchronous", "cryptography"]
license = "MIT OR Apache-2.0"
license.workspace = true
edition.workspace = true
rust-version.workspace = true
@@ -17,6 +17,12 @@ rust-version.workspace = true
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.cargo-machete]
ignored = [
"rustls_021", # specified to force version with add_trust_anchors method
"rustls_webpki_0101", # specified to force secure version
]
[features]
default = ["accept", "connect"]
@@ -29,8 +35,14 @@ connect = []
# use openssl impls
openssl = ["tls-openssl", "tokio-openssl"]
# use rustls impls
rustls = ["tokio-rustls", "webpki-roots"]
# alias for backwards compat
rustls = ["rustls-0_20"]
# use rustls v0.20 impls
rustls-0_20 = ["tokio-rustls-023", "webpki-roots-022"]
# use rustls v0.21 impls
rustls-0_21 = ["tokio-rustls-024", "webpki-roots-025"]
# use native-tls impls
native-tls = ["tokio-native-tls"]
@@ -54,12 +66,18 @@ tracing = { version = "0.1.30", default-features = false, features = ["log"] }
http = { version = "0.2.3", optional = true }
# openssl
tls-openssl = { package = "openssl", version = "0.10.48", optional = true }
tls-openssl = { package = "openssl", version = "0.10.55", optional = true }
tokio-openssl = { version = "0.6", optional = true }
# rustls
tokio-rustls = { version = "0.23", optional = true }
webpki-roots = { version = "0.22", optional = true }
# rustls v0.20
tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true }
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
# rustls v0.21
rustls-021 = { package = "rustls", version = "0.21.6" }
rustls-webpki-0101 = { package = "rustls-webpki", version = "0.101.4" }
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
# native-tls
tokio-native-tls = { version = "0.3", optional = true }
@@ -71,12 +89,11 @@ actix-server = "2"
bytes = "1"
env_logger = "0.10"
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
log = "0.4"
rcgen = "0.10"
rcgen = "0.11"
rustls-pemfile = "1"
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"] }
trust-dns-resolver = "0.22"
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", features = ["dangerous_configuration"] }
trust-dns-resolver = "0.23"
[[example]]
name = "accept-rustls"
required-features = ["accept", "rustls"]
required-features = ["accept", "rustls-0_21"]

View File

@@ -17,12 +17,13 @@
#[rustfmt::skip]
// this `use` is only exists because of how we have organised the crate
// it is not necessary for your actual code; you should import from `rustls` directly
use tokio_rustls::rustls;
// it is not necessary for your actual code; you should import from `rustls` normally
use tokio_rustls_024::rustls;
use std::{
fs::File,
io::{self, BufReader},
path::PathBuf,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
@@ -32,7 +33,7 @@ use std::{
use actix_rt::net::TcpStream;
use actix_server::Server;
use actix_service::ServiceFactoryExt as _;
use actix_tls::accept::rustls::{Acceptor as RustlsAcceptor, TlsStream};
use actix_tls::accept::rustls_0_21::{Acceptor as RustlsAcceptor, TlsStream};
use futures_util::future::ok;
use rustls::{server::ServerConfig, Certificate, PrivateKey};
use rustls_pemfile::{certs, rsa_private_keys};
@@ -42,9 +43,16 @@ use tracing::info;
async fn main() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
let root_path = env!("CARGO_MANIFEST_DIR")
.parse::<PathBuf>()
.unwrap()
.join("examples");
let cert_path = root_path.clone().join("cert.pem");
let key_path = root_path.clone().join("key.pem");
// Load TLS key and cert files
let cert_file = &mut BufReader::new(File::open("./examples/cert.pem").unwrap());
let key_file = &mut BufReader::new(File::open("./examples/key.pem").unwrap());
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
let cert_chain = certs(cert_file)
.unwrap()
@@ -64,7 +72,7 @@ async fn main() -> io::Result<()> {
let count = Arc::new(AtomicUsize::new(0));
let addr = ("127.0.0.1", 8443);
info!("starting server on port: {}", &addr.0);
info!("starting server at: {addr:?}");
Server::build()
.bind("tls-example", addr, move || {

View File

@@ -12,15 +12,27 @@ use actix_utils::counter::Counter;
#[cfg(feature = "openssl")]
pub mod openssl;
#[cfg(feature = "rustls")]
pub mod rustls;
#[cfg(feature = "rustls-0_20")]
pub mod rustls_0_20;
#[doc(hidden)]
#[cfg(feature = "rustls-0_20")]
pub use rustls_0_20 as rustls;
#[cfg(feature = "rustls-0_21")]
pub mod rustls_0_21;
#[cfg(feature = "native-tls")]
pub mod native_tls;
pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
#[cfg(any(feature = "openssl", feature = "rustls", feature = "native-tls"))]
#[cfg(any(
feature = "openssl",
feature = "rustls-0_20",
feature = "rustls-0_21",
feature = "native-tls",
))]
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
std::time::Duration::from_secs(3);

View File

@@ -1,4 +1,4 @@
//! `rustls` based TLS connection acceptor service.
//! `rustls` v0.20 based TLS connection acceptor service.
//!
//! See [`Acceptor`] for main service factory docs.
@@ -24,13 +24,14 @@ use actix_utils::{
use pin_project_lite::pin_project;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
use tokio_rustls_023 as tokio_rustls;
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
pub mod reexports {
//! Re-exports from `rustls` that are useful for acceptors.
pub use tokio_rustls::rustls::ServerConfig;
pub use tokio_rustls_023::rustls::ServerConfig;
}
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].

View File

@@ -0,0 +1,198 @@
//! `rustls` v0.21 based TLS connection acceptor service.
//!
//! See [`Acceptor`] for main service factory docs.
use std::{
convert::Infallible,
future::Future,
io::{self, IoSlice},
pin::Pin,
sync::Arc,
task::{Context, Poll},
time::Duration,
};
use actix_rt::{
net::{ActixStream, Ready},
time::{sleep, Sleep},
};
use actix_service::{Service, ServiceFactory};
use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use pin_project_lite::pin_project;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
use tokio_rustls_024 as tokio_rustls;
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
pub mod reexports {
//! Re-exports from `rustls` that are useful for acceptors.
pub use tokio_rustls_024::rustls::ServerConfig;
}
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
}
}
impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut **self.get_mut()).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
}
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<io::Result<usize>> {
Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
}
fn is_write_vectored(&self) -> bool {
(**self).is_write_vectored()
}
}
impl<IO: ActixStream> ActixStream for TlsStream<IO> {
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
IO::poll_read_ready((**self).get_ref().0, cx)
}
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
IO::poll_write_ready((**self).get_ref().0, cx)
}
}
/// Accept TLS connections via the `rustls` crate.
pub struct Acceptor {
config: Arc<ServerConfig>,
handshake_timeout: Duration,
}
impl Acceptor {
/// Constructs `rustls` based acceptor service factory.
pub fn new(config: ServerConfig) -> Self {
Acceptor {
config: Arc::new(config),
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
}
}
/// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
///
/// Default timeout is 3 seconds.
pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
self.handshake_timeout = handshake_timeout;
self
}
}
impl Clone for Acceptor {
fn clone(&self) -> Self {
Self {
config: self.config.clone(),
handshake_timeout: self.handshake_timeout,
}
}
}
impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
type Response = TlsStream<IO>;
type Error = TlsError<io::Error, Infallible>;
type Config = ();
type Service = AcceptorService;
type InitError = ();
type Future = FutReady<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: ()) -> Self::Future {
let res = MAX_CONN_COUNTER.with(|conns| {
Ok(AcceptorService {
acceptor: self.config.clone().into(),
conns: conns.clone(),
handshake_timeout: self.handshake_timeout,
})
});
ready(res)
}
}
/// Rustls based acceptor service.
pub struct AcceptorService {
acceptor: TlsAcceptor,
conns: Counter,
handshake_timeout: Duration,
}
impl<IO: ActixStream> Service<IO> for AcceptorService {
type Response = TlsStream<IO>;
type Error = TlsError<io::Error, Infallible>;
type Future = AcceptFut<IO>;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
if self.conns.available(cx) {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
}
fn call(&self, req: IO) -> Self::Future {
AcceptFut {
fut: self.acceptor.accept(req),
timeout: sleep(self.handshake_timeout),
_guard: self.conns.get(),
}
}
}
pin_project! {
/// Accept future for Rustls service.
#[doc(hidden)]
pub struct AcceptFut<IO: ActixStream> {
fut: Accept<IO>,
#[pin]
timeout: Sleep,
_guard: CounterGuard,
}
}
impl<IO: ActixStream> Future for AcceptFut<IO> {
type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
match Pin::new(&mut this.fut).poll(cx) {
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
}
}
}

View File

@@ -27,8 +27,15 @@ mod uri;
#[cfg(feature = "openssl")]
pub mod openssl;
#[cfg(feature = "rustls")]
pub mod rustls;
#[cfg(feature = "rustls-0_20")]
pub mod rustls_0_20;
#[doc(hidden)]
#[cfg(feature = "rustls-0_20")]
pub use rustls_0_20 as rustls;
#[cfg(feature = "rustls-0_21")]
pub mod rustls_0_21;
#[cfg(feature = "native-tls")]
pub mod native_tls;

View File

@@ -20,22 +20,21 @@ use tokio_rustls::{
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
};
use tracing::trace;
use webpki_roots::TLS_SERVER_ROOTS;
use tokio_rustls_023 as tokio_rustls;
use crate::connect::{Connection, Host};
pub mod reexports {
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
pub use tokio_rustls::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
pub use webpki_roots::TLS_SERVER_ROOTS;
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
pub use webpki_roots_022::TLS_SERVER_ROOTS;
}
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
pub fn webpki_roots_cert_store() -> RootCertStore {
let mut root_certs = RootCertStore::empty();
for cert in TLS_SERVER_ROOTS.0 {
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
cert.subject,
cert.spki,
@@ -102,12 +101,13 @@ where
actix_service::always_ready!();
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
trace!("TLS handshake start for: {:?}", connection.hostname());
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
let (stream, connection) = connection.replace_io(());
match ServerName::try_from(connection.hostname()) {
Ok(host) => ConnectFut::Future {
connect: RustlsTlsConnector::from(self.connector.clone()).connect(host, stream),
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
.connect(host, stream),
connection: Some(connection),
},
Err(_) => ConnectFut::InvalidDns,
@@ -117,6 +117,7 @@ where
/// Connect future for Rustls service.
#[doc(hidden)]
#[allow(clippy::large_enum_variant)]
pub enum ConnectFut<R, IO> {
/// See issue <https://github.com/briansmith/webpki/issues/54>
InvalidDns,
@@ -131,17 +132,23 @@ where
R: Host,
IO: ActixStream,
{
type Output = Result<Connection<R, AsyncTlsStream<IO>>, io::Error>;
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.get_mut() {
Self::InvalidDns => Poll::Ready(Err(
io::Error::new(io::ErrorKind::Other, "rustls currently only handles hostname-based connections. See https://github.com/briansmith/webpki/issues/54")
)),
Self::Future { connect, connection } => {
Self::InvalidDns => Poll::Ready(Err(io::Error::new(
io::ErrorKind::Other,
"Rustls v0.20 can only handle hostname-based connections. Enable the `rustls-0_21` \
feature and use the Rustls v0.21 utilities to gain this feature.",
))),
Self::Future {
connect,
connection,
} => {
let stream = ready!(Pin::new(connect).poll(cx))?;
let connection = connection.take().unwrap();
trace!("TLS handshake success: {:?}", connection.hostname());
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
Poll::Ready(Ok(connection.replace_io(stream).1))
}
}

View File

@@ -0,0 +1,154 @@
//! Rustls based connector service.
//!
//! See [`TlsConnector`] for main connector service factory docs.
use std::{
convert::TryFrom,
future::Future,
io,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use actix_rt::net::ActixStream;
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::ready;
use tokio_rustls::{
client::TlsStream as AsyncTlsStream,
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
};
use tokio_rustls_024 as tokio_rustls;
use crate::connect::{Connection, Host};
pub mod reexports {
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
pub use webpki_roots_025::TLS_SERVER_ROOTS;
}
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
pub fn webpki_roots_cert_store() -> RootCertStore {
let mut root_certs = RootCertStore::empty();
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
cert.subject,
cert.spki,
cert.name_constraints,
);
let certs = vec![cert].into_iter();
root_certs.add_trust_anchors(certs);
}
root_certs
}
/// Connector service factory using `rustls`.
#[derive(Clone)]
pub struct TlsConnector {
connector: Arc<ClientConfig>,
}
impl TlsConnector {
/// Constructs new connector service factory from a `rustls` client configuration.
pub fn new(connector: Arc<ClientConfig>) -> Self {
TlsConnector { connector }
}
/// Constructs new connector service from a `rustls` client configuration.
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
TlsConnectorService { connector }
}
}
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where
R: Host,
IO: ActixStream + 'static,
{
type Response = Connection<R, AsyncTlsStream<IO>>;
type Error = io::Error;
type Config = ();
type Service = TlsConnectorService;
type InitError = ();
type Future = Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: ()) -> Self::Future {
ok(TlsConnectorService {
connector: self.connector.clone(),
})
}
}
/// Connector service using `rustls`.
#[derive(Clone)]
pub struct TlsConnectorService {
connector: Arc<ClientConfig>,
}
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where
R: Host,
IO: ActixStream,
{
type Response = Connection<R, AsyncTlsStream<IO>>;
type Error = io::Error;
type Future = ConnectFut<R, IO>;
actix_service::always_ready!();
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
let (stream, connection) = connection.replace_io(());
match ServerName::try_from(connection.hostname()) {
Ok(host) => ConnectFut::Future {
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
.connect(host, stream),
connection: Some(connection),
},
Err(_) => ConnectFut::InvalidServerName,
}
}
}
/// Connect future for Rustls service.
#[doc(hidden)]
#[allow(clippy::large_enum_variant)]
pub enum ConnectFut<R, IO> {
InvalidServerName,
Future {
connect: RustlsConnect<IO>,
connection: Option<Connection<R, ()>>,
},
}
impl<R, IO> Future for ConnectFut<R, IO>
where
R: Host,
IO: ActixStream,
{
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.get_mut() {
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidInput,
"connection parameters specified invalid server name",
))),
Self::Future {
connect,
connection,
} => {
let stream = ready!(Pin::new(connect).poll(cx))?;
let connection = connection.take().unwrap();
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
Poll::Ready(Ok(connection.replace_io(stream).1))
}
}
}
}

View File

@@ -3,7 +3,7 @@
#![cfg(all(
feature = "accept",
feature = "connect",
feature = "rustls",
feature = "rustls-0_21",
feature = "openssl"
))]
@@ -15,6 +15,7 @@ use actix_service::ServiceFactoryExt as _;
use actix_tls::accept::openssl::{Acceptor, TlsStream};
use actix_utils::future::ok;
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
use tokio_rustls_024 as tokio_rustls;
fn new_cert_and_key() -> (String, String) {
let cert =
@@ -49,7 +50,7 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
mod danger {
use std::time::SystemTime;
use tokio_rustls::rustls::{
use tokio_rustls_024::rustls::{
self,
client::{ServerCertVerified, ServerCertVerifier},
};

View File

@@ -3,7 +3,7 @@
#![cfg(all(
feature = "accept",
feature = "connect",
feature = "rustls",
feature = "rustls-0_21",
feature = "openssl"
))]
@@ -15,13 +15,14 @@ use actix_rt::net::TcpStream;
use actix_server::TestServer;
use actix_service::ServiceFactoryExt as _;
use actix_tls::{
accept::rustls::{Acceptor, TlsStream},
accept::rustls_0_21::{Acceptor, TlsStream},
connect::openssl::reexports::SslConnector,
};
use actix_utils::future::ok;
use rustls_pemfile::{certs, pkcs8_private_keys};
use tls_openssl::ssl::SslVerifyMode;
use tokio_rustls::rustls::{self, Certificate, PrivateKey, ServerConfig};
use tokio_rustls_024 as tokio_rustls;
fn new_cert_and_key() -> (String, String) {
let cert =

View File

@@ -30,7 +30,7 @@ async fn test_string() {
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-0_21")]
#[actix_rt::test]
async fn test_rustls_string() {
let srv = TestServer::start(|| {
@@ -114,7 +114,7 @@ async fn test_openssl_uri() {
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(all(feature = "rustls", feature = "uri"))]
#[cfg(all(feature = "rustls-0_21", feature = "uri"))]
#[actix_rt::test]
async fn test_rustls_uri() {
use std::convert::TryFrom;

View File

@@ -29,7 +29,7 @@ impl Counter {
/// Returns true if counter is below capacity. Otherwise, register to wake task when it is.
#[inline]
pub fn available(&self, cx: &mut task::Context<'_>) -> bool {
pub fn available(&self, cx: &task::Context<'_>) -> bool {
self.0.available(cx)
}
@@ -59,7 +59,7 @@ impl CounterInner {
}
}
fn available(&self, cx: &mut task::Context<'_>) -> bool {
fn available(&self, cx: &task::Context<'_>) -> bool {
if self.count.get() < self.capacity {
true
} else {

View File

@@ -62,6 +62,7 @@ where
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// SAFETY: we are not moving out of the pinned field
// see https://github.com/rust-lang/rust/pull/102737
#[allow(clippy::needless_borrow)]
(unsafe { &mut self.get_unchecked_mut().f })(cx)
}
}

View File

@@ -22,4 +22,3 @@ serde = { version = "1.0", optional = true }
ahash = { version = "0.8", default-features = false }
serde_json = "1.0"
static_assertions = "1.1"
rustversion = "1"

53
scripts/free-disk-space.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The Azure provided machines typically have the following disk allocation:
# Total space: 85GB
# Allocated: 67 GB
# Free: 17 GB
# This script frees up 28 GB of disk space by deleting unneeded packages and
# large directories.
# The Flink end to end tests download and generate more than 17 GB of files,
# causing unpredictable behavior and build failures.
echo "=============================================================================="
echo "Freeing up disk space on CI system"
echo "=============================================================================="
echo "Listing 100 largest packages"
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100
df -h
echo "Removing large packages"
sudo apt-get remove -y '^dotnet-.*'
sudo apt-get remove -y 'php.*'
sudo apt-get remove -y '^mongodb-.*'
sudo apt-get remove -y '^mysql-.*'
sudo apt-get remove -y azure-cli google-cloud-sdk hhvm google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri
sudo apt-get autoremove -y
sudo apt-get clean
df -h
echo "Removing large directories"
sudo rm -rf /usr/share/dotnet/
sudo rm -rf /usr/local/graalvm/
sudo rm -rf /usr/local/.ghcup/
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/local/share/chromium
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/local/lib/node_modules
df -h