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

Compare commits

..

220 Commits

Author SHA1 Message Date
Rob Ede
97e8c571cf chore(actix-server): prepare release 2.5.0
closes #586
2024-08-04 22:41:04 +01:00
Rob Ede
0d8c7e5085 build: add nix flake 2024-08-04 22:39:19 +01:00
Rob Ede
baf1b6042a docs(server): update changelog 2024-08-04 22:34:17 +01:00
dependabot[bot]
779fa28bd5 build(deps): bump taiki-e/install-action from 2.42.4 to 2.42.10 (#587)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.42.4 to 2.42.10.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.42.4...v2.42.10)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 19:40:21 +00:00
dependabot[bot]
e282811d69 build(deps): update rustversion-msrv requirement from 0.99 to 0.100 (#584)
---
updated-dependencies:
- dependency-name: rustversion-msrv
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 19:27:49 +00:00
dependabot[bot]
5c44115978 build(deps): bump taiki-e/install-action from 2.42.0 to 2.42.4 (#585)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.42.0 to 2.42.4.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.42.0...v2.42.4)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 18:56:19 +00:00
Rob Ede
ead0e2b200 chore: fix nightly warnings 2024-07-20 18:57:00 +01:00
Rob Ede
ace737fc4c chore: overspecified deps 2024-07-20 18:00:39 +01:00
dependabot[bot]
c45ae294fb build(deps): bump taiki-e/install-action from 2.41.11 to 2.42.0 (#583)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.41.11 to 2.42.0.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.41.11...v2.42.0)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 02:14:15 +00:00
dependabot[bot]
939377f6ab build(deps): bump taiki-e/install-action from 2.41.7 to 2.41.11 (#582)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.41.7 to 2.41.11.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.41.7...v2.41.11)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-08 21:40:27 +00:00
dependabot[bot]
20149f957b build(deps): bump JamesIves/github-pages-deploy-action (#581)
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.6.1 to 4.6.3.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.6.1...v4.6.3)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-08 21:40:25 +00:00
dependabot[bot]
544e5d3b40 build(deps): bump taiki-e/install-action from 2.41.3 to 2.41.7 (#579)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.41.3 to 2.41.7.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.41.3...v2.41.7)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 01:08:35 +00:00
dependabot[bot]
d482af529c build(deps): bump taiki-e/install-action from 2.39.1 to 2.41.3 (#578)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.39.1 to 2.41.3.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.39.1...v2.41.3)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 16:32:28 +00:00
Rob Ede
0030800b9a chore: update mio dependency to v1 (#577) 2024-06-20 01:22:33 +01:00
dependabot[bot]
64fa2f8462 build(deps): bump taiki-e/install-action from 2.38.1 to 2.39.1 (#574)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.38.1 to 2.39.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.38.1...v2.39.1)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-17 20:52:59 +00:00
dependabot[bot]
b0d1c8d193 build(deps): bump codecov/codecov-action from 4.4.1 to 4.5.0 (#575)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.4.1 to 4.5.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.4.1...v4.5.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-17 20:52:48 +00:00
Jiri Andras
46cc62c6d8 Fix logging "starting service:..." (#573)
Co-authored-by: Jiří Andras <jiri.andras@braiins.cz>
2024-06-14 17:11:32 +00:00
dependabot[bot]
912daa3d0a build(deps): bump taiki-e/cache-cargo-install-action from 2.0.0 to 2.0.1 (#570)
Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/taiki-e/cache-cargo-install-action/releases)
- [Changelog](https://github.com/taiki-e/cache-cargo-install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/cache-cargo-install-action/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: taiki-e/cache-cargo-install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 19:36:41 +00:00
dependabot[bot]
aefa810496 build(deps): bump actions-rust-lang/setup-rust-toolchain (#571)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases)
- [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: actions-rust-lang/setup-rust-toolchain
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 19:36:09 +00:00
dependabot[bot]
2c443a7620 build(deps): bump taiki-e/install-action from 2.34.1 to 2.38.1 (#572)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.34.1 to 2.38.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.34.1...v2.38.1)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 19:35:52 +00:00
Rob Ede
b3b1583115 docs: update changelog 2024-06-09 18:08:53 +01:00
Rob Ede
0d3d1926bc fix: relax bounds on with_tokio_rt (#569) 2024-06-09 07:12:24 +01:00
Rob Ede
0c26ecf9fa chore(actix-server): prepare release 2.4.0 2024-06-09 06:12:28 +01:00
Rob Ede
1bdb15ec20 chore(actix-rt): prepare release 2.10.0 2024-06-09 06:12:07 +01:00
dependabot[bot]
a524f15e34 build(deps): update tokio-uring requirement from 0.4 to 0.5 (#568)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-06-07 18:51:27 +01:00
dependabot[bot]
451a44c2e0 build(deps): bump taiki-e/install-action from 2.33.34 to 2.34.1 (#567)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.34 to 2.34.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.33.34...v2.34.1)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 18:25:40 +00:00
Rob Ede
18071d1fc0 ci: disable io-uring tests 2024-05-27 22:57:35 +01:00
dependabot[bot]
786014cc2f build(deps): bump taiki-e/install-action from 2.33.26 to 2.33.34 (#566)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.26 to 2.33.34.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.33.26...v2.33.34)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 21:24:55 +00:00
Rob Ede
a7ef438f25 ci: use mold linker on linux jobs 2024-05-27 22:25:35 +01:00
dependabot[bot]
375c352810 --- (#565)
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 19:11:09 +00:00
dependabot[bot]
2d1b5468d0 --- (#563)
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 19:08:43 +00:00
dependabot[bot]
3696cda155 --- (#562)
updated-dependencies:
- dependency-name: itertools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 19:06:51 +00:00
dependabot[bot]
55e89d1f30 --- (#564)
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 19:05:28 +00:00
Rob Ede
24be36b18d chore: prepare actix-tls release v3.4.0 2024-05-18 18:14:26 +01:00
Rob Ede
38ae762569 ci: fix msrv just variable 2024-05-18 17:34:18 +01:00
dependabot[bot]
8cf79d3d13 build(deps): bump taiki-e/install-action from 2.33.17 to 2.33.22 (#561)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.17 to 2.33.22.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.33.17...v2.33.22)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 20:43:50 +00:00
asonix
73451070db actix-tls: Disable default features for rustls 0.23 via tokio-rustls 0.26 (#560)
* actix-tls: Disable default features for rustls 0.23 via tokio-rustls 0.26

This also fixes a panic in accept-rustls due to both ring and aws-lc-rs
being enabled for that example

* Switch a test from aws-lc-rs to ring since aws-lc-rs is no longer enabled in dev-dependencies

* Switch another test from aws-lc-rs to ring since aws-lc-rs is no longer enabled in dev-dependencies

* Go the other way - use aws_lc_rs instead of ring

---------

Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-05-12 21:09:59 +00:00
Rob Ede
2632c984cc ci: fix nightly windows builds 2024-05-12 21:53:26 +01:00
Rob Ede
af8e6cd656 ci: read MSRV from manifest (#559) 2024-05-12 21:35:39 +01:00
SleeplessOne1917
db7988609e feat(actix-tls): support for rustls 0.23 (#554)
* Add feature for using rustls 0.23

* Fix mistake

* Fix use of wrong tokio rustls package

* Fix accept openssl test

* Use rustls 0.23 for the example

* Install nasm in CI step for windows

* Change outdated step name

* Fix CI mistake

* test: install default crypto provider in tests

* docs: update changelog

---------

Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-05-12 18:47:49 +00:00
Rob Ede
1db640f62e chore: update env logger 2024-05-12 19:10:27 +01:00
Rob Ede
9e7d612121 ci: remove 32-bit windows support 2024-05-12 18:25:02 +01:00
Rob Ede
5edbf9e3dc chore: switch to rustversion-msrv 2024-05-12 18:24:37 +01:00
Rob Ede
f028a74240 build: fix rustversion spec 2024-05-11 17:41:31 +01:00
Rob Ede
f4139a0878 chore: update MSRV to 1.70 2024-05-11 17:39:34 +01:00
Rob Ede
3147dbe7ca ci: rely more on just recipes (#558) 2024-05-11 15:10:56 +01:00
dependabot[bot]
95ca8f0318 build(deps): bump taiki-e/install-action from 2.33.12 to 2.33.17 (#555)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.12 to 2.33.17.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.33.12...v2.33.17)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 21:02:51 +00:00
dependabot[bot]
f947374a73 build(deps): bump codecov/codecov-action from 4.3.0 to 4.3.1 (#556)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.3.0...v4.3.1)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 21:02:32 +00:00
dependabot[bot]
85191934c8 build(deps): bump codecov/codecov-action from 4.1.0 to 4.3.0 (#548)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.0 to 4.3.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.1.0...v4.3.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 03:24:47 +01:00
dependabot[bot]
234a4c9c7f build(deps): bump JamesIves/github-pages-deploy-action (#549)
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.5.0...v4.6.0)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 02:20:46 +01:00
dependabot[bot]
d5171c2ab3 build(deps): bump taiki-e/cache-cargo-install-action from 1.3.0 to 2.0.0 (#551)
Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 1.3.0 to 2.0.0.
- [Release notes](https://github.com/taiki-e/cache-cargo-install-action/releases)
- [Changelog](https://github.com/taiki-e/cache-cargo-install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/cache-cargo-install-action/compare/v1.3.0...v2.0.0)

---
updated-dependencies:
- dependency-name: taiki-e/cache-cargo-install-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 02:20:35 +01:00
dependabot[bot]
875218488c build(deps): bump taiki-e/install-action from 2.28.1 to 2.33.12 (#553)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.28.1 to 2.33.12.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.28.1...v2.33.12)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 02:20:21 +01:00
Rob Ede
b826bf8471 ci: relax ahash msrv pin 2024-05-02 01:48:55 +01:00
Rob Ede
10bd847177 ci: fix msrv checks 2024-05-02 01:30:28 +01:00
dependabot[bot]
481cf55414 build(deps): bump codecov/codecov-action from 4.0.2 to 4.1.0 (#538)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.2 to 4.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.0.2...v4.1.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 17:51:42 +00:00
dependabot[bot]
b4990023c4 build(deps): bump taiki-e/install-action from 2.27.11 to 2.28.1 (#537)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.27.11 to 2.28.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.27.11...v2.28.1)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 17:49:17 +00:00
dependabot[bot]
eb5cec0064 build(deps): bump codecov/codecov-action from 4.0.1 to 4.0.2 (#535)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 18:06:10 +00:00
dependabot[bot]
db925bf8e6 build(deps): bump taiki-e/install-action from 2.26.13 to 2.27.11 (#536)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 18:05:48 +00:00
Rob Ede
850f6c0491 chore: allow unused trait in test 2024-02-19 12:32:06 +00:00
Rob Ede
0f71fd5a7a chore: remove redundant imports 2024-02-19 12:19:08 +00:00
Rob Ede
40b10847df chore: remove redundant imports 2024-02-19 12:10:47 +00:00
Rob Ede
39bab04800 chore: remove redundant imports 2024-02-19 11:36:15 +00:00
Rob Ede
3cb247874e ci: workaround ahash msrv 2024-02-19 11:31:41 +00:00
Rob Ede
5792d9f010 docs: fix repo links 2024-02-19 11:29:37 +00:00
dependabot[bot]
bd8bd1020b build(deps): bump taiki-e/install-action from 2.26.7 to 2.26.13 (#531)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 21:10:17 +00:00
dependabot[bot]
21be7d84bd build(deps): bump codecov/codecov-action from 3.1.6 to 4.0.1 (#532)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-02-05 21:10:06 +00:00
Rob Ede
57fd6ea809 chore(actix-tls): prepare release 3.3.0 (#530) 2024-02-03 20:26:15 +00:00
Rob Ede
9a3f3eef6a test(tls): fix accept-openssl test 2024-02-03 17:01:47 +00:00
Rob Ede
e427911cdb feat(tls): rustls-0_22 create feature 2024-02-03 16:39:21 +00:00
Rob Ede
a1ae524512 docs: clean changelog 2024-02-01 06:42:41 +00:00
dependabot[bot]
88833355e4 build(deps): bump taiki-e/install-action from 2.25.2 to 2.26.7 (#527)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 22:41:04 +00:00
dependabot[bot]
7737ba5cfb build(deps): bump codecov/codecov-action from 3.1.4 to 3.1.6 (#529)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 22:40:17 +00:00
Rob Ede
fd32a0a97a ci: workaround half crate msrv 2024-01-30 21:51:12 +00:00
Rob Ede
07e7f82345 chore(actix-codec): prepare release 0.5.2 2024-01-30 21:16:42 +00:00
Rob Ede
1a5d85ec8b fix(tls): resolve http imports 2024-01-17 04:29:44 +00:00
Rob Ede
bd1467e928 chore(tls): changelog wording 2024-01-17 04:27:52 +00:00
Rob Ede
968ad3b854 chore(actix-tls): prepare release 3.2.0 2024-01-17 04:26:46 +00:00
Rob Ede
079f0f66f0 chore(tls): clippy 2024-01-17 04:23:48 +00:00
dependabot[bot]
d85903b31a build(deps): bump taiki-e/install-action from 2.24.1 to 2.25.2 (#521)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.24.1 to 2.25.2.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.24.1...v2.25.2)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 18:28:26 +00:00
dependabot[bot]
a0675fb0dd build(deps): bump actions-rust-lang/setup-rust-toolchain (#520)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 18:47:31 +00:00
dependabot[bot]
af9ccd17d9 build(deps): bump taiki-e/install-action from 2.22.0 to 2.24.1 (#518)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.22.0 to 2.24.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.22.0...v2.24.1)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-08 19:05:18 +00:00
Rob Ede
eb977e9aeb ci: combine install steps 2023-12-26 04:03:49 +00:00
Rob Ede
d28c7db3b3 ci: use cargo-ci-clean-cache 2023-12-26 03:58:34 +00:00
Rob Ede
c5b2d0cd36 chore(tls): fix feature flagging of DEFAULT_TLS_HANDSHAKE_TIMEOUT 2023-12-16 00:43:02 +00:00
Rob Ede
02ac0bb4f7 feat(tls): add accept::rustls_0_22 module 2023-12-16 00:23:11 +00:00
dependabot[bot]
86b000fe71 build(deps): bump taiki-e/install-action from 2.21.26 to 2.22.0 (#514)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.26 to 2.22.0.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.26...v2.22.0)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-11 21:10:42 +00:00
Rob Ede
951e46186b feat: add rustls v0.22 support (#513) 2023-12-06 04:04:39 +00:00
Rob Ede
9edc0b393a feat(tls): add crate feature for rustls native root certs (#506) 2023-12-06 01:39:13 +00:00
morenol
1945fa0675 feat: added suport to http crate 1.0 (#508)
* chore: use same feature

* test: add test for new http version added

* stylistic review

---------

Co-authored-by: Luis Moreno <morenol@users.noreply.github.com>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2023-12-06 00:18:17 +00:00
dependabot[bot]
923a443950 Bump taiki-e/install-action from 2.21.20 to 2.21.26 (#512)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.20 to 2.21.26.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.20...v2.21.26)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 19:15:55 +00:00
dependabot[bot]
b526197a9a Bump JamesIves/github-pages-deploy-action from 4.4.3 to 4.5.0 (#511)
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.4.3 to 4.5.0.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.4.3...v4.5.0)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 19:15:52 +00:00
dependabot[bot]
8fc2253c61 Bump actions-rust-lang/setup-rust-toolchain from 1.5.0 to 1.6.0 (#510)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases)
- [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: actions-rust-lang/setup-rust-toolchain
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 19:15:50 +00:00
dependabot[bot]
4c12b81492 Bump taiki-e/install-action from 2.21.17 to 2.21.20 (#507)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.17 to 2.21.20.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.17...v2.21.20)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-27 20:16:33 +00:00
dependabot[bot]
ef716a8488 Bump taiki-e/install-action from 2.21.11 to 2.21.17 (#505)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.11 to 2.21.17.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.11...v2.21.17)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-20 19:13:51 +00:00
Rob Ede
2a4df30c63 chore(rt): remove hyper example 2023-11-20 18:37:11 +00:00
dependabot[bot]
2d9b147cc3 Bump taiki-e/install-action from 2.21.7 to 2.21.11 (#502)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.7 to 2.21.11.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.7...v2.21.11)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 19:29:01 +00:00
Rob Ede
5515a37002 ci: run on merge groups 2023-11-06 23:53:36 +00:00
Rob Ede
4067fbe8f0 chore: fix check-external-types for rt 2023-11-06 22:19:59 +00:00
dependabot[bot]
01f9910e7c Bump taiki-e/install-action from 2.21.3 to 2.21.7 (#501)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.3 to 2.21.7.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.21.3...v2.21.7)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 22:19:09 +00:00
Rob Ede
df12c10a3f fix check external types 2023-11-06 22:13:45 +00:00
dependabot[bot]
f632ef2ba8 Bump taiki-e/cache-cargo-install-action from 1.2.2 to 1.3.0 (#499)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 19:50:39 +00:00
dependabot[bot]
19d03f0454 Bump taiki-e/install-action from 2.20.2 to 2.21.3 (#500)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 19:03:12 +00:00
Rob Ede
e9c2a0c318 ci: fix check-external-types recipe 2023-10-30 00:26:39 +00:00
Rob Ede
f967562ac4 chore: specify external types for each crate (#496) 2023-10-30 00:07:28 +00:00
Rob Ede
61b6e01b02 chore(bytestring): prepare release 1.3.1 2023-10-29 23:17:28 +00:00
Rob Ede
392e591820 chore(local-channel): prepare release 0.1.5 2023-10-29 23:16:53 +00:00
Rob Ede
87440e5734 chore(local-channel): prepare release 0.1.5 2023-10-29 23:15:19 +00:00
Rob Ede
665dec456f chore(local-waker): prepare release 0.1.4 2023-10-29 23:14:14 +00:00
Rob Ede
7d138f0c31 build: fix min version compat (#498) 2023-10-29 21:15:40 +00:00
Rob Ede
3cd5d8b07a doc: complete ServerBuilder::workers docs 2023-10-29 18:47:38 +00:00
Rob Ede
09548c96b0 doc: fix doc references 2023-10-29 18:45:12 +00:00
Rob Ede
17fd135349 docs: improve docs on ServerBuilder::{bind, workers} 2023-10-29 18:37:29 +00:00
dependabot[bot]
b9b628c47b Update criterion requirement from 0.4 to 0.5 (#495)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-29 05:08:55 +00:00
dependabot[bot]
580af3dec4 Bump actions/checkout from 3 to 4 (#494)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-29 04:17:06 +00:00
dependabot[bot]
db54639f0f Bump taiki-e/install-action from 2.18.9 to 2.21.2 (#497)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-29 03:30:20 +00:00
Rob Ede
6d9eb7e162 ci: specify full action versions 2023-10-29 01:55:34 +00:00
Rob Ede
69e50b5e66 add dependabot updater for actions and cargo 2023-10-29 01:35:12 +00:00
Rob Ede
17409cd203 docs: add bytestring readme 2023-09-17 20:33:36 +01:00
Rob Ede
4a7f2c95af chore: remove dates from changelogs 2023-09-17 20:25:58 +01:00
Rob Ede
c69b8e9ade ci: move coverage to own workflow 2023-09-17 20:11:05 +01:00
Rob Ede
9f59093adc chore(local-channel): prepare release 0.1.4 2023-09-17 19:32:01 +01:00
Paolo Barbolini
bfeb4cd9e7 local-channel: drop futures-util by using future::poll_fn from std (#490) 2023-09-17 11:45:55 +00:00
Rob Ede
14272a1762 chore: force secure rustls-webpki 2023-08-29 18:45:11 +01:00
Rob Ede
7e043048a0 chore(actix-tls): prepare release 3.1.1 2023-08-29 18:41:48 +01:00
Rob Ede
45a7dcba90 chore(tls): fix min rustls version 2023-08-29 18:40:55 +01:00
Rob Ede
5029beb866 prepare actix-tls release 3.1.0 2023-08-26 18:05:39 +01:00
Rob Ede
910c181251 prepare actix-server release 2.3.0 2023-08-26 18:04:22 +01:00
Rob Ede
150d2c05d3 prepare actix-rt release 2.9.0 2023-08-26 18:02:48 +01:00
Alik Aslanyan
3b5716c23e Add getter methods for actix_rt::Runtime and tokio::runtime::Runtime (#484)
Co-authored-by: Alik Aslanyan <inline0@pm.me>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2023-08-26 15:04:08 +00:00
Rob Ede
0bc310a656 Rustls v0.21 support (#480) 2023-08-26 14:59:51 +01:00
Rob Ede
6ce8307060 remove num_cpus dependency (#488) 2023-08-24 00:56:31 +01:00
Rob Ede
9cb8a1fadc remove lint exception 2023-07-24 03:27:44 +01:00
Rob Ede
9017de439f ci: fix post-merge tool installs 2023-07-20 00:22:55 +01:00
Rob Ede
3eba5b152e prepare actix-macros release 0.2.4 2023-07-19 23:52:56 +01:00
Rob Ede
3c4b0c2755 ci: rename post-merge workflow 2023-07-19 23:49:31 +01:00
Rob Ede
462ab6a4f0 ci: try to fix master jobs on windows 2023-07-18 02:06:01 +01:00
Rob Ede
e539f83615 attempt windows CI fix 2023-07-18 01:47:37 +01:00
Martin André
755b231e00 add MPTCP socket protocol (optional) (#466)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2023-07-17 04:10:36 +01:00
Rob Ede
8d5d1dbf6f bump MSRV to 1.65 (#485) 2023-07-17 03:05:39 +01:00
Rob Ede
177590a7d8 increase bytestring test coverage 2023-04-01 22:45:18 +01:00
Rob Ede
4cbe741230 use secure openssl version 2023-04-01 22:26:08 +01:00
Rob Ede
80320a0325 use secure tokio version range 2023-04-01 22:24:10 +01:00
Rob Ede
6d0dc9628b install cargo-hack faster 2023-04-01 22:21:57 +01:00
Rob Ede
dbce150993 update syn to v2 (#481
* update syn to v2

* update changelog
2023-04-01 22:21:14 +01:00
Rob Ede
54ec06cd23 update bitflags to v2 2023-04-01 21:57:10 +01:00
Rob Ede
c0693da9ba update msrv to 1.60 (#482
* update msrv to 1.60

* inherit workspace msrv
2023-04-01 21:39:19 +01:00
Rob Ede
28f36e4e30 update unreleased sections date 2023-04-01 05:24:40 +01:00
Rob Ede
c6ebbcf21b clippy run on -tls 2023-04-01 05:24:00 +01:00
Rob Ede
c60d2f9ddb use doc_auto_cfg 2023-04-01 05:18:22 +01:00
Rob Ede
a6bece7b33 prepare bytestring release 1.3.0 2023-03-03 22:41:09 +00:00
Rob Ede
fbb53f54ef format changelogs with prettier 2023-03-03 22:36:13 +00:00
Rob Ede
9b388a83c9 reinstate actix-macros trybuild tests 2023-02-26 16:26:19 +00:00
Rob Ede
878d3a1c74 impl AsRef<ByteString> 2023-02-26 16:24:48 +00:00
Yuki Okushi
045cf3f3e8 Upgrade GHA workflows to remove deprecation warnings (#477) 2023-01-28 05:36:05 +09:00
Rob Ede
d13461b337 use secure tokio version range
see RUSTSEC-2023-0001

part of actix/actix-web#2962
2023-01-10 08:56:41 +00:00
Juan Aguilar Santillana
dde38bbe06 remove unnecessary Pin in poll_recv calls (#475) 2023-01-02 13:36:46 +00:00
Rob Ede
d973d5974a fix msrv ci 2022-12-21 23:09:16 +00:00
Rob Ede
d7afd60606 workaround env-logger msrv 2022-12-21 21:17:21 +00:00
Rob Ede
7e47bf4055 prepare actix-server release 2.2.0 2022-12-21 20:37:51 +00:00
Rob Ede
05e7be337e prepare actix-rt release 2.8.0 2022-12-21 20:37:04 +00:00
Rob Ede
8d964713c9 fix futures-util version range 2022-12-21 20:36:26 +00:00
Riley
fe38312db0 asonix/tokio uring 04 (#473) 2022-12-21 11:45:31 +09:00
Yuki Okushi
2b83f08a40 Use old cargo-hack for 1.59.0 CI (#472)
* Use old cargo-hack for 1.57.0 CI

Signed-off-by: Yuki Okushi <jtitor@2k36.org>

* Upgrade MSRV to 1.59.0

Signed-off-by: Yuki Okushi <jtitor@2k36.org>

Signed-off-by: Yuki Okushi <jtitor@2k36.org>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2022-11-12 14:00:33 +00:00
Rob Ede
8e9401f8e1 prepare bytestring release 1.2.1 2022-11-12 13:19:09 +00:00
VladimirBramstedt
9ede174e81 fix no_std compatibility (#471)
Co-authored-by: Yuki Okushi <jtitor@2k36.org>
2022-11-12 16:00:06 +09:00
Rob Ede
bb36e2a072 prepare bytestring release 1.2.0 2022-11-07 20:22:47 +00:00
Rob Ede
6061a44a22 slice_ref doc tweaks 2022-11-07 20:21:57 +00:00
Wang, Chi
363984ad75 Add ByteString::slice_ref (#470) 2022-11-07 20:16:46 +00:00
Rob Ede
00654aadc5 use direct tokio exports where possible 2022-10-30 20:25:13 +00:00
fakeshadow
428914e65e remove fakeshadow from author lists (#468) 2022-10-25 16:34:36 +01:00
Rob Ede
df9a9d1a1e don't install cargo-cache on 1.57 CI 2022-10-25 00:10:39 +01:00
Rob Ede
056d2cd573 workaround ci msrv issue 2022-10-24 23:44:29 +01:00
Rob Ede
68228a6cf2 update dev deps 2022-10-21 03:23:40 +01:00
Rob Ede
d5a9a6a1c5 prepare actix-utils release 3.0.1 2022-10-21 03:15:48 +01:00
Rob Ede
ade71b7bd3 address soundness footgun in poll_fn 2022-10-21 03:14:38 +01:00
Rob Ede
cb83922b29 add macos test note 2022-10-17 04:27:34 +01:00
Rob Ede
25209f5bd8 use impl-more in -tls 2022-10-17 04:14:09 +01:00
Rob Ede
c4a0f37d0c fix minimal versions for bytestring 2022-07-23 03:06:44 +01:00
Rob Ede
0e649329b9 fix minimal versions 2022-07-23 01:47:59 +01:00
Rob Ede
66756bc448 update all crates msrv to 1.57 (#464) 2022-07-23 00:51:12 +01:00
Iskandarov Lev
126ed4c2e3 normalize logs capital letter (#463)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2022-07-22 20:53:06 +01:00
Yuki Okushi
283974f3e6 Make actix-codec an optional dependency (#459) 2022-06-23 17:27:36 +01:00
Yuki Okushi
bf2aa3902c Set depth of --feature-powerset on Windows CI (#460) 2022-06-12 02:17:38 +01:00
Rob Ede
71b4e55c92 prepare bytestring release 1.1.0 (#461) 2022-06-11 13:41:11 +01:00
Marcus Griep
eb5fa30ada feat: impls for Box and String conversions (#458)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2022-06-11 04:22:34 +01:00
Rob Ede
49a034259f prepare local-waker release 0.1.3 2022-05-03 14:58:09 +01:00
Rob Ede
3337f63b4e prepare local-channel release 0.1.3 2022-05-03 14:56:40 +01:00
Rob Ede
86ce140249 ensure all crates include license files
closes #456
2022-05-03 14:55:49 +01:00
Guillaume Desmottes
635aebe887 actix-server: fix UNIX signal handling documentation (#455) 2022-05-03 13:37:18 +01:00
Rob Ede
4c1e581a54 add track_caller atrtibute to spawn calls (#454)
* add track_caller attribute to spawn calls

* fix ci
2022-04-25 21:05:48 +01:00
Rob Ede
dc67ba770d fmt with import grouping 2022-04-10 02:48:53 +01:00
Rob Ede
855e3f96fe prepare actix-tls release 3.0.4 2022-03-15 19:43:47 +00:00
Rob Ede
737b438f73 prepare actix-codec release 0.5.1 2022-03-15 19:43:06 +00:00
Rob Ede
0cd70b0536 use tracing for logs (#451) 2022-03-15 19:37:08 +00:00
Rob Ede
4b6a581ef3 prepare actix-server release 2.1.1 2022-03-09 01:08:35 +00:00
Rob Ede
3e132d2bc6 update tokio-uring to 0.3 (#448) 2022-03-08 23:42:52 +00:00
Rob Ede
c5d6174cec add tracing support 2022-03-08 22:13:55 +00:00
Rob Ede
77d4a69b2f update tokio-uring to 0.3 (#449) 2022-03-08 21:57:02 +00:00
Rob Ede
ae5377fd6e update readme 2022-03-08 21:12:46 +00:00
Rob Ede
bd9bda0504 fix readme msrv notes 2022-03-02 16:42:53 +00:00
Rob Ede
41ed48219d bump lower msrv to 1.49 2022-03-02 16:40:11 +00:00
fakeshadow
7804ed12eb block and wait for accept thread to exit. (#443)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2022-03-02 03:52:12 +00:00
Rob Ede
2a54065fae parallel master tests using nextest 2022-02-15 14:19:00 +00:00
Rob Ede
217cbd2228 bump tokio-util to 0.7 (#446) 2022-02-15 01:47:27 +00:00
Rob Ede
d229c1e886 fix min ver check 2022-02-12 08:42:13 +00:00
Rob Ede
6792f799a6 add minimal-versions check 2022-02-12 08:37:56 +00:00
Rob Ede
72481313cc update readme 2022-01-28 22:28:24 +00:00
Rob Ede
59b629c74b fix deps badge 2022-01-28 22:17:12 +00:00
Rob Ede
7988694242 update msrv info 2022-01-28 22:15:16 +00:00
Rob Ede
b8a7741524 fix bind_addr 2022-01-28 22:13:10 +00:00
Rob Ede
5e290d76f8 prepare actix-tls release 3.0.2 2022-01-28 22:11:21 +00:00
Rob Ede
0edb64575f update tls changelog 2022-01-28 22:10:24 +00:00
Rob Ede
941f67dec9 s/e/err 2022-01-28 22:10:06 +00:00
Babur
3e624b8376 Made new constructor for the Connection type public (#439) 2022-01-28 22:09:54 +00:00
Ibraheem Ahmed
26446fdbad Replace derive_more with declarative macros (#438)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2022-01-28 22:09:33 +00:00
Rob Ede
b7b7bd2cbf add actix-server readme 2022-01-19 16:14:06 +00:00
Rob Ede
637625f9b7 prepare actix-server release 2.0.0 (#437) 2022-01-19 14:57:50 +00:00
Rob Ede
b1d5d85e72 prepare actix-server release 2.0.0-rc.4 2022-01-12 14:40:06 +00:00
Rob Ede
ed2c07b304 prepare actix-rt release 2.6.0 2022-01-12 14:40:06 +00:00
Rob Ede
4fe7fec5ef update tokio-uring to 0.2.0 (#436) 2022-01-11 23:36:49 +00:00
127 changed files with 3655 additions and 1475 deletions

View File

@@ -2,25 +2,14 @@
lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture"
# just check the library (without dev deps)
ci-check-min = "hack --workspace check --no-default-features"
ci-check-lib = "hack --workspace --feature-powerset --exclude-features=io-uring check"
ci-check-lib-linux = "hack --workspace --feature-powerset check"
ci-check-lib = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check"
ci-check-lib-linux = "hack --workspace --feature-powerset --depth=2 check"
# check everything
ci-check = "hack --workspace --feature-powerset --exclude-features=io-uring check --tests --examples"
ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
ci-check = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check --tests --examples"
ci-check-linux = "hack --workspace --feature-powerset --depth=2 check --tests --examples"
# tests avoiding io-uring feature
ci-test = " hack --feature-powerset --exclude=actix-rt --exclude=actix-server --exclude-features=io-uring test --workspace --lib --tests --no-fail-fast -- --nocapture"
ci-test-rt = " hack --feature-powerset --exclude-features=io-uring test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
ci-test-server = "hack --feature-powerset --exclude-features=io-uring test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
# test with io-uring feature
ci-test-rt-linux = " hack --feature-powerset test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
ci-test-server-linux = "hack --feature-powerset test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
# test lower msrv
ci-test-lower-msrv = "hack --workspace --exclude=actix-server --exclude=actix-tls --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
ci-test = "hack --feature-powerset --depth=2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

10
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly

View File

@@ -1,145 +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
cargo ci-test-rt
cargo ci-test-server
- 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-rt-linux && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-server-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: stable-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
- 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 }

146
.github/workflows/ci-post-merge.yml vendored Normal file
View File

@@ -0,0 +1,146 @@
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 }
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: Setup mold linker
if: matrix.target.os == 'ubuntu-latest'
uses: rui314/setup-mold@v1
- name: Install nasm
if: matrix.target.os == 'windows-latest'
uses: ilammy/setup-nasm@v1.5.1
- name: Install OpenSSL
if: matrix.target.os == 'windows-latest'
shell: bash
run: |
set -e
choco install openssl --version=1.1.1.2100 -y --no-progress
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
- name: Install Rust (${{ matrix.version }})
uses: actions-rust-lang/setup-rust-toolchain@v1.9.0
with:
toolchain: ${{ matrix.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@v2.42.10
with:
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
- 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
run: just test
# TODO: re-instate some io-uring tests PRs
# - 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: CI cache clean
run: cargo-ci-cache-clean
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.9.0
with:
toolchain: nightly
- name: Install cargo-hack & cargo-minimal-versions
uses: taiki-e/install-action@v2.42.10
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.9.0
- name: Install cargo-nextest
uses: taiki-e/install-action@v2.42.10
with:
tool: cargo-nextest
- name: Test with cargo-nextest
run: cargo nextest run

View File

@@ -1,171 +1,133 @@
name: CI
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [master]
pull_request: {}
merge_group: { types: [checks_requested] }
push: { branches: [master] }
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
read_msrv:
name: Read MSRV
uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@v0.1.0
build_and_test:
needs:
- read_msrv
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:
- 1.52.0 # MSRV for -server and -tls
- stable
- { name: msrv, version: "${{ needs.read_msrv.outputs.msrv }}" }
- { 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
- name: Setup mold linker
if: matrix.target.os == 'ubuntu-latest'
uses: rui314/setup-mold@v1
- name: Install nasm
if: matrix.target.os == 'windows-latest'
uses: ilammy/setup-nasm@v1.5.1
# 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'
shell: bash
run: |
set -e
choco install openssl --version=1.1.1.2100 -y --no-progress
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
- name: Install ${{ matrix.version }}
uses: actions-rs/toolchain@v1
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@v1.9.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
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@v2.42.10
with:
command: install
args: cargo-hack
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
- name: Generate Cargo.lock
run: cargo generate-lockfile
- name: workaround MSRV issues
if: matrix.version.name == 'msrv'
run: just downgrade-for-msrv
- 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 }
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'
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 != 'ubuntu-latest'
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
run: |
cargo ci-test
cargo ci-test-rt
cargo ci-test-server
- 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-rt-linux && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-server-linux"
run: just test
- name: Clear the cargo caches
run: |
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
cargo-cache
- name: CI cache clean
run: cargo-ci-cache-clean
build_and_test_lower_msrv:
name: Linux / 1.46 (lower MSRV)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install 1.46.0 # MSRV for all but -server and -tls
uses: actions-rs/toolchain@v1
with:
toolchain: 1.46.0-x86_64-unknown-linux-gnu
profile: minimal
override: true
- name: Install cargo-hack
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-hack
- name: tests
run: |
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=1.46 cargo ci-test-lower-msrv"
- name: Clear the cargo caches
run: |
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
cargo-cache
rustdoc:
name: rustdoc
docs:
name: Documentation
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.9.0
with:
toolchain: nightly-x86_64-unknown-linux-gnu
profile: minimal
override: true
toolchain: nightly
- 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 just
uses: taiki-e/install-action@v2.42.10
with:
tool: just
- name: doc tests io-uring
run: |
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=nightly cargo ci-doctest"
- name: doc tests
run: just test-docs

View File

@@ -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

39
.github/workflows/coverage.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
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.9.0
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2.42.10
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@v4.5.0
with:
files: codecov.json
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

68
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: Lint
on:
pull_request: {}
merge_group: { types: [checks_requested] }
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1.9.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.9.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.9.0
with:
toolchain: nightly-2023-10-10
- name: Install just
uses: taiki-e/install-action@v2.42.10
with:
tool: just
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v2.0.1
with:
tool: cargo-check-external-types@0.1.10
- name: check external types
run: just check-external-types-all +nightly-2023-10-10

View File

@@ -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.9.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.6.3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: target/doc
folder: target/doc
single-commit: true

4
.gitignore vendored
View File

@@ -13,4 +13,8 @@ guide/build/
# These are backup files generated by rustfmt
**/*.rs.bk
# IDEs
.idea
# direnv
/.direnv

3
.rustfmt.toml Normal file
View File

@@ -0,0 +1,3 @@
group_imports = "StdExternalCrate"
imports_granularity = "Crate"
use_field_init_shorthand = true

View File

@@ -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

View File

@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"actix-codec",
"actix-macros",
@@ -13,6 +14,11 @@ members = [
"local-waker",
]
[workspace.package]
license = "MIT OR Apache-2.0"
edition = "2021"
rust-version = "1.70"
[patch.crates-io]
actix-codec = { path = "actix-codec" }
actix-macros = { path = "actix-macros" }

View File

@@ -2,18 +2,18 @@
> A collection of lower-level libraries for composable network services.
[![CI](https://github.com/actix/actix-net/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/actix/actix-net/actions/workflows/ci.yml)
[![CI](https://github.com/actix/actix-net/actions/workflows/ci.yml/badge.svg?event=push&style=flat-square)](https://github.com/actix/actix-net/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/actix/actix-net/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-net)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)
[![Dependency Status](https://deps.rs/repo/github/actix/actix-extras/status.svg)](https://deps.rs/repo/github/actix/actix-extras)
[![Dependency Status](https://deps.rs/repo/github/actix/actix-net/status.svg)](https://deps.rs/repo/github/actix/actix-net)
## Example
## Examples
See `actix-server/examples` and `actix-tls/examples` for some basic examples.
See example folders for [`actix-server`](./actix-server/examples) and [`actix-tls`](./actix-tls/examples).
### MSRV
## MSRV
This repo's Minimum Supported Rust Version (MSRV) is 1.46.0.
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

View File

@@ -1,42 +1,52 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.70.
## 0.5.2
- Minimum supported Rust version (MSRV) is now 1.65.
## 0.5.1
- Logs emitted now use the `tracing` crate with `log` compatibility.
- Minimum supported Rust version (MSRV) is now 1.49.
## 0.5.0
- Updated `tokio-util` dependency to `0.7.0`.
## 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]
- Added `LinesCodec`.
- `Framed::poll_ready` flushes when the buffer is full.
[#338]: https://github.com/actix/actix-net/pull/338
[#409]: https://github.com/actix/actix-net/pull/409
## 0.4.0
## 0.4.0 - 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]
- Upgrade `bytes` dependency to `1`. [#237]
- Replace `pin-project` with `pin-project-lite`.
- Upgrade `tokio` dependency to `1`.
- Upgrade `tokio-util` dependency to `0.6`.
- Upgrade `bytes` dependency to `1`.
[#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.
@@ -45,31 +55,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.

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-codec"
version = "0.4.2"
version = "0.5.2"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@@ -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.1"
bitflags = "2"
bytes = "1"
futures-core = { version = "0.3.7", default-features = false }
futures-sink = { version = "0.3.7", default-features = false }
log = "0.4"
memchr = "2.3"
pin-project-lite = "0.2"
tokio = "1.13.1"
tokio-util = { version = "0.6", features = ["codec", "io"] }
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]]

View File

@@ -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;
@@ -193,18 +194,18 @@ impl<T, U> Framed<T, U> {
match this.codec.decode_eof(this.read_buf) {
Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
Ok(None) => return Poll::Ready(None),
Err(e) => return Poll::Ready(Some(Err(e))),
Err(err) => return Poll::Ready(Some(Err(err))),
}
}
log::trace!("attempting to decode a frame");
tracing::trace!("attempting to decode a frame");
match this.codec.decode(this.read_buf) {
Ok(Some(frame)) => {
log::trace!("frame decoded from buffer");
tracing::trace!("frame decoded from buffer");
return Poll::Ready(Some(Ok(frame)));
}
Err(e) => return Poll::Ready(Some(Err(e))),
Err(err) => return Poll::Ready(Some(Err(err))),
_ => (), // Need more data
}
@@ -221,7 +222,7 @@ impl<T, U> Framed<T, U> {
let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
Poll::Pending => return Poll::Pending,
Poll::Ready(Err(e)) => return Poll::Ready(Some(Err(e.into()))),
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
Poll::Ready(Ok(cnt)) => cnt,
};
@@ -233,19 +234,16 @@ 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>,
{
let mut this = self.as_mut().project();
log::trace!("flushing framed transport");
tracing::trace!("flushing framed transport");
while !this.write_buf.is_empty() {
log::trace!("writing; remaining={}", this.write_buf.len());
tracing::trace!("writing; remaining={}", this.write_buf.len());
let n = ready!(this.io.as_mut().poll_write(cx, this.write_buf))?;
@@ -264,15 +262,12 @@ impl<T, U> Framed<T, U> {
// Try flushing the underlying IO
ready!(this.io.poll_flush(cx))?;
log::trace!("framed transport flushed");
tracing::trace!("framed transport flushed");
Poll::Ready(Ok(()))
}
/// 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>,

View File

@@ -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 self::bcodec::BytesCodec;
pub use self::framed::{Framed, FramedParts};
pub use self::lines::LinesCodec;
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,
framed::{Framed, FramedParts},
lines::LinesCodec,
};

View File

@@ -7,8 +7,8 @@ use super::{Decoder, Encoder};
/// Lines codec. Reads/writes line delimited strings.
///
/// Will split input up by LF or CRLF delimiters. I.e. carriage return characters at the end of
/// lines are not preserved.
/// Will split input up by LF or CRLF delimiters. Carriage return characters at the end of lines are
/// not preserved.
#[derive(Debug, Copy, Clone, Default)]
#[non_exhaustive]
pub struct LinesCodec;

View File

@@ -1,12 +1,16 @@
use std::{
collections::VecDeque,
io::{self, Write},
pin::Pin,
task::{
Context,
Poll::{self, Pending, Ready},
},
};
use actix_codec::*;
use bytes::Buf;
use bytes::{BufMut, BytesMut};
use bytes::{Buf as _, BufMut as _, BytesMut};
use futures_sink::Sink;
use std::collections::VecDeque;
use std::io::{self, Write};
use std::pin::Pin;
use std::task::Poll::{Pending, Ready};
use std::task::{Context, Poll};
use tokio_test::{assert_ready, task};
macro_rules! bilateral {
@@ -50,7 +54,7 @@ impl Write for Bilateral {
assert_eq!(&data[..], &src[..data.len()]);
Ok(data.len())
}
Some(Err(e)) => Err(e),
Some(Err(err)) => Err(err),
None => panic!("unexpected write; {:?}", src),
}
}
@@ -67,20 +71,17 @@ impl AsyncWrite for Bilateral {
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
match Pin::get_mut(self).write(buf) {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
other => Ready(other),
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match Pin::get_mut(self).flush() {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
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!()
}
}
@@ -99,8 +100,8 @@ impl AsyncRead for Bilateral {
buf.put_slice(&data);
Ready(Ok(()))
}
Some(Err(ref e)) if e.kind() == WouldBlock => Pending,
Some(Err(e)) => Ready(Err(e)),
Some(Err(ref err)) if err.kind() == WouldBlock => Pending,
Some(Err(err)) => Ready(Err(err)),
None => Ready(Ok(())),
}
}

View File

@@ -1,46 +1,53 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.70.
## 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

View File

@@ -1,27 +1,36 @@
[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"
futures-util = { version = "0.3.7", default-features = false }
rustversion = "1"
actix-rt = "2"
futures-util = { version = "0.3.17", default-features = false }
rustversion-msrv = "0.100"
trybuild = "1"

View File

@@ -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()

View File

@@ -1,7 +1,8 @@
#[rustversion::stable(1.46)] // MSRV
#[rustversion_msrv::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");

View File

@@ -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`

View File

@@ -1,186 +1,172 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
## 2.10.0
## 2.5.1 - 2021-12-31
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`. [#430]
- Relax `F`'s bound (`Fn => FnOnce`) on `{Arbiter, System}::with_tokio_rt()` functions.
- Update `tokio-uring` dependency to `0.5`.
- Minimum supported Rust version (MSRV) is now 1.70.
[#430]: https://github.com/actix/actix-net/pull/430
## 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.5.0 - 2021-11-22
- Add `System::run_with_code` to allow retrieving the exit code on stop. [#411]
## 2.8.0
[#411]: https://github.com/actix/actix-net/pull/411
- Add `#[track_caller]` attribute to `spawn` functions and methods.
- Update `tokio-uring` dependency to `0.4`.
- Minimum supported Rust version (MSRV) is now 1.59.
## 2.7.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]
- Update `tokio-uring` dependency to `0.3`.
- Minimum supported Rust version (MSRV) is now 1.49.
[#395]: https://github.com/actix/actix-net/pull/395
[#408]: https://github.com/actix/actix-net/pull/408
## 2.6.0
- Update `tokio-uring` dependency to `0.2`.
## 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]
## 2.5.1
[#369]: https://github.com/actix/actix-net/pull/369
[#374]: https://github.com/actix/actix-net/pull/374
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`.
## 2.5.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.
- Add `System::run_with_code` to allow retrieving the exit code on stop.
[#293]: https://github.com/actix/actix-net/pull/293
## 2.4.0
- Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context.
- Start io-uring with `System::new` when feature is enabled.
## 2.1.0 - 2021-02-24
- Add `ActixStream` extension trait to include readiness methods. [#276]
- Re-export `tokio::net::TcpSocket` in `net` module [#282]
## 2.3.0
[#276]: https://github.com/actix/actix-net/pull/276
[#282]: https://github.com/actix/actix-net/pull/282
- The `spawn` method can now resolve with non-unit outputs.
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux.
## 2.2.0
## 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]
- **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return `Ready` object in ok variant.
- Breakage is acceptable since `ActixStream` was not intended to be public.
[#274]: https://github.com/actix/actix-net/pull/274
[#275]: https://github.com/actix/actix-net/pull/275
## 2.1.0
- Add `ActixStream` extension trait to include readiness methods.
- Re-export `tokio::net::TcpSocket` in `net` module
## 2.0.1 - 2021-02-06
- Expose `JoinError` from Tokio. [#271]
## 2.0.2
[#271]: https://github.com/actix/actix-net/pull/271
- Add `Arbiter::handle` to get a handle of an owned Arbiter.
- Add `System::try_current` for situations where actix may or may not be running a System.
## 2.0.1
## 2.0.0 - 2021-02-02
- Remove all Arbiter-local storage methods. [#262]
- Re-export `tokio::pin`. [#262]
- Expose `JoinError` from Tokio.
[#262]: https://github.com/actix/actix-net/pull/262
## 2.0.0
- Remove all Arbiter-local storage methods.
- Re-export `tokio::pin`.
## 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]
- Rename `Arbiter::{send => spawn}` and `Arbiter::{exec_fn => spawn_fn}`. [#253]
- Remove `Arbiter::exec`. [#253]
- Remove deprecated `Arbiter::local_join` and `Arbiter::is_running`. [#253]
- `Arbiter::spawn` now accepts !Unpin futures. [#256]
- `System::new` no longer takes arguments. [#257]
- Remove `System::with_current`. [#257]
- Remove `Builder`. [#257]
- Add `System::with_init` as replacement for `Builder::run`. [#257]
- Rename `System::{is_set => is_registered}`. [#257]
- Add `ArbiterHandle` for sending messages to non-current-thread arbiters. [#257].
- `System::arbiter` now returns an `&ArbiterHandle`. [#257]
- `Arbiter::current` now returns an `ArbiterHandle` instead. [#257]
- `Arbiter::join` now takes self by value. [#257]
## 2.0.0-beta.3
[#253]: https://github.com/actix/actix-net/pull/253
[#254]: https://github.com/actix/actix-net/pull/254
[#256]: https://github.com/actix/actix-net/pull/256
[#257]: https://github.com/actix/actix-net/pull/257
- Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`.
- Return `JoinHandle` from `actix_rt::spawn`.
- Remove old `Arbiter::spawn`. Implementation is now inlined into `actix_rt::spawn`.
- Rename `Arbiter::{send => spawn}` and `Arbiter::{exec_fn => spawn_fn}`.
- Remove `Arbiter::exec`.
- Remove deprecated `Arbiter::local_join` and `Arbiter::is_running`.
- `Arbiter::spawn` now accepts !Unpin futures.
- `System::new` no longer takes arguments.
- Remove `System::with_current`.
- Remove `Builder`.
- Add `System::with_init` as replacement for `Builder::run`.
- Rename `System::{is_set => is_registered}`.
- Add `ArbiterHandle` for sending messages to non-current-thread arbiters.
- `System::arbiter` now returns an `&ArbiterHandle`.
- `Arbiter::current` now returns an `ArbiterHandle` instead.
- `Arbiter::join` now takes self by value.
## 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 `task` mod with re-export of `tokio::task::{spawn_blocking, yield_now, JoinHandle}`
- 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]
- Add `System::attach_to_tokio` method.
- Update `tokio` dependency to `1.0`.
- Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep` to stay aligned with Tokio's naming.
- Remove `'static` lifetime requirement for `Runtime::block_on` and `SystemRunner::block_on`.
* 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]
- These methods now accept `&self` when calling.
- Remove `'static` lifetime requirement for `System::run` and `Builder::run`.
- `Arbiter::spawn` now panics when `System` is not in scope.
- Fix work load issue by removing `PENDING` thread local.
[#207]: https://github.com/actix/actix-net/pull/207
[#236]: https://github.com/actix/actix-net/pull/236
## 1.1.1
- Fix memory leak due to
## 1.1.1 - 2020-04-30
- Fix memory leak due to [#94] (see [#129] for more detail)
## 1.1.0 _(YANKED)_
[#129]: https://github.com/actix/actix-net/issues/129
- Expose `System::is_set` to check if current system has ben started
- Add `Arbiter::is_running` to check if event loop is running
- Add `Arbiter::local_join` associated function to get be able to `await` for spawned futures
## 1.0.0
## 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]
[#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 - 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

View File

@@ -1,22 +1,24 @@
[package]
name = "actix-rt"
version = "2.5.1"
version = "2.10.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"]
homepage = "https://actix.rs"
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"
edition.workspace = true
rust-version.workspace = true
[lib]
name = "actix_rt"
path = "src/lib.rs"
[package.metadata.cargo_check_external_types]
allowed_external_types = [
"actix_macros::*",
"tokio::*",
]
[features]
default = ["macros"]
@@ -27,11 +29,11 @@ io-uring = ["tokio-uring"]
actix-macros = { version = "0.2.3", optional = true }
futures-core = { version = "0.3", default-features = false }
tokio = { version = "1.13.1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
tokio = { version = "1.23.1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
# runtime for `io-uring` feature
[target.'cfg(target_os = "linux")'.dependencies]
tokio-uring = { version = "0.1", optional = true }
tokio-uring = { version = "0.5", optional = true }
[dev-dependencies]
tokio = { version = "1.13.1", features = ["full"] }
hyper = { version = "0.14", default-features = false, features = ["server", "tcp", "http1"] }
tokio = { version = "1.23.1", features = ["full"] }

View File

@@ -3,11 +3,11 @@
> Tokio-based single-threaded async runtime for the Actix ecosystem.
[![crates.io](https://img.shields.io/crates/v/actix-rt?label=latest)](https://crates.io/crates/actix-rt)
[![Documentation](https://docs.rs/actix-rt/badge.svg?version=2.5.1)](https://docs.rs/actix-rt/2.5.1)
[![Documentation](https://docs.rs/actix-rt/badge.svg?version=2.10.0)](https://docs.rs/actix-rt/2.10.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.5.1/status.svg)](https://deps.rs/crate/actix-rt/2.5.1)
[![dependency status](https://deps.rs/crate/actix-rt/2.10.0/status.svg)](https://deps.rs/crate/actix-rt/2.10.0)
![Download](https://img.shields.io/crates/d/actix-rt.svg)
[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/WghFtEH6Hb)

View File

@@ -1,28 +0,0 @@
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use std::convert::Infallible;
use std::net::SocketAddr;
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("Hello World")))
}
fn main() {
actix_rt::System::with_tokio_rt(|| {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
})
.block_on(async {
let make_service =
make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
let server =
Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
})
}

View File

@@ -16,7 +16,7 @@ use crate::system::{System, SystemCommand};
pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
thread_local!(
static HANDLE: RefCell<Option<ArbiterHandle>> = RefCell::new(None);
static HANDLE: RefCell<Option<ArbiterHandle>> = const { RefCell::new(None) };
);
pub(crate) enum ArbiterCommand {
@@ -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.")
})
}
@@ -110,7 +109,7 @@ impl Arbiter {
#[cfg(not(all(target_os = "linux", feature = "io-uring")))]
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
where
F: Fn() -> tokio::runtime::Runtime + Send + 'static,
F: FnOnce() -> tokio::runtime::Runtime + Send + 'static,
{
let sys = System::current();
let system_id = sys.id();
@@ -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();
@@ -260,6 +255,7 @@ impl Arbiter {
/// If you require a result, include a response channel in the future.
///
/// Returns true if future was sent successfully and false if the Arbiter has died.
#[track_caller]
pub fn spawn<Fut>(&self, future: Fut) -> bool
where
Fut: Future<Output = ()> + Send + 'static,
@@ -275,6 +271,7 @@ impl Arbiter {
/// channel in the function.
///
/// Returns true if function was sent successfully and false if the Arbiter has died.
#[track_caller]
pub fn spawn_fn<F>(&self, f: F) -> bool
where
F: FnOnce() + Send + 'static,
@@ -301,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(()),

View File

@@ -34,6 +34,7 @@
//! ```
//!
//! # `io-uring` Support
//!
//! There is experimental support for using io-uring with this crate by enabling the
//! `io-uring` feature. For now, it is semver exempt.
//!
@@ -51,13 +52,10 @@ compile_error!("io_uring is a linux only feature.");
use std::future::Future;
use tokio::task::JoinHandle;
// Cannot define a main macro when compiled into test harness.
// Workaround for https://github.com/rust-lang/rust/issues/62127.
#[cfg(all(feature = "macros", not(test)))]
pub use actix_macros::main;
#[cfg(feature = "macros")]
pub use actix_macros::test;
@@ -65,11 +63,14 @@ mod arbiter;
mod runtime;
mod system;
pub use self::arbiter::{Arbiter, ArbiterHandle};
pub use self::runtime::Runtime;
pub use self::system::{System, SystemRunner};
pub use tokio::pin;
use tokio::task::JoinHandle;
pub use self::{
arbiter::{Arbiter, ArbiterHandle},
runtime::Runtime,
system::{System, SystemRunner},
};
pub mod signal {
//! Asynchronous signal handling (Tokio re-exports).
@@ -91,13 +92,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)]
@@ -156,10 +157,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 {
@@ -198,6 +198,7 @@ pub mod task {
/// assert!(handle.await.unwrap_err().is_cancelled());
/// # });
/// ```
#[track_caller]
#[inline]
pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output>
where

View File

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

View File

@@ -16,7 +16,7 @@ use crate::{arbiter::ArbiterHandle, Arbiter};
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
thread_local!(
static CURRENT: RefCell<Option<System>> = RefCell::new(None);
static CURRENT: RefCell<Option<System>> = const { RefCell::new(None) };
);
/// A manager for a per-thread distributed async runtime.
@@ -48,7 +48,7 @@ impl System {
/// [tokio-runtime]: tokio::runtime::Runtime
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
where
F: Fn() -> tokio::runtime::Runtime,
F: FnOnce() -> tokio::runtime::Runtime,
{
let (stop_tx, stop_rx) = oneshot::channel();
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
@@ -87,7 +87,7 @@ impl System {
#[doc(hidden)]
pub fn with_tokio_rt<F>(_: F) -> SystemRunner
where
F: Fn() -> tokio::runtime::Runtime,
F: FnOnce() -> tokio::runtime::Runtime,
{
unimplemented!("System::with_tokio_rt is not implemented for io-uring feature yet")
}
@@ -203,7 +203,42 @@ 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]
pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
self.rt.block_on(fut)
@@ -225,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.
@@ -291,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(()),

View File

@@ -4,7 +4,6 @@ use std::{
};
use actix_rt::{task::JoinError, Arbiter, System};
#[cfg(not(feature = "io-uring"))]
use {
std::{sync::mpsc::channel, thread},
@@ -359,7 +358,7 @@ fn tokio_uring_arbiter() {
let f = tokio_uring::fs::File::create("test.txt").await.unwrap();
let buf = b"Hello World!";
let (res, _) = f.write_at(&buf[..], 0).await;
let (res, _) = f.write_all_at(&buf[..], 0).await;
assert!(res.is_ok());
f.sync_all().await.unwrap();

View File

@@ -1,231 +1,227 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
## 2.5.0
- Update `mio` dependency to `1`.
## 2.4.0
- Update `tokio-uring` dependency to `0.5`.
- Minimum supported Rust version (MSRV) is now 1.70.
## 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`.
## 2.1.1
- No significant changes since `2.1.0`.
## 2.1.0
- Update `tokio-uring` dependency to `0.3`.
- Logs emitted now use the `tracing` crate with `log` compatibility.
- Wait for accept thread to stop before sending completion signal.
## 2.0.0
- No significant changes since `2.0.0-rc.4`.
## 2.0.0-rc.4
- Update `tokio-uring` dependency to `0.2`.
## 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]
- Simplify `TestServer`.
[#431]: https://github.com/actix/actix-net/pull/431
## 2.0.0-rc.1
- Hide implementation details of `Server`.
- `Server` now runs only after awaiting it.
## 2.0.0-rc.1 - 2021-12-05
- Hide implementation details of `Server`. [#424]
- `Server` now runs only after awaiting it. [#425]
## 2.0.0-beta.9
[#424]: https://github.com/actix/actix-net/pull/424
[#425]: https://github.com/actix/actix-net/pull/425
- Restore `Arbiter` support lost in `beta.8`.
## 2.0.0-beta.8
## 2.0.0-beta.9 - 2021-11-15
- Restore `Arbiter` support lost in `beta.8`. [#417]
- Fix non-unix signal handler.
[#417]: https://github.com/actix/actix-net/pull/417
## 2.0.0-beta.7
## 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 - 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]
- Add `Server::handle` to obtain handle to server. [#408]
- Rename `ServerBuilder::{maxconn => max_concurrent_connections}`. [#407]
- Deprecate crate-level `new` shortcut for server builder. [#408]
- Server can be started in regular Tokio runtime.
- Expose new `Server` type whose `Future` impl resolves when server stops.
- Rename `Server` to `ServerHandle`.
- Add `Server::handle` to obtain handle to server.
- Rename `ServerBuilder::{maxconn => max_concurrent_connections}`.
- Deprecate crate-level `new` shortcut for server builder.
- Minimum supported Rust version (MSRV) is now 1.52.
[#407]: https://github.com/actix/actix-net/pull/407
[#408]: https://github.com/actix/actix-net/pull/408
## 2.0.0-beta.6
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux.
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block subsequent exit signals from working.
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to this change.
- Remove `ServerBuilder::configure`.
## 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]
- Remove `ServerBuilder::configure` [#349]
## 2.0.0-beta.5
[#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
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all workers to shutdown immediately in force shutdown case.
## 2.0.0-beta.4
## 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]
[#333]: https://github.com/actix/actix-net/pull/333
## 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
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`.
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop.
- Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size.
- Update `actix-rt` to `2.0.0`.
## 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]
- Update `actix-rt` to `2.0.0`. [#273]
## 2.0.0-beta.2
[#246]: https://github.com/actix/actix-net/pull/246
[#264]: https://github.com/actix/actix-net/pull/264
[#265]: https://github.com/actix/actix-net/pull/265
[#273]: https://github.com/actix/actix-net/pull/273
- Merge `actix-testing` to `actix-server` as `test_server` mod.
## 2.0.0-beta.1
## 2.0.0-beta.2 - 2021-01-03
- Merge `actix-testing` to `actix-server` as `test_server` mod. [#242]
- Added explicit info log message on accept queue pause.
- Prevent double registration of sockets when back-pressure is resolved.
- Update `mio` dependency to `0.7.3`.
- Remove `socket2` dependency.
- `ServerBuilder::backlog` now accepts `u32` instead of `i32`.
- Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`.
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using `FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows).
- Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait.
[#242]: https://github.com/actix/actix-net/pull/242
## 1.0.4
## 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]
- 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 - 2020-09-12
- Update actix-codec to 0.3.0.
- Workers must be greater than 0. [#167]
- Workers must be greater than 0.
[#167]: https://github.com/actix/actix-net/pull/167
## 1.0.3
- Replace deprecated `net2` crate with `socket2`.
## 1.0.3 - 2020-05-19
- Replace deprecated `net2` crate with `socket2` [#140]
## 1.0.2
[#140]: https://github.com/actix/actix-net/pull/140
- Avoid error by calling `reregister()` on Windows.
## 1.0.1
## 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 - 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

49
actix-server/Cargo.toml Executable file → Normal file
View File

@@ -1,9 +1,8 @@
[package]
name = "actix-server"
version = "2.0.0-rc.3"
version = "2.5.0"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"fakeshadow <24548779@qq.com>",
"Rob Ede <robjtede@icloud.com>",
"Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
]
@@ -11,39 +10,41 @@ description = "General purpose TCP server built for the Actix ecosystem"
keywords = ["network", "tcp", "server", "framework", "async"]
categories = ["network-programming", "asynchronous"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git"
repository = "https://github.com/actix/actix-net/tree/master/actix-server"
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.4.0", default-features = false }
actix-service = "2.0.0"
actix-utils = "3.0.0"
actix-rt = { version = "2.10", 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"] }
log = "0.4"
mio = { version = "0.8", features = ["os-poll", "net"] }
num_cpus = "1.13"
socket2 = "0.4.2"
tokio = { version = "1.13.1", features = ["sync"] }
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
mio = { version = "1", features = ["os-poll", "net"] }
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
tokio-uring = { version = "0.1", optional = true }
# runtime for `io-uring` feature
[target.'cfg(target_os = "linux")'.dependencies]
tokio-uring = { version = "0.5", optional = true }
[dev-dependencies]
actix-codec = "0.4.2"
actix-rt = "2.4.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"] }
pretty_env_logger = "0.5"
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"] }

21
actix-server/README.md Normal file
View File

@@ -0,0 +1,21 @@
# actix-server
> 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.5.0)](https://docs.rs/actix-server/2.5.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)
![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.5.0/status.svg)](https://deps.rs/crate/actix-server/2.5.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)

View File

@@ -18,10 +18,11 @@ use futures_util::{SinkExt as _, StreamExt as _};
use tokio::{fs::File, io::AsyncReadExt as _};
async fn run() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
pretty_env_logger::formatted_timed_builder()
.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info"));
let addr = ("127.0.0.1", 8080);
log::info!("starting server on port: {}", &addr.0);
tracing::info!("starting server on port: {}", &addr.0);
// Bind socket address and start worker(s). By default, the server uses the number of physical
// CPU cores as the worker count. For this reason, the closure passed to bind needs to return
@@ -39,8 +40,10 @@ async fn run() -> io::Result<()> {
// wait for next line
match framed.next().await {
Some(Ok(line)) => {
match File::open(line).await {
match File::open(&line).await {
Ok(mut file) => {
tracing::info!("reading file: {}", &line);
// read file into String buffer
let mut buf = String::new();
file.read_to_string(&mut buf).await?;
@@ -52,7 +55,7 @@ async fn run() -> io::Result<()> {
break;
}
Err(err) => {
log::error!("{}", err);
tracing::error!("{}", err);
framed
.send("File not found or not readable. Try again.")
.await?;
@@ -72,7 +75,7 @@ async fn run() -> io::Result<()> {
// close connection after file has been copied to TCP stream
Ok(())
})
.map_err(|err| log::error!("Service Error: {:?}", err))
.map_err(|err| tracing::error!("service error: {:?}", err))
})?
.workers(2)
.run()

View File

@@ -22,16 +22,16 @@ use actix_server::Server;
use actix_service::{fn_service, ServiceFactoryExt as _};
use bytes::BytesMut;
use futures_util::future::ok;
use log::{error, info};
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
async fn run() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
pretty_env_logger::formatted_timed_builder()
.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info"));
let count = Arc::new(AtomicUsize::new(0));
let addr = ("127.0.0.1", 8080);
info!("starting server on port: {}", &addr.0);
tracing::info!("starting server on port: {}", &addr.0);
// Bind socket address and start worker(s). By default, the server uses the number of physical
// CPU cores as the worker count. For this reason, the closure passed to bind needs to return
@@ -58,14 +58,14 @@ async fn run() -> io::Result<()> {
// more bytes to process
Ok(bytes_read) => {
info!("[{}] read {} bytes", num, bytes_read);
tracing::info!("[{}] read {} bytes", num, bytes_read);
stream.write_all(&buf[size..]).await.unwrap();
size += bytes_read;
}
// stream error; bail from loop with error
Err(err) => {
error!("Stream Error: {:?}", err);
tracing::error!("stream error: {:?}", err);
return Err(());
}
}
@@ -75,10 +75,10 @@ async fn run() -> io::Result<()> {
Ok((buf.freeze(), size))
}
})
.map_err(|err| error!("Service Error: {:?}", err))
.map_err(|err| tracing::error!("service error: {:?}", err))
.and_then(move |(_, size)| {
let num = num2.load(Ordering::SeqCst);
info!("[{}] total bytes read: {}", num, size);
tracing::info!("[{}] total bytes read: {}", num, size);
ok(size)
})
})?

View File

@@ -1,8 +1,8 @@
use std::{io, thread, time::Duration};
use actix_rt::time::Instant;
use log::{debug, error, info};
use mio::{Interest, Poll, Token as MioToken};
use tracing::{debug, error, info};
use crate::{
availability::Availability,
@@ -24,7 +24,7 @@ struct ServerSocketInfo {
timeout: Option<actix_rt::time::Instant>,
}
/// poll instance of the server.
/// Poll instance of the server.
pub(crate) struct Accept {
poll: Poll,
waker_queue: WakerQueue,
@@ -41,7 +41,7 @@ impl Accept {
pub(crate) fn start(
sockets: Vec<(usize, MioListener)>,
builder: &ServerBuilder,
) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>)> {
) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>, thread::JoinHandle<()>)> {
let handle_server = ServerHandle::new(builder.cmd_tx.clone());
// construct poll instance and its waker
@@ -73,12 +73,12 @@ impl Accept {
handle_server,
)?;
thread::Builder::new()
let accept_handle = thread::Builder::new()
.name("actix-server acceptor".to_owned())
.spawn(move || accept.poll_with(&mut sockets))
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
Ok((waker_queue, handles_server))
Ok((waker_queue, handles_server, accept_handle))
}
fn new_with_sockets(
@@ -127,10 +127,10 @@ impl Accept {
let mut events = mio::Events::with_capacity(256);
loop {
if let Err(e) = self.poll.poll(&mut events, self.timeout) {
match e.kind() {
if let Err(err) = self.poll.poll(&mut events, self.timeout) {
match err.kind() {
io::ErrorKind::Interrupted => {}
_ => panic!("Poll error: {}", e),
_ => panic!("Poll error: {}", err),
}
}
@@ -140,7 +140,7 @@ impl Accept {
WAKER_TOKEN => {
let exit = self.handle_waker(sockets);
if exit {
info!("Accept thread stopped");
info!("accept thread stopped");
return;
}
}
@@ -161,11 +161,13 @@ impl Accept {
// a loop that would try to drain the command channel. It's yet unknown
// if it's necessary/good practice to actively drain the waker queue.
loop {
// take guard with every iteration so no new interest can be added
// until the current task is done.
// Take guard with every iteration so no new interests can be added until the current
// task is done. Take care not to take the guard again inside this loop.
let mut guard = self.waker_queue.guard();
#[allow(clippy::significant_drop_in_scrutinee)]
match guard.pop_front() {
// worker notify it becomes available.
// Worker notified it became available.
Some(WakerInterest::WorkerAvailable(idx)) => {
drop(guard);
@@ -176,7 +178,7 @@ impl Accept {
}
}
// a new worker thread is made and it's handle would be added to Accept
// A new worker thread has been created so store its handle.
Some(WakerInterest::Worker(handle)) => {
drop(guard);
@@ -297,16 +299,16 @@ impl Accept {
fn register_logged(&self, info: &mut ServerSocketInfo) {
match self.register(info) {
Ok(_) => debug!("Resume accepting connections on {}", info.lst.local_addr()),
Err(e) => error!("Can not register server socket {}", e),
Ok(_) => debug!("resume accepting connections on {}", info.lst.local_addr()),
Err(err) => error!("can not register server socket {}", err),
}
}
fn deregister_logged(&self, info: &mut ServerSocketInfo) {
match self.poll.registry().deregister(&mut info.lst) {
Ok(_) => debug!("Paused accepting connections on {}", info.lst.local_addr()),
Err(e) => {
error!("Can not deregister server socket {}", e)
Ok(_) => debug!("paused accepting connections on {}", info.lst.local_addr()),
Err(err) => {
error!("can not deregister server socket {}", err)
}
}
}
@@ -350,7 +352,7 @@ impl Accept {
self.remove_next();
if self.handles.is_empty() {
error!("No workers");
error!("no workers");
// All workers are gone and Conn is nowhere to be sent.
// Treat this situation as Ok and drop Conn.
return Ok(());
@@ -396,10 +398,10 @@ impl Accept {
let conn = Conn { io, token };
self.accept_one(conn);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return,
Err(ref e) if connection_error(e) => continue,
Err(e) => {
error!("Error accepting connection: {}", e);
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return,
Err(ref err) if connection_error(err) => continue,
Err(err) => {
error!("error accepting connection: {}", err);
// deregister listener temporary
self.deregister_logged(info);

View File

@@ -1,19 +1,34 @@
use std::{io, time::Duration};
use std::{io, num::NonZeroUsize, time::Duration};
use actix_rt::net::TcpStream;
use log::{info, trace};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
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>,
@@ -220,10 +297,10 @@ impl ServerBuilder {
{
// The path must not exist when we try to bind.
// Try to remove it to avoid bind error.
if let Err(e) = std::fs::remove_file(addr.as_ref()) {
if let Err(err) = std::fs::remove_file(addr.as_ref()) {
// NotFound is expected and not an issue. Anything else is.
if e.kind() != std::io::ErrorKind::NotFound {
return Err(e);
if err.kind() != std::io::ErrorKind::NotFound {
return Err(err);
}
}
@@ -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,23 +349,25 @@ impl ServerBuilder {
pub(super) fn bind_addr<S: ToSocketAddrs>(
addr: S,
backlog: u32,
mptcp: &MpTcp,
) -> io::Result<Vec<MioTcpListener>> {
let mut err = None;
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);
}
Err(e) => err = Some(e),
Err(err) => opt_err = Some(err),
}
}
if success {
Ok(sockets)
} else if let Some(err) = err.take() {
} else if let Some(err) = opt_err.take() {
Err(err)
} else {
Err(io::Error::new(

View File

@@ -63,10 +63,10 @@ impl<T> Future for JoinAll<T> {
#[cfg(test)]
mod test {
use super::*;
use actix_utils::future::ready;
use super::*;
#[actix_rt::test]
async fn test_join_all() {
let futs = vec![ready(Ok(1)), ready(Err(3)), ready(Ok(9))];

View File

@@ -18,14 +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;
pub use self::test_server::TestServer;
#[doc(hidden)]
pub use self::socket::FromStream;
pub use self::{
builder::{MpTcp, ServerBuilder},
handle::ServerHandle,
server::Server,
service::ServerServiceFactory,
test_server::TestServer,
};
/// Start server building process
#[doc(hidden)]

View File

@@ -3,14 +3,15 @@ use std::{
io, mem,
pin::Pin,
task::{Context, Poll},
thread,
time::Duration,
};
use actix_rt::{time::sleep, System};
use futures_core::{future::BoxFuture, Stream};
use futures_util::stream::StreamExt as _;
use log::{error, info};
use tokio::sync::{mpsc::UnboundedReceiver, oneshot};
use tracing::{error, info};
use crate::{
accept::Accept,
@@ -65,7 +66,7 @@ pub(crate) enum ServerCommand {
/// server has fully shut down.
///
/// # Shutdown Signals
/// On UNIX systems, `SIGQUIT` will start a graceful shutdown and `SIGTERM` or `SIGINT` will start a
/// On UNIX systems, `SIGTERM` will start a graceful shutdown and `SIGQUIT` or `SIGINT` will start a
/// forced shutdown. On Windows, a Ctrl-C signal will start a forced shutdown.
///
/// A graceful shutdown will wait for all workers to stop first.
@@ -158,6 +159,7 @@ impl Future for Server {
pub struct ServerInner {
worker_handles: Vec<WorkerHandleServer>,
accept_handle: Option<thread::JoinHandle<()>>,
worker_config: ServerWorkerConfig,
services: Vec<Box<dyn InternalServiceFactory>>,
waker_queue: WakerQueue,
@@ -181,11 +183,6 @@ impl ServerInner {
}
fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
let sockets = mem::take(&mut builder.sockets)
.into_iter()
.map(|t| (t.0, t.2))
.collect();
// Give log information on what runtime will be used.
let is_actix = actix_rt::System::try_current().is_some();
let is_tokio = tokio::runtime::Handle::try_current().is_ok();
@@ -198,14 +195,19 @@ impl ServerInner {
for (_, name, lst) in &builder.sockets {
info!(
r#"Starting service: "{}", workers: {}, listening on: {}"#,
r#"starting service: "{}", workers: {}, listening on: {}"#,
name,
builder.threads,
lst.local_addr()
);
}
let (waker_queue, worker_handles) = Accept::start(sockets, &builder)?;
let sockets = mem::take(&mut builder.sockets)
.into_iter()
.map(|t| (t.0, t.2))
.collect();
let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
let mux = ServerEventMultiplexer {
signal_fut: (builder.listen_os_signals).then(Signals::new),
@@ -214,6 +216,7 @@ impl ServerInner {
let server = ServerInner {
waker_queue,
accept_handle: Some(accept_handle),
worker_handles,
worker_config: builder.worker_config,
services: builder.factories,
@@ -243,7 +246,8 @@ impl ServerInner {
} => {
self.stopping = true;
// stop accept thread
// Signal accept thread to stop.
// Signal is non-blocking; we wait for thread to stop later.
self.waker_queue.wake(WakerInterest::Stop);
// send stop signal to workers
@@ -258,6 +262,13 @@ impl ServerInner {
let _ = join_all(workers_stop).await;
}
// wait for accept thread stop
self.accept_handle
.take()
.unwrap()
.join()
.expect("Accept thread must not panic in any case");
if let Some(tx) = completion {
let _ = tx.send(());
}
@@ -272,7 +283,7 @@ impl ServerInner {
// TODO: maybe just return with warning log if not found ?
assert!(self.worker_handles.iter().any(|wrk| wrk.idx == idx));
error!("Worker {} has died; restarting", idx);
error!("worker {} has died; restarting", idx);
let factories = self
.services
@@ -352,6 +363,6 @@ impl Stream for ServerEventMultiplexer {
}
}
Pin::new(&mut this.cmd_rx).poll_recv(cx)
this.cmd_rx.poll_recv(cx)
}
}

View File

@@ -7,7 +7,7 @@ use std::{
use actix_service::{Service, ServiceFactory as BaseServiceFactory};
use actix_utils::future::{ready, Ready};
use futures_core::future::LocalBoxFuture;
use log::error;
use tracing::error;
use crate::{
socket::{FromStream, MioStream},
@@ -77,8 +77,8 @@ where
});
Ok(())
}
Err(e) => {
error!("Can not convert to an async tcp stream: {}", e);
Err(err) => {
error!("can not convert to an async TCP stream: {err}");
Err(())
}
})

View File

@@ -5,7 +5,7 @@ use std::{
task::{Context, Poll},
};
use log::trace;
use tracing::trace;
/// Types of process signals.
// #[allow(dead_code)]
@@ -69,8 +69,8 @@ impl Signals {
unix::signal(*kind)
.map(|tokio_sig| (*sig, tokio_sig))
.map_err(|e| {
log::error!(
"Can not initialize stream handler for {:?} err: {}",
tracing::error!(
"can not initialize stream handler for {:?} err: {}",
sig,
e
)
@@ -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);
}

View File

@@ -6,13 +6,13 @@ use std::{fmt, io};
use actix_rt::net::TcpStream;
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)]
@@ -106,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),
}
}
@@ -126,7 +126,7 @@ pub(crate) enum SocketAddr {
Unknown,
Tcp(StdSocketAddr),
#[cfg(unix)]
Uds(mio::net::SocketAddr),
Uds(std::os::unix::net::SocketAddr),
}
impl fmt::Display for SocketAddr {
@@ -225,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)?;
@@ -249,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"));

View File

@@ -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();
}

View File

@@ -1,6 +1,7 @@
use std::{
future::Future,
io, mem,
num::NonZeroUsize,
pin::Pin,
rc::Rc,
sync::{
@@ -17,11 +18,11 @@ use actix_rt::{
Arbiter, ArbiterHandle, System,
};
use futures_core::{future::LocalBoxFuture, ready};
use log::{error, info, trace};
use tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
oneshot,
};
use tracing::{error, info, trace};
use crate::{
service::{BoxedServerService, InternalServiceFactory},
@@ -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,
@@ -337,7 +341,7 @@ impl ServerWorker {
Ok((token, svc)) => services.push((idx, token, svc)),
Err(err) => {
error!("Can not start worker: {:?}", err);
error!("can not start worker: {:?}", err);
return Err(io::Error::new(
io::ErrorKind::Other,
format!("can not start server service {}", idx),
@@ -436,7 +440,7 @@ impl ServerWorker {
Ok((token, svc)) => services.push((idx, token, svc)),
Err(err) => {
error!("Can not start worker: {:?}", err);
error!("can not start worker: {:?}", err);
Arbiter::current().stop();
factory_tx
.send(Err(io::Error::new(
@@ -476,7 +480,7 @@ impl ServerWorker {
fn restart_service(&mut self, idx: usize, factory_id: usize) {
let factory = &self.factories[factory_id];
trace!("Service {:?} failed, restarting", factory.name(idx));
trace!("service {:?} failed, restarting", factory.name(idx));
self.services[idx].status = WorkerServiceStatus::Restarting;
self.state = WorkerState::Restarting(Restart {
factory_id,
@@ -508,7 +512,7 @@ impl ServerWorker {
Poll::Ready(Ok(_)) => {
if srv.status == WorkerServiceStatus::Unavailable {
trace!(
"Service {:?} is available",
"service {:?} is available",
self.factories[srv.factory_idx].name(idx)
);
srv.status = WorkerServiceStatus::Available;
@@ -519,7 +523,7 @@ impl ServerWorker {
if srv.status == WorkerServiceStatus::Available {
trace!(
"Service {:?} is unavailable",
"service {:?} is unavailable",
self.factories[srv.factory_idx].name(idx)
);
srv.status = WorkerServiceStatus::Unavailable;
@@ -527,7 +531,7 @@ impl ServerWorker {
}
Poll::Ready(Err(_)) => {
error!(
"Service {:?} readiness check returned error, restarting",
"service {:?} readiness check returned error, restarting",
self.factories[srv.factory_idx].name(idx)
);
srv.status = WorkerServiceStatus::Failed;
@@ -585,16 +589,14 @@ 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");
info!("shutting down idle worker");
let _ = tx.send(true);
return Poll::Ready(());
} else if graceful {
info!("Graceful worker shutdown; finishing {} connections", num);
info!("graceful worker shutdown; finishing {} connections", num);
this.shutdown(false);
this.state = WorkerState::Shutdown(Shutdown {
@@ -603,7 +605,7 @@ impl Future for ServerWorker {
tx,
});
} else {
info!("Force shutdown worker, closing {} connections", num);
info!("force shutdown worker, closing {} connections", num);
this.shutdown(true);
let _ = tx.send(false);
@@ -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)
@@ -638,7 +641,7 @@ impl Future for ServerWorker {
assert_eq!(token, token_new);
trace!(
"Service {:?} has been restarted",
"service {:?} has been restarted",
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,12 +684,13 @@ 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) {
Ok(true) => {}
Ok(false) => {
trace!("Worker is unavailable");
trace!("worker is unavailable");
this.state = WorkerState::Unavailable;
return self.poll(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)| {

View File

@@ -1,3 +1,5 @@
#![allow(clippy::let_underscore_future)]
use std::{
net,
sync::{
@@ -186,9 +188,9 @@ fn test_start() {
#[actix_rt::test]
async fn test_max_concurrent_connections() {
// Note:
// A tcp listener would accept connects based on it's backlog setting.
// A TCP listener would accept connects based on it's backlog setting.
//
// The limit test on the other hand is only for concurrent tcp stream limiting a work
// The limit test on the other hand is only for concurrent TCP stream limiting a work
// thread accept.
use tokio::io::AsyncWriteExt;
@@ -254,6 +256,7 @@ async fn test_max_concurrent_connections() {
h.join().unwrap().unwrap();
}
// TODO: race-y failures detected due to integer underflow when calling Counter::total
#[actix_rt::test]
async fn test_service_restart() {
use std::task::{Context, Poll};

View File

@@ -1,35 +1,37 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.70.
## 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]
@@ -37,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;
@@ -197,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

View File

@@ -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 }

View File

@@ -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)

View File

@@ -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;

View File

@@ -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,
@@ -209,15 +208,13 @@ where
#[cfg(test)]
mod tests {
use core::task::Poll;
use futures_util::future::lazy;
use super::*;
use crate::{
ok,
pipeline::{pipeline, pipeline_factory},
Ready, Service, ServiceFactory,
Ready,
};
#[derive(Clone)]

View File

@@ -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>,

View File

@@ -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,

View File

@@ -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>>,
@@ -356,7 +351,6 @@ mod tests {
use futures_util::future::lazy;
use super::*;
use crate::{ok, Service, ServiceFactory};
#[actix_rt::test]
async fn test_fn_service() {
@@ -394,18 +388,18 @@ mod tests {
#[actix_rt::test]
async fn test_auto_impl_send() {
use crate::{map_config, ServiceExt, ServiceFactoryExt};
use alloc::rc::Rc;
use crate::{map_config, ServiceExt, ServiceFactoryExt};
let srv_1 = fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8)));
let fac_1 = fn_factory_with_config(|_: Rc<u8>| {
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) {}

View File

@@ -33,15 +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};
pub use self::transform::{apply, ApplyTransform, Transform};
#[allow(unused_imports)]
use self::ready::{err, ok, ready, Ready};
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`.
///

View File

@@ -25,6 +25,8 @@
/// }
/// }
/// ```
///
/// [`forward_ready!`]: crate::forward_ready
#[macro_export]
macro_rules! always_ready {
() => {

View File

@@ -97,7 +97,7 @@ where
match this.fut.poll(cx) {
Poll::Ready(Ok(resp)) => Poll::Ready(Ok((this.f)(resp))),
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
Poll::Pending => Poll::Pending,
}
}
@@ -202,9 +202,7 @@ mod tests {
use futures_util::future::lazy;
use super::*;
use crate::{
ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory, ServiceFactoryExt,
};
use crate::{ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
struct Srv;

View File

@@ -205,10 +205,7 @@ mod tests {
use futures_util::future::lazy;
use super::*;
use crate::{
err, ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory,
ServiceFactoryExt,
};
use crate::{err, ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
struct Srv;

View File

@@ -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,

View File

@@ -226,9 +226,9 @@ mod tests {
use actix_utils::future::{ready, Ready};
use super::*;
use crate::Service;
// pseudo-doctest for Transform trait
#[allow(unused)]
pub struct TimeoutTransform {
timeout: Duration,
}
@@ -250,6 +250,7 @@ mod tests {
}
// pseudo-doctest for Transform trait
#[allow(unused)]
pub struct Timeout<S> {
service: S,
_timeout: Duration,

View File

@@ -1,23 +1,68 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
## 3.4.0
- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features.
- Minimum supported Rust version (MSRV) is now 1.70.
## 3.3.0
- Add `rustls-0_22` crate feature which excludes any root certificate methods or re-exports.
## 3.2.0
- Support Rustls v0.22.
- Add `{accept, connect}::rustls_0_22` modules.
- Add `rustls-0_21-native-roots` and `rustls-0_20-native-roots` crate features which utilize the `rustls-native-certs` crate to enable a `native_roots_cert_store()` functions in each rustls-based `connect` module.
- Implement `Host` for `http::Uri` (`http` crate version `1`).
## 3.1.1
- Fix `rustls` v0.21 version requirement.
## 3.1.0
- Support Rustls v0.21.
- Add `{accept, connect}::rustls_0_21` modules.
- Add `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
- Minimum supported Rust version (MSRV) is now 1.65.
## 3.0.4
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
[#451]: https://github.com/actix/actix-net/pull/451
## 3.0.3
- No significant changes since `3.0.2`.
## 3.0.2
- 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 - 2021-11-29
## 3.0.0-rc.1
### 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]
@@ -27,6 +72,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]
@@ -43,6 +89,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]
@@ -50,8 +97,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]
@@ -60,31 +107,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]
@@ -96,74 +142,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 - 2021-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

123
actix-tls/Cargo.toml Executable file → Normal file
View File

@@ -1,6 +1,6 @@
[package]
name = "actix-tls"
version = "3.0.1"
version = "3.4.0"
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,55 +41,101 @@ accept = []
connect = []
# use openssl impls
openssl = ["tls-openssl", "tokio-openssl"]
openssl = ["dep:tls-openssl", "dep:tokio-openssl"]
# use rustls impls
rustls = ["tokio-rustls", "webpki-roots"]
# alias for backwards compat
rustls = ["rustls-0_20"]
# use rustls v0.20 impls
rustls-0_20 = ["rustls-0_20-webpki-roots"]
rustls-0_20-webpki-roots = ["tokio-rustls-023", "webpki-roots-022"]
rustls-0_20-native-roots = ["tokio-rustls-023", "dep:rustls-native-certs-06"]
# use rustls v0.21 impls
rustls-0_21 = ["rustls-0_21-webpki-roots"]
rustls-0_21-webpki-roots = ["tokio-rustls-024", "webpki-roots-025"]
rustls-0_21-native-roots = ["tokio-rustls-024", "dep:rustls-native-certs-06"]
# use rustls v0.22 impls
rustls-0_22 = ["dep:tokio-rustls-025", "dep:rustls-pki-types-1"]
rustls-0_22-webpki-roots = ["rustls-0_22", "dep:webpki-roots-026"]
rustls-0_22-native-roots = ["rustls-0_22", "dep:rustls-native-certs-07"]
# use rustls v0.23 impls
rustls-0_23 = ["dep:tokio-rustls-026", "dep:rustls-pki-types-1"]
rustls-0_23-webpki-roots = ["rustls-0_23", "dep:webpki-roots-026"]
rustls-0_23-native-roots = ["rustls-0_23", "dep:rustls-native-certs-07"]
# use native-tls impls
native-tls = ["tokio-native-tls"]
native-tls = ["dep:tokio-native-tls"]
# support http::Uri as connect address
uri = ["http"]
uri = ["dep:http-0_2", "dep:http-1"]
[dependencies]
actix-codec = "0.4.2"
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"
derive_more = "0.99.5"
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
log = "0.4"
impl-more = "0.1"
pin-project-lite = "0.2.7"
tokio-util = { version = "0.6.3", default-features = false }
tokio = "1.23.1"
tokio-util = "0.7"
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
# uri
http = { version = "0.2.3", optional = true }
http-0_2 = { package = "http", version = "0.2.3", optional = true }
http-1 = { package = "http", version = "1", optional = true }
# openssl
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 PKI types
rustls-pki-types-1 = { package = "rustls-pki-types", version = "1", optional = true }
# rustls v0.20
tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true }
# rustls v0.21
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
# rustls v0.22
tokio-rustls-025 = { package = "tokio-rustls", version = "0.25", optional = true }
# rustls v0.23
tokio-rustls-026 = { package = "tokio-rustls", version = "0.26", default-features = false, optional = true }
# webpki-roots used with rustls features
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
webpki-roots-026 = { package = "webpki-roots", version = "0.26", optional = true }
# native root certificates for rustls impls
rustls-native-certs-06 = { package = "rustls-native-certs", version = "0.6", optional = true }
rustls-native-certs-07 = { package = "rustls-native-certs", version = "0.7", optional = true }
# native-tls
tokio-native-tls = { version = "0.3", optional = true }
[target.'cfg(any())'.dependencies]
rustls-021 = { package = "rustls", version = "0.21.6", optional = true } # force version with add_trust_anchors method
rustls-webpki-0101 = { package = "rustls-webpki", version = "0.101.4", optional = true } # force secure version
[dev-dependencies]
actix-rt = "2.2.0"
actix-server = "2.0.0-rc.3"
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"
pretty_env_logger = "0.5"
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
itertools = "0.13"
rcgen = "0.12"
rustls-pemfile = "2"
tokio-rustls-026 = { package = "tokio-rustls", version = "0.26" }
trust-dns-resolver = "0.23"
[[example]]
name = "accept-rustls"
required-features = ["accept", "rustls"]
required-features = ["accept", "rustls-0_23"]

21
actix-tls/README.md Normal file
View File

@@ -0,0 +1,21 @@
# `actix-tls`
> TLS acceptor and connector services for the Actix ecosystem.
<!-- prettier-ignore-start -->
[![crates.io](https://img.shields.io/crates/v/actix-tls?label=latest)](https://crates.io/crates/actix-tls)
[![Documentation](https://docs.rs/actix-tls/badge.svg?version=3.4.0)](https://docs.rs/actix-tls/3.4.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)
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-tls.svg)
<br />
[![Dependency Status](https://deps.rs/crate/actix-tls/3.4.0/status.svg)](https://deps.rs/crate/actix-tls/3.4.0)
![Download](https://img.shields.io/crates/d/actix-tls.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-tls)
- [Examples](/actix-tls/examples)

View File

@@ -15,14 +15,12 @@
//! http --verify=false https://127.0.0.1:8443
//! ```
// this use only exists because of how we have organised the crate
// it is not necessary for your actual code
use tokio_rustls::rustls;
// this `use` is only exists because of how we have organised the crate
// it is not necessary for your actual code; you should import from `rustls` normally
use std::{
env,
fs::File,
io::{self, BufReader},
path::PathBuf,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
@@ -32,32 +30,40 @@ 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_23::{Acceptor as RustlsAcceptor, TlsStream};
use futures_util::future::ok;
use log::info;
use rustls::{server::ServerConfig, Certificate, PrivateKey};
use itertools::Itertools as _;
use rustls::server::ServerConfig;
use rustls_pemfile::{certs, rsa_private_keys};
use rustls_pki_types_1::PrivateKeyDer;
use tokio_rustls_026::rustls;
use tracing::info;
#[actix_rt::main]
async fn main() -> io::Result<()> {
env::set_var("RUST_LOG", "info");
env_logger::init();
pretty_env_logger::formatted_timed_builder()
.parse_env(pretty_env_logger::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()
.into_iter()
.map(Certificate)
.collect();
let mut keys = rsa_private_keys(key_file).unwrap();
let cert_chain = certs(cert_file);
let mut keys = rsa_private_keys(key_file);
let tls_config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
.with_single_cert(
cert_chain.try_collect::<_, Vec<_>, _>()?,
PrivateKeyDer::Pkcs1(keys.next().unwrap()?),
)
.unwrap();
let tls_acceptor = RustlsAcceptor::new(tls_config);
@@ -65,7 +71,7 @@ async fn main() -> io::Result<()> {
let count = Arc::new(AtomicUsize::new(0));
let addr = ("127.0.0.1", 8443);
info!("starting server on port: {}", &addr.0);
info!("starting server at: {addr:?}");
Server::build()
.bind("tls-example", addr, move || {

View File

@@ -2,27 +2,45 @@
use std::{
convert::Infallible,
error::Error,
fmt,
sync::atomic::{AtomicUsize, Ordering},
};
use actix_utils::counter::Counter;
use derive_more::{Display, Error};
#[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 = "rustls-0_22")]
pub mod rustls_0_22;
#[cfg(feature = "rustls-0_23")]
pub mod rustls_0_23;
#[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 = "rustls-0_22",
feature = "rustls-0_23",
feature = "native-tls",
))]
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
std::time::Duration::from_secs(3);
@@ -43,20 +61,18 @@ pub fn max_concurrent_tls_connect(num: usize) {
/// TLS handshake error, TLS timeout, or inner service error.
///
/// All TLS acceptors from this crate will return the `SvcErr` type parameter as [`Infallible`],
/// which can be cast to your own service type, inferred or otherwise,
/// using [`into_service_error`](Self::into_service_error).
#[derive(Debug, Display, Error)]
/// which can be cast to your own service type, inferred or otherwise, using [`into_service_error`].
///
/// [`into_service_error`]: Self::into_service_error
#[derive(Debug)]
pub enum TlsError<TlsErr, SvcErr> {
/// TLS handshake has timed-out.
#[display(fmt = "TLS handshake has timed-out")]
Timeout,
/// Wraps TLS service errors.
#[display(fmt = "TLS handshake error")]
Tls(TlsErr),
/// Wraps service errors.
#[display(fmt = "Service error")]
Service(SvcErr),
}
@@ -79,6 +95,30 @@ impl<TlsErr> TlsError<TlsErr, Infallible> {
}
}
impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Timeout => f.write_str("TLS handshake has timed-out"),
Self::Tls(_) => f.write_str("TLS handshake error"),
Self::Service(_) => f.write_str("Service error"),
}
}
}
impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
where
TlsErr: Error + 'static,
SvcErr: Error + 'static,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
TlsError::Tls(err) => Some(err),
TlsError::Service(err) => Some(err),
TlsError::Timeout => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -10,7 +10,6 @@ use std::{
time::Duration,
};
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
use actix_rt::{
net::{ActixStream, Ready},
time::timeout,
@@ -20,8 +19,8 @@ use actix_utils::{
counter::Counter,
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
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};
@@ -33,9 +32,11 @@ pub mod reexports {
}
/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
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(
self: Pin<&mut Self>,
@@ -72,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)
}
}

View File

@@ -11,7 +11,6 @@ use std::{
time::Duration,
};
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
use actix_rt::{
net::{ActixStream, Ready},
time::{sleep, Sleep},
@@ -21,9 +20,9 @@ use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
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};
@@ -36,9 +35,11 @@ pub mod reexports {
}
/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
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(
self: Pin<&mut Self>,
@@ -75,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)
}
}

View File

@@ -1,4 +1,4 @@
//! `rustls` based TLS connection acceptor service.
//! `rustls` v0.20 based TLS connection acceptor service.
//!
//! See [`Acceptor`] for main service factory docs.
@@ -12,7 +12,6 @@ use std::{
time::Duration,
};
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
use actix_rt::{
net::{ActixStream, Ready},
time::{sleep, Sleep},
@@ -22,23 +21,25 @@ use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
use pin_project_lite::pin_project;
use tokio_rustls::rustls::ServerConfig;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_rustls::{Accept, TlsAcceptor};
use tokio_rustls_023 as tokio_rustls;
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
pub mod reexports {
//! Re-exports from `rustls` that are useful for acceptors.
pub use tokio_rustls::rustls::ServerConfig;
pub use tokio_rustls_023::rustls::ServerConfig;
}
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
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>,
@@ -75,29 +76,29 @@ 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)
}
}
/// Accept TLS connections via the `rustls` crate.
pub struct Acceptor {
config: Arc<ServerConfig>,
config: Arc<reexports::ServerConfig>,
handshake_timeout: Duration,
}
impl Acceptor {
/// Constructs `rustls` based acceptor service factory.
pub fn new(config: ServerConfig) -> Self {
pub fn new(config: reexports::ServerConfig) -> Self {
Acceptor {
config: Arc::new(config),
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,

View File

@@ -0,0 +1,198 @@
//! `rustls` v0.21 based TLS connection acceptor service.
//!
//! See [`Acceptor`] for main service factory docs.
use std::{
convert::Infallible,
future::Future,
io::{self, IoSlice},
pin::Pin,
sync::Arc,
task::{Context, Poll},
time::Duration,
};
use actix_rt::{
net::{ActixStream, Ready},
time::{sleep, Sleep},
};
use actix_service::{Service, ServiceFactory};
use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use pin_project_lite::pin_project;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_rustls::{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<reexports::ServerConfig>,
handshake_timeout: Duration,
}
impl Acceptor {
/// Constructs `rustls` based acceptor service factory.
pub fn new(config: reexports::ServerConfig) -> Self {
Acceptor {
config: Arc::new(config),
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
}
}
/// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
///
/// Default timeout is 3 seconds.
pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
self.handshake_timeout = handshake_timeout;
self
}
}
impl Clone for Acceptor {
fn clone(&self) -> Self {
Self {
config: self.config.clone(),
handshake_timeout: self.handshake_timeout,
}
}
}
impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
type Response = TlsStream<IO>;
type Error = TlsError<io::Error, Infallible>;
type Config = ();
type Service = AcceptorService;
type InitError = ();
type Future = FutReady<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: ()) -> Self::Future {
let res = MAX_CONN_COUNTER.with(|conns| {
Ok(AcceptorService {
acceptor: self.config.clone().into(),
conns: conns.clone(),
handshake_timeout: self.handshake_timeout,
})
});
ready(res)
}
}
/// Rustls based acceptor service.
pub struct AcceptorService {
acceptor: TlsAcceptor,
conns: Counter,
handshake_timeout: Duration,
}
impl<IO: ActixStream> Service<IO> for AcceptorService {
type Response = TlsStream<IO>;
type Error = TlsError<io::Error, Infallible>;
type Future = AcceptFut<IO>;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
if self.conns.available(cx) {
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
}
fn call(&self, req: IO) -> Self::Future {
AcceptFut {
fut: self.acceptor.accept(req),
timeout: sleep(self.handshake_timeout),
_guard: self.conns.get(),
}
}
}
pin_project! {
/// Accept future for Rustls service.
#[doc(hidden)]
pub struct AcceptFut<IO: ActixStream> {
fut: Accept<IO>,
#[pin]
timeout: Sleep,
_guard: CounterGuard,
}
}
impl<IO: ActixStream> Future for AcceptFut<IO> {
type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
match Pin::new(&mut this.fut).poll(cx) {
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
}
}
}

View File

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

View File

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

View File

@@ -1,20 +1,17 @@
use derive_more::{Deref, DerefMut};
use super::Host;
/// Wraps underlying I/O and the connection request that initiated it.
#[derive(Debug, Deref, DerefMut)]
#[derive(Debug)]
pub struct Connection<R, IO> {
pub(crate) req: R,
#[deref]
#[deref_mut]
pub(crate) 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.
pub(crate) fn new(req: R, io: IO) -> Self {
pub fn new(req: R, io: IO) -> Self {
Self { req, io }
}
}

View File

@@ -1,30 +1,38 @@
use std::{error::Error, io};
use derive_more::Display;
use std::{error::Error, fmt, io};
/// Errors that can result from using a connector service.
#[derive(Debug, Display)]
#[derive(Debug)]
pub enum ConnectError {
/// Failed to resolve the hostname
#[display(fmt = "Failed resolving hostname")]
/// Failed to resolve the hostname.
Resolver(Box<dyn std::error::Error>),
/// No DNS records
#[display(fmt = "No DNS records found for the input")]
/// No DNS records.
NoRecords,
/// Invalid input
/// Invalid input.
InvalidInput,
/// Unresolved host name
#[display(fmt = "Connector received `Connect` method with unresolved host")]
/// Unresolved host name.
Unresolved,
/// Connection IO error
#[display(fmt = "{}", _0)]
/// Connection IO error.
Io(io::Error),
}
impl fmt::Display for ConnectError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoRecords => f.write_str("No DNS records found for the input"),
Self::InvalidInput => f.write_str("Invalid input"),
Self::Unresolved => {
f.write_str("Connector received `Connect` method with unresolved host")
}
Self::Resolver(_) => f.write_str("Failed to resolve hostname"),
Self::Io(_) => f.write_str("I/O error"),
}
}
}
impl Error for ConnectError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {

View File

@@ -27,25 +27,25 @@ pub trait Host: Unpin + 'static {
impl Host for String {
fn hostname(&self) -> &str {
str_split_once(self, ':')
self.split_once(':')
.map(|(hostname, _)| hostname)
.unwrap_or(self)
}
fn port(&self) -> Option<u16> {
str_split_once(self, ':').and_then(|(_, port)| port.parse().ok())
self.split_once(':').and_then(|(_, port)| port.parse().ok())
}
}
impl Host for &'static str {
fn hostname(&self) -> &str {
str_split_once(self, ':')
self.split_once(':')
.map(|(hostname, _)| hostname)
.unwrap_or(self)
}
fn port(&self) -> Option<u16> {
str_split_once(self, ':').and_then(|(_, port)| port.parse().ok())
self.split_once(':').and_then(|(_, port)| port.parse().ok())
}
}
@@ -69,11 +69,3 @@ mod tests {
assert_connection_info_eq!("example.com:false:false", "example.com", None);
}
}
// `str::split_once` is stabilized in 1.52.0
fn str_split_once(str: &str, delimiter: char) -> Option<(&str, &str)> {
let mut splitn = str.splitn(2, delimiter);
let prefix = splitn.next()?;
let suffix = splitn.next()?;
Some((prefix, suffix))
}

View File

@@ -118,6 +118,7 @@ impl<R: Host> ConnectInfo<R> {
/// let mut addrs = conn.addrs();
/// assert_eq!(addrs.next().unwrap(), addr);
/// ```
#[allow(clippy::implied_bounds_in_impls)]
pub fn addrs(
&self,
) -> impl Iterator<Item = SocketAddr>
@@ -149,6 +150,7 @@ impl<R: Host> ConnectInfo<R> {
/// let mut addrs = conn.take_addrs();
/// assert_eq!(addrs.next().unwrap(), addr);
/// ```
#[allow(clippy::implied_bounds_in_impls)]
pub fn take_addrs(
&mut self,
) -> impl Iterator<Item = SocketAddr>

View File

@@ -22,25 +22,45 @@ 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(any(
feature = "rustls-0_20-webpki-roots",
feature = "rustls-0_20-native-roots",
))]
pub mod rustls_0_20;
#[doc(hidden)]
#[cfg(any(
feature = "rustls-0_20-webpki-roots",
feature = "rustls-0_20-native-roots",
))]
pub use rustls_0_20 as rustls;
#[cfg(any(
feature = "rustls-0_21-webpki-roots",
feature = "rustls-0_21-native-roots",
))]
pub mod rustls_0_21;
#[cfg(feature = "rustls-0_22")]
pub mod rustls_0_22;
#[cfg(feature = "rustls-0_23")]
pub mod rustls_0_23;
#[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},
};

View File

@@ -8,20 +8,18 @@ use actix_rt::net::ActixStream;
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::future::LocalBoxFuture;
use log::trace;
use tokio_native_tls::{
native_tls::TlsConnector as NativeTlsConnector, TlsConnector as AsyncNativeTlsConnector,
TlsStream as AsyncTlsStream,
};
use tracing::trace;
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`.
@@ -75,16 +73,16 @@ where
let connector = self.connector.clone();
Box::pin(async move {
trace!("SSL Handshake start for: {:?}", stream.hostname());
trace!("TLS handshake start for: {:?}", stream.hostname());
connector
.connect(stream.hostname(), io)
.await
.map(|res| {
trace!("SSL Handshake success: {:?}", stream.hostname());
trace!("TLS handshake success: {:?}", stream.hostname());
stream.replace_io(res).1
})
.map_err(|e| {
trace!("SSL Handshake error: {:?}", e);
trace!("TLS handshake error: {:?}", e);
io::Error::new(io::ErrorKind::Other, format!("{}", e))
})
})

View File

@@ -13,19 +13,16 @@ use actix_rt::net::ActixStream;
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::ready;
use log::trace;
use openssl::ssl::SslConnector;
use tokio_openssl::SslStream as AsyncSslStream;
use tracing::trace;
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;
}
@@ -98,7 +95,8 @@ where
actix_service::always_ready!();
fn call(&self, stream: Connection<R, IO>) -> Self::Future {
trace!("SSL Handshake start for: {:?}", stream.hostname());
trace!("TLS handshake start for: {:?}", stream.hostname());
let (io, stream) = stream.replace_io(());
let host = stream.hostname();
@@ -138,12 +136,15 @@ where
match ready!(Pin::new(this.io.as_mut().unwrap()).poll_connect(cx)) {
Ok(_) => {
let stream = this.stream.take().unwrap();
trace!("SSL Handshake success: {:?}", stream.hostname());
trace!("TLS handshake success: {:?}", stream.hostname());
Poll::Ready(Ok(stream.replace_io(this.io.take().unwrap()).1))
}
Err(e) => {
trace!("SSL Handshake error: {:?}", e);
Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, format!("{}", e))))
Err(err) => {
trace!("TLS handshake error: {:?}", err);
Poll::Ready(Err(io::Error::new(
io::ErrorKind::Other,
format!("{}", err),
)))
}
}
}

View File

@@ -12,7 +12,7 @@ use actix_rt::task::{spawn_blocking, JoinHandle};
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::{future::LocalBoxFuture, ready};
use log::trace;
use tracing::trace;
use super::{ConnectError, ConnectInfo, Host, Resolve};
@@ -164,8 +164,8 @@ impl<R: Host> Future for ResolverFut<R> {
Self::LookUp(fut, req) => {
let res = match ready!(Pin::new(fut).poll(cx)) {
Ok(Ok(res)) => Ok(res),
Ok(Err(e)) => Err(ConnectError::Resolver(Box::new(e))),
Err(e) => Err(ConnectError::Io(e.into())),
Ok(Err(err)) => Err(ConnectError::Resolver(Box::new(err))),
Err(err) => Err(ConnectError::Io(err.into())),
};
let req = req.take().unwrap();

View File

@@ -3,7 +3,6 @@
//! See [`TlsConnector`] for main connector service factory docs.
use std::{
convert::TryFrom,
future::Future,
io,
pin::Pin,
@@ -15,29 +14,50 @@ use actix_rt::net::ActixStream;
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::ready;
use log::trace;
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 webpki_roots::TLS_SERVER_ROOTS;
use tokio_rustls::{
client::TlsStream as AsyncTlsStream,
rustls::{client::ServerName, ClientConfig, 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.
//! Re-exports from the `rustls` v0.20 ecosystem that are useful for connectors.
pub use tokio_rustls::rustls::ClientConfig;
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
#[cfg(feature = "rustls-0_20-webpki-roots")]
pub use webpki_roots_022::TLS_SERVER_ROOTS;
}
pub use tokio_rustls::client::TlsStream as AsyncTlsStream;
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
///
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
///
/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_06::load_native_certs()
#[cfg(feature = "rustls-0_20-native-roots")]
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
let mut root_certs = RootCertStore::empty();
pub use webpki_roots::TLS_SERVER_ROOTS;
for cert in rustls_native_certs_06::load_native_certs()? {
root_certs
.add(&tokio_rustls_023::rustls::Certificate(cert.0))
.unwrap();
}
Ok(root_certs)
}
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
#[cfg(feature = "rustls-0_20-webpki-roots")]
pub fn webpki_roots_cert_store() -> RootCertStore {
use tokio_rustls_023::rustls;
let mut root_certs = RootCertStore::empty();
for cert in TLS_SERVER_ROOTS.0 {
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
cert.subject,
cert.spki,
cert.name_constraints,
@@ -45,6 +65,7 @@ pub fn webpki_roots_cert_store() -> RootCertStore {
let certs = vec![cert].into_iter();
root_certs.add_server_trust_anchors(certs);
}
root_certs
}
@@ -103,12 +124,13 @@ where
actix_service::always_ready!();
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
trace!("SSL 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,
@@ -118,6 +140,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,
@@ -132,17 +155,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!("SSL Handshake success: {:?}", connection.hostname());
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
Poll::Ready(Ok(connection.replace_io(stream).1))
}
}

View File

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

View File

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

View File

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

View File

@@ -15,8 +15,8 @@ use actix_rt::net::{TcpSocket, TcpStream};
use actix_service::{Service, ServiceFactory};
use actix_utils::future::{ok, Ready};
use futures_core::ready;
use log::{error, trace};
use tokio_util::sync::ReusableBoxFuture;
use tracing::{error, trace};
use super::{connect_addrs::ConnectAddrs, error::ConnectError, ConnectInfo, Connection, Host};
@@ -79,7 +79,7 @@ pub enum TcpConnectorFut<R> {
port: u16,
local_addr: Option<IpAddr>,
addrs: Option<VecDeque<SocketAddr>>,
stream: ReusableBoxFuture<Result<TcpStream, io::Error>>,
stream: ReusableBoxFuture<'static, Result<TcpStream, io::Error>>,
},
Error(Option<ConnectError>),
@@ -114,8 +114,8 @@ impl<R: Host> TcpConnectorFut<R> {
stream: ReusableBoxFuture::new(connect(addr, local_addr)),
},
// when resolver returns multiple socket addr for request they would be popped from
// front end of queue and returns with the first successful tcp connection.
// When resolver returns multiple socket addr for request they would be popped from
// front end of queue and returns with the first successful TCP connection.
ConnectAddrs::Multi(mut addrs) => {
let addr = addrs.pop_front().unwrap();

View File

@@ -1,8 +1,19 @@
use http::Uri;
use super::Host;
impl Host for Uri {
impl Host for http_0_2::Uri {
fn hostname(&self) -> &str {
self.host().unwrap_or("")
}
fn port(&self) -> Option<u16> {
match self.port_u16() {
Some(port) => Some(port),
None => scheme_to_port(self.scheme_str()),
}
}
}
impl Host for http_1::Uri {
fn hostname(&self) -> &str {
self.host().unwrap_or("")
}

View File

@@ -4,17 +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;

View File

@@ -3,25 +3,27 @@
#![cfg(all(
feature = "accept",
feature = "connect",
feature = "rustls",
feature = "rustls-0_23",
feature = "openssl"
))]
use std::{convert::TryFrom, io::Write, sync::Arc};
use std::{io::Write as _, sync::Arc};
use actix_rt::net::TcpStream;
use actix_server::TestServer;
use actix_service::ServiceFactoryExt as _;
use actix_tls::accept::openssl::{Acceptor, TlsStream};
use actix_tls::{
accept::openssl::{Acceptor, TlsStream},
connect::rustls_0_23::reexports::ClientConfig,
};
use actix_utils::future::ok;
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
use rustls_pki_types_1::ServerName;
use tokio_rustls_026::rustls::RootCertStore;
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();
@@ -47,30 +49,48 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
builder.build()
}
#[allow(dead_code)]
mod danger {
use std::time::SystemTime;
use super::*;
use tokio_rustls::rustls::{
self,
client::{ServerCertVerified, ServerCertVerifier},
};
use rustls_pki_types_1::{CertificateDer, ServerName, UnixTime};
use tokio_rustls_026::rustls;
/// Disables certificate verification to allow self-signed certs from rcgen.
#[derive(Debug)]
pub struct NoCertificateVerification;
impl ServerCertVerifier for NoCertificateVerification {
impl rustls::client::danger::ServerCertVerifier for NoCertificateVerification {
fn verify_server_cert(
&self,
_end_entity: &Certificate,
_intermediates: &[Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: SystemTime,
) -> Result<ServerCertVerified, rustls::Error> {
Ok(ServerCertVerified::assertion())
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp: &[u8],
_now: UnixTime,
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
Ok(rustls::client::danger::ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
_message: &[u8],
_cert: &rustls_pki_types_1::CertificateDer<'_>,
_dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
}
fn verify_tls13_signature(
&self,
_message: &[u8],
_cert: &rustls_pki_types_1::CertificateDer<'_>,
_dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
}
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
rustls::crypto::aws_lc_rs::default_provider()
.signature_verification_algorithms
.supported_schemes()
}
}
}
@@ -78,7 +98,6 @@ mod danger {
#[allow(dead_code)]
fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
let mut config = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(RootCertStore::empty())
.with_no_client_auth();
@@ -92,6 +111,10 @@ fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
#[actix_rt::test]
async fn accepts_connections() {
tokio_rustls_026::rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.unwrap();
let (cert, key) = new_cert_and_key();
let srv = TestServer::start({
@@ -118,13 +141,13 @@ async fn accepts_connections() {
let config = rustls_connector(cert, key);
let config = Arc::new(config);
let mut conn = tokio_rustls::rustls::ClientConnection::new(
let mut conn = tokio_rustls_026::rustls::ClientConnection::new(
config,
ServerName::try_from("localhost").unwrap(),
)
.unwrap();
let mut stream = tokio_rustls::rustls::Stream::new(&mut conn, &mut sock);
let mut stream = tokio_rustls_026::rustls::Stream::new(&mut conn, &mut sock);
stream.flush().expect("TLS handshake failed");
}

View File

@@ -3,7 +3,7 @@
#![cfg(all(
feature = "accept",
feature = "connect",
feature = "rustls",
feature = "rustls-0_23",
feature = "openssl"
))]
@@ -14,19 +14,19 @@ 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_23::{reexports::ServerConfig, Acceptor, TlsStream},
connect::openssl::reexports::SslConnector,
};
use actix_utils::future::ok;
use rustls_pemfile::{certs, pkcs8_private_keys};
use rustls_pki_types_1::PrivateKeyDer;
use tls_openssl::ssl::SslVerifyMode;
use tokio_rustls::rustls::{self, Certificate, PrivateKey, ServerConfig};
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();
@@ -34,19 +34,20 @@ fn new_cert_and_key() -> (String, String) {
(cert, key)
}
fn rustls_server_config(cert: String, key: String) -> rustls::ServerConfig {
fn rustls_server_config(cert: String, key: String) -> ServerConfig {
// Load TLS key and cert files
let cert = &mut BufReader::new(cert.as_bytes());
let key = &mut BufReader::new(key.as_bytes());
let cert_chain = certs(cert).unwrap().into_iter().map(Certificate).collect();
let mut keys = pkcs8_private_keys(key).unwrap();
let cert_chain = certs(cert).collect::<Result<Vec<_>, _>>().unwrap();
let mut keys = pkcs8_private_keys(key)
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
.with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0)))
.unwrap();
config.alpn_protocols = vec![b"http/1.1".to_vec()];
@@ -72,6 +73,10 @@ fn openssl_connector(cert: String, key: String) -> SslConnector {
#[actix_rt::test]
async fn accepts_connections() {
tokio_rustls_026::rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.unwrap();
let (cert, key) = new_cert_and_key();
let srv = TestServer::start({

View File

@@ -9,10 +9,9 @@ use actix_codec::{BytesCodec, Framed};
use actix_rt::net::TcpStream;
use actix_server::TestServer;
use actix_service::{fn_service, Service, ServiceFactory};
use bytes::Bytes;
use futures_util::sink::SinkExt;
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
use bytes::Bytes;
use futures_util::sink::SinkExt as _;
#[cfg(feature = "openssl")]
#[actix_rt::test]
@@ -31,7 +30,7 @@ async fn test_string() {
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-0_23")]
#[actix_rt::test]
async fn test_rustls_string() {
let srv = TestServer::start(|| {
@@ -99,8 +98,6 @@ async fn service_factory() {
#[cfg(all(feature = "openssl", feature = "uri"))]
#[actix_rt::test]
async fn test_openssl_uri() {
use std::convert::TryFrom;
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
@@ -110,16 +107,14 @@ async fn test_openssl_uri() {
});
let connector = Connector::default().service();
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let addr = http_0_2::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let con = connector.call(addr.into()).await.unwrap();
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(all(feature = "rustls", feature = "uri"))]
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
#[actix_rt::test]
async fn test_rustls_uri() {
use std::convert::TryFrom;
async fn test_rustls_uri_http1() {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
@@ -129,7 +124,24 @@ async fn test_rustls_uri() {
});
let conn = Connector::default().service();
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let con = conn.call(addr.into()).await.unwrap();
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
#[actix_rt::test]
async fn test_rustls_uri() {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
Ok::<_, io::Error>(())
})
});
let conn = Connector::default().service();
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
let con = conn.call(addr.into()).await.unwrap();
assert_eq!(con.peer_addr().unwrap(), srv.addr());
}
@@ -144,6 +156,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));

View File

@@ -8,11 +8,10 @@ use std::{
use actix_rt::net::TcpStream;
use actix_server::TestServer;
use actix_service::{fn_service, Service, ServiceFactory};
use futures_core::future::LocalBoxFuture;
use actix_tls::connect::{
ConnectError, ConnectInfo, Connection, Connector, Host, Resolve, Resolver,
};
use futures_core::future::LocalBoxFuture;
#[actix_rt::test]
async fn custom_resolver() {
@@ -52,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,

View File

@@ -1,5 +1,9 @@
# Changes
## [0.1.0] - 2020-01-15
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.70.
## 0.1.0
- Initial release

View File

@@ -5,23 +5,28 @@ authors = ["Rajasekharan Vengalil <avranju@gmail.com>"]
description = "Support for tokio tracing with Actix services"
keywords = ["network", "framework", "tracing"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git"
repository = "https://github.com/actix/actix-net/tree/master/actix-tracing"
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"
tracing = "0.1.35"
tracing-futures = "0.2"
[dev_dependencies]
actix-rt = "2.0.0"
[dev-dependencies]
actix-rt = "2"
slab = "0.4"

View File

@@ -118,18 +118,20 @@ where
#[cfg(test)]
mod test {
use super::*;
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;
use tracing::{span, Event, Level, Metadata, Subscriber};
use super::*;
thread_local! {
static SPAN: RefCell<Vec<span::Id>> = RefCell::new(Vec::new());
static SPAN: RefCell<Vec<span::Id>> = const { RefCell::new(Vec::new()) };
}
#[derive(Default)]

View File

@@ -1,19 +1,25 @@
# Changes
## Unreleased - 2021-xx-xx
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.70.
## 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]
@@ -22,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]
@@ -37,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.

View File

@@ -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"

Some files were not shown because too many files have changed in this diff Show More