mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-27 19:12:56 +01:00
Merge branch 'master' into remove-tokio-net-signal-dependency
This commit is contained in:
commit
c008d716c9
@ -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"
|
||||
|
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
- package-ecosystem: cargo
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
210
.github/workflows/ci-master.yml
vendored
210
.github/workflows/ci-master.yml
vendored
@ -1,210 +0,0 @@
|
||||
name: CI (master only)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build_and_test_nightly:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- nightly
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
|
||||
env:
|
||||
VCPKGRS_DYNAMIC: 1
|
||||
|
||||
steps:
|
||||
- name: Setup Routing
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# install OpenSSL on Windows
|
||||
- name: Set vcpkg root
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-msvc' || matrix.target.triple == 'i686-pc-windows-msvc'
|
||||
run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
- name: Install OpenSSL
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-msvc'
|
||||
run: vcpkg install openssl:x64-windows
|
||||
- name: Install OpenSSL
|
||||
if: matrix.target.triple == 'i686-pc-windows-msvc'
|
||||
run: vcpkg install openssl:x86-windows
|
||||
|
||||
- name: Install ${{ matrix.version }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
# - name: Install MSYS2
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# uses: msys2/setup-msys2@v2
|
||||
# - name: Install MinGW Packages
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# run: |
|
||||
# msys2 -c 'pacman -Sy --noconfirm pacman'
|
||||
# msys2 -c 'pacman --noconfirm -S base-devel pkg-config'
|
||||
|
||||
# - name: Generate Cargo.lock
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with: { command: generate-lockfile }
|
||||
# - name: Cache Dependencies
|
||||
# uses: Swatinem/rust-cache@v1.2.0
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: check lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib }
|
||||
- name: check lib
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib-linux }
|
||||
- name: check lib
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-min }
|
||||
|
||||
- name: check full
|
||||
# TODO: compile OpenSSL and run tests on MinGW
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check }
|
||||
- name: check all
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-linux }
|
||||
|
||||
- name: tests
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
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"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
coverage:
|
||||
name: coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@v1.3.0
|
||||
|
||||
- name: Generate coverage file
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
cargo install cargo-tarpaulin
|
||||
cargo tarpaulin --out Xml --verbose
|
||||
- name: Upload to Codecov
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: codecov/codecov-action@v1
|
||||
with: { file: cobertura.xml }
|
||||
|
||||
minimal-versions:
|
||||
name: minimal versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@v1.3.0
|
||||
|
||||
- name: Install cargo-minimal-versions
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-minimal-versions
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: Check With Minimal Versions
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: minimal-versions
|
||||
args: check
|
||||
|
||||
nextest:
|
||||
name: nextest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@v1.3.0
|
||||
|
||||
- name: Install cargo-nextest
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-nextest
|
||||
|
||||
- name: Test with cargo-nextest
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: nextest
|
||||
args: run
|
141
.github/workflows/ci-post-merge.yml
vendored
Normal file
141
.github/workflows/ci-post-merge.yml
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
name: CI (master only)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_and_test_nightly:
|
||||
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 }
|
||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- nightly
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
|
||||
env: {}
|
||||
|
||||
steps:
|
||||
- name: Setup Routing
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- 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
|
||||
- name: Set OpenSSL dir in env
|
||||
if: matrix.target.os == 'windows-latest'
|
||||
run: |
|
||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | 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 }})
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with:
|
||||
toolchain: ${{ matrix.version }}
|
||||
|
||||
- uses: taiki-e/install-action@v2.21.7
|
||||
with:
|
||||
tool: cargo-hack
|
||||
|
||||
- name: check lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: cargo ci-check-lib
|
||||
- name: check lib
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: cargo ci-check-lib-linux
|
||||
- name: check lib
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
run: cargo ci-check-min
|
||||
|
||||
- name: check full
|
||||
# TODO: compile OpenSSL and run tests on MinGW
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: cargo ci-check
|
||||
- name: check all
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: cargo ci-check-linux
|
||||
|
||||
- name: tests
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
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-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: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
minimal-versions:
|
||||
name: minimal versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with:
|
||||
toolchain: nightly
|
||||
|
||||
- name: Install cargo-hack & cargo-minimal-versions
|
||||
uses: taiki-e/install-action@v2.21.7
|
||||
with:
|
||||
tool: cargo-hack,cargo-minimal-versions
|
||||
|
||||
- name: Check With Minimal Versions
|
||||
run: cargo minimal-versions check
|
||||
|
||||
nextest:
|
||||
name: nextest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
|
||||
- name: Install cargo-nextest
|
||||
uses: taiki-e/install-action@v2.21.7
|
||||
with:
|
||||
tool: cargo-nextest
|
||||
|
||||
- name: Test with cargo-nextest
|
||||
run: cargo nextest run
|
125
.github/workflows/ci.yml
vendored
125
.github/workflows/ci.yml
vendored
@ -1,16 +1,22 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request: {}
|
||||
push: { branches: [master] }
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
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 }
|
||||
@ -18,91 +24,75 @@ jobs:
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- 1.57.0
|
||||
- stable
|
||||
- { name: msrv, version: 1.65.0 }
|
||||
- { name: stable, version: stable }
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version.name }}
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
|
||||
env:
|
||||
VCPKGRS_DYNAMIC: 1
|
||||
env: {}
|
||||
|
||||
steps:
|
||||
- name: Setup Routing
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Free Disk Space
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: ./scripts/free-disk-space.sh
|
||||
|
||||
# install OpenSSL on Windows
|
||||
- name: Set vcpkg root
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-msvc' || matrix.target.triple == 'i686-pc-windows-msvc'
|
||||
run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
- name: Install OpenSSL
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-msvc'
|
||||
run: vcpkg install openssl:x64-windows
|
||||
- name: Install OpenSSL
|
||||
if: matrix.target.triple == 'i686-pc-windows-msvc'
|
||||
run: vcpkg install openssl:x86-windows
|
||||
if: matrix.target.os == 'windows-latest'
|
||||
run: choco install openssl -y --forcex64 --no-progress
|
||||
- name: Set OpenSSL dir in env
|
||||
if: matrix.target.os == 'windows-latest'
|
||||
run: |
|
||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Install ${{ matrix.version }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
- name: Install Rust (${{ matrix.version.name }})
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with:
|
||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||
profile: minimal
|
||||
override: true
|
||||
toolchain: ${{ matrix.version.version }}
|
||||
|
||||
# - name: Install MSYS2
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# uses: msys2/setup-msys2@v2
|
||||
# - name: Install MinGW Packages
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# run: |
|
||||
# msys2 -c 'pacman -Sy --noconfirm pacman'
|
||||
# msys2 -c 'pacman --noconfirm -S base-devel pkg-config'
|
||||
|
||||
# - name: Generate Cargo.lock
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with: { command: generate-lockfile }
|
||||
# - name: Cache Dependencies
|
||||
# uses: Swatinem/rust-cache@v1.2.0
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
- uses: taiki-e/install-action@v2.21.7
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
tool: cargo-hack
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
run: cargo generate-lockfile
|
||||
|
||||
- name: workaround MSRV issues
|
||||
if: matrix.version.name == 'msrv'
|
||||
run: |
|
||||
cargo update -p=time --precise=0.3.16
|
||||
cargo update -p=clap --precise=4.3.24
|
||||
cargo update -p=clap_lex --precise=0.5.0
|
||||
cargo update -p=anstyle --precise=1.0.2
|
||||
|
||||
- name: check lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib }
|
||||
run: cargo ci-check-lib
|
||||
- name: check lib
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib-linux }
|
||||
run: cargo ci-check-lib-linux
|
||||
- name: check lib
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-min }
|
||||
run: cargo ci-check-min
|
||||
|
||||
- name: check full
|
||||
# TODO: compile OpenSSL and run tests on MinGW
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check }
|
||||
run: cargo ci-check
|
||||
- name: check all
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-linux }
|
||||
run: cargo ci-check-linux
|
||||
|
||||
- name: tests
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
@ -114,8 +104,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.version }} cargo ci-test-rustls-020
|
||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version.version }} cargo ci-test-rustls-021
|
||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version.version }} cargo ci-test-linux
|
||||
"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
@ -127,20 +124,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with:
|
||||
toolchain: nightly-x86_64-unknown-linux-gnu
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@v1.3.0
|
||||
toolchain: nightly
|
||||
|
||||
- name: doc tests io-uring
|
||||
run: |
|
||||
|
42
.github/workflows/clippy-fmt.yml
vendored
42
.github/workflows/clippy-fmt.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
override: true
|
||||
- name: Rustfmt Check
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
components: clippy
|
||||
override: true
|
||||
- name: Clippy Check
|
||||
uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --workspace --all-features --tests --examples --bins -- -Dclippy::todo
|
37
.github/workflows/coverage.yml
vendored
Normal file
37
.github/workflows/coverage.yml
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
name: Coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with:
|
||||
components: llvm-tools-preview
|
||||
|
||||
- name: Install cargo-llvm-cov
|
||||
uses: taiki-e/install-action@v2.21.7
|
||||
with:
|
||||
tool: cargo-llvm-cov
|
||||
|
||||
- name: Generate code coverage
|
||||
run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3.1.4
|
||||
with:
|
||||
files: codecov.json
|
||||
fail_ci_if_error: true
|
66
.github/workflows/lint.yml
vendored
Normal file
66
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
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
|
||||
|
||||
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.5.0
|
||||
with:
|
||||
toolchain: nightly-2023-10-10
|
||||
|
||||
- name: Install just
|
||||
uses: taiki-e/install-action@v2.21.7
|
||||
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
|
35
.github/workflows/upload-doc.yml
vendored
35
.github/workflows/upload-doc.yml
vendored
@ -1,35 +1,36 @@
|
||||
name: Upload documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
push: { branches: [master] }
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly-x86_64-unknown-linux-gnu
|
||||
profile: minimal
|
||||
override: true
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1.5.0
|
||||
with: { toolchain: nightly }
|
||||
|
||||
- name: Build Docs
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: doc
|
||||
args: --workspace --all-features --no-deps
|
||||
run: cargo doc --workspace --all-features --no-deps
|
||||
|
||||
- name: Tweak HTML
|
||||
run: echo '<meta http-equiv="refresh" content="0;url=actix_server/index.html">' > target/doc/index.html
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
FOLDER: target/doc
|
||||
folder: target/doc
|
||||
single-commit: true
|
||||
|
3
.rustfmt.toml
Normal file
3
.rustfmt.toml
Normal file
@ -0,0 +1,3 @@
|
||||
group_imports = "StdExternalCrate"
|
||||
imports_granularity = "Crate"
|
||||
use_field_init_shorthand = true
|
@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
@ -39,7 +39,7 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be repor
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
[@robjtede]: https://github.com/robjtede
|
||||
[@JohnTitor]: https://github.com/JohnTitor
|
||||
[@johntitor]: https://github.com/JohnTitor
|
||||
|
||||
## Attribution
|
||||
|
||||
|
@ -12,6 +12,12 @@ members = [
|
||||
"local-channel",
|
||||
"local-waker",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
|
||||
[patch.crates-io]
|
||||
actix-codec = { path = "actix-codec" }
|
||||
|
@ -13,7 +13,7 @@ See example folders for [`actix-server`](./actix-server/examples) and [`actix-tl
|
||||
|
||||
## MSRV
|
||||
|
||||
Most crates in this repo's have a Minimum Supported Rust Version (MSRV) of 1.49.0. Only `actix-tls` and `actix-server` have MSRV of 1.54.0. As a policy, we permit MSRV increases in non-breaking releases.
|
||||
Crates in this repo currently have a Minimum Supported Rust Version (MSRV) of 1.65. As a policy, we permit MSRV increases in non-breaking releases.
|
||||
|
||||
## License
|
||||
|
||||
|
@ -1,39 +1,40 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 0.5.1
|
||||
|
||||
## 0.5.1 - 2022-03-15
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#451]: https://github.com/actix/actix-net/pull/451
|
||||
|
||||
## 0.5.0
|
||||
|
||||
## 0.5.0 - 2022-02-15
|
||||
- Updated `tokio-util` dependency to `0.7.0`. [#446]
|
||||
|
||||
[#446]: https://github.com/actix/actix-net/pull/446
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.2 - 2021-12-31
|
||||
- No significant changes since `0.4.1`.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
## 0.4.1 - 2021-11-05
|
||||
- Added `LinesCodec.` [#338]
|
||||
- `Framed::poll_ready` flushes when the buffer is full. [#409]
|
||||
|
||||
[#338]: https://github.com/actix/actix-net/pull/338
|
||||
[#409]: https://github.com/actix/actix-net/pull/409
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## 0.4.0 - 2021-04-20
|
||||
- No significant changes since v0.4.0-beta.1.
|
||||
|
||||
## 0.4.0-beta.1
|
||||
|
||||
## 0.4.0-beta.1 - 2020-12-28
|
||||
- Replace `pin-project` with `pin-project-lite`. [#237]
|
||||
- Upgrade `tokio` dependency to `1`. [#237]
|
||||
- Upgrade `tokio-util` dependency to `0.6`. [#237]
|
||||
@ -41,16 +42,16 @@
|
||||
|
||||
[#237]: https://github.com/actix/actix-net/pull/237
|
||||
|
||||
## 0.3.0
|
||||
|
||||
## 0.3.0 - 2020-08-23
|
||||
- No changes from beta 2.
|
||||
|
||||
## 0.3.0-beta.2
|
||||
|
||||
## 0.3.0-beta.2 - 2020-08-19
|
||||
- Remove unused type parameter from `Framed::replace_codec`.
|
||||
|
||||
## 0.3.0-beta.1
|
||||
|
||||
## 0.3.0-beta.1 - 2020-08-19
|
||||
- Use `.advance()` instead of `.split_to()`.
|
||||
- Upgrade `tokio-util` to `0.3`.
|
||||
- Improve `BytesCodec::encode()` performance.
|
||||
@ -59,31 +60,31 @@
|
||||
- Add method on `Framed` to get a pinned reference to the underlying I/O.
|
||||
- Add method on `Framed` check emptiness of read buffer.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2019-12-10
|
||||
- Use specific futures dependencies.
|
||||
|
||||
|
||||
## 0.2.0-alpha.4
|
||||
|
||||
- Fix buffer remaining capacity calculation.
|
||||
|
||||
|
||||
## 0.2.0-alpha.3
|
||||
|
||||
- Use tokio 0.2.
|
||||
- Fix low/high watermark for write/read buffers.
|
||||
|
||||
|
||||
## 0.2.0-alpha.2
|
||||
|
||||
- Migrated to `std::future`.
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2019-03-27
|
||||
- Added `Framed::map_io()` method.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2019-03-06
|
||||
- Added `FramedParts::with_read_buffer()` method.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
- Move codec to separate crate.
|
||||
|
@ -10,25 +10,31 @@ keywords = ["network", "framework", "async", "futures"]
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "actix_codec"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"bytes::*",
|
||||
"futures_core::*",
|
||||
"futures_sink::*",
|
||||
"tokio::*",
|
||||
"tokio_util::*",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2"
|
||||
bitflags = "2"
|
||||
bytes = "1"
|
||||
futures-core = { version = "0.3.7", default-features = false }
|
||||
futures-sink = { version = "0.3.7", default-features = false }
|
||||
memchr = "2.3"
|
||||
pin-project-lite = "0.2"
|
||||
tokio = "1.13.1"
|
||||
tokio = "1.23.1"
|
||||
tokio-util = { version = "0.7", features = ["codec", "io"] }
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.3", features = ["html_reports"] }
|
||||
criterion = { version = "0.5", features = ["html_reports"] }
|
||||
tokio-test = "0.4.2"
|
||||
|
||||
[[bench]]
|
||||
|
@ -18,6 +18,7 @@ const LW: usize = 1024;
|
||||
const HW: usize = 8 * 1024;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Flags: u8 {
|
||||
const EOF = 0b0001;
|
||||
const READABLE = 0b0010;
|
||||
@ -233,10 +234,7 @@ impl<T, U> Framed<T, U> {
|
||||
}
|
||||
|
||||
/// Flush write buffer to underlying I/O stream.
|
||||
pub fn flush<I>(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), U::Error>>
|
||||
pub fn flush<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
U: Encoder<I>,
|
||||
@ -269,10 +267,7 @@ impl<T, U> Framed<T, U> {
|
||||
}
|
||||
|
||||
/// Flush write buffer and shutdown underlying I/O stream.
|
||||
pub fn close<I>(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), U::Error>>
|
||||
pub fn close<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
U: Encoder<I>,
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! Codec utilities for working with framed protocols.
|
||||
//!
|
||||
//! Contains adapters to go from streams of bytes, [`AsyncRead`] and
|
||||
//! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`].
|
||||
//! Framed streams are also known as `transports`.
|
||||
//! Contains adapters to go from streams of bytes, [`AsyncRead`] and [`AsyncWrite`], to framed
|
||||
//! streams implementing [`Sink`] and [`Stream`]. Framed streams are also known as `transports`.
|
||||
//!
|
||||
//! [`Sink`]: futures_sink::Sink
|
||||
//! [`Stream`]: futures_core::Stream
|
||||
@ -12,14 +11,18 @@
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
pub use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
pub use tokio_util::{
|
||||
codec::{Decoder, Encoder},
|
||||
io::poll_read_buf,
|
||||
};
|
||||
|
||||
mod bcodec;
|
||||
mod framed;
|
||||
mod lines;
|
||||
|
||||
pub use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
pub use tokio_util::codec::{Decoder, Encoder};
|
||||
pub use tokio_util::io::poll_read_buf;
|
||||
|
||||
pub use self::bcodec::BytesCodec;
|
||||
pub use self::framed::{Framed, FramedParts};
|
||||
pub use self::lines::LinesCodec;
|
||||
pub use self::{
|
||||
bcodec::BytesCodec,
|
||||
framed::{Framed, FramedParts},
|
||||
lines::LinesCodec,
|
||||
};
|
||||
|
@ -81,10 +81,7 @@ impl AsyncWrite for Bilateral {
|
||||
other => Ready(other),
|
||||
}
|
||||
}
|
||||
fn poll_shutdown(
|
||||
self: Pin<&mut Self>,
|
||||
_cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), io::Error>> {
|
||||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,51 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
## 0.2.4
|
||||
|
||||
- Update `syn` dependency to `2`.
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 0.2.3
|
||||
|
||||
## 0.2.3 - 2021-10-19
|
||||
- Fix test macro in presence of other imports named "test". [#399]
|
||||
|
||||
[#399]: https://github.com/actix/actix-net/pull/399
|
||||
|
||||
## 0.2.2
|
||||
|
||||
## 0.2.2 - 2021-10-14
|
||||
- Improve error recovery potential when macro input is invalid. [#391]
|
||||
- Allow custom `System`s on test macro. [#391]
|
||||
|
||||
[#391]: https://github.com/actix/actix-net/pull/391
|
||||
|
||||
## 0.2.1
|
||||
|
||||
## 0.2.1 - 2021-02-02
|
||||
- Add optional argument `system` to `main` macro which can be used to specify the path to `actix_rt::System` (useful for re-exports). [#363]
|
||||
|
||||
[#363]: https://github.com/actix/actix-net/pull/363
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2021-02-02
|
||||
- Update to latest `actix_rt::System::new` signature. [#261]
|
||||
|
||||
[#261]: https://github.com/actix/actix-net/pull/261
|
||||
|
||||
## 0.2.0-beta.1
|
||||
|
||||
## 0.2.0-beta.1 - 2021-01-09
|
||||
- Remove `actix-reexport` feature. [#218]
|
||||
|
||||
[#218]: https://github.com/actix/actix-net/pull/218
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2020-12-03
|
||||
- Add `actix-reexport` feature. [#218]
|
||||
|
||||
[#218]: https://github.com/actix/actix-net/pull/218
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2020-05-18
|
||||
- Forward actix_rt::test arguments to test function [#127]
|
||||
|
||||
[#127]: https://github.com/actix/actix-net/pull/127
|
||||
|
@ -1,27 +1,37 @@
|
||||
[package]
|
||||
name = "actix-macros"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Ibraheem Ahmed <ibrah1440@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
]
|
||||
description = "Macros for Actix system and runtime"
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = [
|
||||
"proc_macro2", # specified for minimal versions compat
|
||||
]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.3"
|
||||
syn = { version = "^1", features = ["full"] }
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full"] }
|
||||
|
||||
# minimal versions compat
|
||||
[target.'cfg(any())'.dependencies]
|
||||
proc-macro2 = "1.0.60"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-rt = "2"
|
||||
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
futures-util = { version = "0.3.17", default-features = false }
|
||||
rustversion = "1"
|
||||
trybuild = "1"
|
||||
|
@ -15,6 +15,9 @@
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::parse::Parser as _;
|
||||
|
||||
type AttributeArgs = syn::punctuated::Punctuated<syn::Meta, syn::Token![,]>;
|
||||
|
||||
/// Marks async entry-point function to be executed by Actix system.
|
||||
///
|
||||
@ -25,9 +28,7 @@ use quote::quote;
|
||||
/// println!("Hello world");
|
||||
/// }
|
||||
/// ```
|
||||
#[allow(clippy::needless_doctest_main)]
|
||||
#[proc_macro_attribute]
|
||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
|
||||
Ok(input) => input,
|
||||
@ -35,7 +36,11 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
Err(err) => return input_and_compile_error(item, err),
|
||||
};
|
||||
|
||||
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
|
||||
let parser = AttributeArgs::parse_terminated;
|
||||
let args = match parser.parse(args.clone()) {
|
||||
Ok(args) => args,
|
||||
Err(err) => return input_and_compile_error(args, err),
|
||||
};
|
||||
|
||||
let attrs = &input.attrs;
|
||||
let vis = &input.vis;
|
||||
@ -55,11 +60,15 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
for arg in &args {
|
||||
match arg {
|
||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
value:
|
||||
syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}),
|
||||
..
|
||||
})) => match path
|
||||
}) => match path
|
||||
.get_ident()
|
||||
.map(|i| i.to_string().to_lowercase())
|
||||
.as_deref()
|
||||
@ -78,6 +87,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
.into();
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
return syn::Error::new_spanned(arg, "Unknown attribute specified")
|
||||
.to_compile_error()
|
||||
@ -114,7 +124,11 @@ pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
Err(err) => return input_and_compile_error(item, err),
|
||||
};
|
||||
|
||||
let args = syn::parse_macro_input!(args as syn::AttributeArgs);
|
||||
let parser = AttributeArgs::parse_terminated;
|
||||
let args = match parser.parse(args.clone()) {
|
||||
Ok(args) => args,
|
||||
Err(err) => return input_and_compile_error(args, err),
|
||||
};
|
||||
|
||||
let attrs = &input.attrs;
|
||||
let vis = &input.vis;
|
||||
@ -123,7 +137,7 @@ pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut has_test_attr = false;
|
||||
|
||||
for attr in attrs {
|
||||
if attr.path.is_ident("test") {
|
||||
if attr.path().is_ident("test") {
|
||||
has_test_attr = true;
|
||||
}
|
||||
}
|
||||
@ -149,11 +163,15 @@ pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
for arg in &args {
|
||||
match arg {
|
||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
value:
|
||||
syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}),
|
||||
..
|
||||
})) => match path
|
||||
}) => match path
|
||||
.get_ident()
|
||||
.map(|i| i.to_string().to_lowercase())
|
||||
.as_deref()
|
||||
|
@ -1,7 +1,8 @@
|
||||
#[rustversion::stable(1.46)] // MSRV
|
||||
#[rustversion::stable(1.65)] // MSRV
|
||||
#[test]
|
||||
fn compile_macros() {
|
||||
let t = trybuild::TestCases::new();
|
||||
|
||||
t.pass("tests/trybuild/main-01-basic.rs");
|
||||
t.compile_fail("tests/trybuild/main-02-only-async.rs");
|
||||
t.pass("tests/trybuild/main-03-fn-params.rs");
|
||||
|
@ -1,14 +1,11 @@
|
||||
error: the async keyword is missing from the function declaration
|
||||
--> $DIR/main-02-only-async.rs:2:1
|
||||
--> tests/trybuild/main-02-only-async.rs:2:1
|
||||
|
|
||||
2 | fn main() {
|
||||
| ^^
|
||||
|
||||
error[E0601]: `main` function not found in crate `$CRATE`
|
||||
--> $DIR/main-02-only-async.rs:1:1
|
||||
--> tests/trybuild/main-02-only-async.rs:4:2
|
||||
|
|
||||
1 | / #[actix_rt::main]
|
||||
2 | | fn main() {
|
||||
3 | | futures_util::future::ready(()).await
|
||||
4 | | }
|
||||
| |_^ consider adding a `main` function to `$DIR/tests/trybuild/main-02-only-async.rs`
|
||||
4 | }
|
||||
| ^ consider adding a `main` function to `$DIR/tests/trybuild/main-02-only-async.rs`
|
||||
|
@ -1,91 +1,101 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
## Unreleased
|
||||
|
||||
## 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
|
||||
|
||||
- Add `#[track_caller]` attribute to `spawn` functions and methods. [#454]
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
- Update `tokio-uring` dependency to `0.4`. [#473]
|
||||
- Minimum supported Rust version (MSRV) is now 1.59.
|
||||
|
||||
[#454]: https://github.com/actix/actix-net/pull/454
|
||||
[#473]: https://github.com/actix/actix-net/pull/473
|
||||
|
||||
## 2.7.0
|
||||
|
||||
## 2.7.0 - 2022-03-08
|
||||
- Update `tokio-uring` dependency to `0.3.0`. [#448]
|
||||
- Update `tokio-uring` dependency to `0.3`. [#448]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#448]: https://github.com/actix/actix-net/pull/448
|
||||
|
||||
## 2.6.0
|
||||
|
||||
## 2.6.0 - 2022-01-12
|
||||
- Update `tokio-uring` dependency to `0.2.0`. [#436]
|
||||
- Update `tokio-uring` dependency to `0.2`. [#436]
|
||||
|
||||
[#436]: https://github.com/actix/actix-net/pull/436
|
||||
|
||||
## 2.5.1
|
||||
|
||||
## 2.5.1 - 2021-12-31
|
||||
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`. [#430]
|
||||
|
||||
[#430]: https://github.com/actix/actix-net/pull/430
|
||||
|
||||
## 2.5.0
|
||||
|
||||
## 2.5.0 - 2021-11-22
|
||||
- Add `System::run_with_code` to allow retrieving the exit code on stop. [#411]
|
||||
|
||||
[#411]: https://github.com/actix/actix-net/pull/411
|
||||
|
||||
## 2.4.0
|
||||
|
||||
## 2.4.0 - 2021-11-05
|
||||
- Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context. [#408]
|
||||
- Start io-uring with `System::new` when feature is enabled. [#395]
|
||||
|
||||
[#395]: https://github.com/actix/actix-net/pull/395
|
||||
[#408]: https://github.com/actix/actix-net/pull/408
|
||||
|
||||
## 2.3.0
|
||||
|
||||
## 2.3.0 - 2021-10-11
|
||||
- The `spawn` method can now resolve with non-unit outputs. [#369]
|
||||
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||
|
||||
[#369]: https://github.com/actix/actix-net/pull/369
|
||||
[#374]: https://github.com/actix/actix-net/pull/374
|
||||
|
||||
## 2.2.0
|
||||
|
||||
## 2.2.0 - 2021-03-29
|
||||
- **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return
|
||||
`Ready` object in ok variant. [#293]
|
||||
* Breakage is acceptable since `ActixStream` was not intended to be public.
|
||||
- **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return `Ready` object in ok variant. [#293]
|
||||
- Breakage is acceptable since `ActixStream` was not intended to be public.
|
||||
|
||||
[#293]: https://github.com/actix/actix-net/pull/293
|
||||
|
||||
## 2.1.0
|
||||
|
||||
## 2.1.0 - 2021-02-24
|
||||
- Add `ActixStream` extension trait to include readiness methods. [#276]
|
||||
- Re-export `tokio::net::TcpSocket` in `net` module [#282]
|
||||
|
||||
[#276]: https://github.com/actix/actix-net/pull/276
|
||||
[#282]: https://github.com/actix/actix-net/pull/282
|
||||
|
||||
## 2.0.2
|
||||
|
||||
## 2.0.2 - 2021-02-06
|
||||
- Add `Arbiter::handle` to get a handle of an owned Arbiter. [#274]
|
||||
- Add `System::try_current` for situations where actix may or may not be running a System. [#275]
|
||||
|
||||
[#274]: https://github.com/actix/actix-net/pull/274
|
||||
[#275]: https://github.com/actix/actix-net/pull/275
|
||||
|
||||
## 2.0.1
|
||||
|
||||
## 2.0.1 - 2021-02-06
|
||||
- Expose `JoinError` from Tokio. [#271]
|
||||
|
||||
[#271]: https://github.com/actix/actix-net/pull/271
|
||||
|
||||
## 2.0.0
|
||||
|
||||
## 2.0.0 - 2021-02-02
|
||||
- Remove all Arbiter-local storage methods. [#262]
|
||||
- Re-export `tokio::pin`. [#262]
|
||||
|
||||
[#262]: https://github.com/actix/actix-net/pull/262
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
## 2.0.0-beta.3 - 2021-01-31
|
||||
- Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`. [#253]
|
||||
- Return `JoinHandle` from `actix_rt::spawn`. [#253]
|
||||
- Remove old `Arbiter::spawn`. Implementation is now inlined into `actix_rt::spawn`. [#253]
|
||||
@ -108,21 +118,20 @@
|
||||
[#256]: https://github.com/actix/actix-net/pull/256
|
||||
[#257]: https://github.com/actix/actix-net/pull/257
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-09
|
||||
- Add `task` mod with re-export of `tokio::task::{spawn_blocking, yield_now, JoinHandle}` [#245]
|
||||
- Add default "macros" feature to allow faster compile times when using `default-features=false`.
|
||||
|
||||
[#245]: https://github.com/actix/actix-net/pull/245
|
||||
|
||||
## 2.0.0-beta.1
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
- Add `System::attach_to_tokio` method. [#173]
|
||||
- Update `tokio` dependency to `1.0`. [#236]
|
||||
- Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep`
|
||||
to stay aligned with Tokio's naming. [#236]
|
||||
- Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep` to stay aligned with Tokio's naming. [#236]
|
||||
- Remove `'static` lifetime requirement for `Runtime::block_on` and `SystemRunner::block_on`.
|
||||
* These methods now accept `&self` when calling. [#236]
|
||||
- These methods now accept `&self` when calling. [#236]
|
||||
- Remove `'static` lifetime requirement for `System::run` and `Builder::run`. [#236]
|
||||
- `Arbiter::spawn` now panics when `System` is not in scope. [#207]
|
||||
- Fix work load issue by removing `PENDING` thread local. [#207]
|
||||
@ -130,74 +139,73 @@
|
||||
[#207]: https://github.com/actix/actix-net/pull/207
|
||||
[#236]: https://github.com/actix/actix-net/pull/236
|
||||
|
||||
## 1.1.1
|
||||
|
||||
## 1.1.1 - 2020-04-30
|
||||
- Fix memory leak due to [#94] (see [#129] for more detail)
|
||||
|
||||
[#129]: https://github.com/actix/actix-net/issues/129
|
||||
|
||||
## 1.1.0 _(YANKED)_
|
||||
|
||||
## 1.1.0 - 2020-04-08 _(YANKED)_
|
||||
- Expose `System::is_set` to check if current system has ben started [#99]
|
||||
- Add `Arbiter::is_running` to check if event loop is running [#124]
|
||||
- Add `Arbiter::local_join` associated function
|
||||
to get be able to `await` for spawned futures [#94]
|
||||
- Add `Arbiter::local_join` associated function to get be able to `await` for spawned futures [#94]
|
||||
|
||||
[#94]: https://github.com/actix/actix-net/pull/94
|
||||
[#99]: https://github.com/actix/actix-net/pull/99
|
||||
[#124]: https://github.com/actix/actix-net/pull/124
|
||||
|
||||
## 1.0.0
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
- Update dependencies
|
||||
|
||||
## 1.0.0-alpha.3
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
- Migrate to tokio 0.2
|
||||
- Fix compilation on non-unix platforms
|
||||
|
||||
## 1.0.0-alpha.2
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
- Export `main` and `test` attribute macros
|
||||
- Export `time` module (re-export of tokio-timer)
|
||||
- Export `net` module (re-export of tokio-net)
|
||||
|
||||
## 1.0.0-alpha.1
|
||||
|
||||
## 1.0.0-alpha.1 - 2019-11-22
|
||||
- Migrate to std::future and tokio 0.2
|
||||
|
||||
## 0.2.6
|
||||
|
||||
## 0.2.6 - 2019-11-14
|
||||
- Allow to join arbiter's thread. #60
|
||||
- Fix arbiter's thread panic message.
|
||||
|
||||
## 0.2.5
|
||||
|
||||
## 0.2.5 - 2019-09-02
|
||||
- Add arbiter specific storage
|
||||
|
||||
## 0.2.4
|
||||
|
||||
## 0.2.4 - 2019-07-17
|
||||
- Avoid a copy of the Future when initializing the Box. #29
|
||||
|
||||
## 0.2.3
|
||||
|
||||
## 0.2.3 - 2019-06-22
|
||||
- Allow to start System using existing CurrentThread Handle #22
|
||||
|
||||
## 0.2.2
|
||||
|
||||
## 0.2.2 - 2019-03-28
|
||||
- Moved `blocking` module to `actix-threadpool` crate
|
||||
|
||||
## 0.2.1
|
||||
|
||||
## 0.2.1 - 2019-03-11
|
||||
- Added `blocking` module
|
||||
- Added `Arbiter::exec_fn` - execute fn on the arbiter's thread
|
||||
- Added `Arbiter::exec` - execute fn on the arbiter's thread and wait result
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2019-03-06
|
||||
- `run` method returns `io::Result<()>`
|
||||
- Removed `Handle`
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
- Initial release
|
||||
|
@ -1,10 +1,9 @@
|
||||
[package]
|
||||
name = "actix-rt"
|
||||
version = "2.7.0"
|
||||
version = "2.9.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
"fakeshadow <24548779@qq.com>",
|
||||
]
|
||||
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
||||
keywords = ["async", "futures", "io", "runtime"]
|
||||
@ -12,11 +11,13 @@ homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "actix_rt"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"tokio::*",
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["macros", "net"]
|
||||
@ -28,12 +29,12 @@ net = ["tokio/net", "tokio/signal"]
|
||||
actix-macros = { version = "0.2.3", optional = true }
|
||||
|
||||
futures-core = { version = "0.3", default-features = false }
|
||||
tokio = { version = "1.13.1", features = ["rt", "parking_lot", "sync", "time"] }
|
||||
tokio = { version = "1.23.1", features = ["rt", "parking_lot", "sync", "time"] }
|
||||
|
||||
# runtime for `io-uring` feature
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-uring = { version = "0.3", optional = true }
|
||||
tokio-uring = { version = "0.4", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.13.1", features = ["full"] }
|
||||
tokio = { version = "1.23.1", features = ["full"] }
|
||||
hyper = { version = "0.14.10", default-features = false, features = ["server", "tcp", "http1"] }
|
||||
|
@ -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.7.0)](https://docs.rs/actix-rt/2.7.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.7.0/status.svg)](https://deps.rs/crate/actix-rt/2.7.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)
|
||||
|
||||
|
@ -20,8 +20,7 @@ fn main() {
|
||||
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);
|
||||
let server = Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
|
||||
|
||||
if let Err(err) = server.await {
|
||||
eprintln!("server error: {}", err);
|
||||
|
@ -99,8 +99,7 @@ impl Arbiter {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Arbiter {
|
||||
Self::with_tokio_rt(|| {
|
||||
crate::runtime::default_tokio_runtime()
|
||||
.expect("Cannot create new Arbiter's Runtime.")
|
||||
crate::runtime::default_tokio_runtime().expect("Cannot create new Arbiter's Runtime.")
|
||||
})
|
||||
}
|
||||
|
||||
@ -149,9 +148,7 @@ impl Arbiter {
|
||||
.send(SystemCommand::DeregisterArbiter(arb_id));
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("Cannot spawn Arbiter's thread: {:?}. {:?}", &name, err)
|
||||
});
|
||||
.unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
|
||||
|
||||
ready_rx.recv().unwrap();
|
||||
|
||||
@ -201,9 +198,7 @@ impl Arbiter {
|
||||
.send(SystemCommand::DeregisterArbiter(arb_id));
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("Cannot spawn Arbiter's thread: {:?}. {:?}", &name, err)
|
||||
});
|
||||
.unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
|
||||
|
||||
ready_rx.recv().unwrap();
|
||||
|
||||
@ -303,7 +298,7 @@ impl Future for ArbiterRunner {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// process all items currently buffered in channel
|
||||
loop {
|
||||
match ready!(Pin::new(&mut self.rx).poll_recv(cx)) {
|
||||
match ready!(self.rx.poll_recv(cx)) {
|
||||
// channel closed; no more messages can be received
|
||||
None => return Poll::Ready(()),
|
||||
|
||||
|
@ -65,9 +65,11 @@ mod system;
|
||||
pub use tokio::pin;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
pub use self::arbiter::{Arbiter, ArbiterHandle};
|
||||
pub use self::runtime::Runtime;
|
||||
pub use self::system::{System, SystemRunner};
|
||||
pub use self::{
|
||||
arbiter::{Arbiter, ArbiterHandle},
|
||||
runtime::Runtime,
|
||||
system::{System, SystemRunner},
|
||||
};
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
pub mod signal {
|
||||
@ -91,12 +93,13 @@ pub mod net {
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
pub use tokio::io::Ready;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, Interest};
|
||||
pub use tokio::net::UdpSocket;
|
||||
pub use tokio::net::{TcpListener, TcpSocket, TcpStream};
|
||||
#[cfg(unix)]
|
||||
pub use tokio::net::{UnixDatagram, UnixListener, UnixStream};
|
||||
pub use tokio::{
|
||||
io::Ready,
|
||||
net::{TcpListener, TcpSocket, TcpStream, UdpSocket},
|
||||
};
|
||||
|
||||
/// Extension trait over async read+write types that can also signal readiness.
|
||||
#[doc(hidden)]
|
||||
@ -155,10 +158,9 @@ pub mod net {
|
||||
pub mod time {
|
||||
//! Utilities for tracking time (Tokio re-exports).
|
||||
|
||||
pub use tokio::time::Instant;
|
||||
pub use tokio::time::{interval, interval_at, Interval};
|
||||
pub use tokio::time::{sleep, sleep_until, Sleep};
|
||||
pub use tokio::time::{timeout, Timeout};
|
||||
pub use tokio::time::{
|
||||
interval, interval_at, sleep, sleep_until, timeout, Instant, Interval, Sleep, Timeout,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod task {
|
||||
|
@ -69,6 +69,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
|
||||
|
@ -203,6 +203,40 @@ impl SystemRunner {
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||
}
|
||||
|
||||
/// Retrieves a reference to the underlying [Actix runtime](crate::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 [`Runtime`] to spawn
|
||||
/// tasks on the same runtime.
|
||||
///
|
||||
/// Read more in the documentation for [`Runtime`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// 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
|
||||
/// ```
|
||||
///
|
||||
/// # 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.
|
||||
///
|
||||
/// [`Runtime`]: crate::Runtime
|
||||
pub fn runtime(&self) -> &crate::runtime::Runtime {
|
||||
&self.rt
|
||||
}
|
||||
|
||||
/// Runs the provided future, blocking the current thread until the future completes.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
@ -226,9 +260,7 @@ impl SystemRunner {
|
||||
|
||||
/// Runs the event loop until [stopped](System::stop_with_code), returning the exit code.
|
||||
pub fn run_with_code(self) -> io::Result<i32> {
|
||||
unimplemented!(
|
||||
"SystemRunner::run_with_code is not implemented for io-uring feature yet"
|
||||
);
|
||||
unimplemented!("SystemRunner::run_with_code is not implemented for io-uring feature yet");
|
||||
}
|
||||
|
||||
/// Runs the provided future, blocking the current thread until the future completes.
|
||||
@ -292,7 +324,7 @@ impl Future for SystemController {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// process all items currently buffered in channel
|
||||
loop {
|
||||
match ready!(Pin::new(&mut self.cmd_rx).poll_recv(cx)) {
|
||||
match ready!(self.cmd_rx.poll_recv(cx)) {
|
||||
// channel closed; no more messages can be received
|
||||
None => return Poll::Ready(()),
|
||||
|
||||
|
@ -1,63 +1,74 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## 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
|
||||
|
||||
- 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
|
||||
|
||||
## 2.1.1 - 2022-03-09
|
||||
- No significant changes since `2.1.0`.
|
||||
|
||||
## 2.1.0
|
||||
|
||||
## 2.1.0 - 2022-03-08
|
||||
- Update `tokio-uring` dependency to `0.3.0`. [#448]
|
||||
- Update `tokio-uring` dependency to `0.3`. [#448]
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#448]
|
||||
- Wait for accept thread to stop before sending completion signal. [#443]
|
||||
|
||||
[#443]: https://github.com/actix/actix-net/pull/443
|
||||
[#448]: https://github.com/actix/actix-net/pull/448
|
||||
|
||||
## 2.0.0
|
||||
|
||||
## 2.0.0 - 2022-01-19
|
||||
- No significant changes since `2.0.0-rc.4`.
|
||||
|
||||
## 2.0.0-rc.4
|
||||
|
||||
## 2.0.0-rc.4 - 2022-01-12
|
||||
- Update `tokio-uring` dependency to `0.2.0`. [#436]
|
||||
- Update `tokio-uring` dependency to `0.2`. [#436]
|
||||
|
||||
[#436]: https://github.com/actix/actix-net/pull/436
|
||||
|
||||
## 2.0.0-rc.3
|
||||
|
||||
## 2.0.0-rc.3 - 2021-12-31
|
||||
- No significant changes since `2.0.0-rc.2`.
|
||||
|
||||
## 2.0.0-rc.2
|
||||
|
||||
## 2.0.0-rc.2 - 2021-12-27
|
||||
- Simplify `TestServer`. [#431]
|
||||
|
||||
[#431]: https://github.com/actix/actix-net/pull/431
|
||||
|
||||
## 2.0.0-rc.1
|
||||
|
||||
## 2.0.0-rc.1 - 2021-12-05
|
||||
- Hide implementation details of `Server`. [#424]
|
||||
- `Server` now runs only after awaiting it. [#425]
|
||||
|
||||
[#424]: https://github.com/actix/actix-net/pull/424
|
||||
[#425]: https://github.com/actix/actix-net/pull/425
|
||||
|
||||
## 2.0.0-beta.9
|
||||
|
||||
## 2.0.0-beta.9 - 2021-11-15
|
||||
- Restore `Arbiter` support lost in `beta.8`. [#417]
|
||||
|
||||
[#417]: https://github.com/actix/actix-net/pull/417
|
||||
|
||||
## 2.0.0-beta.8
|
||||
|
||||
## 2.0.0-beta.8 - 2021-11-05 _(YANKED)_
|
||||
- Fix non-unix signal handler. [#410]
|
||||
|
||||
[#410]: https://github.com/actix/actix-net/pull/410
|
||||
|
||||
## 2.0.0-beta.7
|
||||
|
||||
## 2.0.0-beta.7 - 2021-11-05 _(YANKED)_
|
||||
- Server can be started in regular Tokio runtime. [#408]
|
||||
- Expose new `Server` type whose `Future` impl resolves when server stops. [#408]
|
||||
- Rename `Server` to `ServerHandle`. [#407]
|
||||
@ -69,34 +80,31 @@
|
||||
[#407]: https://github.com/actix/actix-net/pull/407
|
||||
[#408]: https://github.com/actix/actix-net/pull/408
|
||||
|
||||
## 2.0.0-beta.6
|
||||
|
||||
## 2.0.0-beta.6 - 2021-10-11
|
||||
- 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]
|
||||
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to
|
||||
this change. [#349]
|
||||
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block subsequent exit signals from working. [#389]
|
||||
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to this change. [#349]
|
||||
- Remove `ServerBuilder::configure` [#349]
|
||||
|
||||
[#374]: https://github.com/actix/actix-net/pull/374
|
||||
[#349]: https://github.com/actix/actix-net/pull/349
|
||||
[#389]: https://github.com/actix/actix-net/pull/389
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
## 2.0.0-beta.5 - 2021-04-20
|
||||
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all
|
||||
workers to shutdown immediately in force shutdown case. [#333]
|
||||
- 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
|
||||
|
||||
## 2.0.0-beta.4 - 2021-04-01
|
||||
- Prevent panic when `shutdown_timeout` is very large. [f9262db]
|
||||
|
||||
[f9262db]: https://github.com/actix/actix-net/commit/f9262db
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
## 2.0.0-beta.3 - 2021-02-06
|
||||
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`. [#246]
|
||||
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop. [#264]
|
||||
- Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size. [#265]
|
||||
@ -107,149 +115,148 @@
|
||||
[#265]: https://github.com/actix/actix-net/pull/265
|
||||
[#273]: https://github.com/actix/actix-net/pull/273
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-03
|
||||
- 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
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
- Added explicit info log message on accept queue pause. [#215]
|
||||
- Prevent double registration of sockets when back-pressure is resolved. [#223]
|
||||
- Update `mio` dependency to `0.7.3`. [#239]
|
||||
- Remove `socket2` dependency. [#239]
|
||||
- `ServerBuilder::backlog` now accepts `u32` instead of `i32`. [#239]
|
||||
- Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`. [#239]
|
||||
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using
|
||||
`FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows). [#239]
|
||||
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using `FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows). [#239]
|
||||
- Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait. [#239]
|
||||
|
||||
[#215]: https://github.com/actix/actix-net/pull/215
|
||||
[#223]: https://github.com/actix/actix-net/pull/223
|
||||
[#239]: https://github.com/actix/actix-net/pull/239
|
||||
|
||||
## 1.0.4
|
||||
|
||||
## 1.0.4 - 2020-09-12
|
||||
- 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
|
||||
|
||||
## 1.0.3 - 2020-05-19
|
||||
- Replace deprecated `net2` crate with `socket2` [#140]
|
||||
|
||||
[#140]: https://github.com/actix/actix-net/pull/140
|
||||
|
||||
## 1.0.2
|
||||
|
||||
## 1.0.2 - 2020-02-26
|
||||
- Avoid error by calling `reregister()` on Windows [#103]
|
||||
|
||||
[#103]: https://github.com/actix/actix-net/pull/103
|
||||
|
||||
## 1.0.1
|
||||
|
||||
## 1.0.1 - 2019-12-29
|
||||
- Rename `.start()` method to `.run()`
|
||||
|
||||
## 1.0.0
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
- Use actix-net releases
|
||||
|
||||
## 1.0.0-alpha.4
|
||||
|
||||
## 1.0.0-alpha.4 - 2019-12-08
|
||||
- Use actix-service 1.0.0-alpha.4
|
||||
|
||||
## 1.0.0-alpha.3
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
- Migrate to tokio 0.2
|
||||
- Fix compilation on non-unix platforms
|
||||
- Better handling server configuration
|
||||
|
||||
## 1.0.0-alpha.2
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
- Simplify server service (remove actix-server-config)
|
||||
- Allow to wait on `Server` until server stops
|
||||
|
||||
## 0.8.0-alpha.1
|
||||
|
||||
## 0.8.0-alpha.1 - 2019-11-22
|
||||
- Migrate to `std::future`
|
||||
|
||||
## 0.7.0
|
||||
|
||||
## 0.7.0 - 2019-10-04
|
||||
- Update `rustls` to 0.16
|
||||
- Minimum required Rust version upped to 1.37.0
|
||||
|
||||
## 0.6.1
|
||||
|
||||
## 0.6.1 - 2019-09-25
|
||||
- Add UDS listening support to `ServerBuilder`
|
||||
|
||||
## 0.6.0
|
||||
|
||||
## 0.6.0 - 2019-07-18
|
||||
- Support Unix domain sockets #3
|
||||
|
||||
## 0.5.1
|
||||
|
||||
## 0.5.1 - 2019-05-18
|
||||
- ServerBuilder::shutdown_timeout() accepts u64
|
||||
|
||||
## 0.5.0
|
||||
|
||||
## 0.5.0 - 2019-05-12
|
||||
- Add `Debug` impl for `SslError`
|
||||
- Derive debug for `Server` and `ServerCommand`
|
||||
- Upgrade to actix-service 0.4
|
||||
|
||||
## 0.4.3
|
||||
|
||||
## 0.4.3 - 2019-04-16
|
||||
- Re-export `IoStream` trait
|
||||
- Depend on `ssl` and `rust-tls` features from actix-server-config
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.2 - 2019-03-30
|
||||
- Fix SIGINT force shutdown
|
||||
|
||||
## 0.4.1
|
||||
|
||||
## 0.4.1 - 2019-03-14
|
||||
- `SystemRuntime::on_start()` - allow to run future before server service initialization
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## 0.4.0 - 2019-03-12
|
||||
- Use `ServerConfig` for service factory
|
||||
- Wrap tcp socket to `Io` type
|
||||
- Upgrade actix-service
|
||||
|
||||
## 0.3.1
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
- 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
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
- Use new `NewService` trait
|
||||
|
||||
## 0.2.1
|
||||
|
||||
## 0.2.1 - 2019-02-09
|
||||
- Drop service response
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
- Migrate to actix-service 0.2
|
||||
- Updated rustls dependency
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2018-12-21
|
||||
- Fix max concurrent connections handling
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2018-12-12
|
||||
- rename ServiceConfig::rt() to ServiceConfig::apply()
|
||||
- Fix back-pressure for concurrent ssl handshakes
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2018-12-11
|
||||
- Fix signal handling on windows
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
- Move server to separate crate
|
||||
|
@ -1,9 +1,8 @@
|
||||
[package]
|
||||
name = "actix-server"
|
||||
version = "2.1.1"
|
||||
version = "2.3.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"fakeshadow <24548779@qq.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
"Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
|
||||
]
|
||||
@ -13,38 +12,39 @@ categories = ["network-programming", "asynchronous"]
|
||||
homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "actix_server"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"tokio::*",
|
||||
]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
||||
|
||||
[dependencies]
|
||||
actix-rt = { version = "2.7", default-features = false }
|
||||
actix-rt = { version = "2.8", default-features = false }
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
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.4.2"
|
||||
tokio = { version = "1.13.1", features = ["sync"] }
|
||||
socket2 = "0.5"
|
||||
tokio = { version = "1.23.1", features = ["sync"] }
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
# runtime for `io-uring` feature
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-uring = { version = "0.3", optional = true }
|
||||
tokio-uring = { version = "0.4", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-codec = "0.5.0"
|
||||
actix-rt = "2.6.0"
|
||||
actix-codec = "0.5"
|
||||
actix-rt = "2.8"
|
||||
|
||||
bytes = "1"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink", "async-await-macro"] }
|
||||
tokio = { version = "1.13.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
|
||||
env_logger = "0.10"
|
||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink", "async-await-macro"] }
|
||||
tokio = { version = "1.23.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
|
||||
|
@ -2,14 +2,20 @@
|
||||
|
||||
> General purpose TCP server built for the Actix ecosystem.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[![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.1.1)](https://docs.rs/actix-server/2.1.1)
|
||||
[![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.1.1/status.svg)](https://deps.rs/crate/actix-server/2.1.1)
|
||||
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-server.svg)
|
||||
<br />
|
||||
[![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)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Resources
|
||||
|
||||
- [Library Documentation](https://docs.rs/actix-server)
|
||||
- [Examples](/actix-server/examples)
|
||||
|
@ -1,19 +1,34 @@
|
||||
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};
|
||||
use tracing::{info, trace};
|
||||
|
||||
use crate::{
|
||||
server::ServerCommand,
|
||||
service::{InternalServiceFactory, ServerServiceFactory, StreamNewService},
|
||||
socket::{
|
||||
create_mio_tcp_listener, MioListener, MioTcpListener, StdTcpListener, ToSocketAddrs,
|
||||
},
|
||||
socket::{create_mio_tcp_listener, MioListener, MioTcpListener, StdTcpListener, ToSocketAddrs},
|
||||
worker::ServerWorkerConfig,
|
||||
Server,
|
||||
};
|
||||
|
||||
/// Multipath TCP (MPTCP) preference.
|
||||
///
|
||||
/// Currently only useful on Linux.
|
||||
///
|
||||
#[cfg_attr(target_os = "linux", doc = "Also see [`ServerBuilder::mptcp()`].")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MpTcp {
|
||||
/// MPTCP will not be used when binding sockets.
|
||||
Disabled,
|
||||
|
||||
/// MPTCP will be attempted when binding sockets. If errors occur, regular TCP will be
|
||||
/// attempted, too.
|
||||
TcpFallback,
|
||||
|
||||
/// MPTCP will be used when binding sockets (with no fallback).
|
||||
NoFallback,
|
||||
}
|
||||
|
||||
/// [Server] builder.
|
||||
pub struct ServerBuilder {
|
||||
pub(crate) threads: usize,
|
||||
@ -21,6 +36,7 @@ pub struct ServerBuilder {
|
||||
pub(crate) backlog: u32,
|
||||
pub(crate) factories: Vec<Box<dyn InternalServiceFactory>>,
|
||||
pub(crate) sockets: Vec<(usize, String, MioListener)>,
|
||||
pub(crate) mptcp: MpTcp,
|
||||
pub(crate) exit: bool,
|
||||
pub(crate) listen_os_signals: bool,
|
||||
pub(crate) cmd_tx: UnboundedSender<ServerCommand>,
|
||||
@ -40,11 +56,12 @@ 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(),
|
||||
backlog: 2048,
|
||||
mptcp: MpTcp::Disabled,
|
||||
exit: false,
|
||||
listen_os_signals: true,
|
||||
cmd_tx,
|
||||
@ -53,13 +70,19 @@ impl ServerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set number of workers to start.
|
||||
/// Sets number of workers to start.
|
||||
///
|
||||
/// See [`bind()`](Self::bind()) for more details on how worker count affects the number of
|
||||
/// server factory instantiations.
|
||||
///
|
||||
/// The default worker count is the determined by [`std::thread::available_parallelism()`]. See
|
||||
/// its documentation to determine what behavior you should expect when server is run.
|
||||
///
|
||||
/// `num` must be greater than 0.
|
||||
///
|
||||
/// 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.
|
||||
pub fn workers(mut self, num: usize) -> Self {
|
||||
assert_ne!(num, 0, "workers must be greater than 0");
|
||||
self.threads = num;
|
||||
@ -98,6 +121,24 @@ impl ServerBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets MultiPath TCP (MPTCP) preference on bound sockets.
|
||||
///
|
||||
/// Multipath TCP (MPTCP) builds on top of TCP to improve connection redundancy and performance
|
||||
/// by sharing a network data stream across multiple underlying TCP sessions. See [mptcp.dev]
|
||||
/// for more info about MPTCP itself.
|
||||
///
|
||||
/// MPTCP is available on Linux kernel version 5.6 and higher. In addition, you'll also need to
|
||||
/// ensure the kernel option is enabled using `sysctl net.mptcp.enabled=1`.
|
||||
///
|
||||
/// This method will have no effect if called after a `bind()`.
|
||||
///
|
||||
/// [mptcp.dev]: https://www.mptcp.dev
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn mptcp(mut self, mptcp_enabled: MpTcp) -> Self {
|
||||
self.mptcp = mptcp_enabled;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum per-worker number of concurrent connections.
|
||||
///
|
||||
/// All socket listeners will stop accepting connections when this limit is reached for
|
||||
@ -115,13 +156,15 @@ impl ServerBuilder {
|
||||
self.max_concurrent_connections(num)
|
||||
}
|
||||
|
||||
/// Stop Actix `System` after server shutdown.
|
||||
/// Sets flag to stop Actix `System` after server shutdown.
|
||||
///
|
||||
/// This has no effect when server is running in a Tokio-only runtime.
|
||||
pub fn system_exit(mut self) -> Self {
|
||||
self.exit = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Disable OS signal handling.
|
||||
/// Disables OS signal handling.
|
||||
pub fn disable_signals(mut self) -> Self {
|
||||
self.listen_os_signals = false;
|
||||
self
|
||||
@ -139,25 +182,49 @@ impl ServerBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Add new service to the server.
|
||||
pub fn bind<F, U, N>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||
/// Adds new service to the server.
|
||||
///
|
||||
/// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
|
||||
///
|
||||
/// # Worker Count
|
||||
///
|
||||
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||
/// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by
|
||||
/// `addrs`.
|
||||
///
|
||||
/// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1`
|
||||
/// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost`
|
||||
/// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing
|
||||
/// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses).
|
||||
///
|
||||
/// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple
|
||||
/// the number of instantiations in a similar way.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an `io::Error` if:
|
||||
/// - `addrs` cannot be resolved into one or more socket addresses;
|
||||
/// - all the resolved socket addresses are already bound.
|
||||
pub fn bind<F, U, N>(mut self, name: N, addrs: U, factory: F) -> io::Result<Self>
|
||||
where
|
||||
F: ServerServiceFactory<TcpStream>,
|
||||
U: ToSocketAddrs,
|
||||
N: AsRef<str>,
|
||||
{
|
||||
let sockets = bind_addr(addr, self.backlog)?;
|
||||
let sockets = bind_addr(addrs, self.backlog, &self.mptcp)?;
|
||||
|
||||
trace!("binding server to: {:?}", &sockets);
|
||||
tracing::trace!("binding server to: {sockets:?}");
|
||||
|
||||
for lst in sockets {
|
||||
let token = self.next_token();
|
||||
|
||||
self.factories.push(StreamNewService::create(
|
||||
name.as_ref().to_string(),
|
||||
token,
|
||||
factory.clone(),
|
||||
lst.local_addr()?,
|
||||
));
|
||||
|
||||
self.sockets
|
||||
.push((token, name.as_ref().to_string(), MioListener::Tcp(lst)));
|
||||
}
|
||||
@ -165,7 +232,12 @@ impl ServerBuilder {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Add new service to the server.
|
||||
/// Adds service to the server using a socket listener already bound.
|
||||
///
|
||||
/// # Worker Count
|
||||
///
|
||||
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||
/// instantiations is: number of [`workers`](Self::workers()).
|
||||
pub fn listen<F, N: AsRef<str>>(
|
||||
mut self,
|
||||
name: N,
|
||||
@ -197,7 +269,7 @@ impl ServerBuilder {
|
||||
if self.sockets.is_empty() {
|
||||
panic!("Server should have at least one bound socket");
|
||||
} else {
|
||||
info!("starting {} workers", self.threads);
|
||||
tracing::info!("starting {} workers", self.threads);
|
||||
Server::new(self)
|
||||
}
|
||||
}
|
||||
@ -211,7 +283,12 @@ impl ServerBuilder {
|
||||
|
||||
#[cfg(unix)]
|
||||
impl ServerBuilder {
|
||||
/// Add new unix domain service to the server.
|
||||
/// Adds new service to the server using a UDS (unix domain socket) address.
|
||||
///
|
||||
/// # Worker Count
|
||||
///
|
||||
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||
/// instantiations is: number of [`workers`](Self::workers()).
|
||||
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||
where
|
||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||
@ -231,9 +308,14 @@ impl ServerBuilder {
|
||||
self.listen_uds(name, lst, factory)
|
||||
}
|
||||
|
||||
/// Add new unix domain service to the server.
|
||||
/// Adds new service to the server using a UDS (unix domain socket) listener already bound.
|
||||
///
|
||||
/// Useful when running as a systemd service and a socket FD is acquired externally.
|
||||
///
|
||||
/// # Worker Count
|
||||
///
|
||||
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||
/// instantiations is: number of [`workers`](Self::workers()).
|
||||
pub fn listen_uds<F, N: AsRef<str>>(
|
||||
mut self,
|
||||
name: N,
|
||||
@ -244,18 +326,22 @@ impl ServerBuilder {
|
||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||
{
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
lst.set_nonblocking(true)?;
|
||||
|
||||
let token = self.next_token();
|
||||
let addr =
|
||||
crate::socket::StdSocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
let addr = crate::socket::StdSocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
|
||||
self.factories.push(StreamNewService::create(
|
||||
name.as_ref().to_string(),
|
||||
token,
|
||||
factory,
|
||||
addr,
|
||||
));
|
||||
|
||||
self.sockets
|
||||
.push((token, name.as_ref().to_string(), MioListener::from(lst)));
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
@ -263,13 +349,14 @@ impl ServerBuilder {
|
||||
pub(super) fn bind_addr<S: ToSocketAddrs>(
|
||||
addr: S,
|
||||
backlog: u32,
|
||||
mptcp: &MpTcp,
|
||||
) -> io::Result<Vec<MioTcpListener>> {
|
||||
let mut opt_err = None;
|
||||
let mut success = false;
|
||||
let mut sockets = Vec::new();
|
||||
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
match create_mio_tcp_listener(addr, backlog) {
|
||||
match create_mio_tcp_listener(addr, backlog, mptcp) {
|
||||
Ok(lst) => {
|
||||
success = true;
|
||||
sockets.push(lst);
|
||||
|
@ -18,13 +18,15 @@ mod test_server;
|
||||
mod waker_queue;
|
||||
mod worker;
|
||||
|
||||
pub use self::builder::ServerBuilder;
|
||||
pub use self::handle::ServerHandle;
|
||||
pub use self::server::Server;
|
||||
pub use self::service::ServerServiceFactory;
|
||||
#[doc(hidden)]
|
||||
pub use self::socket::FromStream;
|
||||
pub use self::test_server::TestServer;
|
||||
pub use self::{
|
||||
builder::{MpTcp, ServerBuilder},
|
||||
handle::ServerHandle,
|
||||
server::Server,
|
||||
service::ServerServiceFactory,
|
||||
test_server::TestServer,
|
||||
};
|
||||
|
||||
/// Start server building process
|
||||
#[doc(hidden)]
|
||||
|
@ -363,6 +363,6 @@ impl Stream for ServerEventMultiplexer {
|
||||
}
|
||||
}
|
||||
|
||||
Pin::new(&mut this.cmd_rx).poll_recv(cx)
|
||||
this.cmd_rx.poll_recv(cx)
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
error!("can not convert to an async TCP stream: {}", err);
|
||||
error!("can not convert to an async TCP stream: {err}");
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
|
@ -96,7 +96,7 @@ impl Future for Signals {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
for (sig, fut) in self.signals.iter_mut() {
|
||||
if Pin::new(fut).poll_recv(cx).is_ready() {
|
||||
if fut.poll_recv(cx).is_ready() {
|
||||
trace!("{} received", sig);
|
||||
return Poll::Ready(*sig);
|
||||
}
|
||||
|
@ -8,10 +8,11 @@ pub(crate) use mio::net::TcpListener as MioTcpListener;
|
||||
use mio::{event::Source, Interest, Registry, Token};
|
||||
#[cfg(unix)]
|
||||
pub(crate) use {
|
||||
mio::net::UnixListener as MioUnixListener,
|
||||
std::os::unix::net::UnixListener as StdUnixListener,
|
||||
mio::net::UnixListener as MioUnixListener, std::os::unix::net::UnixListener as StdUnixListener,
|
||||
};
|
||||
|
||||
use crate::builder::MpTcp;
|
||||
|
||||
pub(crate) enum MioListener {
|
||||
Tcp(MioTcpListener),
|
||||
#[cfg(unix)]
|
||||
@ -105,7 +106,7 @@ impl fmt::Debug for MioListener {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
MioListener::Tcp(ref lst) => write!(f, "{:?}", lst),
|
||||
#[cfg(all(unix))]
|
||||
#[cfg(unix)]
|
||||
MioListener::Uds(ref lst) => write!(f, "{:?}", lst),
|
||||
}
|
||||
}
|
||||
@ -224,10 +225,30 @@ mod unix_impl {
|
||||
pub(crate) fn create_mio_tcp_listener(
|
||||
addr: StdSocketAddr,
|
||||
backlog: u32,
|
||||
mptcp: &MpTcp,
|
||||
) -> io::Result<MioTcpListener> {
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
|
||||
let socket = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let protocol = Protocol::TCP;
|
||||
#[cfg(target_os = "linux")]
|
||||
let protocol = if matches!(mptcp, MpTcp::Disabled) {
|
||||
Protocol::TCP
|
||||
} else {
|
||||
Protocol::MPTCP
|
||||
};
|
||||
|
||||
let socket = match Socket::new(Domain::for_address(addr), Type::STREAM, Some(protocol)) {
|
||||
Ok(sock) => sock,
|
||||
|
||||
Err(err) if matches!(mptcp, MpTcp::TcpFallback) => {
|
||||
tracing::warn!("binding socket as MPTCP failed: {err}");
|
||||
tracing::warn!("falling back to TCP");
|
||||
Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?
|
||||
}
|
||||
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
socket.set_reuse_address(true)?;
|
||||
socket.set_nonblocking(true)?;
|
||||
@ -248,7 +269,7 @@ mod tests {
|
||||
assert_eq!(format!("{}", addr), "127.0.0.1:8080");
|
||||
|
||||
let addr: StdSocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
let lst = create_mio_tcp_listener(addr, 128).unwrap();
|
||||
let lst = create_mio_tcp_listener(addr, 128, &MpTcp::Disabled).unwrap();
|
||||
let lst = MioListener::Tcp(lst);
|
||||
assert!(format!("{:?}", lst).contains("TcpListener"));
|
||||
assert!(format!("{}", lst).contains("127.0.0.1"));
|
||||
|
@ -117,7 +117,7 @@ impl TestServerHandle {
|
||||
|
||||
/// Stop server.
|
||||
fn stop(&mut self) {
|
||||
let _ = self.server_handle.stop(false);
|
||||
drop(self.server_handle.stop(false));
|
||||
self.thread_handle.take().unwrap().join().unwrap().unwrap();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
@ -585,9 +589,7 @@ impl Future for ServerWorker {
|
||||
let this = self.as_mut().get_mut();
|
||||
|
||||
// `StopWorker` message handler
|
||||
if let Poll::Ready(Some(Stop { graceful, tx })) =
|
||||
Pin::new(&mut this.stop_rx).poll_recv(cx)
|
||||
{
|
||||
if let Poll::Ready(Some(Stop { graceful, tx })) = this.stop_rx.poll_recv(cx) {
|
||||
let num = this.counter.total();
|
||||
if num == 0 {
|
||||
info!("shutting down idle worker");
|
||||
@ -623,12 +625,13 @@ impl Future for ServerWorker {
|
||||
self.poll(cx)
|
||||
}
|
||||
},
|
||||
|
||||
WorkerState::Restarting(ref mut restart) => {
|
||||
let factory_id = restart.factory_id;
|
||||
let token = restart.token;
|
||||
|
||||
let (token_new, service) = ready!(restart.fut.as_mut().poll(cx))
|
||||
.unwrap_or_else(|_| {
|
||||
let (token_new, service) =
|
||||
ready!(restart.fut.as_mut().poll(cx)).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Can not restart {:?} service",
|
||||
this.factories[factory_id].name(token)
|
||||
@ -647,9 +650,10 @@ 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)) = Pin::new(&mut this.conn_rx).poll_recv(cx) {
|
||||
while let Poll::Ready(Some(conn)) = this.conn_rx.poll_recv(cx) {
|
||||
// WorkerCounterGuard is needed as Accept thread has incremented counter.
|
||||
// It's guard's job to decrement the counter together with drop of Conn.
|
||||
let guard = this.counter.guard();
|
||||
@ -680,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) {
|
||||
@ -696,10 +701,13 @@ impl Future for ServerWorker {
|
||||
}
|
||||
|
||||
// handle incoming io stream
|
||||
match ready!(Pin::new(&mut this.conn_rx).poll_recv(cx)) {
|
||||
match ready!(this.conn_rx.poll_recv(cx)) {
|
||||
Some(msg) => {
|
||||
let guard = this.counter.guard();
|
||||
let _ = this.services[msg.token].service.call((guard, msg.io));
|
||||
let _ = this.services[msg.token]
|
||||
.service
|
||||
.call((guard, msg.io))
|
||||
.into_inner();
|
||||
}
|
||||
None => return Poll::Ready(()),
|
||||
};
|
||||
@ -708,9 +716,7 @@ impl Future for ServerWorker {
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_worker_services(
|
||||
services: Vec<(usize, usize, BoxedServerService)>,
|
||||
) -> Vec<WorkerService> {
|
||||
fn wrap_worker_services(services: Vec<(usize, usize, BoxedServerService)>) -> Vec<WorkerService> {
|
||||
services
|
||||
.into_iter()
|
||||
.fold(Vec::new(), |mut services, (idx, token, service)| {
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![allow(clippy::let_underscore_future)]
|
||||
|
||||
use std::{
|
||||
net,
|
||||
sync::{
|
||||
|
@ -1,36 +1,37 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 2.0.2
|
||||
|
||||
## 2.0.2 - 2021-12-18
|
||||
- Service types can now be `Send` and `'static` regardless of request, response, and config types, etc. [#397]
|
||||
|
||||
[#397]: https://github.com/actix/actix-net/pull/397
|
||||
|
||||
## 2.0.1
|
||||
|
||||
## 2.0.1 - 2021-10-11
|
||||
- Documentation fix. [#388]
|
||||
|
||||
[#388]: https://github.com/actix/actix-net/pull/388
|
||||
|
||||
## 2.0.0
|
||||
|
||||
## 2.0.0 - 2021-04-16
|
||||
- Removed pipeline and related structs/functions. [#335]
|
||||
|
||||
[#335]: https://github.com/actix/actix-net/pull/335
|
||||
|
||||
## 2.0.0-beta.5
|
||||
|
||||
## 2.0.0-beta.5 - 2021-03-15
|
||||
- Add default `Service` trait impl for `Rc<S: Service>` and `&S: Service`. [#288]
|
||||
- Add `boxed::rc_service` function for constructing `boxed::RcService` type [#290]
|
||||
|
||||
[#288]: https://github.com/actix/actix-net/pull/288
|
||||
[#290]: https://github.com/actix/actix-net/pull/290
|
||||
|
||||
## 2.0.0-beta.4
|
||||
|
||||
## 2.0.0-beta.4 - 2021-02-04
|
||||
- `Service::poll_ready` and `Service::call` receive `&self`. [#247]
|
||||
- `apply_fn` and `apply_fn_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
- `apply_cfg` and `apply_cfg_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
@ -38,158 +39,153 @@
|
||||
|
||||
[#247]: https://github.com/actix/actix-net/pull/247
|
||||
|
||||
## 2.0.0-beta.3
|
||||
|
||||
## 2.0.0-beta.3 - 2021-01-09
|
||||
- The `forward_ready!` macro converts errors. [#246]
|
||||
|
||||
[#246]: https://github.com/actix/actix-net/pull/246
|
||||
|
||||
## 2.0.0-beta.2
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-03
|
||||
- Remove redundant type parameter from `map_config`.
|
||||
|
||||
## 2.0.0-beta.1
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
- `Service`, other traits, and many type signatures now take the the request type as a type
|
||||
parameter instead of an associated type. [#232]
|
||||
- `Service`, other traits, and many type signatures now take the the request type as a type parameter instead of an associated type. [#232]
|
||||
- Add `always_ready!` and `forward_ready!` macros. [#233]
|
||||
- Crate is now `no_std`. [#233]
|
||||
- Migrate pin projections to `pin-project-lite`. [#233]
|
||||
- Remove `AndThenApplyFn` and Pipeline `and_then_apply_fn`. Use the
|
||||
`.and_then(apply_fn(...))` construction. [#233]
|
||||
- Remove `AndThenApplyFn` and Pipeline `and_then_apply_fn`. Use the `.and_then(apply_fn(...))` construction. [#233]
|
||||
- Move non-vital methods to `ServiceExt` and `ServiceFactoryExt` extension traits. [#235]
|
||||
|
||||
[#232]: https://github.com/actix/actix-net/pull/232
|
||||
[#233]: https://github.com/actix/actix-net/pull/233
|
||||
[#235]: https://github.com/actix/actix-net/pull/235
|
||||
|
||||
## 1.0.6
|
||||
|
||||
## 1.0.6 - 2020-08-09
|
||||
- Removed unsound custom Cell implementation that allowed obtaining several mutable references to
|
||||
the same data, which is undefined behavior in Rust and could lead to violations of memory safety. External code could obtain several mutable references to the same data through
|
||||
service combinators. Attempts to acquire several mutable references to the same data will instead
|
||||
result in a panic.
|
||||
- Removed unsound custom Cell implementation that allowed obtaining several mutable references to the same data, which is undefined behavior in Rust and could lead to violations of memory safety. External code could obtain several mutable references to the same data through service combinators. Attempts to acquire several mutable references to the same data will instead result in a panic.
|
||||
|
||||
## 1.0.5
|
||||
|
||||
## 1.0.5 - 2020-01-16
|
||||
- Fixed unsoundness in .and_then()/.then() service combinators.
|
||||
|
||||
## 1.0.4
|
||||
|
||||
## 1.0.4 - 2020-01-15
|
||||
- Revert 1.0.3 change
|
||||
|
||||
## 1.0.3
|
||||
|
||||
## 1.0.3 - 2020-01-15
|
||||
- Fixed unsoundness in `AndThenService` impl.
|
||||
|
||||
## 1.0.2
|
||||
|
||||
## 1.0.2 - 2020-01-08
|
||||
- Add `into_service` helper function.
|
||||
|
||||
## 1.0.1
|
||||
|
||||
## 1.0.1 - 2019-12-22
|
||||
- `map_config()` and `unit_config()` now accept `IntoServiceFactory` type.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
- Add Clone impl for Apply service
|
||||
|
||||
## 1.0.0-alpha.4
|
||||
|
||||
## 1.0.0-alpha.4 - 2019-12-08
|
||||
- Renamed `service_fn` to `fn_service`
|
||||
- Renamed `factory_fn` to `fn_factory`
|
||||
- Renamed `factory_fn_cfg` to `fn_factory_with_config`
|
||||
|
||||
## 1.0.0-alpha.3
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-06
|
||||
- Add missing Clone impls
|
||||
- Restore `Transform::map_init_err()` combinator
|
||||
- Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||
- Optimize service combinators and futures memory layout
|
||||
|
||||
## 1.0.0-alpha.2
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
- Use owned config value for service factory
|
||||
- Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||
|
||||
## 1.0.0-alpha.1
|
||||
|
||||
## 1.0.0-alpha.1 - 2019-11-25
|
||||
- Migrated to `std::future`
|
||||
- `NewService` renamed to `ServiceFactory`
|
||||
- Added `pipeline` and `pipeline_factory` function
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.2 - 2019-08-27
|
||||
- Check service readiness for `new_apply_cfg` combinator
|
||||
|
||||
## 0.4.1
|
||||
|
||||
## 0.4.1 - 2019-06-06
|
||||
- Add `new_apply_cfg` function
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## 0.4.0 - 2019-05-12
|
||||
- Add `NewService::map_config` and `NewService::unit_config` combinators.
|
||||
- Use associated type for `NewService` config.
|
||||
- Change `apply_cfg` function.
|
||||
- Renamed helper functions.
|
||||
|
||||
## 0.3.6
|
||||
|
||||
## 0.3.6 - 2019-04-07
|
||||
- Poll boxed service call result immediately
|
||||
|
||||
## 0.3.5
|
||||
|
||||
## 0.3.5 - 2019-03-29
|
||||
- Add `impl<S: Service> Service for Rc<RefCell<S>>`.
|
||||
|
||||
## 0.3.4
|
||||
|
||||
## 0.3.4 - 2019-03-12
|
||||
- Add `Transform::from_err()` combinator
|
||||
- Add `apply_fn` helper
|
||||
- Add `apply_fn_factory` helper
|
||||
- Add `apply_transform` helper
|
||||
- Add `apply_cfg` helper
|
||||
|
||||
## 0.3.3
|
||||
|
||||
## 0.3.3 - 2019-03-09
|
||||
- Add `ApplyTransform` new service for transform and new service.
|
||||
- Add `NewService::apply_cfg()` combinator, allows to use nested `NewService` with different config parameter.
|
||||
- Revert IntoFuture change
|
||||
|
||||
## 0.3.2
|
||||
|
||||
## 0.3.2 - 2019-03-04
|
||||
- Change `NewService::Future` and `Transform::Future` to the `IntoFuture` trait.
|
||||
- Export `AndThenTransform` type
|
||||
|
||||
## 0.3.1
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
- Simplify Transform trait
|
||||
|
||||
## 0.3.0
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
- Added boxed NewService and Service.
|
||||
- Added `Config` parameter to `NewService` trait.
|
||||
- Added `Config` parameter to `NewTransform` trait.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
## 0.2.2 - 2019-02-19
|
||||
- Added `NewService` impl for `Rc<S> where S: NewService`
|
||||
- Added `NewService` impl for `Arc<S> where S: NewService`
|
||||
|
||||
## 0.2.1
|
||||
|
||||
## 0.2.1 - 2019-02-03
|
||||
- Generalize `.apply` combinator with Transform trait
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
- Use associated type instead of generic for Service definition.
|
||||
* Before:
|
||||
- Before:
|
||||
```rust
|
||||
impl Service<Request> for Client {
|
||||
type Response = Response;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
* After:
|
||||
- After:
|
||||
```rust
|
||||
impl Service for Client {
|
||||
type Request = Request;
|
||||
@ -198,31 +194,31 @@
|
||||
}
|
||||
```
|
||||
|
||||
## 0.1.6
|
||||
|
||||
## 0.1.6 - 2019-01-24
|
||||
- Use `FnMut` instead of `Fn` for .apply() and .map() combinators and `FnService` type
|
||||
- Change `.apply()` error semantic, new service's error is `From<Self::Error>`
|
||||
|
||||
## 0.1.5
|
||||
|
||||
## 0.1.5 - 2019-01-13
|
||||
- Make `Out::Error` convertible from `T::Error` for apply combinator
|
||||
|
||||
## 0.1.4
|
||||
|
||||
## 0.1.4 - 2019-01-11
|
||||
- Use `FnMut` instead of `Fn` for `FnService`
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2018-12-12
|
||||
- Split service combinators to separate trait
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2018-12-12
|
||||
- Release future early for `.and_then()` and `.then()` combinators
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2018-12-09
|
||||
- Added Service impl for `Box<S: Service>`
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
- Initial import
|
||||
|
@ -4,25 +4,21 @@ version = "2.0.2"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
"fakeshadow <24548779@qq.com>",
|
||||
]
|
||||
description = "Service trait and combinators for representing asynchronous request/response operations."
|
||||
keywords = ["network", "framework", "async", "futures", "service"]
|
||||
categories = ["network-programming", "asynchronous", "no-std"]
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "actix_service"
|
||||
path = "src/lib.rs"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
futures-core = { version = "0.3.7", default-features = false }
|
||||
futures-core = { version = "0.3.17", default-features = false }
|
||||
paste = "1"
|
||||
pin-project-lite = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
actix-rt = "2"
|
||||
actix-utils = "3"
|
||||
futures-util = { version = "0.3.17", default-features = false }
|
||||
|
@ -5,7 +5,7 @@
|
||||
[![crates.io](https://img.shields.io/crates/v/actix-service?label=latest)](https://crates.io/crates/actix-service)
|
||||
[![Documentation](https://docs.rs/actix-service/badge.svg?version=2.0.2)](https://docs.rs/actix-service/2.0.2)
|
||||
[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
||||
![License](https://img.shields.io/crates/l/actix-service.svg)
|
||||
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-service.svg)
|
||||
[![Dependency Status](https://deps.rs/crate/actix-service/2.0.2/status.svg)](https://deps.rs/crate/actix-service/2.0.2)
|
||||
![Download](https://img.shields.io/crates/d/actix-service.svg)
|
||||
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
||||
|
@ -121,12 +121,7 @@ pub struct AndThenServiceFactory<A, B, Req>
|
||||
where
|
||||
A: ServiceFactory<Req>,
|
||||
A::Config: Clone,
|
||||
B: ServiceFactory<
|
||||
A::Response,
|
||||
Config = A::Config,
|
||||
Error = A::Error,
|
||||
InitError = A::InitError,
|
||||
>,
|
||||
B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
|
||||
{
|
||||
inner: Rc<(A, B)>,
|
||||
_phantom: PhantomData<Req>,
|
||||
@ -136,12 +131,7 @@ impl<A, B, Req> AndThenServiceFactory<A, B, Req>
|
||||
where
|
||||
A: ServiceFactory<Req>,
|
||||
A::Config: Clone,
|
||||
B: ServiceFactory<
|
||||
A::Response,
|
||||
Config = A::Config,
|
||||
Error = A::Error,
|
||||
InitError = A::InitError,
|
||||
>,
|
||||
B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
|
||||
{
|
||||
/// Create new `AndThenFactory` combinator
|
||||
pub(crate) fn new(a: A, b: B) -> Self {
|
||||
@ -156,12 +146,7 @@ impl<A, B, Req> ServiceFactory<Req> for AndThenServiceFactory<A, B, Req>
|
||||
where
|
||||
A: ServiceFactory<Req>,
|
||||
A::Config: Clone,
|
||||
B: ServiceFactory<
|
||||
A::Response,
|
||||
Config = A::Config,
|
||||
Error = A::Error,
|
||||
InitError = A::InitError,
|
||||
>,
|
||||
B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
|
||||
{
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
@ -184,12 +169,7 @@ impl<A, B, Req> Clone for AndThenServiceFactory<A, B, Req>
|
||||
where
|
||||
A: ServiceFactory<Req>,
|
||||
A::Config: Clone,
|
||||
B: ServiceFactory<
|
||||
A::Response,
|
||||
Config = A::Config,
|
||||
Error = A::Error,
|
||||
InitError = A::InitError,
|
||||
>,
|
||||
B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
@ -334,9 +314,8 @@ mod tests {
|
||||
async fn test_new_service() {
|
||||
let cnt = Rc::new(Cell::new(0));
|
||||
let cnt2 = cnt.clone();
|
||||
let new_srv =
|
||||
pipeline_factory(fn_factory(move || ready(Ok::<_, ()>(Srv1(cnt2.clone())))))
|
||||
.and_then(move || ready(Ok(Srv2(cnt.clone()))));
|
||||
let new_srv = pipeline_factory(fn_factory(move || ready(Ok::<_, ()>(Srv1(cnt2.clone())))))
|
||||
.and_then(move || ready(Ok(Srv2(cnt.clone()))));
|
||||
|
||||
let srv = new_srv.new_service(()).await.unwrap();
|
||||
let res = srv.call("srv1").await;
|
||||
|
@ -140,8 +140,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<SF, F, Fut, Req, In, Res, Err> ServiceFactory<Req>
|
||||
for ApplyFactory<SF, F, Req, In, Res, Err>
|
||||
impl<SF, F, Fut, Req, In, Res, Err> ServiceFactory<Req> for ApplyFactory<SF, F, Req, In, Res, Err>
|
||||
where
|
||||
SF: ServiceFactory<In, Error = Err>,
|
||||
F: Fn(Req, &SF::Service) -> Fut + Clone,
|
||||
|
@ -198,8 +198,7 @@ pin_project! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<SF, Req, F, Cfg, Fut, S> Future
|
||||
for ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
|
||||
impl<SF, Req, F, Cfg, Fut, S> Future for ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
|
||||
where
|
||||
SF: ServiceFactory<Req, Config = ()>,
|
||||
SF::InitError: From<SF::Error>,
|
||||
|
@ -91,8 +91,7 @@ type Inner<C, Req, Res, Err, InitErr> = Box<
|
||||
>,
|
||||
>;
|
||||
|
||||
impl<C, Req, Res, Err, InitErr> ServiceFactory<Req>
|
||||
for BoxServiceFactory<C, Req, Res, Err, InitErr>
|
||||
impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr>
|
||||
where
|
||||
Req: 'static,
|
||||
Res: 'static,
|
||||
|
@ -3,9 +3,7 @@ use core::{future::Future, marker::PhantomData};
|
||||
use crate::{ok, IntoService, IntoServiceFactory, Ready, Service, ServiceFactory};
|
||||
|
||||
/// Create `ServiceFactory` for function that can act as a `Service`
|
||||
pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(
|
||||
f: F,
|
||||
) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
|
||||
pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(f: F) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
|
||||
where
|
||||
F: Fn(Req) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
@ -48,9 +46,7 @@ where
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>(
|
||||
f: F,
|
||||
) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
|
||||
pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>(f: F) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
|
||||
where
|
||||
F: Fn() -> Fut,
|
||||
Fut: Future<Output = Result<Srv, Err>>,
|
||||
@ -265,8 +261,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, Fut, Cfg, Srv, Req, Err> ServiceFactory<Req>
|
||||
for FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
|
||||
impl<F, Fut, Cfg, Srv, Req, Err> ServiceFactory<Req> for FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
|
||||
where
|
||||
F: Fn(Cfg) -> Fut,
|
||||
Fut: Future<Output = Result<Srv, Err>>,
|
||||
@ -404,9 +399,8 @@ mod tests {
|
||||
ok::<_, Rc<u8>>(fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8))))
|
||||
});
|
||||
|
||||
let fac_2 = fn_factory(|| {
|
||||
ok::<_, Rc<u8>>(fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8))))
|
||||
});
|
||||
let fac_2 =
|
||||
fn_factory(|| ok::<_, Rc<u8>>(fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8)))));
|
||||
|
||||
fn is_send<T: Send + Sync + Clone>(_: &T) {}
|
||||
|
||||
|
@ -33,14 +33,16 @@ mod then;
|
||||
mod transform;
|
||||
mod transform_err;
|
||||
|
||||
pub use self::apply::{apply_fn, apply_fn_factory};
|
||||
pub use self::apply_cfg::{apply_cfg, apply_cfg_factory};
|
||||
pub use self::ext::{ServiceExt, ServiceFactoryExt, TransformExt};
|
||||
pub use self::fn_service::{fn_factory, fn_factory_with_config, fn_service};
|
||||
pub use self::map_config::{map_config, unit_config};
|
||||
#[allow(unused_imports)]
|
||||
use self::ready::{err, ok, ready, Ready};
|
||||
pub use self::transform::{apply, ApplyTransform, Transform};
|
||||
pub use self::{
|
||||
apply::{apply_fn, apply_fn_factory},
|
||||
apply_cfg::{apply_cfg, apply_cfg_factory},
|
||||
ext::{ServiceExt, ServiceFactoryExt, TransformExt},
|
||||
fn_service::{fn_factory, fn_factory_with_config, fn_service},
|
||||
map_config::{map_config, unit_config},
|
||||
transform::{apply, ApplyTransform, Transform},
|
||||
};
|
||||
|
||||
/// An asynchronous operation from `Request` to a `Response`.
|
||||
///
|
||||
|
@ -25,6 +25,8 @@
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`forward_ready!`]: crate::forward_ready
|
||||
#[macro_export]
|
||||
macro_rules! always_ready {
|
||||
() => {
|
||||
|
@ -206,8 +206,7 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
err, ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory,
|
||||
ServiceFactoryExt,
|
||||
err, ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory, ServiceFactoryExt,
|
||||
};
|
||||
|
||||
struct Srv;
|
||||
|
@ -6,12 +6,14 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::and_then::{AndThenService, AndThenServiceFactory};
|
||||
use crate::map::{Map, MapServiceFactory};
|
||||
use crate::map_err::{MapErr, MapErrServiceFactory};
|
||||
use crate::map_init_err::MapInitErr;
|
||||
use crate::then::{ThenService, ThenServiceFactory};
|
||||
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
||||
use crate::{
|
||||
and_then::{AndThenService, AndThenServiceFactory},
|
||||
map::{Map, MapServiceFactory},
|
||||
map_err::{MapErr, MapErrServiceFactory},
|
||||
map_init_err::MapInitErr,
|
||||
then::{ThenService, ThenServiceFactory},
|
||||
IntoService, IntoServiceFactory, Service, ServiceFactory,
|
||||
};
|
||||
|
||||
/// Construct new pipeline with one service in pipeline chain.
|
||||
pub(crate) fn pipeline<I, S, Req>(service: I) -> Pipeline<S, Req>
|
||||
@ -252,10 +254,7 @@ where
|
||||
}
|
||||
|
||||
/// Map this service's error to a different error, returning a new service.
|
||||
pub fn map_err<F, E>(
|
||||
self,
|
||||
f: F,
|
||||
) -> PipelineFactory<MapErrServiceFactory<SF, Req, F, E>, Req>
|
||||
pub fn map_err<F, E>(self, f: F) -> PipelineFactory<MapErrServiceFactory<SF, Req, F, E>, Req>
|
||||
where
|
||||
Self: Sized,
|
||||
F: Fn(SF::Error) -> E + Clone,
|
||||
|
@ -1,41 +1,52 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## 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
|
||||
|
||||
## 3.0.4 - 2022-03-15
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
||||
|
||||
[#451]: https://github.com/actix/actix-net/pull/451
|
||||
|
||||
## 3.0.3
|
||||
|
||||
## 3.0.3 - 2022-02-15
|
||||
- No significant changes since `3.0.2`.
|
||||
|
||||
## 3.0.2
|
||||
|
||||
## 3.0.2 - 2022-01-28
|
||||
- Expose `connect::Connection::new`. [#439]
|
||||
|
||||
[#439]: https://github.com/actix/actix-net/pull/439
|
||||
|
||||
## 3.0.1
|
||||
|
||||
## 3.0.1 - 2022-01-11
|
||||
- No significant changes since `3.0.0`.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
## 3.0.0 - 2021-12-26
|
||||
- No significant changes since `3.0.0-rc.2`.
|
||||
|
||||
## 3.0.0-rc.2
|
||||
|
||||
## 3.0.0-rc.2 - 2021-12-10
|
||||
- Re-export `openssl::SslConnectorBuilder` in `connect::openssl::reexports`. [#429]
|
||||
|
||||
[#429]: https://github.com/actix/actix-net/pull/429
|
||||
|
||||
## 3.0.0-rc.1
|
||||
|
||||
## 3.0.0-rc.1 - 2021-11-29
|
||||
### Added
|
||||
|
||||
- Derive `Debug` for `connect::Connection`. [#422]
|
||||
- Implement `Display` for `accept::TlsError`. [#422]
|
||||
- Implement `Error` for `accept::TlsError` where both types also implement `Error`. [#422]
|
||||
@ -45,6 +56,7 @@
|
||||
- Implement `Default` for `connect::ConnectorService`. [#423]
|
||||
|
||||
### Changed
|
||||
|
||||
- The crate's default features flags no longer include `uri`. [#422]
|
||||
- Useful re-exports from underlying TLS crates are exposed in a `reexports` modules in all acceptors and connectors.
|
||||
- Convert `connect::ResolverService` from enum to struct. [#422]
|
||||
@ -61,6 +73,7 @@
|
||||
- Inline modules in `connect::tls` to `connect` module. [#422]
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `connect::{new_connector, new_connector_factory, default_connector, default_connector_factory}` methods. [#422]
|
||||
- Remove `connect::native_tls::Connector::service` method. [#422]
|
||||
- Remove redundant `connect::Connection::from_parts` method. [#422]
|
||||
@ -68,8 +81,8 @@
|
||||
[#422]: https://github.com/actix/actix-net/pull/422
|
||||
[#423]: https://github.com/actix/actix-net/pull/423
|
||||
|
||||
## 3.0.0-beta.9
|
||||
|
||||
## 3.0.0-beta.9 - 2021-11-22
|
||||
- Add configurable timeout for accepting TLS connection. [#393]
|
||||
- Added `TlsError::Timeout` variant. [#393]
|
||||
- All TLS acceptor services now use `TlsError` for their error types. [#393]
|
||||
@ -78,31 +91,30 @@
|
||||
[#393]: https://github.com/actix/actix-net/pull/393
|
||||
[#420]: https://github.com/actix/actix-net/pull/420
|
||||
|
||||
## 3.0.0-beta.8
|
||||
|
||||
## 3.0.0-beta.8 - 2021-11-15
|
||||
- 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
|
||||
|
||||
## 3.0.0-beta.7 - 2021-10-20
|
||||
- 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
|
||||
|
||||
## 3.0.0-beta.6 - 2021-10-19
|
||||
- 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]
|
||||
- Minimum supported Rust version (MSRV) is now 1.52.
|
||||
|
||||
[#396]: https://github.com/actix/actix-net/pull/396
|
||||
|
||||
## 3.0.0-beta.5
|
||||
|
||||
## 3.0.0-beta.5 - 2021-03-29
|
||||
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef`
|
||||
generation failed instead of panic. [#296]
|
||||
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef` generation failed instead of panic. [#296]
|
||||
- Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
|
||||
- Remove `connect::ssl::openssl::OpensslConnectService`. [#297]
|
||||
- Add `connect::ssl::native_tls` module for native tls support. [#295]
|
||||
@ -114,74 +126,72 @@
|
||||
[#297]: https://github.com/actix/actix-net/pull/297
|
||||
[#299]: https://github.com/actix/actix-net/pull/299
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.4 - 2021-02-24
|
||||
- Rename `accept::openssl::{SslStream => TlsStream}`.
|
||||
- Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
|
||||
- `connector::TcpConnector` service will try to bind to local_addr of `IpAddr` when given. [#282]
|
||||
|
||||
[#282]: https://github.com/actix/actix-net/pull/282
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
## 3.0.0-beta.3 - 2021-02-06
|
||||
- Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
|
||||
- Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
|
||||
- Add `Resolve` trait for custom DNS resolvers. [#248]
|
||||
- Add `Resolver::new_custom` function to construct custom resolvers. [#248]
|
||||
- Export `webpki_roots::TLS_SERVER_ROOTS` in `actix_tls::connect` mod and remove
|
||||
the export from `actix_tls::accept` [#248]
|
||||
- Remove `ConnectTakeAddrsIter`. `Connect::take_addrs` now returns `ConnectAddrsIter<'static>`
|
||||
as owned iterator. [#248]
|
||||
- Export `webpki_roots::TLS_SERVER_ROOTS` in `actix_tls::connect` mod and remove the export from `actix_tls::accept` [#248]
|
||||
- Remove `ConnectTakeAddrsIter`. `Connect::take_addrs` now returns `ConnectAddrsIter<'static>` as owned iterator. [#248]
|
||||
- Rename `Address::{host => hostname}` to more accurately describe which URL segment is returned.
|
||||
- Update `actix-rt` to `2.0.0`. [#273]
|
||||
|
||||
[#248]: https://github.com/actix/actix-net/pull/248
|
||||
[#273]: https://github.com/actix/actix-net/pull/273
|
||||
|
||||
## 3.0.0-beta.2
|
||||
|
||||
## 3.0.0-beta.2 - 2022-xx-xx
|
||||
- Depend on stable trust-dns packages. [#204]
|
||||
|
||||
[#204]: https://github.com/actix/actix-net/pull/204
|
||||
|
||||
## 3.0.0-beta.1
|
||||
|
||||
## 3.0.0-beta.1 - 2020-12-29
|
||||
- Move acceptors under `accept` module. [#238]
|
||||
- Merge `actix-connect` crate under `connect` module. [#238]
|
||||
- Add feature flags to enable acceptors and/or connectors individually. [#238]
|
||||
|
||||
[#238]: https://github.com/actix/actix-net/pull/238
|
||||
|
||||
## 2.0.0
|
||||
|
||||
## 2.0.0 - 2020-09-03
|
||||
- `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
|
||||
- Where possible, "SSL" terminology is replaced with "TLS".
|
||||
* `SslError` is renamed to `TlsError`.
|
||||
* `TlsError::Ssl` enum variant is renamed to `TlsError::Tls`.
|
||||
* `max_concurrent_ssl_connect` is renamed to `max_concurrent_tls_connect`.
|
||||
- `SslError` is renamed to `TlsError`.
|
||||
- `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
|
||||
|
||||
## 2.0.0-alpha.2 - 2020-08-17
|
||||
- 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]
|
||||
|
||||
## [2.0.0-alpha.1] - 2020-03-03
|
||||
- Update `rustls` dependency to 0.17
|
||||
- Update `tokio-rustls` dependency to 0.13
|
||||
- Update `webpki-roots` dependency to 0.19
|
||||
|
||||
## [1.0.0]
|
||||
|
||||
## [1.0.0] - 2019-12-11
|
||||
- 1.0.0 release
|
||||
|
||||
## [1.0.0-alpha.3]
|
||||
|
||||
## [1.0.0-alpha.3] - 2019-12-07
|
||||
- Migrate to tokio 0.2
|
||||
- Enable rustls acceptor service
|
||||
- Enable native-tls acceptor service
|
||||
|
||||
## [1.0.0-alpha.1]
|
||||
|
||||
## [1.0.0-alpha.1] - 2019-12-02
|
||||
- Split openssl acceptor from actix-server package
|
||||
|
@ -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,16 +9,27 @@ 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"
|
||||
edition = "2018"
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[lib]
|
||||
name = "actix_tls"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"actix_service::*",
|
||||
"actix_utils::*",
|
||||
"futures_core::*",
|
||||
"tokio::*",
|
||||
]
|
||||
|
||||
[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"]
|
||||
@ -30,25 +41,32 @@ accept = []
|
||||
connect = []
|
||||
|
||||
# use openssl impls
|
||||
openssl = ["tls-openssl", "tokio-openssl", "actix-codec"]
|
||||
openssl = ["tls-openssl", "tokio-openssl"]
|
||||
|
||||
# use rustls impls
|
||||
rustls = ["tokio-rustls", "webpki-roots", "actix-codec"]
|
||||
# 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", "actix-codec"]
|
||||
native-tls = ["tokio-native-tls"]
|
||||
|
||||
# support http::Uri as connect address
|
||||
uri = ["http"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = { version = "0.5.0", optional = true }
|
||||
actix-rt = { version = "2.2.0", default-features = false }
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-rt = { version = "2.2", default-features = false }
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
impl-more = "0.1"
|
||||
pin-project-lite = "0.2.7"
|
||||
tokio = "1.23.1"
|
||||
tokio-util = "0.7"
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
@ -56,29 +74,34 @@ 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.9", 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 }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-codec = "0.5.0"
|
||||
actix-rt = "2.2.0"
|
||||
actix-server = "2.0.0"
|
||||
actix-codec = "0.5"
|
||||
actix-rt = "2.2"
|
||||
actix-server = "2"
|
||||
bytes = "1"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
|
||||
log = "0.4"
|
||||
rcgen = "0.8"
|
||||
rustls-pemfile = "0.2.1"
|
||||
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"] }
|
||||
trust-dns-resolver = "0.20.0"
|
||||
env_logger = "0.10"
|
||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
||||
rcgen = "0.11"
|
||||
rustls-pemfile = "1"
|
||||
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"]
|
||||
|
@ -17,13 +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::{
|
||||
env,
|
||||
fs::File,
|
||||
io::{self, BufReader},
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
@ -33,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};
|
||||
@ -41,12 +41,18 @@ use tracing::info;
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
env::set_var("RUST_LOG", "info");
|
||||
env_logger::init();
|
||||
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()
|
||||
@ -66,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 || {
|
||||
|
@ -10,20 +10,29 @@ use std::{
|
||||
use actix_utils::counter::Counter;
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
|
||||
pub mod openssl;
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
#[cfg_attr(docsrs, doc(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")]
|
||||
#[cfg_attr(docsrs, doc(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);
|
||||
|
||||
@ -59,6 +68,25 @@ pub enum TlsError<TlsErr, SvcErr> {
|
||||
Service(SvcErr),
|
||||
}
|
||||
|
||||
impl<TlsErr> TlsError<TlsErr, Infallible> {
|
||||
/// Casts the infallible service error type returned from acceptors into caller's type.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::convert::Infallible;
|
||||
/// # use actix_tls::accept::TlsError;
|
||||
/// let a: TlsError<u32, Infallible> = TlsError::Tls(42);
|
||||
/// let _b: TlsError<u32, u64> = a.into_service_error();
|
||||
/// ```
|
||||
pub fn into_service_error<SvcErr>(self) -> TlsError<TlsErr, SvcErr> {
|
||||
match self {
|
||||
Self::Timeout => TlsError::Timeout,
|
||||
Self::Tls(err) => TlsError::Tls(err),
|
||||
Self::Service(err) => match err {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
@ -83,25 +111,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TlsErr> TlsError<TlsErr, Infallible> {
|
||||
/// Casts the infallible service error type returned from acceptors into caller's type.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::convert::Infallible;
|
||||
/// # use actix_tls::accept::TlsError;
|
||||
/// let a: TlsError<u32, Infallible> = TlsError::Tls(42);
|
||||
/// let _b: TlsError<u32, u64> = a.into_service_error();
|
||||
/// ```
|
||||
pub fn into_service_error<SvcErr>(self) -> TlsError<TlsErr, SvcErr> {
|
||||
match self {
|
||||
Self::Timeout => TlsError::Timeout,
|
||||
Self::Tls(err) => TlsError::Tls(err),
|
||||
Self::Service(err) => match err {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -10,7 +10,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use actix_rt::{
|
||||
net::{ActixStream, Ready},
|
||||
time::timeout,
|
||||
@ -21,10 +20,10 @@ use actix_utils::{
|
||||
future::{ready, Ready as FutReady},
|
||||
};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use tokio_native_tls::{native_tls::Error, TlsAcceptor};
|
||||
|
||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||
use crate::impl_more;
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `native-tls` that are useful for acceptors.
|
||||
@ -35,9 +34,8 @@ pub mod reexports {
|
||||
/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
|
||||
pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_native_tls::TlsStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_native_tls::TlsStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
impl_more::impl_from!(<IO> in tokio_native_tls::TlsStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
@ -75,17 +73,17 @@ impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
(&**self).is_write_vectored()
|
||||
(**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().get_ref().get_ref(), cx)
|
||||
IO::poll_read_ready((**self).get_ref().get_ref().get_ref(), cx)
|
||||
}
|
||||
|
||||
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||
IO::poll_write_ready((&**self).get_ref().get_ref().get_ref(), cx)
|
||||
IO::poll_write_ready((**self).get_ref().get_ref().get_ref(), cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use actix_rt::{
|
||||
net::{ActixStream, Ready},
|
||||
time::{sleep, Sleep},
|
||||
@ -23,9 +22,9 @@ use actix_utils::{
|
||||
};
|
||||
use openssl::ssl::{Error, Ssl, SslAcceptor};
|
||||
use pin_project_lite::pin_project;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
|
||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||
use crate::impl_more;
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `openssl` that are useful for acceptors.
|
||||
@ -38,9 +37,8 @@ pub mod reexports {
|
||||
/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
|
||||
pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_openssl::SslStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_openssl::SslStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
impl_more::impl_from!(<IO> in tokio_openssl::SslStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
@ -78,17 +76,17 @@ impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
(&**self).is_write_vectored()
|
||||
(**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(), cx)
|
||||
IO::poll_read_ready((**self).get_ref(), cx)
|
||||
}
|
||||
|
||||
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||
IO::poll_write_ready((&**self).get_ref(), cx)
|
||||
IO::poll_write_ready((**self).get_ref(), cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
@ -12,7 +12,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use actix_rt::{
|
||||
net::{ActixStream, Ready},
|
||||
time::{sleep, Sleep},
|
||||
@ -23,24 +22,23 @@ use actix_utils::{
|
||||
future::{ready, Ready as FutReady},
|
||||
};
|
||||
use pin_project_lite::pin_project;
|
||||
use tokio_rustls::rustls::ServerConfig;
|
||||
use tokio_rustls::{Accept, TlsAcceptor};
|
||||
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};
|
||||
use crate::impl_more;
|
||||
|
||||
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`].
|
||||
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_rustls::server::TlsStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_rustls::server::TlsStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
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(
|
||||
@ -78,17 +76,17 @@ impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
(&**self).is_write_vectored()
|
||||
(**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)
|
||||
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)
|
||||
IO::poll_write_ready((**self).get_ref().0, cx)
|
||||
}
|
||||
}
|
||||
|
198
actix-tls/src/accept/rustls_0_21.rs
Normal file
198
actix-tls/src/accept/rustls_0_21.rs
Normal 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)),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
use super::Host;
|
||||
use crate::impl_more;
|
||||
|
||||
/// Wraps underlying I/O and the connection request that initiated it.
|
||||
#[derive(Debug)]
|
||||
@ -8,8 +7,7 @@ pub struct Connection<R, IO> {
|
||||
pub(crate) io: IO,
|
||||
}
|
||||
|
||||
impl_more::deref! { Connection<R, IO> => io: IO }
|
||||
impl_more::deref_mut! { Connection<R, IO> => io }
|
||||
impl_more::impl_deref_and_mut!(<R, IO> in Connection<R, IO> => io: IO);
|
||||
|
||||
impl<R, IO> Connection<R, IO> {
|
||||
/// Construct new `Connection` from request and IO parts.
|
||||
|
@ -22,25 +22,30 @@ mod resolver;
|
||||
pub mod tcp;
|
||||
|
||||
#[cfg(feature = "uri")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "uri")))]
|
||||
mod uri;
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
|
||||
pub mod openssl;
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
#[cfg_attr(docsrs, doc(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")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
|
||||
pub mod native_tls;
|
||||
|
||||
pub use self::connection::Connection;
|
||||
pub use self::connector::{Connector, ConnectorService};
|
||||
pub use self::error::ConnectError;
|
||||
pub use self::host::Host;
|
||||
pub use self::info::ConnectInfo;
|
||||
pub use self::resolve::Resolve;
|
||||
pub use self::resolver::{Resolver, ResolverService};
|
||||
pub use self::{
|
||||
connection::Connection,
|
||||
connector::{Connector, ConnectorService},
|
||||
error::ConnectError,
|
||||
host::Host,
|
||||
info::ConnectInfo,
|
||||
resolve::Resolve,
|
||||
resolver::{Resolver, ResolverService},
|
||||
};
|
||||
|
@ -19,8 +19,7 @@ use crate::connect::{Connection, Host};
|
||||
pub mod reexports {
|
||||
//! Re-exports from `native-tls` and `tokio-native-tls` that are useful for connectors.
|
||||
|
||||
pub use tokio_native_tls::native_tls::TlsConnector;
|
||||
pub use tokio_native_tls::TlsStream as AsyncTlsStream;
|
||||
pub use tokio_native_tls::{native_tls::TlsConnector, TlsStream as AsyncTlsStream};
|
||||
}
|
||||
|
||||
/// Connector service and factory using `native-tls`.
|
||||
|
@ -22,9 +22,7 @@ use crate::connect::{Connection, Host};
|
||||
pub mod reexports {
|
||||
//! Re-exports from `openssl` and `tokio-openssl` that are useful for connectors.
|
||||
|
||||
pub use openssl::ssl::{
|
||||
Error, HandshakeError, SslConnector, SslConnectorBuilder, SslMethod,
|
||||
};
|
||||
pub use openssl::ssl::{Error, HandshakeError, SslConnector, SslConnectorBuilder, SslMethod};
|
||||
pub use tokio_openssl::SslStream as AsyncSslStream;
|
||||
}
|
||||
|
||||
|
@ -15,26 +15,26 @@ use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use tokio_rustls::rustls::{client::ServerName, OwnedTrustAnchor, RootCertStore};
|
||||
use tokio_rustls::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||
use tokio_rustls::{Connect as RustlsConnect, TlsConnector as RustlsTlsConnector};
|
||||
use tracing::trace;
|
||||
use webpki_roots::TLS_SERVER_ROOTS;
|
||||
use tokio_rustls::{
|
||||
client::TlsStream as AsyncTlsStream,
|
||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||
};
|
||||
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;
|
||||
pub use tokio_rustls::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,
|
||||
@ -101,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,
|
||||
@ -116,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,
|
||||
@ -130,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))
|
||||
}
|
||||
}
|
154
actix-tls/src/connect/rustls_0_21.rs
Normal file
154
actix-tls/src/connect/rustls_0_21.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/// A helper to implement `Deref` for a type.
|
||||
#[macro_export]
|
||||
macro_rules! deref {
|
||||
($ty:ident $(<$($generic:ident),*>)? => $field:tt: $target:ty) => {
|
||||
impl $(<$($generic),*>)? ::core::ops::Deref for $ty $(<$($generic),*>)? {
|
||||
type Target = $target;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.$field
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A helper to implement `DerefMut` for a type.
|
||||
#[macro_export]
|
||||
macro_rules! deref_mut {
|
||||
($ty:ident $(<$($generic:ident),*>)? => $field:tt) => {
|
||||
impl $(<$($generic),*>)? ::core::ops::DerefMut for $ty $(<$($generic),*>)? {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.$field
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A helper to implement `From` for a unit struct.
|
||||
#[macro_export]
|
||||
macro_rules! from {
|
||||
($from:ty => $ty:ident $(<$($generic:ident),*>)?) => {
|
||||
impl $(<$($generic),*>)? ::core::convert::From<$from> for $ty $(<$($generic),*>)? {
|
||||
fn from(from: $from) -> Self {
|
||||
Self(from)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use crate::{deref, deref_mut, from};
|
@ -4,19 +4,14 @@
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
// enable unstable doc_cfg feature only on on docs.rs where nightly compiler is used
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate tls_openssl as openssl;
|
||||
|
||||
#[cfg(feature = "accept")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "accept")))]
|
||||
pub mod accept;
|
||||
|
||||
#[cfg(feature = "connect")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "connect")))]
|
||||
pub mod connect;
|
||||
|
||||
mod impl_more;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![cfg(all(
|
||||
feature = "accept",
|
||||
feature = "connect",
|
||||
feature = "rustls",
|
||||
feature = "rustls-0_21",
|
||||
feature = "openssl"
|
||||
))]
|
||||
|
||||
@ -15,13 +15,12 @@ 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 = rcgen::generate_simple_self_signed(vec![
|
||||
"127.0.0.1".to_owned(),
|
||||
"localhost".to_owned(),
|
||||
])
|
||||
.unwrap();
|
||||
let cert =
|
||||
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
||||
.unwrap();
|
||||
|
||||
let key = cert.serialize_private_key_pem();
|
||||
let cert = cert.serialize_pem().unwrap();
|
||||
@ -51,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},
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![cfg(all(
|
||||
feature = "accept",
|
||||
feature = "connect",
|
||||
feature = "rustls",
|
||||
feature = "rustls-0_21",
|
||||
feature = "openssl"
|
||||
))]
|
||||
|
||||
@ -14,19 +14,20 @@ use std::io::{BufReader, Write};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::TestServer;
|
||||
use actix_service::ServiceFactoryExt as _;
|
||||
use actix_tls::accept::rustls::{Acceptor, TlsStream};
|
||||
use actix_tls::connect::openssl::reexports::SslConnector;
|
||||
use actix_tls::{
|
||||
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 = rcgen::generate_simple_self_signed(vec![
|
||||
"127.0.0.1".to_owned(),
|
||||
"localhost".to_owned(),
|
||||
])
|
||||
.unwrap();
|
||||
let cert =
|
||||
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
||||
.unwrap();
|
||||
|
||||
let key = cert.serialize_private_key_pem();
|
||||
let cert = cert.serialize_pem().unwrap();
|
||||
|
@ -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;
|
||||
@ -143,6 +143,9 @@ async fn test_local_addr() {
|
||||
})
|
||||
});
|
||||
|
||||
// if you've arrived here because of a failing test on macOS run this in your terminal:
|
||||
// sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
let conn = Connector::default().service();
|
||||
let local = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3));
|
||||
|
||||
|
@ -51,8 +51,7 @@ async fn custom_resolver_connect() {
|
||||
|
||||
use trust_dns_resolver::TokioAsyncResolver;
|
||||
|
||||
let srv =
|
||||
TestServer::start(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
|
||||
let srv = TestServer::start(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
|
||||
|
||||
struct MyResolver {
|
||||
trust_dns: TokioAsyncResolver,
|
||||
|
@ -1,8 +1,9 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2020-01-15
|
||||
- Initial release
|
||||
|
@ -9,19 +9,24 @@ repository = "https://github.com/actix/actix-net.git"
|
||||
documentation = "https://docs.rs/actix-tracing"
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "actix_tracing"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"actix_service::*",
|
||||
"actix_utils::*",
|
||||
"tracing::*",
|
||||
"tracing_futures::*",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
tracing = "0.1.35"
|
||||
tracing-futures = "0.2"
|
||||
|
||||
[dev_dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-rt = "2"
|
||||
slab = "0.4"
|
||||
|
@ -118,9 +118,11 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use actix_service::{fn_factory, fn_service};
|
||||
use slab::Slab;
|
||||
|
@ -1,20 +1,25 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
## Unreleased
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 3.0.1
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
## 3.0.0 - 2021-04-16
|
||||
- No significant changes from `3.0.0-beta.4`.
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.4 - 2021-04-01
|
||||
- Add `future::Either` type. [#305]
|
||||
|
||||
[#305]: https://github.com/actix/actix-net/pull/305
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
## 3.0.0-beta.3 - 2021-04-01
|
||||
- Moved `mpsc` to own crate `local-channel`. [#301]
|
||||
- Moved `task::LocalWaker` to own crate `local-waker`. [#301]
|
||||
- Remove `timeout` module. [#301]
|
||||
@ -23,14 +28,14 @@
|
||||
|
||||
[#301]: https://github.com/actix/actix-net/pull/301
|
||||
|
||||
## 3.0.0-beta.2
|
||||
|
||||
## 3.0.0-beta.2 - 2021-02-06
|
||||
- Update `actix-rt` to `2.0.0`. [#273]
|
||||
|
||||
[#273]: https://github.com/actix/actix-net/pull/273
|
||||
|
||||
## 3.0.0-beta.1
|
||||
|
||||
## 3.0.0-beta.1 - 2020-12-28
|
||||
- Update `bytes` dependency to `1`. [#237]
|
||||
- Use `pin-project-lite` to replace `pin-project`. [#229]
|
||||
- Remove `condition`,`either`,`inflight`,`keepalive`,`oneshot`,`order`,`stream` and `time` mods. [#229]
|
||||
@ -38,146 +43,146 @@
|
||||
[#229]: https://github.com/actix/actix-net/pull/229
|
||||
[#237]: https://github.com/actix/actix-net/pull/237
|
||||
|
||||
## 2.0.0
|
||||
|
||||
## 2.0.0 - 2020-08-23
|
||||
- No changes from beta 1.
|
||||
|
||||
## 2.0.0-beta.1
|
||||
|
||||
## 2.0.0-beta.1 - 2020-08-19
|
||||
- Upgrade `tokio-util` to `0.3`.
|
||||
- Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`.
|
||||
- Rename method to correctly spelled `LocalWaker::is_registered`.
|
||||
|
||||
## 1.0.6
|
||||
|
||||
## 1.0.6 - 2020-01-08
|
||||
- Add `Clone` impl for `condition::Waiter`.
|
||||
|
||||
## 1.0.5
|
||||
|
||||
## 1.0.5 - 2020-01-08
|
||||
- Add `Condition` type.
|
||||
- Add `Pool` of one-shot's.
|
||||
|
||||
## 1.0.4
|
||||
|
||||
## 1.0.4 - 2019-12-20
|
||||
- Add methods to check `LocalWaker` registration state.
|
||||
|
||||
## 1.0.3
|
||||
|
||||
## 1.0.3 - 2019-12-11
|
||||
- Revert InOrder service changes
|
||||
|
||||
## 1.0.2
|
||||
|
||||
## 1.0.2 - 2019-12-11
|
||||
- Allow to create `framed::Dispatcher` with custom `mpsc::Receiver`.
|
||||
- Add `oneshot::Sender::is_canceled()` method.
|
||||
|
||||
## 1.0.1
|
||||
|
||||
## 1.0.1 - 2019-12-11
|
||||
- Optimize InOrder service.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
- Simplify oneshot and mpsc implementations.
|
||||
|
||||
## 1.0.0-alpha.3
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
- Migrate to tokio 0.2.
|
||||
- Fix oneshot.
|
||||
|
||||
## 1.0.0-alpha.2
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
- Migrate to `std::future`.
|
||||
|
||||
## 0.4.7
|
||||
|
||||
## 0.4.7 - 2019-10-14
|
||||
- Re-register task on every framed transport poll.
|
||||
|
||||
## 0.4.6
|
||||
|
||||
## 0.4.6 - 2019-10-08
|
||||
- Refactor `Counter` type. register current task in available method.
|
||||
|
||||
## 0.4.5
|
||||
|
||||
## 0.4.5 - 2019-07-19
|
||||
- Deprecated `CloneableService` as it is not safe.
|
||||
|
||||
## 0.4.4
|
||||
|
||||
## 0.4.4 - 2019-07-17
|
||||
- Undeprecate `FramedTransport` as it is actually useful.
|
||||
|
||||
## 0.4.3
|
||||
|
||||
## 0.4.3 - 2019-07-17
|
||||
- Deprecate `CloneableService` as it is not safe and in general not very useful.
|
||||
- Deprecate `FramedTransport` in favor of `actix-ioframe`.
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.2 - 2019-06-26
|
||||
- Do not block on sink drop for FramedTransport.
|
||||
|
||||
## 0.4.1
|
||||
|
||||
## 0.4.1 - 2019-05-15
|
||||
- Change `Either` constructor.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## 0.4.0 - 2019-05-11
|
||||
- Change `Either` to handle two nexted services.
|
||||
- Upgrade actix-service 0.4.
|
||||
- Removed framed related services.
|
||||
- Removed stream related services.
|
||||
|
||||
## 0.3.5
|
||||
|
||||
## 0.3.5 - 2019-04-04
|
||||
- Allow to send messages to `FramedTransport` via mpsc channel.
|
||||
- Remove `'static` constraint from Clonable service.
|
||||
|
||||
## 0.3.4
|
||||
|
||||
## 0.3.4 - 2019-03-12
|
||||
- `TimeoutService`, `InOrderService`, `InFlightService` accepts generic IntoService services.
|
||||
- Fix `InFlightService::poll_ready()` nested service readiness check.
|
||||
- Fix `InOrderService::poll_ready()` nested service readiness check.
|
||||
|
||||
## 0.3.3
|
||||
|
||||
## 0.3.3 - 2019-03-09
|
||||
- Revert IntoFuture change.
|
||||
- Add generic config param for IntoFramed and TakeOne new services.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
## 0.3.2 - 2019-03-04
|
||||
- Use IntoFuture for new services.
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
## 0.3.1
|
||||
|
||||
- Use new type of transform trait.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
- Use new `NewService` trait
|
||||
- BoxedNewService` and `BoxedService` types moved to actix-service crate.
|
||||
- BoxedNewService`and`BoxedService` types moved to actix-service crate.
|
||||
|
||||
## 0.2.4
|
||||
|
||||
## 0.2.4 - 2019-02-21
|
||||
- Custom `BoxedNewService` implementation.
|
||||
|
||||
## 0.2.3
|
||||
|
||||
## 0.2.3 - 2019-02-21
|
||||
- Add `BoxedNewService` and `BoxedService`.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
## 0.2.2 - 2019-02-11
|
||||
- Add `Display` impl for `TimeoutError`.
|
||||
- Add `Display` impl for `InOrderError`.
|
||||
|
||||
## 0.2.1
|
||||
|
||||
## 0.2.1 - 2019-02-06
|
||||
- Add `InOrder` service. the service yields responses as they become available,
|
||||
in the order that their originating requests were submitted to the service.
|
||||
- Add `InOrder` service. the service yields responses as they become available, in the order that their originating requests were submitted to the service.
|
||||
- Convert `Timeout` and `InFlight` services to a transforms.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
- Fix framed transport error handling.
|
||||
- Added Clone impl for Either service.
|
||||
- Added Clone impl for Timeout service factory.
|
||||
- Added Service and NewService for Stream dispatcher.
|
||||
- Switch to actix-service 0.2.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
- Move utils services to separate crate.
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-utils"
|
||||
version = "3.0.0"
|
||||
version = "3.0.1"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@ -10,17 +10,14 @@ keywords = ["network", "framework", "async", "futures"]
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "actix_utils"
|
||||
path = "src/lib.rs"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pin-project-lite = "0.2"
|
||||
local-waker = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
actix-rt = "2"
|
||||
futures-util = { version = "0.3.17", default-features = false }
|
||||
static_assertions = "1.1"
|
||||
|
@ -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 {
|
||||
|
@ -1,9 +1,11 @@
|
||||
//! Asynchronous values.
|
||||
//! Helpers for constructing futures.
|
||||
|
||||
mod either;
|
||||
mod poll_fn;
|
||||
mod ready;
|
||||
|
||||
pub use self::either::Either;
|
||||
pub use self::poll_fn::{poll_fn, PollFn};
|
||||
pub use self::ready::{err, ok, ready, Ready};
|
||||
pub use self::{
|
||||
either::Either,
|
||||
poll_fn::{poll_fn, PollFn},
|
||||
ready::{err, ok, ready, Ready},
|
||||
};
|
||||
|
@ -8,6 +8,31 @@ use core::{
|
||||
};
|
||||
|
||||
/// Creates a future driven by the provided function that receives a task context.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::task::Poll;
|
||||
/// # use actix_utils::future::poll_fn;
|
||||
/// # async fn test_poll_fn() {
|
||||
/// let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
/// assert_eq!(res, 42);
|
||||
///
|
||||
/// let mut i = 5;
|
||||
/// let res = poll_fn(|cx| {
|
||||
/// i -= 1;
|
||||
///
|
||||
/// if i > 0 {
|
||||
/// cx.waker().wake_by_ref();
|
||||
/// Poll::Pending
|
||||
/// } else {
|
||||
/// Poll::Ready(42)
|
||||
/// }
|
||||
/// })
|
||||
/// .await;
|
||||
/// assert_eq!(res, 42);
|
||||
/// # }
|
||||
/// # actix_rt::Runtime::new().unwrap().block_on(test_poll_fn());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn poll_fn<F, T>(f: F) -> PollFn<F>
|
||||
where
|
||||
@ -16,13 +41,11 @@ where
|
||||
PollFn { f }
|
||||
}
|
||||
|
||||
/// A Future driven by the inner function.
|
||||
/// Future for the [`poll_fn`] function.
|
||||
pub struct PollFn<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
impl<F> fmt::Debug for PollFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PollFn").finish()
|
||||
@ -36,15 +59,23 @@ where
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
(self.f)(cx)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::marker::PhantomPinned;
|
||||
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_impl_all!(PollFn<()>: Unpin);
|
||||
static_assertions::assert_not_impl_all!(PollFn<PhantomPinned>: Unpin);
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_poll_fn() {
|
||||
let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
@ -64,4 +95,29 @@ mod tests {
|
||||
.await;
|
||||
assert_eq!(res, 42);
|
||||
}
|
||||
|
||||
// following soundness tests taken from https://github.com/tokio-rs/tokio/pull/5087
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn require_send<T: Send>(_t: &T) {}
|
||||
#[allow(dead_code)]
|
||||
fn require_sync<T: Sync>(_t: &T) {}
|
||||
|
||||
trait AmbiguousIfUnpin<A> {
|
||||
fn some_item(&self) {}
|
||||
}
|
||||
impl<T: ?Sized> AmbiguousIfUnpin<()> for T {}
|
||||
impl<T: ?Sized + Unpin> AmbiguousIfUnpin<[u8; 0]> for T {}
|
||||
|
||||
const _: fn() = || {
|
||||
let pinned = std::marker::PhantomPinned;
|
||||
let f = poll_fn(move |_| {
|
||||
// Use `pinned` to take ownership of it.
|
||||
let _ = &pinned;
|
||||
std::task::Poll::Pending::<()>
|
||||
});
|
||||
require_send(&f);
|
||||
require_sync(&f);
|
||||
AmbiguousIfUnpin::some_item(&f);
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! When MSRV is 1.48, replace with `core::future::Ready` and `core::future::ready()`.
|
||||
//! When `core::future::Ready` has a `into_inner()` method, this can be deprecated.
|
||||
|
||||
use core::{
|
||||
future::Future,
|
||||
@ -6,7 +6,7 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Future for the [`ready`](ready()) function.
|
||||
/// Future for the [`ready`] function.
|
||||
///
|
||||
/// Panic will occur if polled more than once.
|
||||
///
|
||||
|
@ -1,45 +1,65 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
## Unreleased
|
||||
|
||||
## 1.3.1
|
||||
|
||||
- No significant changes since `1.3.0`.
|
||||
|
||||
## 1.3.0
|
||||
|
||||
- Implement `AsRef<ByteString>` for `ByteString`.
|
||||
|
||||
## 1.2.1
|
||||
|
||||
- Fix `#[no_std]` compatibility. [#471]
|
||||
|
||||
[#471]: https://github.com/actix/actix-net/pull/471
|
||||
|
||||
## 1.2.0
|
||||
|
||||
- Add `ByteString::slice_ref` which can safely slice a `ByteString` into a new one with zero copy. [#470]
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
[#470]: https://github.com/actix/actix-net/pull/470
|
||||
|
||||
## 1.1.0
|
||||
|
||||
## 1.1.0 - 2022-06-11
|
||||
- Implement `From<Box<str>>` for `ByteString`. [#458]
|
||||
- Implement `Into<String>` for `ByteString`. [#458]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#458]: https://github.com/actix/actix-net/pull/458
|
||||
|
||||
## 1.0.0
|
||||
|
||||
## 1.0.0 - 2020-12-31
|
||||
- Update `bytes` dependency to `1`.
|
||||
- Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
||||
- Rename `get_ref` to `as_bytes` and rename `into_inner` to `into_bytes`.
|
||||
- `ByteString::new` is now a `const fn`.
|
||||
- Crate is now `#[no_std]` compatible.
|
||||
|
||||
## 0.1.5
|
||||
|
||||
## 0.1.5 - 2020-03-30
|
||||
- Serde support
|
||||
|
||||
## 0.1.4
|
||||
|
||||
## 0.1.4 - 2020-01-14
|
||||
- Fix `AsRef<str>` impl
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2020-01-13
|
||||
- Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2019-12-22
|
||||
- Fix `new()` method
|
||||
- Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2019-12-07
|
||||
- Fix hash impl
|
||||
|
||||
## 0.1.0
|
||||
|
||||
## 0.1.0 - 2019-12-07
|
||||
- Initial release
|
||||
|
@ -1,28 +1,30 @@
|
||||
[package]
|
||||
name = "bytestring"
|
||||
version = "1.1.0"
|
||||
version = "1.3.1"
|
||||
description = "A UTF-8 encoded read-only string using `Bytes` as storage"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
]
|
||||
description = "An immutable UTF-8 encoded string using Bytes as storage"
|
||||
keywords = ["string", "bytes", "utf8", "web", "actix"]
|
||||
categories = ["no-std", "web-programming"]
|
||||
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"
|
||||
edition = "2018"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "bytestring"
|
||||
path = "src/lib.rs"
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"bytes::*",
|
||||
"serde::*",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.2"
|
||||
bytes = { version = "1.2", default-features = false }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
ahash = { version = "0.7.6", default-features = false }
|
||||
ahash = { version = "0.8", default-features = false }
|
||||
serde_json = "1.0"
|
||||
static_assertions = "1.1"
|
||||
rustversion = "1"
|
||||
|
16
bytestring/README.md
Normal file
16
bytestring/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# `bytestring`
|
||||
|
||||
> A UTF-8 encoded read-only string using `Bytes` as storage.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[![crates.io](https://img.shields.io/crates/v/bytestring?label=latest)](https://crates.io/crates/bytestring)
|
||||
[![Documentation](https://docs.rs/bytestring/badge.svg?version=1.3.1)](https://docs.rs/bytestring/1.3.1)
|
||||
[![Version](https://img.shields.io/badge/rustc-1.52+-ab6000.svg)](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/bytestring.svg)
|
||||
<br />
|
||||
[![Dependency Status](https://deps.rs/crate/bytestring/1.3.1/status.svg)](https://deps.rs/crate/bytestring/1.3.1)
|
||||
![Download](https://img.shields.io/crates/d/bytestring.svg)
|
||||
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
@ -1,4 +1,6 @@
|
||||
//! A UTF-8 encoded read-only string using Bytes as storage.
|
||||
//! A UTF-8 encoded read-only string using `Bytes` as storage.
|
||||
//!
|
||||
//! See docs for [`ByteString`].
|
||||
|
||||
#![no_std]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
@ -11,7 +13,7 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
use core::{borrow::Borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
@ -50,6 +52,44 @@ impl ByteString {
|
||||
pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
|
||||
Self(src)
|
||||
}
|
||||
|
||||
/// Returns a new byte string that is equivalent to the given `subset`.
|
||||
///
|
||||
/// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
|
||||
/// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
|
||||
/// `&str` into another `ByteString`, as if one had sliced the `ByteString` with the offsets
|
||||
/// that correspond to `subset`.
|
||||
///
|
||||
/// Corresponds to [`Bytes::slice_ref`].
|
||||
///
|
||||
/// This operation is `O(1)`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `subset` is not a sub-slice of this byte string.
|
||||
///
|
||||
/// Note that strings which are only subsets from an equality perspective do not uphold this
|
||||
/// requirement; see examples.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bytestring::ByteString;
|
||||
/// let string = ByteString::from_static(" foo ");
|
||||
/// let subset = string.trim();
|
||||
/// let substring = string.slice_ref(subset);
|
||||
/// assert_eq!(substring, "foo");
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use bytestring::ByteString;
|
||||
/// // panics because the given slice is not derived from the original byte string, despite
|
||||
/// // being a logical subset of the string
|
||||
/// ByteString::from_static("foo bar").slice_ref("foo");
|
||||
/// ```
|
||||
pub fn slice_ref(&self, subset: &str) -> Self {
|
||||
Self(self.0.slice_ref(subset.as_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for ByteString {
|
||||
@ -64,6 +104,12 @@ impl<T: AsRef<str>> PartialEq<T> for ByteString {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<ByteString> for ByteString {
|
||||
fn as_ref(&self) -> &ByteString {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for ByteString {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
@ -88,13 +134,12 @@ impl ops::Deref for ByteString {
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
let bytes = self.0.as_ref();
|
||||
// SAFETY:
|
||||
// UTF-8 validity is guaranteed at during construction.
|
||||
// SAFETY: UTF-8 validity is guaranteed during construction.
|
||||
unsafe { str::from_utf8_unchecked(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
impl borrow::Borrow<str> for ByteString {
|
||||
impl Borrow<str> for ByteString {
|
||||
fn borrow(&self) -> &str {
|
||||
self
|
||||
}
|
||||
@ -210,8 +255,10 @@ impl fmt::Display for ByteString {
|
||||
mod serde {
|
||||
use alloc::string::String;
|
||||
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde::{
|
||||
de::{Deserialize, Deserializer},
|
||||
ser::{Serialize, Serializer},
|
||||
};
|
||||
|
||||
use super::ByteString;
|
||||
|
||||
@ -248,8 +295,11 @@ mod serde {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use alloc::borrow::ToOwned;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use alloc::{borrow::ToOwned, format, vec};
|
||||
use core::{
|
||||
hash::{Hash, Hasher},
|
||||
panic::{RefUnwindSafe, UnwindSafe},
|
||||
};
|
||||
|
||||
use ahash::AHasher;
|
||||
use static_assertions::assert_impl_all;
|
||||
@ -259,19 +309,10 @@ mod test {
|
||||
assert_impl_all!(ByteString: Send, Sync, Unpin, Sized);
|
||||
assert_impl_all!(ByteString: Clone, Default, Eq, PartialOrd, Ord);
|
||||
assert_impl_all!(ByteString: fmt::Debug, fmt::Display);
|
||||
|
||||
#[rustversion::since(1.56)]
|
||||
mod above_1_56_impls {
|
||||
// `[Ref]UnwindSafe` traits were only in std until rust 1.56
|
||||
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
|
||||
use super::*;
|
||||
assert_impl_all!(ByteString: UnwindSafe, RefUnwindSafe);
|
||||
}
|
||||
assert_impl_all!(ByteString: UnwindSafe, RefUnwindSafe);
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq() {
|
||||
fn eq() {
|
||||
let s: ByteString = ByteString::from_static("test");
|
||||
assert_eq!(s, "test");
|
||||
assert_eq!(s, *"test");
|
||||
@ -279,12 +320,45 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
fn new() {
|
||||
let _: ByteString = ByteString::new();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
fn as_bytes() {
|
||||
let buf = ByteString::new();
|
||||
assert!(buf.as_bytes().is_empty());
|
||||
|
||||
let buf = ByteString::from("hello");
|
||||
assert_eq!(buf.as_bytes(), "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_bytes_unchecked() {
|
||||
let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::new()) };
|
||||
assert!(buf.is_empty());
|
||||
|
||||
let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::from("hello")) };
|
||||
assert_eq!(buf, "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_ref() {
|
||||
let buf = ByteString::new();
|
||||
|
||||
let _: &ByteString = buf.as_ref();
|
||||
let _: &[u8] = buf.as_ref();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn borrow() {
|
||||
let buf = ByteString::new();
|
||||
|
||||
let _: &str = buf.borrow();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash() {
|
||||
let mut hasher1 = AHasher::default();
|
||||
"str".hash(&mut hasher1);
|
||||
|
||||
@ -295,7 +369,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_string() {
|
||||
fn from_string() {
|
||||
let s: ByteString = "hello".to_owned().into();
|
||||
assert_eq!(&s, "hello");
|
||||
let t: &str = s.as_ref();
|
||||
@ -303,23 +377,30 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
fn from_str() {
|
||||
let _: ByteString = "str".into();
|
||||
let _: ByteString = "str".to_owned().into_boxed_str().into();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_static_str() {
|
||||
fn to_string() {
|
||||
let buf = ByteString::from("foo");
|
||||
assert_eq!(String::from(buf), "foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_static_str() {
|
||||
static _S: ByteString = ByteString::from_static("hello");
|
||||
let _ = ByteString::from_static("str");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_slice() {
|
||||
fn try_from_slice() {
|
||||
let _ = ByteString::try_from(b"nice bytes").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_array() {
|
||||
fn try_from_array() {
|
||||
assert_eq!(
|
||||
ByteString::try_from([b'h', b'i']).unwrap(),
|
||||
ByteString::from_static("hi")
|
||||
@ -327,26 +408,61 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytes() {
|
||||
fn try_from_vec() {
|
||||
let _ = ByteString::try_from(vec![b'f', b'o', b'o']).unwrap();
|
||||
ByteString::try_from(vec![0, 159, 146, 150]).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_bytes() {
|
||||
let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_bytes_mut() {
|
||||
fn try_from_bytes_mut() {
|
||||
let _ = ByteString::try_from(bytes::BytesMut::from(&b"nice bytes"[..])).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display() {
|
||||
let buf = ByteString::from("bar");
|
||||
assert_eq!(format!("{buf}"), "bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug() {
|
||||
let buf = ByteString::from("baz");
|
||||
assert_eq!(format!("{buf:?}"), r#""baz""#);
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
fn serialize() {
|
||||
let s: ByteString = serde_json::from_str(r#""nice bytes""#).unwrap();
|
||||
assert_eq!(s, "nice bytes");
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
fn deserialize() {
|
||||
let s = serde_json::to_string(&ByteString::from_static("nice bytes")).unwrap();
|
||||
assert_eq!(s, r#""nice bytes""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice_ref() {
|
||||
let string = ByteString::from_static(" foo ");
|
||||
let subset = string.trim();
|
||||
// subset is derived from original byte string
|
||||
let substring = string.slice_ref(subset);
|
||||
assert_eq!(substring, "foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn slice_ref_catches_not_a_subset() {
|
||||
// panics because the given slice is not derived from the original byte string, despite
|
||||
// being a logical subset of the string
|
||||
ByteString::from_static("foo bar").slice_ref("foo");
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
msrv = "1.57"
|
37
justfile
Normal file
37
justfile
Normal file
@ -0,0 +1,37 @@
|
||||
_list:
|
||||
@just --list
|
||||
|
||||
# Document crates in workspace.
|
||||
doc:
|
||||
RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl
|
||||
|
||||
# Document crates in workspace and watch for changes.
|
||||
doc-watch:
|
||||
RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open
|
||||
cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,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}}
|
@ -1,16 +1,23 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
## 0.1.5
|
||||
|
||||
- No significant changes since `0.1.4`.
|
||||
|
||||
## 0.1.4
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2022-05-03
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2021-04-01
|
||||
- No significant changes from `0.1.1`.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2021-03-29
|
||||
- Move local mpsc channel to it's own crate.
|
||||
- Move local MPSC channel to it's own crate.
|
||||
|
@ -1,21 +1,28 @@
|
||||
[package]
|
||||
name = "local-channel"
|
||||
version = "0.1.3"
|
||||
version = "0.1.5"
|
||||
description = "A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
]
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
keywords = ["channel", "local", "futures"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"futures_core::*",
|
||||
"futures_sink::*",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
futures-core = { version = "0.3.7", default-features = false }
|
||||
futures-sink = { version = "0.3.7", default-features = false }
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
futures-core = "0.3.17"
|
||||
futures-sink = "0.3.17"
|
||||
local-waker = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.13.1", features = ["rt", "macros"] }
|
||||
futures-util = { version = "0.3.17", default-features = false }
|
||||
tokio = { version = "1.23.1", features = ["rt", "macros"] }
|
||||
|
16
local-channel/README.md
Normal file
16
local-channel/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# `local-channel`
|
||||
|
||||
> A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[![crates.io](https://img.shields.io/crates/v/local-channel?label=latest)](https://crates.io/crates/local-channel)
|
||||
[![Documentation](https://docs.rs/local-channel/badge.svg?version=0.1.5)](https://docs.rs/local-channel/0.1.5)
|
||||
[![Version](https://img.shields.io/badge/rustc-1.52+-ab6000.svg)](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/local-channel.svg)
|
||||
<br />
|
||||
[![Dependency Status](https://deps.rs/crate/local-channel/0.1.5/status.svg)](https://deps.rs/crate/local-channel/0.1.5)
|
||||
![Download](https://img.shields.io/crates/d/local-channel.svg)
|
||||
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
@ -1,4 +1,6 @@
|
||||
//! Non-thread-safe channels.
|
||||
//!
|
||||
//! See docs for [`mpsc::channel()`].
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
|
@ -4,6 +4,7 @@ use alloc::{collections::VecDeque, rc::Rc};
|
||||
use core::{
|
||||
cell::RefCell,
|
||||
fmt,
|
||||
future::poll_fn,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
@ -11,7 +12,6 @@ use std::error::Error;
|
||||
|
||||
use futures_core::stream::Stream;
|
||||
use futures_sink::Sink;
|
||||
use futures_util::future::poll_fn;
|
||||
use local_waker::LocalWaker;
|
||||
|
||||
/// Creates a unbounded in-memory channel with buffered storage.
|
||||
|
@ -1,16 +1,19 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
## Unreleased
|
||||
|
||||
## 0.1.4
|
||||
|
||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## 0.1.3 - 2022-05-03
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
## 0.1.2
|
||||
|
||||
## 0.1.2 - 2021-12-18
|
||||
- Fix crate metadata.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
## 0.1.1 - 2021-03-29
|
||||
- Move `LocalWaker` to it's own crate.
|
||||
|
@ -1,15 +1,16 @@
|
||||
[package]
|
||||
name = "local-waker"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
description = "A synchronization primitive for thread-local task wakeup"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
]
|
||||
repository = "https://github.com/actix/actix-net"
|
||||
keywords = ["waker", "local", "futures", "no-std"]
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
categories = ["asynchronous", "no-std"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
16
local-waker/README.md
Normal file
16
local-waker/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# `local-waker`
|
||||
|
||||
> A synchronization primitive for thread-local task wakeup.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[![crates.io](https://img.shields.io/crates/v/local-waker?label=latest)](https://crates.io/crates/local-waker)
|
||||
[![Documentation](https://docs.rs/local-waker/badge.svg?version=0.1.4)](https://docs.rs/local-waker/0.1.4)
|
||||
[![Version](https://img.shields.io/badge/rustc-1.52+-ab6000.svg)](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/local-waker.svg)
|
||||
<br />
|
||||
[![Dependency Status](https://deps.rs/crate/local-waker/0.1.4/status.svg)](https://deps.rs/crate/local-waker/0.1.4)
|
||||
![Download](https://img.shields.io/crates/d/local-waker.svg)
|
||||
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
@ -1,2 +0,0 @@
|
||||
max_width = 96
|
||||
group_imports = "StdExternalCrate"
|
53
scripts/free-disk-space.sh
Executable file
53
scripts/free-disk-space.sh
Executable 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
|
Loading…
Reference in New Issue
Block a user