mirror of
https://github.com/fafhrd91/actix-net
synced 2025-08-23 19:55:13 +02:00
Compare commits
32 Commits
local-wake
...
codec-v0.5
Author | SHA1 | Date | |
---|---|---|---|
|
fd32a0a97a | ||
|
07e7f82345 | ||
|
1a5d85ec8b | ||
|
bd1467e928 | ||
|
968ad3b854 | ||
|
079f0f66f0 | ||
|
d85903b31a | ||
|
a0675fb0dd | ||
|
af9ccd17d9 | ||
|
eb977e9aeb | ||
|
d28c7db3b3 | ||
|
c5b2d0cd36 | ||
|
02ac0bb4f7 | ||
|
86b000fe71 | ||
|
951e46186b | ||
|
9edc0b393a | ||
|
1945fa0675 | ||
|
923a443950 | ||
|
b526197a9a | ||
|
8fc2253c61 | ||
|
4c12b81492 | ||
|
ef716a8488 | ||
|
2a4df30c63 | ||
|
2d9b147cc3 | ||
|
5515a37002 | ||
|
4067fbe8f0 | ||
|
01f9910e7c | ||
|
df12c10a3f | ||
|
f632ef2ba8 | ||
|
19d03f0454 | ||
|
e9c2a0c318 | ||
|
f967562ac4 |
@@ -6,20 +6,20 @@ ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocaptur
|
|||||||
|
|
||||||
# just check the library (without dev deps)
|
# just check the library (without dev deps)
|
||||||
ci-check-min = "hack --workspace check --no-default-features"
|
ci-check-min = "hack --workspace check --no-default-features"
|
||||||
ci-check-lib = "hack --workspace --feature-powerset --exclude-features=io-uring check"
|
ci-check-lib = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check"
|
||||||
ci-check-lib-linux = "hack --workspace --feature-powerset check"
|
ci-check-lib-linux = "hack --workspace --feature-powerset --depth=2 check"
|
||||||
|
|
||||||
# check everything
|
# check everything
|
||||||
ci-check = "hack --workspace --feature-powerset --exclude-features=io-uring check --tests --examples"
|
ci-check = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check --tests --examples"
|
||||||
ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
|
ci-check-linux = "hack --workspace --feature-powerset --depth=2 check --tests --examples"
|
||||||
|
|
||||||
# tests avoiding io-uring feature
|
# tests avoiding io-uring feature
|
||||||
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test = "hack --feature-powerset --depth=2 --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-020 = "hack --feature-powerset --depth=2 --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"
|
ci-test-rustls-021 = "hack --feature-powerset --depth=2 --exclude-features=io-uring,rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
|
||||||
# tests avoiding io-uring feature on Windows
|
# 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
|
# test with io-uring feature
|
||||||
ci-test-linux = "hack --feature-powerset --exclude-features=rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test-linux = "hack --feature-powerset --depth=2 --exclude-features=rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
|
21
.github/workflows/ci-post-merge.yml
vendored
21
.github/workflows/ci-post-merge.yml
vendored
@@ -52,13 +52,14 @@ jobs:
|
|||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
|
|
||||||
- name: Install Rust (${{ matrix.version }})
|
- name: Install Rust (${{ matrix.version }})
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}
|
toolchain: ${{ matrix.version }}
|
||||||
|
|
||||||
- uses: taiki-e/install-action@v2.21.2
|
- name: Install cargo-hack and cargo-ci-cache-clean
|
||||||
|
uses: taiki-e/install-action@v2.25.2
|
||||||
with:
|
with:
|
||||||
tool: cargo-hack
|
tool: cargo-hack,cargo-ci-cache-clean
|
||||||
|
|
||||||
- name: check lib
|
- name: check lib
|
||||||
if: >
|
if: >
|
||||||
@@ -99,10 +100,8 @@ jobs:
|
|||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
||||||
"
|
"
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: CI cache clean
|
||||||
run: |
|
run: cargo-ci-cache-clean
|
||||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
|
||||||
cargo-cache
|
|
||||||
|
|
||||||
minimal-versions:
|
minimal-versions:
|
||||||
name: minimal versions
|
name: minimal versions
|
||||||
@@ -111,12 +110,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
- name: Install Rust (nightly)
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with:
|
with:
|
||||||
toolchain: nightly
|
toolchain: nightly
|
||||||
|
|
||||||
- name: Install cargo-hack & cargo-minimal-versions
|
- name: Install cargo-hack & cargo-minimal-versions
|
||||||
uses: taiki-e/install-action@v2.21.2
|
uses: taiki-e/install-action@v2.25.2
|
||||||
with:
|
with:
|
||||||
tool: cargo-hack,cargo-minimal-versions
|
tool: cargo-hack,cargo-minimal-versions
|
||||||
|
|
||||||
@@ -130,10 +129,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
|
|
||||||
- name: Install cargo-nextest
|
- name: Install cargo-nextest
|
||||||
uses: taiki-e/install-action@v2.21.2
|
uses: taiki-e/install-action@v2.25.2
|
||||||
with:
|
with:
|
||||||
tool: cargo-nextest
|
tool: cargo-nextest
|
||||||
|
|
||||||
|
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@@ -2,6 +2,7 @@ name: CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
|
merge_group: { types: [checks_requested] }
|
||||||
push: { branches: [master] }
|
push: { branches: [master] }
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -53,13 +54,14 @@ jobs:
|
|||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
|
|
||||||
- name: Install Rust (${{ matrix.version.name }})
|
- name: Install Rust (${{ matrix.version.name }})
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version.version }}
|
toolchain: ${{ matrix.version.version }}
|
||||||
|
|
||||||
- uses: taiki-e/install-action@v2.21.2
|
- name: Install cargo-hack and cargo-ci-cache-clean
|
||||||
|
uses: taiki-e/install-action@v2.25.2
|
||||||
with:
|
with:
|
||||||
tool: cargo-hack
|
tool: cargo-hack,cargo-ci-cache-clean
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
run: cargo generate-lockfile
|
run: cargo generate-lockfile
|
||||||
@@ -67,6 +69,8 @@ jobs:
|
|||||||
- name: workaround MSRV issues
|
- name: workaround MSRV issues
|
||||||
if: matrix.version.name == 'msrv'
|
if: matrix.version.name == 'msrv'
|
||||||
run: |
|
run: |
|
||||||
|
cargo update -p=ciborium --precise=0.2.1
|
||||||
|
cargo update -p=ciborium-ll --precise=0.2.1
|
||||||
cargo update -p=time --precise=0.3.16
|
cargo update -p=time --precise=0.3.16
|
||||||
cargo update -p=clap --precise=4.3.24
|
cargo update -p=clap --precise=4.3.24
|
||||||
cargo update -p=clap_lex --precise=0.5.0
|
cargo update -p=clap_lex --precise=0.5.0
|
||||||
@@ -114,10 +118,8 @@ jobs:
|
|||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version.version }} cargo ci-test-linux
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version.version }} cargo ci-test-linux
|
||||||
"
|
"
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: CI cache clean
|
||||||
run: |
|
run: cargo-ci-cache-clean
|
||||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
|
||||||
cargo-cache
|
|
||||||
|
|
||||||
rustdoc:
|
rustdoc:
|
||||||
name: rustdoc
|
name: rustdoc
|
||||||
@@ -127,7 +129,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
- name: Install Rust (nightly)
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with:
|
with:
|
||||||
toolchain: nightly
|
toolchain: nightly
|
||||||
|
|
||||||
|
43
.github/workflows/clippy-fmt.yml
vendored
43
.github/workflows/clippy-fmt.yml
vendored
@@ -1,43 +0,0 @@
|
|||||||
name: Lint
|
|
||||||
|
|
||||||
on: [pull_request]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
fmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Rustfmt Check
|
|
||||||
run: cargo fmt --all -- --check
|
|
||||||
|
|
||||||
clippy:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
|
||||||
with: { components: clippy }
|
|
||||||
|
|
||||||
- uses: giraffate/clippy-action@v1.0.1
|
|
||||||
with:
|
|
||||||
reporter: 'github-pr-check'
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints
|
|
4
.github/workflows/coverage.yml
vendored
4
.github/workflows/coverage.yml
vendored
@@ -18,12 +18,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with:
|
with:
|
||||||
components: llvm-tools-preview
|
components: llvm-tools-preview
|
||||||
|
|
||||||
- name: Install cargo-llvm-cov
|
- name: Install cargo-llvm-cov
|
||||||
uses: taiki-e/install-action@v2.21.2
|
uses: taiki-e/install-action@v2.25.2
|
||||||
with:
|
with:
|
||||||
tool: cargo-llvm-cov
|
tool: cargo-llvm-cov
|
||||||
|
|
||||||
|
68
.github/workflows/lint.yml
vendored
Normal file
68
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request: {}
|
||||||
|
merge_group: { types: [checks_requested] }
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
components: rustfmt
|
||||||
|
|
||||||
|
- name: Rustfmt Check
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
|
with: { components: clippy }
|
||||||
|
|
||||||
|
- uses: giraffate/clippy-action@v1.0.1
|
||||||
|
with:
|
||||||
|
reporter: 'github-pr-check'
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints
|
||||||
|
|
||||||
|
check-external-types:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust (nightly-2023-10-10)
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
|
with:
|
||||||
|
toolchain: nightly-2023-10-10
|
||||||
|
|
||||||
|
- name: Install just
|
||||||
|
uses: taiki-e/install-action@v2.25.2
|
||||||
|
with:
|
||||||
|
tool: just
|
||||||
|
|
||||||
|
- name: Install cargo-check-external-types
|
||||||
|
uses: taiki-e/cache-cargo-install-action@v1.3.0
|
||||||
|
with:
|
||||||
|
tool: cargo-check-external-types@0.1.10
|
||||||
|
|
||||||
|
- name: check external types
|
||||||
|
run: just check-external-types-all +nightly-2023-10-10
|
4
.github/workflows/upload-doc.yml
vendored
4
.github/workflows/upload-doc.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
- uses: actions-rust-lang/setup-rust-toolchain@v1.8.0
|
||||||
with: { toolchain: nightly }
|
with: { toolchain: nightly }
|
||||||
|
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
run: echo '<meta http-equiv="refresh" content="0;url=actix_server/index.html">' > target/doc/index.html
|
run: echo '<meta http-equiv="refresh" content="0;url=actix_server/index.html">' > target/doc/index.html
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: JamesIves/github-pages-deploy-action@v4.4.3
|
uses: JamesIves/github-pages-deploy-action@v4.5.0
|
||||||
with:
|
with:
|
||||||
folder: target/doc
|
folder: target/doc
|
||||||
single-commit: true
|
single-commit: true
|
||||||
|
@@ -2,20 +2,18 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 0.5.1
|
## 0.5.1
|
||||||
|
|
||||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
- Logs emitted now use the `tracing` crate with `log` compatibility.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||||
|
|
||||||
[#451]: https://github.com/actix/actix-net/pull/451
|
|
||||||
|
|
||||||
## 0.5.0
|
## 0.5.0
|
||||||
|
|
||||||
- Updated `tokio-util` dependency to `0.7.0`. [#446]
|
- Updated `tokio-util` dependency to `0.7.0`.
|
||||||
|
|
||||||
[#446]: https://github.com/actix/actix-net/pull/446
|
|
||||||
|
|
||||||
## 0.4.2
|
## 0.4.2
|
||||||
|
|
||||||
@@ -23,11 +21,8 @@
|
|||||||
|
|
||||||
## 0.4.1
|
## 0.4.1
|
||||||
|
|
||||||
- Added `LinesCodec.` [#338]
|
- Added `LinesCodec`.
|
||||||
- `Framed::poll_ready` flushes when the buffer is full. [#409]
|
- `Framed::poll_ready` flushes when the buffer is full.
|
||||||
|
|
||||||
[#338]: https://github.com/actix/actix-net/pull/338
|
|
||||||
[#409]: https://github.com/actix/actix-net/pull/409
|
|
||||||
|
|
||||||
## 0.4.0
|
## 0.4.0
|
||||||
|
|
||||||
@@ -35,12 +30,10 @@
|
|||||||
|
|
||||||
## 0.4.0-beta.1
|
## 0.4.0-beta.1
|
||||||
|
|
||||||
- Replace `pin-project` with `pin-project-lite`. [#237]
|
- Replace `pin-project` with `pin-project-lite`.
|
||||||
- Upgrade `tokio` dependency to `1`. [#237]
|
- Upgrade `tokio` dependency to `1`.
|
||||||
- Upgrade `tokio-util` dependency to `0.6`. [#237]
|
- Upgrade `tokio-util` dependency to `0.6`.
|
||||||
- Upgrade `bytes` dependency to `1`. [#237]
|
- Upgrade `bytes` dependency to `1`.
|
||||||
|
|
||||||
[#237]: https://github.com/actix/actix-net/pull/237
|
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-codec"
|
name = "actix-codec"
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
@@ -13,6 +13,15 @@ license = "MIT OR Apache-2.0"
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"bytes::*",
|
||||||
|
"futures_core::*",
|
||||||
|
"futures_sink::*",
|
||||||
|
"tokio::*",
|
||||||
|
"tokio_util::*",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
@@ -8,12 +8,18 @@ authors = [
|
|||||||
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
||||||
keywords = ["async", "futures", "io", "runtime"]
|
keywords = ["async", "futures", "io", "runtime"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"actix_macros::*",
|
||||||
|
"tokio::*",
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["macros"]
|
default = ["macros"]
|
||||||
macros = ["actix-macros"]
|
macros = ["actix-macros"]
|
||||||
@@ -31,4 +37,3 @@ tokio-uring = { version = "0.4", optional = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.23.1", features = ["full"] }
|
tokio = { version = "1.23.1", features = ["full"] }
|
||||||
hyper = { version = "0.14.10", default-features = false, features = ["server", "tcp", "http1"] }
|
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
use std::{convert::Infallible, net::SocketAddr};
|
|
||||||
|
|
||||||
use hyper::{
|
|
||||||
service::{make_service_fn, service_fn},
|
|
||||||
Body, Request, Response, Server,
|
|
||||||
};
|
|
||||||
|
|
||||||
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
|
||||||
Ok(Response::new(Body::from("Hello World")))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
actix_rt::System::with_tokio_rt(|| {
|
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
.block_on(async {
|
|
||||||
let make_service =
|
|
||||||
make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
|
|
||||||
|
|
||||||
let server = Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
|
|
||||||
|
|
||||||
if let Err(err) = server.await {
|
|
||||||
eprintln!("server error: {}", err);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@@ -15,6 +15,11 @@ license = "MIT OR Apache-2.0"
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"tokio::*",
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
||||||
|
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 3.2.0
|
||||||
|
|
||||||
|
- Support Rustls v0.22.
|
||||||
|
- Add `{accept, connect}::rustls_0_22` modules.
|
||||||
|
- Add `rustls-0_21-native-roots` and `rustls-0_20-native-roots` crate features which utilize the `rustls-native-certs` crate to enable a `native_roots_cert_store()` functions in each rustls-based `connect` module.
|
||||||
|
- Implement `Host` for `http::Uri` (`http` crate version `1`).
|
||||||
|
|
||||||
## 3.1.1
|
## 3.1.1
|
||||||
|
|
||||||
- Fix `rustls` v0.21 version requirement.
|
- Fix `rustls` v0.21 version requirement.
|
||||||
@@ -9,8 +16,8 @@
|
|||||||
## 3.1.0
|
## 3.1.0
|
||||||
|
|
||||||
- Support Rustls v0.21.
|
- Support Rustls v0.21.
|
||||||
- Added `{accept, connect}::rustls_0_21` modules.
|
- Add `{accept, connect}::rustls_0_21` modules.
|
||||||
- Added `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
|
- Add `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 3.0.4
|
## 3.0.4
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-tls"
|
name = "actix-tls"
|
||||||
version = "3.1.1"
|
version = "3.2.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
@@ -17,6 +17,14 @@ rust-version.workspace = true
|
|||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"actix_service::*",
|
||||||
|
"actix_utils::*",
|
||||||
|
"futures_core::*",
|
||||||
|
"tokio::*",
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata.cargo-machete]
|
[package.metadata.cargo-machete]
|
||||||
ignored = [
|
ignored = [
|
||||||
"rustls_021", # specified to force version with add_trust_anchors method
|
"rustls_021", # specified to force version with add_trust_anchors method
|
||||||
@@ -33,22 +41,30 @@ accept = []
|
|||||||
connect = []
|
connect = []
|
||||||
|
|
||||||
# use openssl impls
|
# use openssl impls
|
||||||
openssl = ["tls-openssl", "tokio-openssl"]
|
openssl = ["dep:tls-openssl", "dep:tokio-openssl"]
|
||||||
|
|
||||||
# alias for backwards compat
|
# alias for backwards compat
|
||||||
rustls = ["rustls-0_20"]
|
rustls = ["rustls-0_20"]
|
||||||
|
|
||||||
# use rustls v0.20 impls
|
# use rustls v0.20 impls
|
||||||
rustls-0_20 = ["tokio-rustls-023", "webpki-roots-022"]
|
rustls-0_20 = ["rustls-0_20-webpki-roots"]
|
||||||
|
rustls-0_20-webpki-roots = ["tokio-rustls-023", "webpki-roots-022"]
|
||||||
|
rustls-0_20-native-roots = ["tokio-rustls-023", "dep:rustls-native-certs-06"]
|
||||||
|
|
||||||
# use rustls v0.21 impls
|
# use rustls v0.21 impls
|
||||||
rustls-0_21 = ["tokio-rustls-024", "webpki-roots-025"]
|
rustls-0_21 = ["rustls-0_21-webpki-roots"]
|
||||||
|
rustls-0_21-webpki-roots = ["tokio-rustls-024", "webpki-roots-025"]
|
||||||
|
rustls-0_21-native-roots = ["tokio-rustls-024", "dep:rustls-native-certs-06"]
|
||||||
|
|
||||||
|
# use rustls v0.22 impls
|
||||||
|
rustls-0_22-webpki-roots = ["dep:tokio-rustls-025", "dep:rustls-pki-types-1", "dep:webpki-roots-026"]
|
||||||
|
rustls-0_22-native-roots = ["dep:tokio-rustls-025", "dep:rustls-pki-types-1", "dep:rustls-native-certs-07"]
|
||||||
|
|
||||||
# use native-tls impls
|
# use native-tls impls
|
||||||
native-tls = ["tokio-native-tls"]
|
native-tls = ["dep:tokio-native-tls"]
|
||||||
|
|
||||||
# support http::Uri as connect address
|
# support http::Uri as connect address
|
||||||
uri = ["http"]
|
uri = ["dep:http-0_2", "dep:http-1"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = { version = "2.2", default-features = false }
|
actix-rt = { version = "2.2", default-features = false }
|
||||||
@@ -63,7 +79,8 @@ tokio-util = "0.7"
|
|||||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||||
|
|
||||||
# uri
|
# uri
|
||||||
http = { version = "0.2.3", optional = true }
|
http-0_2 = { package = "http", version = "0.2.3", optional = true }
|
||||||
|
http-1 = { package = "http", version = "1", optional = true }
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
tls-openssl = { package = "openssl", version = "0.10.55", optional = true }
|
tls-openssl = { package = "openssl", version = "0.10.55", optional = true }
|
||||||
@@ -74,11 +91,20 @@ tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true
|
|||||||
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
|
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
|
||||||
|
|
||||||
# rustls v0.21
|
# rustls v0.21
|
||||||
rustls-021 = { package = "rustls", version = "0.21.6" }
|
rustls-021 = { package = "rustls", version = "0.21.6", optional = true }
|
||||||
rustls-webpki-0101 = { package = "rustls-webpki", version = "0.101.4" }
|
rustls-webpki-0101 = { package = "rustls-webpki", version = "0.101.4", optional = true }
|
||||||
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
|
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
|
||||||
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
||||||
|
|
||||||
|
# rustls v0.22
|
||||||
|
rustls-pki-types-1 = { package = "rustls-pki-types", version = "1", optional = true }
|
||||||
|
tokio-rustls-025 = { package = "tokio-rustls", version = "0.25", optional = true }
|
||||||
|
webpki-roots-026 = { package = "webpki-roots", version = "0.26", optional = true }
|
||||||
|
|
||||||
|
# native root certificates for rustls impls
|
||||||
|
rustls-native-certs-06 = { package = "rustls-native-certs", version = "0.6", optional = true }
|
||||||
|
rustls-native-certs-07 = { package = "rustls-native-certs", version = "0.7", optional = true }
|
||||||
|
|
||||||
# native-tls
|
# native-tls
|
||||||
tokio-native-tls = { version = "0.3", optional = true }
|
tokio-native-tls = { version = "0.3", optional = true }
|
||||||
|
|
||||||
@@ -89,11 +115,12 @@ actix-server = "2"
|
|||||||
bytes = "1"
|
bytes = "1"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
||||||
|
itertools = "0.12"
|
||||||
rcgen = "0.11"
|
rcgen = "0.11"
|
||||||
rustls-pemfile = "1"
|
rustls-pemfile = "2"
|
||||||
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", features = ["dangerous_configuration"] }
|
tokio-rustls-025 = { package = "tokio-rustls", version = "0.25" }
|
||||||
trust-dns-resolver = "0.23"
|
trust-dns-resolver = "0.23"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "accept-rustls"
|
name = "accept-rustls"
|
||||||
required-features = ["accept", "rustls-0_21"]
|
required-features = ["accept", "rustls-0_22-webpki-roots"]
|
||||||
|
@@ -15,11 +15,8 @@
|
|||||||
//! http --verify=false https://127.0.0.1:8443
|
//! http --verify=false https://127.0.0.1:8443
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
// this `use` is only exists because of how we have organised the crate
|
// 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` normally
|
// it is not necessary for your actual code; you should import from `rustls` normally
|
||||||
use tokio_rustls_024::rustls;
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, BufReader},
|
io::{self, BufReader},
|
||||||
@@ -33,10 +30,13 @@ use std::{
|
|||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::accept::rustls_0_21::{Acceptor as RustlsAcceptor, TlsStream};
|
use actix_tls::accept::rustls_0_22::{Acceptor as RustlsAcceptor, TlsStream};
|
||||||
use futures_util::future::ok;
|
use futures_util::future::ok;
|
||||||
use rustls::{server::ServerConfig, Certificate, PrivateKey};
|
use itertools::Itertools as _;
|
||||||
|
use rustls::server::ServerConfig;
|
||||||
use rustls_pemfile::{certs, rsa_private_keys};
|
use rustls_pemfile::{certs, rsa_private_keys};
|
||||||
|
use rustls_pki_types_1::PrivateKeyDer;
|
||||||
|
use tokio_rustls_025::rustls;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
@@ -54,17 +54,15 @@ async fn main() -> io::Result<()> {
|
|||||||
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
|
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
|
||||||
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
|
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
|
||||||
|
|
||||||
let cert_chain = certs(cert_file)
|
let cert_chain = certs(cert_file);
|
||||||
.unwrap()
|
let mut keys = rsa_private_keys(key_file);
|
||||||
.into_iter()
|
|
||||||
.map(Certificate)
|
|
||||||
.collect();
|
|
||||||
let mut keys = rsa_private_keys(key_file).unwrap();
|
|
||||||
|
|
||||||
let tls_config = ServerConfig::builder()
|
let tls_config = ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
|
.with_single_cert(
|
||||||
|
cert_chain.try_collect::<_, Vec<_>, _>()?,
|
||||||
|
PrivateKeyDer::Pkcs1(keys.next().unwrap()?),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let tls_acceptor = RustlsAcceptor::new(tls_config);
|
let tls_acceptor = RustlsAcceptor::new(tls_config);
|
||||||
|
@@ -22,6 +22,12 @@ pub use rustls_0_20 as rustls;
|
|||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(feature = "rustls-0_21")]
|
||||||
pub mod rustls_0_21;
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_22-webpki-roots",
|
||||||
|
feature = "rustls-0_22-native-roots",
|
||||||
|
))]
|
||||||
|
pub mod rustls_0_22;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
|
||||||
@@ -31,6 +37,8 @@ pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
|
|||||||
feature = "openssl",
|
feature = "openssl",
|
||||||
feature = "rustls-0_20",
|
feature = "rustls-0_20",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_21",
|
||||||
|
feature = "rustls-0_22-webpki-roots",
|
||||||
|
feature = "rustls-0_22-native-roots",
|
||||||
feature = "native-tls",
|
feature = "native-tls",
|
||||||
))]
|
))]
|
||||||
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
||||||
|
@@ -23,7 +23,7 @@ use actix_utils::{
|
|||||||
};
|
};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
use tokio_rustls_023 as tokio_rustls;
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
|
|
||||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
@@ -92,13 +92,13 @@ impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
|||||||
|
|
||||||
/// Accept TLS connections via the `rustls` crate.
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
pub struct Acceptor {
|
pub struct Acceptor {
|
||||||
config: Arc<ServerConfig>,
|
config: Arc<reexports::ServerConfig>,
|
||||||
handshake_timeout: Duration,
|
handshake_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Acceptor {
|
impl Acceptor {
|
||||||
/// Constructs `rustls` based acceptor service factory.
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
pub fn new(config: ServerConfig) -> Self {
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
Acceptor {
|
Acceptor {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
@@ -23,7 +23,7 @@ use actix_utils::{
|
|||||||
};
|
};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
@@ -92,13 +92,13 @@ impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
|||||||
|
|
||||||
/// Accept TLS connections via the `rustls` crate.
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
pub struct Acceptor {
|
pub struct Acceptor {
|
||||||
config: Arc<ServerConfig>,
|
config: Arc<reexports::ServerConfig>,
|
||||||
handshake_timeout: Duration,
|
handshake_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Acceptor {
|
impl Acceptor {
|
||||||
/// Constructs `rustls` based acceptor service factory.
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
pub fn new(config: ServerConfig) -> Self {
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
Acceptor {
|
Acceptor {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
198
actix-tls/src/accept/rustls_0_22.rs
Normal file
198
actix-tls/src/accept/rustls_0_22.rs
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
//! `rustls` v0.22 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::{Accept, TlsAcceptor};
|
||||||
|
use tokio_rustls_025 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_025::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<reexports::ServerConfig>,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Acceptor {
|
||||||
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
|
pub fn new(config: reexports::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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -118,6 +118,7 @@ impl<R: Host> ConnectInfo<R> {
|
|||||||
/// let mut addrs = conn.addrs();
|
/// let mut addrs = conn.addrs();
|
||||||
/// assert_eq!(addrs.next().unwrap(), addr);
|
/// assert_eq!(addrs.next().unwrap(), addr);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[allow(clippy::implied_bounds_in_impls)]
|
||||||
pub fn addrs(
|
pub fn addrs(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = SocketAddr>
|
) -> impl Iterator<Item = SocketAddr>
|
||||||
@@ -149,6 +150,7 @@ impl<R: Host> ConnectInfo<R> {
|
|||||||
/// let mut addrs = conn.take_addrs();
|
/// let mut addrs = conn.take_addrs();
|
||||||
/// assert_eq!(addrs.next().unwrap(), addr);
|
/// assert_eq!(addrs.next().unwrap(), addr);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[allow(clippy::implied_bounds_in_impls)]
|
||||||
pub fn take_addrs(
|
pub fn take_addrs(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> impl Iterator<Item = SocketAddr>
|
) -> impl Iterator<Item = SocketAddr>
|
||||||
|
@@ -27,16 +27,31 @@ mod uri;
|
|||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
pub mod openssl;
|
pub mod openssl;
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_20")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_20-webpki-roots",
|
||||||
|
feature = "rustls-0_20-native-roots",
|
||||||
|
))]
|
||||||
pub mod rustls_0_20;
|
pub mod rustls_0_20;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "rustls-0_20")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_20-webpki-roots",
|
||||||
|
feature = "rustls-0_20-native-roots",
|
||||||
|
))]
|
||||||
pub use rustls_0_20 as rustls;
|
pub use rustls_0_20 as rustls;
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_21-webpki-roots",
|
||||||
|
feature = "rustls-0_21-native-roots",
|
||||||
|
))]
|
||||||
pub mod rustls_0_21;
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_22-webpki-roots",
|
||||||
|
feature = "rustls-0_22-native-roots",
|
||||||
|
))]
|
||||||
|
pub mod rustls_0_22;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ use actix_utils::future::{ok, Ready};
|
|||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream as AsyncTlsStream,
|
client::TlsStream as AsyncTlsStream,
|
||||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
rustls::{client::ServerName, ClientConfig, RootCertStore},
|
||||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
};
|
};
|
||||||
use tokio_rustls_023 as tokio_rustls;
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
@@ -25,17 +25,38 @@ use tokio_rustls_023 as tokio_rustls;
|
|||||||
use crate::connect::{Connection, Host};
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
//! Re-exports from the `rustls` v0.20 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_20-webpki-roots")]
|
||||||
pub use webpki_roots_022::TLS_SERVER_ROOTS;
|
pub use webpki_roots_022::TLS_SERVER_ROOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
pub fn webpki_roots_cert_store() -> RootCertStore {
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
#[cfg(feature = "rustls-0_20-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
|
||||||
let mut root_certs = RootCertStore::empty();
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_06::load_native_certs()? {
|
||||||
|
root_certs
|
||||||
|
.add(&tokio_rustls_023::rustls::Certificate(cert.0))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_20-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
use tokio_rustls_023::rustls;
|
||||||
|
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
|
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
|
||||||
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
cert.subject,
|
cert.subject,
|
||||||
cert.spki,
|
cert.spki,
|
||||||
cert.name_constraints,
|
cert.name_constraints,
|
||||||
@@ -43,6 +64,7 @@ pub fn webpki_roots_cert_store() -> RootCertStore {
|
|||||||
let certs = vec![cert].into_iter();
|
let certs = vec![cert].into_iter();
|
||||||
root_certs.add_server_trust_anchors(certs);
|
root_certs.add_server_trust_anchors(certs);
|
||||||
}
|
}
|
||||||
|
|
||||||
root_certs
|
root_certs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ use actix_utils::future::{ok, Ready};
|
|||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream as AsyncTlsStream,
|
client::TlsStream as AsyncTlsStream,
|
||||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
rustls::{client::ServerName, ClientConfig, RootCertStore},
|
||||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
};
|
};
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
@@ -25,17 +25,38 @@ use tokio_rustls_024 as tokio_rustls;
|
|||||||
use crate::connect::{Connection, Host};
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
//! Re-exports from the `rustls` v0.21 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_21-webpki-roots")]
|
||||||
pub use webpki_roots_025::TLS_SERVER_ROOTS;
|
pub use webpki_roots_025::TLS_SERVER_ROOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
pub fn webpki_roots_cert_store() -> RootCertStore {
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
#[cfg(feature = "rustls-0_21-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
|
||||||
let mut root_certs = RootCertStore::empty();
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_06::load_native_certs()? {
|
||||||
|
root_certs
|
||||||
|
.add(&tokio_rustls_024::rustls::Certificate(cert.0))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_21-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
use tokio_rustls_024::rustls;
|
||||||
|
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
|
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
|
||||||
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
cert.subject,
|
cert.subject,
|
||||||
cert.spki,
|
cert.spki,
|
||||||
cert.name_constraints,
|
cert.name_constraints,
|
||||||
@@ -43,6 +64,7 @@ pub fn webpki_roots_cert_store() -> RootCertStore {
|
|||||||
let certs = vec![cert].into_iter();
|
let certs = vec![cert].into_iter();
|
||||||
root_certs.add_trust_anchors(certs);
|
root_certs.add_trust_anchors(certs);
|
||||||
}
|
}
|
||||||
|
|
||||||
root_certs
|
root_certs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
162
actix-tls/src/connect/rustls_0_22.rs
Normal file
162
actix-tls/src/connect/rustls_0_22.rs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
//! Rustls based connector service.
|
||||||
|
//!
|
||||||
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
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 rustls_pki_types_1::ServerName;
|
||||||
|
use tokio_rustls::{
|
||||||
|
client::TlsStream as AsyncTlsStream,
|
||||||
|
rustls::{ClientConfig, RootCertStore},
|
||||||
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
|
};
|
||||||
|
use tokio_rustls_025 as tokio_rustls;
|
||||||
|
|
||||||
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from the `rustls` v0.22 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_025::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_22-webpki-roots")]
|
||||||
|
pub use webpki_roots_026::TLS_SERVER_ROOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
#[cfg(feature = "rustls-0_22-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_07::load_native_certs()? {
|
||||||
|
root_certs.add(cert).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_22-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
|
||||||
|
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, conn) = connection.replace_io(());
|
||||||
|
|
||||||
|
match ServerName::try_from(conn.hostname()) {
|
||||||
|
Ok(host) => ConnectFut::Future {
|
||||||
|
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||||
|
.connect(host.to_owned(), stream),
|
||||||
|
connection: Some(conn),
|
||||||
|
},
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,19 @@
|
|||||||
use http::Uri;
|
|
||||||
|
|
||||||
use super::Host;
|
use super::Host;
|
||||||
|
|
||||||
impl Host for Uri {
|
impl Host for http_0_2::Uri {
|
||||||
|
fn hostname(&self) -> &str {
|
||||||
|
self.host().unwrap_or("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port(&self) -> Option<u16> {
|
||||||
|
match self.port_u16() {
|
||||||
|
Some(port) => Some(port),
|
||||||
|
None => scheme_to_port(self.scheme_str()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Host for http_1::Uri {
|
||||||
fn hostname(&self) -> &str {
|
fn hostname(&self) -> &str {
|
||||||
self.host().unwrap_or("")
|
self.host().unwrap_or("")
|
||||||
}
|
}
|
||||||
|
@@ -3,19 +3,20 @@
|
|||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_22",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
use std::{convert::TryFrom, io::Write, sync::Arc};
|
use std::{io::Write as _, sync::Arc};
|
||||||
|
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::TestServer;
|
use actix_server::TestServer;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::accept::openssl::{Acceptor, TlsStream};
|
use actix_tls::accept::openssl::{Acceptor, TlsStream};
|
||||||
use actix_utils::future::ok;
|
use actix_utils::future::ok;
|
||||||
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
|
use rustls_pki_types_1::ServerName;
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls::rustls::{ClientConfig, RootCertStore};
|
||||||
|
use tokio_rustls_025 as tokio_rustls;
|
||||||
|
|
||||||
fn new_cert_and_key() -> (String, String) {
|
fn new_cert_and_key() -> (String, String) {
|
||||||
let cert =
|
let cert =
|
||||||
@@ -48,28 +49,45 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod danger {
|
mod danger {
|
||||||
use std::time::SystemTime;
|
use tokio_rustls_025::rustls;
|
||||||
|
|
||||||
use tokio_rustls_024::rustls::{
|
|
||||||
self,
|
|
||||||
client::{ServerCertVerified, ServerCertVerifier},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NoCertificateVerification;
|
pub struct NoCertificateVerification;
|
||||||
|
|
||||||
impl ServerCertVerifier for NoCertificateVerification {
|
impl rustls::client::danger::ServerCertVerifier for NoCertificateVerification {
|
||||||
fn verify_server_cert(
|
fn verify_server_cert(
|
||||||
&self,
|
&self,
|
||||||
_end_entity: &Certificate,
|
end_entity: &rustls_pki_types_1::CertificateDer::CertificateDer<'_>,
|
||||||
_intermediates: &[Certificate],
|
intermediates: &[rustls_pki_types_1::CertificateDer::CertificateDer<'_>],
|
||||||
_server_name: &ServerName,
|
server_name: &rustls_pki_types_1::CertificateDer::ServerName<'_>,
|
||||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
ocsp_response: &[u8],
|
||||||
_ocsp_response: &[u8],
|
now: rustls_pki_types_1::CertificateDer::UnixTime,
|
||||||
_now: SystemTime,
|
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
|
||||||
) -> Result<ServerCertVerified, rustls::Error> {
|
Ok(rustls::client::danger::ServerCertVerified::assertion())
|
||||||
Ok(ServerCertVerified::assertion())
|
}
|
||||||
|
|
||||||
|
fn verify_tls12_signature(
|
||||||
|
&self,
|
||||||
|
message: &[u8],
|
||||||
|
cert: &rustls_pki_types_1::CertificateDer<'_>,
|
||||||
|
dss: &rustls::DigitallySignedStruct,
|
||||||
|
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_tls13_signature(
|
||||||
|
&self,
|
||||||
|
message: &[u8],
|
||||||
|
cert: &rustls_pki_types_1::CertificateDer<'_>,
|
||||||
|
dss: &rustls::DigitallySignedStruct,
|
||||||
|
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||||
|
rustls::crypto::ring::default_provider()
|
||||||
|
.signature_verification_algorithms
|
||||||
|
.supported_schemes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +95,6 @@ mod danger {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
||||||
let mut config = ClientConfig::builder()
|
let mut config = ClientConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_root_certificates(RootCertStore::empty())
|
.with_root_certificates(RootCertStore::empty())
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_22",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
@@ -41,8 +41,10 @@ fn rustls_server_config(cert: String, key: String) -> rustls::ServerConfig {
|
|||||||
let cert = &mut BufReader::new(cert.as_bytes());
|
let cert = &mut BufReader::new(cert.as_bytes());
|
||||||
let key = &mut BufReader::new(key.as_bytes());
|
let key = &mut BufReader::new(key.as_bytes());
|
||||||
|
|
||||||
let cert_chain = certs(cert).unwrap().into_iter().map(Certificate).collect();
|
let cert_chain = certs(cert).collect::<Result<Vec<_>, _>>().unwrap();
|
||||||
let mut keys = pkcs8_private_keys(key).unwrap();
|
let mut keys = pkcs8_private_keys(key)
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut config = ServerConfig::builder()
|
let mut config = ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
.with_safe_defaults()
|
||||||
|
@@ -11,7 +11,7 @@ use actix_server::TestServer;
|
|||||||
use actix_service::{fn_service, Service, ServiceFactory};
|
use actix_service::{fn_service, Service, ServiceFactory};
|
||||||
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::sink::SinkExt;
|
use futures_util::sink::SinkExt as _;
|
||||||
|
|
||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@@ -30,7 +30,7 @@ async fn test_string() {
|
|||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(feature = "rustls-0_22")]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_string() {
|
async fn test_rustls_string() {
|
||||||
let srv = TestServer::start(|| {
|
let srv = TestServer::start(|| {
|
||||||
@@ -109,12 +109,29 @@ async fn test_openssl_uri() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let connector = Connector::default().service();
|
let connector = Connector::default().service();
|
||||||
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
let addr = http_0_2::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
let con = connector.call(addr.into()).await.unwrap();
|
let con = connector.call(addr.into()).await.unwrap();
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rustls-0_21", feature = "uri"))]
|
#[cfg(all(feature = "rustls-0_22", feature = "uri"))]
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_rustls_uri_http1() {
|
||||||
|
let srv = TestServer::start(|| {
|
||||||
|
fn_service(|io: TcpStream| async {
|
||||||
|
let mut framed = Framed::new(io, BytesCodec);
|
||||||
|
framed.send(Bytes::from_static(b"test")).await?;
|
||||||
|
Ok::<_, io::Error>(())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let conn = Connector::default().service();
|
||||||
|
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
|
let con = conn.call(addr.into()).await.unwrap();
|
||||||
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rustls-0_22", feature = "uri"))]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_uri() {
|
async fn test_rustls_uri() {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -128,7 +145,7 @@ async fn test_rustls_uri() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let conn = Connector::default().service();
|
let conn = Connector::default().service();
|
||||||
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
let con = conn.call(addr.into()).await.unwrap();
|
let con = conn.call(addr.into()).await.unwrap();
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,14 @@ license = "MIT OR Apache-2.0"
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"actix_service::*",
|
||||||
|
"actix_utils::*",
|
||||||
|
"tracing::*",
|
||||||
|
"tracing_futures::*",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
@@ -9,11 +9,17 @@ authors = [
|
|||||||
keywords = ["string", "bytes", "utf8", "web", "actix"]
|
keywords = ["string", "bytes", "utf8", "web", "actix"]
|
||||||
categories = ["no-std", "web-programming"]
|
categories = ["no-std", "web-programming"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"bytes::*",
|
||||||
|
"serde::*",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = { version = "1.2", default-features = false }
|
bytes = { version = "1.2", default-features = false }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
|
30
justfile
30
justfile
@@ -7,5 +7,31 @@ doc:
|
|||||||
|
|
||||||
# Document crates in workspace and watch for changes.
|
# Document crates in workspace and watch for changes.
|
||||||
doc-watch:
|
doc-watch:
|
||||||
RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open
|
RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls-0_20,rustls-0_21,rustls-0_20-native-roots,rustls-0_21-native-roots,openssl --open
|
||||||
cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl
|
cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls-0_20,rustls-0_21,rustls-0_20-native-roots,rustls-0_21-native-roots,openssl
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on all crates in workspace.
|
||||||
|
check-external-types-all toolchain="+nightly":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
exit=0
|
||||||
|
for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do
|
||||||
|
if ! just check-external-types-manifest "$f" {{toolchain}}; then exit=1; fi
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
exit $exit
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on all crates in workspace.
|
||||||
|
check-external-types-all-table toolchain="+nightly":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do
|
||||||
|
echo
|
||||||
|
echo "Checking for $f"
|
||||||
|
just check-external-types-manifest "$f" {{toolchain}} --output-format=markdown-table
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on a crate.
|
||||||
|
check-external-types-manifest manifest_path toolchain="+nightly" *extra_args="":
|
||||||
|
cargo {{toolchain}} check-external-types --manifest-path "{{manifest_path}}" {{extra_args}}
|
||||||
|
@@ -12,6 +12,12 @@ license.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = [
|
||||||
|
"futures_core::*",
|
||||||
|
"futures_sink::*",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-core = "0.3.17"
|
futures-core = "0.3.17"
|
||||||
futures-sink = "0.3.17"
|
futures-sink = "0.3.17"
|
||||||
|
Reference in New Issue
Block a user