Compare commits

...

1090 Commits

Author SHA1 Message Date
dependabot[bot] 7030b26a7c
build(deps): bump socket2 from 0.5.8 to 0.5.9 (#661)
Bumps [socket2](https://github.com/rust-lang/socket2) from 0.5.8 to 0.5.9.
- [Release notes](https://github.com/rust-lang/socket2/releases)
- [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/socket2/commits)

---
updated-dependencies:
- dependency-name: socket2
  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>
2025-04-03 16:35:18 +00:00
dependabot[bot] d7f60b88d3
build(deps): bump taiki-e/install-action from 2.49.34 to 2.49.40 (#660)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.49.34 to 2.49.40.
- [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.49.34...v2.49.40)

---
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>
2025-04-03 16:35:15 +00:00
dependabot[bot] b57ab7e8f0
build(deps): bump taiki-e/install-action from 2.49.32 to 2.49.34 (#659)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.49.32 to 2.49.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.49.32...v2.49.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>
2025-03-25 00:34:54 +00:00
dependabot[bot] 887975ab11
build(deps): bump taiki-e/install-action from 2.49.19 to 2.49.28 (#657)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.49.19 to 2.49.28.
- [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.49.19...v2.49.28)

---
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>
2025-03-21 06:02:34 +00:00
Rob Ede 9069fd8590
build: fix msrv 2025-03-21 05:38:25 +00:00
dependabot[bot] 8204690568
build(deps): bump syn from 2.0.99 to 2.0.100 (#652)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.99 to 2.0.100.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.99...2.0.100)

---
updated-dependencies:
- dependency-name: syn
  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>
2025-03-10 18:34:13 +00:00
dependabot[bot] bbb3139c45
build(deps): bump taiki-e/install-action from 2.49.11 to 2.49.19 (#653)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.49.11 to 2.49.19.
- [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.49.11...v2.49.19)

---
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>
2025-03-10 18:32:15 +00:00
dependabot[bot] 0915904bdb
build(deps): bump serde from 1.0.218 to 1.0.219 (#654)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.218 to 1.0.219.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

---
updated-dependencies:
- dependency-name: serde
  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>
2025-03-10 18:31:58 +00:00
Rob Ede 70f0008f42
chore(actix-service): prepare release 2.0.3 2025-03-09 17:36:45 +00:00
Dylan Anthony 12df4d7027
Remove need for paste (#649)
Co-authored-by: Dylan Anthony <dbanty@users.noreply.github.com>
2025-03-09 16:53:48 +00:00
dependabot[bot] 6f5b81d2a0
build(deps): bump codecov/codecov-action from 5.3.1 to 5.4.0 (#647)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.1 to 5.4.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/v5.3.1...v5.4.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>
2025-03-08 18:07:04 +00:00
dependabot[bot] 4cf37171b5
build(deps): bump actions-rust-lang/setup-rust-toolchain (#645)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.10.1 to 1.11.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.10.1...v1.11.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>
2025-03-08 18:02:05 +00:00
dependabot[bot] 00f40e1471
build(deps): bump taiki-e/install-action from 2.49.1 to 2.49.11 (#646)
* build(deps): bump taiki-e/install-action from 2.49.1 to 2.49.11

Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.49.1 to 2.49.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.49.1...v2.49.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>

* ci: fix msrv

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2025-03-08 17:52:46 +00:00
Rob Ede 15f0b63492
test: fix panic in tokio stream construction 2025-03-08 17:37:40 +00:00
Rob Ede 9d4b1673aa
chore(actix-server): prepare release 2.5.1 2025-03-08 17:32:46 +00:00
Rob Ede fc902b2d56
chore: check lockfile in 2025-03-08 17:24:28 +00:00
Rob Ede f4175a4ad4
chore: fix doc recipe 2025-03-08 17:24:28 +00:00
Rob Ede 323a2e2931
fix(server): fix panic in test server 2025-03-08 17:24:28 +00:00
dependabot[bot] 4b9f7ae46d
build(deps): bump ilammy/setup-nasm from 1.5.1 to 1.5.2 (#643)
Bumps [ilammy/setup-nasm](https://github.com/ilammy/setup-nasm) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/ilammy/setup-nasm/releases)
- [Commits](https://github.com/ilammy/setup-nasm/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: ilammy/setup-nasm
  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>
2025-02-24 22:22:32 +00:00
dependabot[bot] 0e119fd9b2
build(deps): bump taiki-e/install-action from 2.48.13 to 2.49.1 (#644)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.48.13 to 2.49.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.48.13...v2.49.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>
2025-02-24 22:22:23 +00:00
Rob Ede b04b88e81a
ci: fix msrv job 2025-02-24 22:00:44 +00:00
dependabot[bot] 0a8f2baa11
build(deps): bump taiki-e/install-action from 2.48.6 to 2.48.13 (#642)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.48.6 to 2.48.13.
- [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.48.6...v2.48.13)

---
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>
2025-02-17 18:37:23 +00:00
dependabot[bot] d79d500ffe
build(deps): bump taiki-e/install-action from 2.48.1 to 2.48.6 (#641)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.48.1 to 2.48.6.
- [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.48.1...v2.48.6)

---
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>
2025-02-10 22:39:52 +00:00
dependabot[bot] 7a7e3de430
build(deps): bump taiki-e/cache-cargo-install-action from 2.1.0 to 2.1.1 (#640)
Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 2.1.0 to 2.1.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.1.0...v2.1.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>
2025-02-10 22:39:50 +00:00
dependabot[bot] f062ede06f
build(deps): bump codecov/codecov-action from 5.1.2 to 5.3.1 (#637)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.2 to 5.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/v5.1.2...v5.3.1)

---
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>
2025-02-03 18:56:29 +00:00
dependabot[bot] 1338276934
build(deps): bump taiki-e/install-action from 2.47.19 to 2.48.1 (#639)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.47.19 to 2.48.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.47.19...v2.48.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>
2025-02-03 18:26:03 +00:00
dependabot[bot] 4746b4e2fa
build(deps): bump taiki-e/install-action from 2.47.12 to 2.47.19 (#634)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.47.12 to 2.47.19.
- [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.47.12...v2.47.19)

---
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>
2025-01-23 01:32:18 +00:00
dependabot[bot] 0509f0cede
build(deps): bump taiki-e/cache-cargo-install-action from 2.0.1 to 2.1.0 (#635)
Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 2.0.1 to 2.1.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/v2.0.1...v2.1.0)

---
updated-dependencies:
- dependency-name: taiki-e/cache-cargo-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>
2025-01-23 01:32:07 +00:00
dependabot[bot] 3831e0d7fe
build(deps): bump taiki-e/install-action from 2.47.7 to 2.47.12 (#633)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.47.7 to 2.47.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.47.7...v2.47.12)

---
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>
2025-01-13 20:01:14 +00:00
dependabot[bot] 60945d0481
build(deps): bump taiki-e/install-action from 2.47.0 to 2.47.7 (#632)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.47.0 to 2.47.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.47.0...v2.47.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>
2025-01-08 10:40:55 +00:00
dependabot[bot] 2615a19e28
build(deps): update itertools requirement from 0.13 to 0.14 (#631)
Updates the requirements on [itertools](https://github.com/rust-itertools/itertools) to permit the latest version.
- [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-itertools/itertools/compare/v0.13.0...v0.14.0)

---
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>
2025-01-08 10:40:41 +00:00
Rob Ede 1a0f44fff1
chore: allow missing docs on tests 2024-12-29 14:44:11 +00:00
Rob Ede 8d1cd2ec87
chore: allow missing docs on tests 2024-12-29 14:40:37 +00:00
Rob Ede b87174b5f2
chore: allow missing docs on tests 2024-12-29 14:34:28 +00:00
Rob Ede 8097af6a27
chore: allow missing docs on tests 2024-12-29 14:31:46 +00:00
Rob Ede ecba6e21da
chore: fmt project 2024-12-29 14:27:58 +00:00
dependabot[bot] 23f797a81d
build(deps): bump codecov/codecov-action from 5.1.1 to 5.1.2 (#629)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.1 to 5.1.2.
- [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/v5.1.1...v5.1.2)

---
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-12-29 13:59:48 +00:00
dependabot[bot] d2a5091451
build(deps): bump taiki-e/install-action from 2.46.4 to 2.47.0 (#630)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.46.4 to 2.47.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.46.4...v2.47.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-12-29 13:57:58 +00:00
Rob Ede e0c09c2aa4
ci: remove public-api-diff job 2024-12-29 13:44:48 +00:00
Rob Ede 8234543066
ci: fix tests 2024-12-29 13:41:41 +00:00
dependabot[bot] 34826c6253
build(deps): bump codecov/codecov-action from 5.0.7 to 5.1.1 (#624)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.0.7 to 5.1.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/v5.0.7...v5.1.1)

---
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-12-10 11:48:11 +00:00
dependabot[bot] 42b788d131
build(deps): bump taiki-e/install-action from 2.45.6 to 2.46.4 (#625)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.45.6 to 2.46.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.45.6...v2.46.4)

---
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-12-10 11:48:02 +00:00
dependabot[bot] 9796593b24
build(deps): bump actions-rust-lang/setup-rust-toolchain (#620)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.8.0 to 1.10.1.
- [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...v1.10.1)

---
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-12-02 08:31:34 +00:00
dependabot[bot] c362fc4414
build(deps): bump codecov/codecov-action from 5.0.2 to 5.0.7 (#621)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.0.2 to 5.0.7.
- [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/v5.0.2...v5.0.7)

---
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-12-02 08:31:21 +00:00
dependabot[bot] 52733337e4
build(deps): bump taiki-e/install-action from 2.34.0 to 2.45.6 (#622)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.34.0 to 2.45.6.
- [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.0...v2.45.6)

---
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-12-02 08:31:14 +00:00
Rob Ede 0e36c5f5c4
feat(bytestring): split_at method (#619) 2024-11-24 00:55:18 +00:00
dependabot[bot] 47f0017899
build(deps): bump codecov/codecov-action from 4.6.0 to 5.0.2 (#617)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.6.0 to 5.0.2.
- [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.6.0...v5.0.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-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-11-18 21:25:34 +00:00
dependabot[bot] bb4fc31461
build(deps): bump taiki-e/install-action from 2.44.69 to 2.44.71 (#618)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.44.69 to 2.44.71.
- [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.44.69...v2.44.71)

---
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-11-18 21:25:24 +00:00
dependabot[bot] 01a104eb82
build(deps): bump taiki-e/install-action from 2.44.60 to 2.44.69 (#616)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.44.60 to 2.44.69.
- [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.44.60...v2.44.69)

---
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-11-14 09:05:08 +00:00
Rob Ede 4ab27bfc4a
ci: move nightly rust versions to vars (#615) 2024-11-14 08:43:47 +00:00
dependabot[bot] 8084cec705
build(deps): bump taiki-e/install-action from 2.44.54 to 2.44.60 (#613)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 21:48:44 +00:00
dependabot[bot] a2517da225
build(deps): bump taiki-e/install-action from 2.44.44 to 2.44.54 (#612)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-29 23:03:00 +00:00
dependabot[bot] a4b6943ddc
build(deps): bump taiki-e/install-action from 2.44.35 to 2.44.44 (#611)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.44.35 to 2.44.44.
- [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.44.35...v2.44.44)

---
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-10-23 14:04:33 +00:00
dependabot[bot] 7d24196d5c
build(deps): bump taiki-e/install-action from 2.44.26 to 2.44.35 (#610)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 20:55:07 +01:00
dependabot[bot] 582edf5444
build(deps): bump actions-rust-lang/setup-rust-toolchain (#609)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.10.0 to 1.10.1.
- [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.10.0...v1.10.1)

---
updated-dependencies:
- dependency-name: actions-rust-lang/setup-rust-toolchain
  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-10-07 18:48:02 +00:00
dependabot[bot] 57485f1a21
build(deps): bump taiki-e/install-action from 2.44.13 to 2.44.26 (#607)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.44.13 to 2.44.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.44.13...v2.44.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>
2024-10-07 18:47:49 +00:00
dependabot[bot] e8871d0d06
build(deps): bump codecov/codecov-action from 4.5.0 to 4.6.0 (#608)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.5.0 to 4.6.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.5.0...v4.6.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-10-07 18:47:43 +00:00
Rob Ede 83e896a6e5
ci: remove upload doc job 2024-10-01 04:41:12 +01:00
dependabot[bot] af00dada5c
build(deps): bump taiki-e/install-action from 2.44.7 to 2.44.13 (#605)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.44.7 to 2.44.13.
- [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.44.7...v2.44.13)

---
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-09-30 23:51:19 +00:00
dependabot[bot] 0681b515de
build(deps): bump actions-rust-lang/setup-rust-toolchain (#602)
Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.9.0 to 1.10.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.9.0...v1.10.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-09-30 17:43:14 +00:00
dependabot[bot] 3672137d17
build(deps): bump taiki-e/install-action from 2.42.37 to 2.44.7 (#603)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.42.37 to 2.44.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.42.37...v2.44.7)

---
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-09-30 17:43:02 +00:00
ahbkc fad1fda194
Fix fist to first (#598)
Co-authored-by: yinqilei <yinqilei_ug@126.com>
2024-09-05 01:55:49 +01:00
dependabot[bot] cfae737314
build(deps): bump JamesIves/github-pages-deploy-action (#594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 05:15:44 +01:00
dependabot[bot] 4583daa3c2
build(deps): bump taiki-e/install-action from 2.42.18 to 2.42.37 (#595)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 05:15:36 +01:00
ahbkc b1cbacc7f6
fix actix-service/src/ext.rs 'fist' to 'first' (#596)
Co-authored-by: yinqilei <yinqilei_ug@126.com>
2024-09-03 05:15:24 +01:00
dependabot[bot] 77588aba81
build(deps): update rcgen requirement from 0.12 to 0.13 (#590)
* build(deps): update rcgen requirement from 0.12 to 0.13

Updates the requirements on [rcgen](https://github.com/rustls/rcgen) to permit the latest version.
- [Commits](https://github.com/rustls/rcgen/compare/v0.12.0...v0.13.1)

---
updated-dependencies:
- dependency-name: rcgen
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: fix rcgen tests

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-08-06 23:54:18 +00:00
dependabot[bot] aad3a48edd
build(deps): bump taiki-e/install-action from 2.42.10 to 2.42.18 (#589)
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.42.10 to 2.42.18.
- [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.10...v2.42.18)

---
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-08-05 22:52:43 +00:00
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
Rob Ede 4c9ee88ec4
prepare actix-tls release 3.0.1 2022-01-11 22:17:31 +00:00
david-mcgillicuddy-moixa 9ec3cc0fe7
Replace str_split_once to lower actix-tls msrv to 1.50.0 and bump actix-net to 1.50.0 (#434) 2022-01-10 17:00:04 +00:00
Rob Ede 01e0f922de
fix ci 2021-12-31 08:38:37 +00:00
Rob Ede 10d3bb6d0d
only run coverage on master ci 2021-12-31 08:36:13 +00:00
Rob Ede 3ba4eafde5
prepare actix-server release 2.0.0-rc.3 2021-12-31 08:09:28 +00:00
Rob Ede 5faa98f6d2
prepare actix-rt release 2.5.1 2021-12-31 08:09:10 +00:00
Rob Ede b552d847ed
prepare actix-codec release 0.4.2 2021-12-31 08:08:14 +00:00
Rob Ede 5058e2d14e
bump tokio in local-channel dev deps 2021-12-31 08:06:41 +00:00
Rob Ede ae9afd4de7
prepare actix-server release 2.0.0-rc.2 2021-12-27 18:33:57 +00:00
Rob Ede 01d2f18f68
simplify test server (#431) 2021-12-27 18:27:54 +00:00
Rob Ede e92b5aaf31
expose with_tokio_rt (#430) 2021-12-27 16:00:26 +00:00
Rob Ede 459a6d1b02
update readme 2021-12-27 00:57:16 +00:00
Rob Ede 9935883905
add file reader example 2021-12-26 22:32:35 +00:00
Rob Ede 89a4c2ee27
prepare actix-tls release 3.0.0 2021-12-26 21:12:19 +00:00
Rob Ede a4681831a7
fix changelogs 2021-12-18 03:35:18 +00:00
Rob Ede 5d2da0fdc7
prepare actix-service release 2.0.2 2021-12-18 03:26:59 +00:00
Rob Ede ef18a8342e
prepare local-waker release 0.1.2 2021-12-18 03:20:49 +00:00
Rob Ede 621deba990
fix changelog bullet points 2021-12-18 02:49:23 +00:00
Rob Ede 6a9f13c8b4
inline simple future functions 2021-12-18 02:18:01 +00:00
Rob Ede 705b31230f
fix impl assertion tests 2021-12-18 02:17:48 +00:00
Rob Ede eb490a9125
re-export openssl connector builder (#429) 2021-12-10 23:11:24 +00:00
Rob Ede 90f205a465
standardize crate level lints 2021-12-08 06:09:46 +00:00
Rob Ede 3a3d654cea
use "physical" cpu cores as default worker count 2021-12-08 05:42:54 +00:00
Rob Ede ba901c70df
prepare actix-server release 2.0.0-rc.1 2021-12-05 19:34:36 +00:00
Ali MJ Al-Nasrawy 4e0dd091f5
Server: run after await (#426)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-12-05 19:22:47 +00:00
Ali MJ Al-Nasrawy 8c4ec34cd4
Server: hide internal structure (#424) 2021-12-05 16:44:06 +00:00
Ali MJ Al-Nasrawy 62ffe5f389
fix auto-traits for service types (#397) 2021-12-04 22:30:04 +00:00
Rob Ede 07e3b19461
dedupe tls changelog 2021-12-04 19:51:33 +00:00
Rob Ede 183bcf6ae3
prepare actix-tls release 3.0.0-rc.1 (#423) 2021-11-30 12:34:46 +00:00
Rob Ede 5dc2bfcb01
actix-tls release candidate prep (#422) 2021-11-29 23:53:06 +00:00
Rob Ede 5556afd524
fix bytestring test on older rust versions 2021-11-28 01:19:57 +00:00
Rob Ede de5908bfe7
tls doc updates 2021-11-28 00:56:15 +00:00
Rob Ede c63880a292
doc updates 2021-11-28 00:46:29 +00:00
Rob Ede 44e4381879
add some internal server documentation 2021-11-28 00:35:34 +00:00
Rob Ede 18eced7305
add static assertions to bytestring 2021-11-25 03:29:30 +00:00
Rob Ede a2437eed29
prepare actix-tls release 3.0.0-beta.9 2021-11-22 13:34:54 +00:00
Rob Ede 67b357a175
add `TlsError::into_service_error` (#420) 2021-11-22 13:33:20 +00:00
Rob Ede 3597af5c45
prepare actix-rt release 2.5.0 2021-11-22 01:15:18 +00:00
Rob Ede 8891c2681e
address unused warning 2021-11-21 23:42:51 +00:00
Rob Ede 233c61ba08
remove dead code 2021-11-21 23:29:25 +00:00
Rob Ede 161f239f12
server: panic earlier if neither runtime detected 2021-11-21 23:29:06 +00:00
fakeshadow 7e7df2f931
add timeout for accepting tls connections (#393)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-11-16 00:22:24 +00:00
Luca Bruno ce8ec15eaa
system: run and return exit code on stop (#411)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-11-15 18:49:02 +00:00
Rob Ede ae28ce5377
update mio to 0.8 2021-11-15 18:48:37 +00:00
Rob Ede 54d1d9e520
prepare actix-tls release 3.0.0-beta.8 2021-11-15 17:55:23 +00:00
Alexander Polakov 0b0cbd5388
actix-tls: allow getting uri from Connect (#415)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-11-15 10:39:42 +00:00
Rob Ede 443a328fb4
prepare actix-server release 2.0.0-beta.9 2021-11-15 02:39:55 +00:00
Rob Ede 58a67ade32
improve docs of system_exit 2021-11-15 02:33:13 +00:00
Rob Ede 38caa8f088
Fix server arbiter support (#417) 2021-11-14 19:45:15 +00:00
Rob Ede ed987eef06
prepare actix-server release 2.0.0-beta.8 2021-11-07 15:46:59 +00:00
fakeshadow 3658929010
fix io-uring feature for actix-server (#414)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-11-07 15:43:59 +00:00
fakeshadow 3f49d8ab54
remove usage of mio::net::TcpSocket (#413) 2021-11-07 14:18:23 +00:00
fakeshadow 161d1ee94b
fix accept timeout and worker graceful shutdown (#412) 2021-11-07 13:00:19 +00:00
Rob Ede 81ba7cafaa
fix server non-unix signal impl send (#410) 2021-11-05 02:16:13 +00:00
Rob Ede f8f51a2240
prepare actix-server release 2.0.0-beta.7 2021-11-05 01:14:28 +00:00
Rob Ede a2e765ea6e
prepare actix-codec release 0.4.1 2021-11-05 01:05:51 +00:00
Rob Ede 03dae6a4a4
prepare actix-rt release 2.4.0 2021-11-05 00:51:34 +00:00
brockelmore 2080f4c149
`Framed::poll_ready` flushes when buffer is full (#409) 2021-11-05 00:43:33 +00:00
Rob Ede b2cef8fcdb
add lines codec (#338) 2021-11-05 00:12:02 +00:00
Rob Ede 15279eaf3d
sync wait for service factories to be ready 2021-11-04 23:26:56 +00:00
Rob Ede 7d98247cb0
fix server worker name 2021-11-04 23:00:43 +00:00
Rob Ede 5b537c7b10
actix-rt-less (#408) 2021-11-04 20:30:43 +00:00
Rob Ede 81d7295486 clippy 2021-11-01 23:41:28 +00:00
Rob Ede 581e599209
rename Server => ServerHandler (#407) 2021-11-01 23:36:51 +00:00
Rob Ede 1c8fcaebbc
tweak server logging 2021-10-22 18:17:26 +01:00
fakeshadow a1d15f2e08
minimal support of System type with io-uring (#395) 2021-10-21 11:04:51 +01:00
Rob Ede 70ea5322ab
prepare actix-tls 3.0.0-beta.7 release (#401) 2021-10-20 17:12:11 +01:00
Rob Ede 303666278a
prepare actix-tls release 3.0.0-beta.6 2021-10-19 16:51:40 +01:00
Edward Shen 669e868370
Use tokio-rustls 0.23 (#396)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-10-19 16:48:23 +01:00
Rob Ede 47f278b17a
fix test macro in presence of other imports named test (#399) 2021-10-19 16:13:13 +01:00
Rob Ede ca77d8d835
split -server and -tls msrv and raise to 1.52 (#398) 2021-10-19 14:53:42 +01:00
Rob Ede 00775884f8
prepare actix-macros release 0.2.2 2021-10-14 11:08:02 +01:00
Rob Ede 4ff8a2cf68
make runtime macros more IDE friendly (#391) 2021-10-14 10:54:39 +01:00
Rob Ede 5c555a9408
prepare actix-rt release 2.3.0 2021-10-11 22:55:23 +01:00
Rob Ede ca435b2575
prepare actix-server release 2.0.0-beta.6 2021-10-11 05:14:34 +01:00
Rob Ede 9fa8d7fc5a
avoid dependency on older tokios 2021-10-11 05:12:57 +01:00
Rob Ede b03fe7c5b6
prepare actix-service release v2.0.1 2021-10-11 04:20:37 +01:00
fakeshadow 6fed1c3e7d
add support for io-uring (#374)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-10-11 02:58:11 +01:00
Thales c3d697df97
server: Don't listen for SIGHUP (#389) 2021-10-04 02:48:10 +01:00
Riley 80a362712f
Fix Service<u8> request documentation (#388) 2021-09-26 01:30:11 +01:00
Ibraheem Ahmed 2b1edb95ea
`spawn` should allow futures with non-unit outputs (#369)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-09-01 21:51:03 +01:00
Rob Ede 4644fa41cf
run doc test in parallel (#387) 2021-09-01 21:30:26 +01:00
Rob Ede 98c37fe47d
clippy 2021-09-01 20:59:54 +01:00
Rob Ede b9455d2ca9
move router crate 2021-08-06 19:05:29 +01:00
Rob Ede 0183b0f8cc
soft-disallow prefix resources with tail segments (#379) 2021-08-06 18:48:49 +01:00
Ali MJ Al-Nasrawy b122a1ae1a
ResourceDef::join (#380) 2021-08-06 18:48:30 +01:00
Rob Ede 4303058243
enforce path / separators on dynamic prefixes (#378) 2021-08-06 18:25:21 +01:00
Aravinth Manivannan 48b2e11509
improve malformed path error message (#384) 2021-08-06 18:06:29 +01:00
Ali MJ Al-Nasrawy 5379a46a99
ResourceDef: relax unnecessary bounds (#381) 2021-08-06 17:45:10 +01:00
Rob Ede f8f1ac94bc
add Patterns::is_empty and impl IntoPatterns for Patterns 2021-07-20 08:18:50 +01:00
Rob Ede 82cd5b8290
prepare router release 0.5.0-beta.1 2021-07-20 07:43:50 +01:00
Rob Ede c65e8524b2
rework resourcedef (#373) 2021-07-19 22:37:54 +01:00
Rob Ede a83dfaa162
Update macros.rs
closes #234
2021-07-17 20:54:53 +01:00
Rob Ede e4ec956001
fix examples on msrv 2021-07-17 03:11:25 +01:00
Rob Ede 95cba659ff
add zero cost profiling to router 2021-07-17 01:09:29 +01:00
Rob Ede 5687e81d9f
rework IntoPatterns trait and codegen (#372) 2021-07-17 01:06:23 +01:00
Rob Ede a0fe2a9b2e
clippy 2021-07-16 21:46:32 +01:00
Rob Ede ad22a93466
allow path building when resource has tail (#371) 2021-07-16 21:41:57 +01:00
Rob Ede c2d5b2398a
Rename `Path::{len => segment_count}` (#370) 2021-07-16 19:43:48 +01:00
Ali MJ Al-Nasrawy 5b1ff30dd9
router: fix multi-pattern and path tail matches (#366) 2021-07-16 18:17:00 +01:00
Ali MJ Al-Nasrawy e1317bb3a0
`path.len()` != `path.path().len()` (#368)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-07-15 15:34:49 +01:00
Ali MJ Al-Nasrawy dcea009158
`ResourceDef`: cleanup (#365) 2021-07-15 15:09:01 +01:00
Rob Ede 13c18b8a51
Update CHANGES.md 2021-07-14 10:37:49 +01:00
Rob Ede 06b17d6a43
fix ci 2021-06-28 15:06:29 +01:00
Rob Ede 605ec25143
prepare macros release 0.2.1 2021-06-08 17:48:30 +01:00
Ibraheem Ahmed 3824493fd3
take custom system path in `actix_rt::main` macro (#363) 2021-06-08 17:33:05 +01:00
Rob Ede 3be3e11aa5
change actix-router version to 0.4.0 2021-06-06 18:48:27 +01:00
Rob Ede 6a5ea0342b
prepare router release 0.3.0 (#362) 2021-06-06 18:43:22 +01:00
Ali MJ Al-Nasrawy 23b1f63345
router: handle newline char '\n' in url (#360) 2021-06-06 03:38:58 +01:00
Ali MJ Al-Nasrawy 3aa037d07d
fix changelog (#361) 2021-06-05 19:24:30 +01:00
Ali MJ Al-Nasrawy cf21df14f2
`Path`: fix unsafe malformed string (#359) 2021-06-05 18:29:00 +01:00
Ali MJ Al-Nasrawy a1bf8662c9
router: don't decode %25 to '%' (#357) 2021-06-06 01:34:16 +09:00
Ibraheem Ahmed 6f4d2220fa
store Cow in actix-router Path (#345) 2021-06-05 01:46:40 +01:00
Danilo Bargen 54b22f9fce
Docs: Fix signature of Service::call (#358) 2021-06-02 21:10:36 +01:00
fakeshadow 983abec77d
Fix interrupt handling. Fix double server pause/resume (#353) 2021-04-30 13:42:25 +01:00
fakeshadow e4d4ae21ee
refactor connection counter (#343)
* Remove restart_worker test

* Remove Slab

* Rework counter

* Make counter limit switch accurate

* Remove backpressure. Add pause state

* make changes for review

* fix doc comment for counter
2021-04-29 23:27:08 +08:00
fakeshadow 8ad5f58d38
Remove ServerBuilder::configure (#349) 2021-04-27 23:58:02 +01:00
fakeshadow 613b2be51f
Fix Display impl of MioListener (#350) 2021-04-27 11:54:18 -07:00
Rob Ede b2e9640952
prepare codec 0.4.0 release (#346) 2021-04-21 11:08:43 +01:00
Rob Ede 76338a5822
prepare server release 2.0.0-beta.5 2021-04-20 05:16:32 +01:00
Rob Ede 978e4f25fb
prepare actix-utils release 3.0.0 (#342) 2021-04-17 02:00:36 +01:00
Rob Ede 1c4e965366
prepare service release 2.0.0 (#339) 2021-04-16 15:18:53 +01:00
fakeshadow 2435520e67
Remove/restart worker test (#341) 2021-04-16 14:40:21 +01:00
fakeshadow 19468feef8
Fix memory ordering of WorkerAvailability (#340) 2021-04-16 11:20:08 +01:00
fakeshadow bd48908792
Return worker index in WakerInterest::WorkerAvailable (#337) 2021-04-16 05:59:10 +01:00
fakeshadow 20c2da17ed
Fix worker_avail (#336)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-04-16 03:20:02 +01:00
Rob Ede fdafc1dd65
amend licences 2021-04-16 02:08:44 +01:00
Rob Ede 7749dfe46a
address msrv todo in router 2021-04-16 02:06:11 +01:00
fakeshadow aeb81ad3fd
Fix worker are notified to stop with non_graceful shutdown (#333) 2021-04-16 00:54:15 +01:00
Rob Ede 47fba25d67
remove pipeline from public api (#335) 2021-04-16 00:00:02 +01:00
Rob Ede 7a82288066
docs tweak 2021-04-15 21:58:18 +01:00
Rob Ede 4e6d88d143
improve boxed service docs 2021-04-15 20:43:02 +01:00
Rob Ede ef206f40fb
update ignored service docs to new traits 2021-04-15 20:13:27 +01:00
fakeshadow 8e98d9168c
add test for restart worker thread (#328) 2021-04-15 18:49:43 +01:00
fakeshadow 3c1f57706a
Make ServerWorker drop stop Arbiter it runs on (#334) 2021-04-15 13:31:03 +01:00
fakeshadow d49ecf7203
Fix bug where backpressure happen too early (#332) 2021-04-14 14:48:05 +01:00
fakeshadow e0fb67f646
Reduce ServerWorker size (#321) 2021-04-13 01:12:59 +01:00
fakeshadow ddce2d6d12
Reduce cfg flags in actix_server::socket (#325) 2021-04-10 16:05:50 +01:00
fakeshadow 0a11cf5cba
Separate WorkerHandle to two parts (#323) 2021-04-10 01:03:28 +01:00
Rob Ede 859f45868d
Revert "do no drain backlog on backpressure" (#324)
This reverts commit d4829b046d.
2021-04-09 21:04:41 +01:00
fakeshadow d4829b046d
do no drain backlog on backpressure (#322) 2021-04-08 23:15:10 +01:00
fakeshadow 5961eb892e
Fix bug where worker service restart could skip failing services and not being able to restart multiple services (#318) 2021-04-05 20:39:05 +01:00
fakeshadow 995efcf427
Fix bug where paused Accept would register timed out sockets (#312) 2021-04-05 13:38:41 +01:00
fakeshadow f1573931dd
Remove MAX_CONN (#316) 2021-04-04 23:00:12 +01:00
fakeshadow 3859e91799
Use named type for WorkerState::Restarting and Shutdown (#317) 2021-04-04 21:53:19 +01:00
fakeshadow 8aade720ed
Refactor WorkerState::Shutdown (#310) 2021-04-04 20:34:52 +01:00
fakeshadow 8079c50ddb
Add ServerWorker::restart_service method (#314)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-04-04 13:22:34 +01:00
fakeshadow 05689b86d9
Remove Option wrapper for CounterGuard (#313) 2021-04-04 10:53:06 +01:00
fakeshadow fd3e5fba02
Refactor actix_server WorkerState::Restarting enum variant. (#306)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-04-03 19:40:12 +01:00
fakeshadow 39d1f282f7
add test for max concurrent connections (#311) 2021-04-03 19:01:00 +01:00
fakeshadow d8889c63ef
Do not do double check on connection num when entering graceful shutdown (#309) 2021-04-02 12:49:12 +01:00
fakeshadow fdac52aa11
Refactor Worker::shutdown mehtod (#308) 2021-04-02 12:22:05 +01:00
Rob Ede 6d66cfb06a
prepare utils release 3.0.0-beta.4 2021-04-01 13:57:08 +01:00
Rob Ede fb27ffc525
add future::Either type to utils (#305) 2021-04-01 13:53:44 +01:00
Rob Ede b068ea16f8
prepare server release 2.0.0-beta.4 2021-04-01 09:36:07 +01:00
Rob Ede 4eebdf4070
prepare actix-utils release 3.0.0-beta.3 2021-04-01 09:31:42 +01:00
Rob Ede b09e7cd417
fix local waker metadata 2021-04-01 09:01:56 +01:00
fakeshadow 2c5c9167a5
Fix bug where timed out socket would register itself when server in b… (#302)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-04-01 08:25:24 +01:00
fakeshadow ee3a548a85
Refactor Accept::accept_one (#303) 2021-04-01 07:45:49 +01:00
fakeshadow f21eaa954f
Reduce size of Conn by removing unused addr field (#304) 2021-04-01 06:55:33 +01:00
Rob Ede 8becb0db70
refactor crates for better api stability (#301) 2021-03-30 13:39:10 +01:00
fakeshadow 26a5af70cb
reduce branch in Accept::accept method (#300) 2021-03-29 08:19:37 +01:00
Rob Ede 0ee8d032b6
prepare actix-tls release 3.0.0-beta.5 2021-03-29 06:57:47 +01:00
Rob Ede 3cf1c548fd
prepare actix-rt release 2.2.0 2021-03-29 06:57:14 +01:00
fakeshadow 4544562e1b
Remove unused TcpConnectService (#299) 2021-03-27 21:03:24 +00:00
fakeshadow bb27bac216
Add native tls support for actix_tls::connect module (#295)
Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-03-27 00:20:17 +00:00
Rob Ede f9262dbec0
prevent large shutdown timeout from panicking
closes #298
2021-03-26 23:37:01 +00:00
fakeshadow 12d3942b98
Remove unused types in actix-tls. Add ActixStream impl for Box<dyn Ac… (#297) 2021-03-26 13:03:03 +00:00
fakeshadow a3c9ebc7fa
fix rustls panic when generating dns name from ip (#296)
* fix rustls panic when generating dns name from ip

* Update rustls.rs

* update changelog

Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-03-24 09:32:04 -07:00
fakeshadow b7bfff2b32
add example of using multi-thread tokio runtime (#294)
* add example of using multi-thread tokio runtime

* Update multi_thread_system.rs

Co-authored-by: Rob Ede <robjtede@icloud.com>
2021-03-24 04:56:13 -07:00
fakeshadow 0c73f13c8b
ActixStream readiness methods return Ready object (#293) 2021-03-23 05:50:48 +00:00
Rob Ede 945479e0c3
unvendor openssl (#292) 2021-03-17 00:26:04 +00:00
Rob Ede 746cc2ab89
prepare service release 2.0.0-beta.5 2021-03-15 23:09:34 +00:00
Rob Ede 91ea8c5dad
remove service dev module and add transformext trait
also improve docs on transform and boxed mods
2021-03-10 03:18:09 +00:00
Rob Ede 0a705b1023
add docs for *_ready macros 2021-03-10 02:23:24 +00:00
fakeshadow 9e2bcec226
add RcService type and rc_service construct function (#290) 2021-02-28 23:01:05 +00:00
Rob Ede 382830a37e
refactor dispatcher / add Receiver::recv (#286) 2021-02-28 21:11:16 +00:00
fakeshadow 493a1a32c0
rc service changelog (#289) 2021-02-28 19:54:57 +00:00
fakeshadow 50a195e9ce
add impl Service for Rc<S: Service> (#288) 2021-02-28 19:42:11 +00:00
Rob Ede 06ddad0051
prepare rt and tls releases (#287) 2021-02-25 11:50:24 +00:00
Rob Ede 789e6a8a46
update ci (#284) 2021-02-24 09:48:41 +00:00
Rob Ede 6e590fd042
Merge pull request #285 from actix/dep/actix-server 2021-02-24 09:09:44 +00:00
fakeshadow fa8ded3a34 bump tokio version for actix-server 2021-02-24 15:54:28 +08:00
Rob Ede 841c611233
doc nits 2021-02-24 01:39:02 +00:00
Rob Ede 81a2b6a425
add local_addr binding to connector service (#282) 2021-02-23 18:52:28 +00:00
fakeshadow a6e79453d0 remove default reuse_addr 2021-02-24 02:26:11 +08:00
fakeshadow 17f711a9d6 update changelog 2021-02-24 01:20:01 +08:00
fakeshadow c3be839a69 add local_addr binding to connector service 2021-02-24 01:13:17 +08:00
Rob Ede 8d74cf387d
standardize openssl based stream name 2021-02-20 18:04:05 +00:00
Rob Ede 7e483cc356
tweak task and stream docs 2021-02-20 17:34:04 +00:00
fakeshadow 75d7ae3139
add actix stream trait (#276) 2021-02-20 17:25:22 +00:00
Juan Aguilar 2cfe1d88ad
Refactor LocalWaker for use Cell and remove deprecated methods (#278) 2021-02-19 17:12:30 +00:00
Rob Ede cb07ead392
prepare rt release 2.0.2 2021-02-06 22:52:53 +00:00
Rob Ede 32543809f9
add System::try_current (#275) 2021-02-06 22:45:03 +00:00
Rob Ede eb4d29e15e
add arbiter handle assoc fn (#274)
* add arbiter handle assoc fn
2021-02-06 22:27:56 +00:00
Rob Ede 7ee42b50b4
prepare router 0.2.7 release 2021-02-06 19:50:48 +00:00
Rob Ede 0da848e4ae
fix server dev dep 2021-02-06 19:35:29 +00:00
Rob Ede 5f80d85010
fix server version 2021-02-06 19:34:58 +00:00
Rob Ede 16ba77c4c8
prepare next set of betas (#273) 2021-02-06 19:24:52 +00:00
Rob Ede b4a3f51659
prepare rt release 2.0.1 2021-02-06 15:54:11 +00:00
Riley 9d0901e07f
actix-rt: expose JoinError (#271) 2021-02-06 15:50:38 +00:00
fakeshadow ebb9cd055f
use static dispatch on signal handling. reduce allocation (#272) 2021-02-06 03:38:11 +00:00
Rob Ede a77b70aed2
prepare service 2.0.0-beta.4 release (#269) 2021-02-04 20:44:13 +00:00
Rob Ede c918da906b
use reexported tls crates when possible 2021-02-04 15:23:06 +00:00
Rob Ede b5399c5631
use reusable box future in tls connector 2021-02-04 15:23:06 +00:00
fakeshadow 7f0eddd794
add blocking thread customize (#265) 2021-02-04 15:01:51 +00:00
shuo db3385e865
retry on EINTR in accept loop (#264)
Co-authored-by: lishuo <lishuo.03@bytedance.com>
2021-02-04 10:20:37 +00:00
Rob Ede 4a8693d000
readme grammar 2021-02-03 11:18:35 +00:00
Rob Ede 4ec358575e
prepare actix-rt v2.0.0 release (#262) 2021-02-03 10:25:31 +00:00
Rob Ede 66bd5bf4a2
prepare macros v0.2.0 release (#261) 2021-02-02 02:07:58 +00:00
Rob Ede 057e7cd7c9
prepare rt v2.0.0-beta.3 2021-01-31 05:19:30 +00:00
Rob Ede 0b656f51e1
deprecate rt TLS item storage 2021-01-31 04:48:03 +00:00
Rob Ede 0eb68d1c7b
Revert "remove arbiter TLS item storage"
This reverts commit 3e6f69885c.
2021-01-31 04:45:27 +00:00
Rob Ede 3e6f69885c
remove arbiter TLS item storage 2021-01-31 04:43:35 +00:00
Rob Ede 2fa60b07ae
prevent arbiter leaks by waiting for registration 2021-01-31 04:41:28 +00:00
Rob Ede b75254403a
remove builder and introduce worker handle (#257) 2021-01-31 03:34:07 +00:00
Rob Ede 1b35ff8ee6
express spawn fn as spawn fut (#256) 2021-01-29 15:16:30 +00:00
Rob Ede 2924419905
prevent spawn_fn panic bubbling (#255) 2021-01-29 14:16:10 +00:00
Rob Ede 6b86b5efc5
rename arbiter to worker (#254) 2021-01-29 04:08:14 +00:00
Rob Ede ba39c8436d
remove tokio runners (#253) 2021-01-29 02:21:06 +00:00
fakeshadow feac376c17
fix actix-tls build (#252) 2021-01-28 10:31:57 +00:00
Rob Ede a633d2353c
fix addr iterator 2021-01-27 11:23:28 +00:00
Rob Ede 45edff625e
add rt tests and doc tests 2021-01-26 09:46:14 +00:00
Rob Ede cff9deb729
attribute nits 2021-01-26 09:45:43 +00:00
Rob Ede eaefe21b98
add tests for custom resolver 2021-01-26 08:05:19 +00:00
fakeshadow 636cef8868
service trait takes shared self reference (#247) 2021-01-23 03:06:22 +00:00
fakeshadow 874e5f2e50
change default name resolver and allow custom resolvers (#248) 2021-01-23 01:33:50 +00:00
Rob Ede 6112a47529
update local deps 2021-01-09 15:19:16 +00:00
Rob Ede a2e03700e7
update rt changelog 2021-01-09 15:16:31 +00:00
Rob Ede 6edf9b8278
prepare rt 2.0.0-beta.2 release 2021-01-09 15:12:59 +00:00
Rob Ede f07d807707
remove actix-threadpool crate 2021-01-09 15:04:55 +00:00
Rob Ede d4c46b7da9
fix macros code 2021-01-09 14:58:15 +00:00
Rob Ede b0a8f8411b
prepare macros 0.2.0-beta.1 release 2021-01-09 14:56:07 +00:00
Rob Ede 46bfe5de36
prepare service 2.0.0-beta.3 release 2021-01-09 14:28:33 +00:00
Rob Ede a95afe2800
prepare router release 0.2.6 2021-01-09 14:18:20 +00:00
Rob Ede f751cf5acb
use convert err on forward_ready! (#246) 2021-01-09 14:13:16 +00:00
fakeshadow a1982bdbad
add actix-rt::task (#245) 2021-01-03 18:16:57 +00:00
Rob Ede 147c4f4f2c
test bytestring with ahash 2021-01-03 04:42:08 +00:00
Rob Ede 5285656bdc
prepare next beta releases 2021-01-03 04:39:37 +00:00
Rob Ede 296294061f
update readme 2020-12-31 02:52:55 +00:00
Rob Ede 93865de848
move router to actix-router 2020-12-31 02:29:27 +00:00
Rob Ede 6bcf6d8160
use bytestring crate name as dir name 2020-12-31 02:21:50 +00:00
Rob Ede 14ff379150
prepare bytestring release 1.0.0 (#243) 2020-12-31 02:20:49 +00:00
fakeshadow 647817ef14
tokio 1.0 and mio 0.7 (#204) 2020-12-30 22:11:50 +00:00
fakeshadow b5eefb4d42
merge actix-testing into actix-server (#242) 2020-12-29 21:20:24 +00:00
fakeshadow 03eb96d6d4
fix actix-tls tests (#241) 2020-12-29 11:36:17 +00:00
Rob Ede 0934078947
prepare tls beta release 2020-12-29 01:04:21 +00:00
Rob Ede 5759c9e144
merge -connect and -tls and upgrade to rt v2 (#238) 2020-12-29 00:38:41 +00:00
Rob Ede 3c6de3a81b
use correct service version for tracing 2020-12-29 00:08:59 +00:00
Rob Ede ef83647ac9
prepare testing beta release 2020-12-28 23:54:21 +00:00
Rob Ede 98a17081b8
prepare server beta release 2020-12-28 23:50:00 +00:00
fakeshadow b7202db8fd
update actix-server and actix-testing to tokio 1.0 (#239) 2020-12-28 23:44:53 +00:00
Rob Ede a09f9abfcb
prepare utils release 3.0.0-beta.1 2020-12-28 03:32:28 +00:00
Rob Ede e4a44b77e6
prepare codec release 0.4.0-beta.1 2020-12-28 03:24:43 +00:00
fakeshadow 2ee8f45f5d
update actix-codec and actix-utils to tokio 1.0 (#237) 2020-12-28 03:16:37 +00:00
Rob Ede f48e3f4cb0
prepare release for rt and service 2020-12-28 01:58:31 +00:00
Rob Ede 3d3bd60368
fix rt override 2020-12-28 01:53:11 +00:00
Rob Ede d684128831
fix rt override 2020-12-28 01:48:19 +00:00
fakeshadow 0c12930796
update to tokio 1.0 for actix-rt (#236) 2020-12-28 01:40:22 +00:00
Rob Ede ba44ea7d0b
remove futures-util from service deps (#235) 2020-12-27 18:24:57 +00:00
Rob Ede 8a58a341a4
service improvements (#233) 2020-12-27 14:15:42 +00:00
Rob Ede 33c9aa6988
bump msrv to 1.46 2020-12-27 04:36:08 +00:00
Rob Ede 3ab8c3eb69
service trait takes request type parameter (#232) 2020-12-27 04:28:00 +00:00
fakeshadow 518bf3f6a6
remove RUNNING Q PENDING thread locals from actix-rt (#207) 2020-12-26 23:26:02 +00:00
fakeshadow 43ce25cda1
Remove unused mods in actix-utils (#229) 2020-12-26 21:27:59 +00:00
Yuki Okushi 4e4122b702
Disable PR comment from codecov 2020-12-17 21:42:21 +09:00
Aravinth Manivannan b296d0f254
Intradoc links conversion (#227)
* intra doc conversion

* rm trailing blank comment
2020-12-14 08:22:30 +00:00
Juan Aguilar 02a902068f
Refactor LocalWaker (#224) 2020-12-13 19:26:57 +00:00
fakeshadow 049795662f
remove ServerMessage type. remove one unused InternalServiceFactory impl (#225) 2020-12-13 00:46:32 +00:00
Rob Ede 4e43216b99
standardise compiler lints across all crates (#226) 2020-12-12 23:24:00 +00:00
Rob Ede 93889776c4
prevent double registration of sockets when backpressure is resolved (#223) 2020-12-12 17:19:20 +00:00
Yuki Okushi ab496a71b5
Fix release date 2020-12-03 08:59:59 +09:00
Yuki Okushi 76d956e25c
macros: Add `actix-reexport` feature (#218) 2020-12-03 08:59:13 +09:00
Ivan Babrou 89e56cf661
Notify about paused accept loop (#215) 2020-11-29 15:30:13 +00:00
Rob Ede 8aca8d4d07
fix clippy warnings (#214)
and make my spelling checker happy
2020-11-25 01:41:14 +00:00
fakeshadow e0dd2a3d76
remove actix-threadpool re-export from actix-rt (#212) 2020-11-24 17:03:09 +00:00
Rob Ede 59e976aaca
address clippy error (#213) 2020-11-24 16:35:47 +00:00
Zura Benashvili 4cc1c87724
docs(transform): remove extra generic parameter (#211) 2020-11-20 22:45:57 +00:00
Yuki Okushi ca39917d2c Update CoC contact information 2020-10-31 12:08:06 +09:00
ghizzo01 704af672b9
Bump pin-project to 1.0 (#202) 2020-10-25 19:42:40 +09:00
Rob Ede 242bef269f
delete ioframe removed package readme
closes #199
2020-09-22 12:29:07 +01:00
Rob Ede 6c65e2a79f
prepare router 0.2.5 release (#198) 2020-09-21 22:46:59 +01:00
nujz e5ca271764
actix-router: fix from_hex error (#196) 2020-09-20 18:04:18 +01:00
nujz 98a2197a09
fix doc error (#195) 2020-09-19 23:12:41 +09:00
Rob Ede fb0aa02b3c
move and update server+tls examples (#190) 2020-09-13 10:12:07 +01:00
Rob Ede 681eeb497d
prepare server release 1.0.4 (#188) 2020-09-12 15:28:17 +01:00
Igor Aleksanov 3e04b87311
actix-service: Fix broken link in readme (#189) 2020-09-12 15:08:03 +01:00
Rob Ede 77b7826658
prepare tls v2 release (#186) 2020-09-08 18:00:07 +01:00
Igor Aleksanov b7a9cb7bb4
actix-rt: Make the process of running System in existing Runtime more clear (#173) 2020-09-06 11:01:24 +01:00
Robert Gabriel Jakabosky 88d99ac89c
Fix clippy errors. (#187) 2020-09-06 10:41:42 +01:00
Rob Ede 7632f51509
prepare connect v2 stable release (#185) 2020-09-02 22:14:07 +01:00
Rob Ede d28687d0d7
promote codec/utils out of beta (#184) 2020-08-24 09:18:37 +01:00
Rob Ede 27c6be9881
remove unused type parameter from Framed::replace_codec (#183) 2020-08-20 00:30:26 +01:00
Rob Ede 119dc39f5b
prepare codec and utils betas (#182) 2020-08-19 11:00:12 +01:00
Rob Ede b3010c13e0
solve framed integration with actix-http (#179) 2020-08-18 23:27:37 +01:00
Adrian Wechner fecdfcd8d4
assert workers greater than zero (#167) 2020-08-18 16:44:22 +01:00
Yuki Okushi 578a560853
connect,tls: Bump up to next alpha versions (#181) 2020-08-17 15:39:17 +01:00
Rob Ede fb098536ee
bump MSRV to 1.42 (#180) 2020-08-17 15:37:57 +01:00
Rob Ede 5d28be9ad6
fix actix-service readme reference (#176) 2020-08-11 12:20:09 +01:00
Rob Ede a5a6b6704c
prepare actix-service 1.0.6 release (#175) 2020-08-09 16:10:58 +01:00
Igor Aleksanov afb0a3c9fc
actix-service: Fix clippy warning in benches (#174) 2020-08-07 17:16:45 +09:00
Miloas 02aaa75591
fix actix-service doc error (#172) 2020-08-06 11:21:51 +01:00
Yuki Okushi ed4b708c66
Fix CI on MSRV check (#171) 2020-08-05 09:02:41 +09:00
Yuki Okushi 235a76dcd4
GHA: Switch action to the official setup-msys2 (#169) 2020-07-29 08:47:32 +09:00
Matt Kantor 0c5f1da625
Remove garbled doc comment for actix_router::IntoPattern::is_single (#168) 2020-07-29 05:46:53 +09:00
Yuki Okushi 8ace9264b7
Check code style with rustfmt on CI (#164) 2020-07-22 12:32:13 +09:00
Yuki Okushi 0dca1a705a
actix-utils: Remove unsound custom Cell as well (#161) 2020-07-22 01:14:32 +01:00
Juan Aguilar 5d6d309e66
Simplify bcodec decode (#162) 2020-07-20 23:09:24 +09:00
Juan Aguilar 8d0bd7ce1c
Improve bcodec encode performance (#157) 2020-07-19 22:36:51 +01:00
Sergey "Shnatsel" Davidoff a67e38b4a0
Remove unsound custom Cell (#158) 2020-07-20 06:05:36 +09:00
Rob Ede 334c98575a
Upgrade tokio utils to 0.3 (#138) 2020-07-20 05:44:26 +09:00
Rob Ede a9b5a7b070
Create PULL_REQUEST_TEMPLATE.md (#159) 2020-07-20 03:01:09 +09:00
Yuki Okushi 61176f6410
Update `rustls`-related dependencies (#154) 2020-07-14 11:14:06 +01:00
Yuki Okushi 10b4c30a06
Use `OR` instead of deprecated `/` in license field (#155) 2020-07-14 11:11:30 +01:00
Yuki Okushi 7f550bcf0f
threadpool: Bump up to 0.3.3 (#156) 2020-07-14 11:10:15 +01:00
Yuki Okushi 887f11f787
Merge pull request #153 from actix/tweak-actions
Tweak actions trigger events
2020-07-08 09:04:05 +09:00
Yuki Okushi e2a6d352b0
Tweak actions trigger events 2020-07-08 08:38:24 +09:00
Yuki Okushi f6c697a2dd
Merge pull request #152 from paolobarbolini/pl-011
Update parking_lot to 0.11
2020-07-04 03:20:08 +09:00
Paolo Barbolini 5ecdfd684a Update parking_lot to 0.11 2020-07-03 17:37:10 +02:00
Yuki Okushi 7140c04c44
Merge pull request #149 from taiki-e/pin-project
Remove uses of pin_project::project attribute
2020-06-07 02:01:08 +09:00
Taiki Endo 9528df4486 Remove uses of pin_project::project attribute
pin-project will deprecate the project attribute due to some unfixable
limitations.

Refs: https://github.com/taiki-e/pin-project/issues/225
2020-06-06 06:42:45 +09:00
Pen Tree 755a8bb9d1
fix codec doc links (#148) 2020-06-02 18:05:39 +01:00
Yuki Okushi f3cb6efc30
Merge pull request #146 from actix/cache-v2
Update `actions/cache` to v2
2020-05-28 04:59:34 +09:00
Yuki Okushi 87b857705c
Update `actions/cache` to v2 2020-05-28 03:14:01 +09:00
Yuki Okushi c897c5d3eb
Merge pull request #145 from JohnTitor/new-threalpool
threadpool: Bump up to 0.3.2
2020-05-20 15:24:39 +09:00
Yuki Okushi 134e76b8b4
threadpool: Bump up to 0.3.2 2020-05-20 14:19:16 +09:00
Yuki Okushi f3a401c23b
Merge pull request #144 from JohnTitor/codecov-config
Add codecov config
2020-05-20 11:03:31 +09:00
Yuki Okushi f7e8a912b3
Add codecov config 2020-05-19 14:45:39 +09:00
Yuki Okushi 11a1e11858
Merge pull request #143 from JohnTitor/new-testing
testing: Bump up to 1.0.1
2020-05-19 14:37:54 +09:00
Yuki Okushi d0b27ee7e6
testing: Bump up to 1.0.1 2020-05-19 14:08:08 +09:00
Yuki Okushi 2d2b0591a2
Merge pull request #142 from JohnTitor/new-server
server: Bump up to 1.0.3
2020-05-19 13:58:39 +09:00
Yuki Okushi abbc5f715f
server: Bump up to 1.0.3 2020-05-19 10:23:17 +09:00
Yuki Okushi 140a6c76e3
Merge pull request #141 from actix/fix-ci
Only check compilation on mingw CI
2020-05-19 09:39:03 +09:00
Yuki Okushi 2395b28c5e
Only check compilation on mingw CI
Disabled to run tests since somehow linking with OpenSSL is broken.
2020-05-19 09:11:27 +09:00
Yuki Okushi aad4812ba6
Merge pull request #140 from JohnTitor/replace-net2
Replace deprecated `net2` crate with `socket2`
2020-05-19 08:58:40 +09:00
Yuki Okushi ac6c78c476
testing: Replace `net2` crate with `socket2` 2020-05-19 08:21:40 +09:00
Yuki Okushi 8218a098e8
server: Replace `net2` crate with `socket2` 2020-05-19 08:17:44 +09:00
Yuki Okushi 49a6f525be
Merge pull request #139 from JohnTitor/next-macros
macros: Bump up to 0.1.2
2020-05-19 07:50:46 +09:00
Yuki Okushi f59ff82395
macros: Bump up to 0.1.2 2020-05-18 15:36:23 +09:00
Yuki Okushi f7cc62564d
Merge pull request #136 from JohnTitor/connect-alpha-3
actix-connect: Bump up to 2.0.0-alpha.3
2020-05-08 01:36:16 +09:00
Yuki Okushi b125e2bdce
actix-connect: Bump up to 2.0.0-alpha.3 2020-05-08 01:07:57 +09:00
Yuki Okushi a5c185e80e
Merge pull request #135 from actix/fix/unresolverd
correct spelling of ConnectError::Unresolved
2020-05-06 14:45:30 +09:00
Rob Ede 523cee0351
correct spelling of ConnectError::Unresolved 2020-05-03 23:14:22 +01:00
Yuki Okushi 343b3c09fc
Merge pull request #134 from JohnTitor/new-rt
Bump up `actix-rt` to 1.1.1
2020-04-30 14:34:17 +09:00
Yuki Okushi 8a10580663
Bump up `actix-rt` to 1.1.1 2020-04-30 03:07:12 +09:00
Yuki Okushi 1b4a117063
Merge pull request #128 from Jonathas-Conceicao/topic/fix_memory_leak
actix-rt: Spawn future to cleanup pending JoinHandles
2020-04-30 02:58:13 +09:00
Yuki Okushi 700997fe48
Merge pull request #133 from actix/macro-compile-testing
add macro compile tests
2020-04-29 15:33:00 +09:00
Rob Ede 4c5568ed70
add trybuild compile tests 2020-04-26 20:11:16 +01:00
Yuki Okushi 7d0cfe1b4d
Merge pull request #131 from danpintara/pull-1
actix-macros: Simplify test macros by using original signature
2020-04-23 02:33:52 +09:00
Daniel Pintara e35c261c9f actix-macros: test: Simplify by using #sig instead of #name(#inputs) #ret 2020-04-22 00:13:32 +07:00
Yuki Okushi 115ef3fcb3
Merge pull request #130 from JohnTitor/dont-clone
Remove unnecessary clone usage
2020-04-20 08:37:10 +09:00
Yuki Okushi c0482e2532
Remove unnecessary clone usage 2020-04-20 08:02:08 +09:00
Jonathas-Conceicao 6906f25e01 actix-rt: Set threshold size for arbiter's pending futures list
Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-04-16 03:12:05 -03:00
Jonathas-Conceicao 06bca19524 actix-rt: Spawn future to cleanup pending JoinHandles
Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-04-09 20:36:44 -03:00
Yuki Okushi e9e2185296
Merge pull request #127 from rubdos/test-fixture-integration
Forward actix_rt::test arguments to test function.
2020-04-09 17:45:17 +09:00
Ruben De Smet aae52a80ab Forward actix_rt::test arguments to test function.
Previously,

```rust
async fn foo(_a: u32) {}
```

would compile to

```rust
fn foo() {/* something */}
```

This patches changes this behaviour to

```rust
fn foo(_a: u32) {/* something */}
```

by simply forwarding the input arguments.

This allows any test fixture library (e.g. `rstest`, cfr.
https://github.com/la10736/rstest/issues/85) to integrate with
actix::test.
2020-04-08 16:48:10 +02:00
Yuki Okushi 65e2e8052e
Release actix-rt 1.1.0 (#126)
* Release actix-rt 1.1.0

* Update actix-rt/CHANGES.md
2020-04-08 16:34:07 +09:00
Jonathas-Conceicao 783880bb0a actix-rt: Add Arbiter::is_running helper and fix System::is_set doc
`Arbiter::is_running` can be used to check if the current even-loop is currently
running; which should also work after the system has stopped. `System::is_set`
was updated to reflect what it actually does, it tells if the event loop has
started, which alone can't tell if it has stopped.

Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-04-05 21:00:54 -03:00
Jonathas-Conceicao 69e8df9d62 actix-rt: Run rustfmt
Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-04-05 21:00:54 -03:00
Yuki Okushi 9addf1a36b
Merge pull request #125 from actix/fix/noisy-check
fix noisy check warning
2020-04-05 13:20:25 +09:00
Rob Ede 187a58472d
fix noisy check warning 2020-04-04 23:57:52 +01:00
Nikolay Kim 30aa0b7bb6 add serde support to bytestring 2020-03-30 11:54:40 +06:00
Yuki Okushi e775d08d76
Merge pull request #122 from actix/JohnTitor-patch-1
Upload coverage on PRs
2020-03-18 05:31:59 +09:00
Yuki Okushi d5f95b54b7
Upload coverage on PRs 2020-03-18 05:03:37 +09:00
Yuki Okushi 904f90abc2
Merge pull request #121 from actix/revert-115-JohnTitor-patch-2
Revert "Disable windows-mingw builder temporarily"
2020-03-16 18:06:42 +09:00
Yuki Okushi 950c73077c
Revert "Disable windows-mingw builder temporarily" 2020-03-16 17:31:10 +09:00
Yuki Okushi 732731a9c8
Merge pull request #120 from kornelski/err
std Error for BlockingError
2020-03-14 00:14:42 +09:00
Kornel Lesiński 0dd5a7ce1d std Error for BlockingError
#93
2020-03-13 12:35:20 +00:00
Yuki Okushi 7105091e51
Merge pull request #119 from JohnTitor/futures
Minimize `futures-*` dependencies
2020-03-13 05:12:37 +09:00
Yuki Okushi 08959dfc21
actix-tracing: Minimize `futures-util` dependencies 2020-03-12 07:13:32 +09:00
Yuki Okushi 2792433ad6
actix-codec: Minimize `futures-*` dependencies 2020-03-12 07:13:32 +09:00
Yuki Okushi 437a7b05c6
actix-rt: Fix build 2020-03-12 07:13:32 +09:00
Yuki Okushi 3d125c5381
actix-testing: Remove unused deps 2020-03-12 07:13:32 +09:00
Yuki Okushi fbf7d6ef33
Update examples 2020-03-12 07:13:32 +09:00
Yuki Okushi e6b6f08369
actix-utils: Minimize `futures-*` dependencies 2020-03-12 07:13:32 +09:00
Yuki Okushi 4e806b3e3f
actix-tls: Minimize `futures-*` dependencies 2020-03-12 07:13:31 +09:00
Yuki Okushi f5b07053fc
actix-server: Minimize `futures-*` dependencies 2020-03-12 07:13:31 +09:00
Yuki Okushi dd3bec83bf
actix-ioframe: Minimize `futures-*` dependencies 2020-03-12 07:13:31 +09:00
Yuki Okushi f955e49930
actix-connect: Minimize `futures-*` dependencies 2020-03-12 04:22:38 +09:00
Yuki Okushi 4be11b541b
Merge pull request #117 from actix/new-connect
Release actix-http v2.0.0-alpha.2
2020-03-08 15:13:52 +09:00
Yuki Okushi baba533407
Update `actix-http` dependency 2020-03-08 14:38:07 +09:00
Yuki Okushi 2bf50826b0
Bump up to 2.0.0-alpha.2 2020-03-08 14:37:33 +09:00
Yuki Okushi 41b2a3b2e2
Merge pull request #116 from Jonathas-Conceicao/topic/upgrade_trust_dns
actix-connect: Upgrade versions of trust-dns
2020-03-08 14:31:07 +09:00
Jonathas-Conceicao 7fdd4a1118 actix-connect: Upgrade versions of trust-dns
- `Address` trait is now required to have static lifetime;
- `start_resolver` and `start_default_resolver` are now `async` and may return
  a `ConnectError`;

Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-03-07 14:52:41 -03:00
Jonathas-Conceicao cb30f9e86a actix-connect: Run cargo fmt
Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-03-07 14:37:39 -03:00
Yuki Okushi 873f69be51
Merge pull request #115 from actix/JohnTitor-patch-2
Disable windows-mingw builder temporarily
2020-03-06 14:11:50 +09:00
Yuki Okushi 0967061f30
Merge pull request #114 from actix/JohnTitor-patch-1
Unpin quote version
2020-03-06 14:11:28 +09:00
Yuki Okushi 59902cb3a3
Disable windows-mingw builder temporarily 2020-03-06 13:48:55 +09:00
Yuki Okushi 857e50120b
Unpin quote version 2020-03-06 13:45:21 +09:00
Yuki Okushi 36a2edf1cd
Merge pull request #111 from dunnock/master
Fix build with failing quote
2020-03-05 23:05:19 +09:00
Maksym Vorobiov 346bd072d3 fix build with failing quote 2020-03-05 14:58:44 +02:00
Yuki Okushi 8d3d58b3b7
Merge pull request #110 from Aaron1011/fix/better-pin
Replace calls to `Pin::new_unchecked` with `pin_project`.
2020-03-05 21:52:55 +09:00
Aaron Hill c41b5d8dd4
Replace calls to `Pin::new_unchecked` with `pin_project`.
This is a breaking change, as it changes some public methods to take
`Pin<&mut Self>` rather than `&mut self`.

This brings these methods into line with `Stream::poll_next`, which also
takes a `Pin<&mut Self>`
2020-03-04 12:08:52 -05:00
Yuki Okushi 693d5132a9
Merge pull request #109 from JohnTitor/new-tls
actix-tls: Bump up to 2.0.0-alpha.1
2020-03-03 22:29:08 +09:00
Yuki Okushi f7dac3feb4 Bump up to 2.0.0-alpha.1 2020-03-03 19:47:40 +09:00
Yuki Okushi ebc11d03f2
Merge pull request #108 from JohnTitor/new-connect
Release `actix-connect` v2.0.0-alpha.1
2020-03-03 18:33:08 +09:00
Yuki Okushi e3ad5de270 Update `actix-connect` dependency 2020-03-03 17:24:41 +09:00
Yuki Okushi 91118bb2ce Bump up to 2.0.0-alpha.1 2020-03-03 17:24:25 +09:00
Yuki Okushi 6628688bcf
Merge pull request #107 from JohnTitor/rustls-017
Update `rustls` and `tokio-rustls`
2020-03-01 23:48:13 +09:00
Yuki Okushi b9567359fd actix-tls: Update `rustls` and `tokio-rustls` 2020-03-01 12:08:14 +09:00
Yuki Okushi 7dbc0264b1 actix-connect: Update `rustls` and `tokio-rustls` 2020-03-01 12:08:14 +09:00
Erich Gubler 1b7c969f6a
`actix-rt`: minimize `futures` dependencies to `futures-{channel,util}` with default features off (#104)
* build(deps): minimize `futures` deps by using `futures-channel` and `futures-util` directly

* style(actix-rt): enforce spaces around equals in `Cargo.toml`
2020-02-27 01:15:21 +09:00
Jonathas-Conceicao f1685d8253 Add Arbiter::local_join associated function
Arbiter::local_join function can be used to await for futures spawned
on current arbiter.

Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-02-26 12:59:46 -03:00
Jonathas-Conceicao e3b6a33b97 Add integration tests
These initial tests validade basic usage with timed futures for:
- `System::block_on`;
- `Arbiter::new`;
- `Arbiter::stop`;
- `Arbiter::join`;

Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
2020-02-26 12:59:46 -03:00
Yuki Okushi 13b503435f
Merge pull request #106 from JohnTitor/server-102
Release actix-server 1.0.2
2020-02-26 20:53:00 +09:00
Yuki Okushi 98f0290f65 actix-server: Bump up to 1.0.2 2020-02-26 19:48:52 +09:00
Yuki Okushi b8f66f5e7f Update changelog 2020-02-26 19:48:41 +09:00
Yuki Okushi dd59ee498e Add FIXME comment 2020-02-26 19:48:27 +09:00
Dany Laporte 83320efa31
Avoid error by `register()` on Windows (#103) 2020-02-26 18:40:31 +09:00
Yuki Okushi c69bc11e3e
Merge pull request #105 from actix/bench
Add action to check benchmark
2020-02-26 17:33:37 +09:00
Yuki Okushi aad5c42ad7 Add action to check benchmark 2020-02-26 17:11:46 +09:00
Maxim Vorobjov 4d37858fc6
Benchmarks for actix-service: focused around UnsafeCell usage (#98)
* add benchmark comparing unsafecell vs refcell

* fix syntax

* add benches for and_then implementation options

* repeat benches to stabilize
2020-02-26 16:45:23 +09:00
Yuki Okushi d402f08bb5
Merge pull request #102 from JohnTitor/single-import
Remove single import
2020-02-25 19:11:04 +09:00
Yuki Okushi fa25e30427 Remove single import 2020-02-25 18:41:15 +09:00
Bo Yao 602db1779e
Expose is_set (#99)
* Expose is_set

* Update doc and changes.md
2020-02-25 02:55:02 -03:00
Yuki Okushi 4f2910c6b3
Merge pull request #96 from actix/JohnTitor-patch-1
Disable coverage for PRs
2020-02-15 01:55:20 +09:00
Yuki Okushi 9f7d6bc068
Disable coverage for PRs 2020-02-14 07:30:21 +09:00
Yuki Okushi 6908b58943
Merge pull request #92 from actix/bye-travis
Move script from Travis to Actions
2020-02-02 06:28:42 +09:00
Yuki Okushi 043057ecbd Fix import scopes 2020-02-01 23:32:08 +09:00
Yuki Okushi e12bf9200b Clean up metadata 2020-01-31 02:21:25 +09:00
Yuki Okushi 03d431e663 Add badges on README 2020-01-31 00:01:47 +09:00
Yuki Okushi f0d352604e Remove travis config 2020-01-31 00:01:34 +09:00
Yuki Okushi 2f67e4f563 Use markdown format 2020-01-31 00:01:24 +09:00
Yuki Okushi d1155d60ec Tweak Actions 2020-01-31 00:01:11 +09:00
Yuki Okushi 28d9c6a760
Merge pull request #90 from actix/fix-ci
Tweak GitHub Actions
2020-01-30 00:46:21 +09:00
Yuki Okushi a970c2c997 Remove AppVeyor config 2020-01-29 12:05:55 +09:00
Yuki Okushi d5a6c83207 Suppress/fix clippy warnings 2020-01-29 12:05:55 +09:00
Yuki Okushi ee0db9a617 Tweak GitHub Actions 2020-01-29 12:05:55 +09:00
zero-systems e5b5df1261 Optimize vector fill in builder. (#89)
* optimize vector fill
2020-01-22 06:35:22 +09:00
Nikolay Kim dbfa13d6be Fixed unsoundness in .and_then()/.then() service combinators 2020-01-16 16:58:11 -08:00
Nikolay Kim e7c2439543 prep release 2020-01-15 13:35:07 -08:00
Nikolay Kim 3116db5168 revert 1.0.3 changes 2020-01-15 13:24:38 -08:00
Nikolay Kim 5940731ef0 Fix actix-service 1.0.3 compatibility 2020-01-15 11:58:06 -08:00
Rajasekharan Vengalil aed5fecc8a Add support for tokio tracing for actix Service. (#86)
* Add support for tokio tracing for actix Service.

* Address comments

* Change trace's return type to ApplyTransform

* Remove redundant type args

* Remove reference to MakeSpan from docs
2020-01-15 11:43:52 -08:00
Nikolay Kim a751899aad Fixed unsoundness in AndThenService impl #83 2020-01-15 11:40:15 -08:00
Nikolay Kim fa800aeba3 Fix AsRef<str> impl 2020-01-14 15:06:02 -08:00
Nikolay Kim 2f89483635 Merge branch 'master' of github.com:actix/actix-net 2020-01-14 00:42:29 -08:00
Nikolay Kim 3048073919 Add PartialEq<T: AsRef<str>>, AsRef<[u8]> impls 2020-01-13 11:58:31 +06:00
amosonn 4bbba803c1 Fix Service documentation (#85) 2020-01-12 07:44:01 +09:00
Sven-Hendrik Haase 4dcdeb6795
Merge pull request #84 from currency-engineering/master
Minor grammatical fix to docs.
2020-01-10 15:28:19 +01:00
Eric Findlay 3b4f222242 Minor grammatical fix to docs. 2020-01-10 20:52:49 +09:00
Nikolay Kim 7c5fa25b23 Add into_service helper function 2020-01-08 18:31:50 +06:00
Nikolay Kim 3551d6674d Add Clone impl for condition::Waiter 2020-01-08 11:18:56 +06:00
Nikolay Kim 9f00daea80 add Condition and Pool 2020-01-08 10:59:27 +06:00
Nikolay Kim 7dddeab2a8 Add ResourceDef::resource_path_named() path generation method 2019-12-31 18:02:43 +06:00
Nikolay Kim dcbcc40da2 Revert "Support named parameters for ResourceDef::resource_path() in form of ((&k, &v), ...)"
This reverts commit b0d44198ba.
2019-12-31 15:14:53 +06:00
Nikolay Kim b0d44198ba Support named parameters for ResourceDef::resource_path() in form of ((&k, &v), ...) 2019-12-31 14:53:30 +06:00
Nikolay Kim 974bd6b01e leak string instead of rc 2019-12-31 12:04:35 +06:00
Nikolay Kim 5779da0f49 refactor service and state manahement 2019-12-29 13:42:42 +06:00
Nikolay Kim 1918c8d4f8 rename .run to .start() 2019-12-29 10:07:46 +06:00
Nikolay Kim e21c58930b Add impl IntoPattern for &String 2019-12-25 21:34:14 +04:00
Nikolay Kim 59c5e9be6a Use IntoPattern for RouterBuilder::path() 2019-12-25 21:01:07 +04:00
Nikolay Kim a2a9d9764d introduce IntoPattern trait 2019-12-25 19:54:20 +04:00
Nikolay Kim bf0a9d2f6e Add IntoPatterns trait 2019-12-25 15:34:21 +04:00
Nikolay Kim 119027f822 fmt 2019-12-25 15:10:13 +04:00
Nikolay Kim 0fe8038d23 allow specify set of resource patters 2019-12-25 15:10:01 +04:00
Nikolay Kim b599bc4a0c map_config() and unit_config() accepts IntoServiceFactory type 2019-12-22 16:30:49 +04:00
Nikolay Kim a80e1f8370 fix new() method and make from_static and from_bytes_unchecked methods const 2019-12-22 16:24:28 +04:00
Nikolay Kim 5fe759cc02 Merge branch 'master' of github.com:actix/actix-net 2019-12-20 09:15:19 +06:00
Nikolay Kim 05549f0b42 Add methods to check LocalWaker registration state 2019-12-20 09:13:11 +06:00
Yuki Okushi b1430eaded
Run tests for all features as possible (#78) 2019-12-19 16:31:32 +09:00
Nikolay Kim 0d3f9e74c5 Use .advance() intead of .split_to() 2019-12-19 09:50:31 +06:00
Nikolay Kim cab73791ed pin trsut-dns-proto 2019-12-15 13:04:26 +06:00
Nikolay Kim a7ac1a76ed add license files to actix-macros 2019-12-14 23:01:55 +06:00
Nikolay Kim 37bedff6fb use parking_lot 0.10 2019-12-12 06:57:40 +06:00
Nikolay Kim 33fd6adc11 better InOrder test 2019-12-12 06:56:45 +06:00
Nikolay Kim 4305cdba2c Revert InOrder service changes 2019-12-11 23:10:02 +06:00
Nikolay Kim 52ecb4bcc5 Add oneshot::Sender::is_canceled() method 2019-12-11 20:52:57 +06:00
Nikolay Kim b28f32e82c Allow to create framed::Dispatcher with custom mpsc::Receiver 2019-12-11 20:23:14 +06:00
Nikolay Kim 081205a02f Disconnect callback accepts owned state 2019-12-11 18:57:43 +06:00
Nikolay Kim 8bb81c0768 optimize InOrder service 2019-12-11 18:55:53 +06:00
Nikolay Kim c7a8743bf9 remove E param 2019-12-11 16:44:09 +06:00
Nikolay Kim f26fcc703b prep release 2019-12-11 14:56:05 +06:00
Nikolay Kim ce4587df82 prepare actix-tls release 2019-12-11 14:53:58 +06:00
Nikolay Kim 9957f28137 prepare actix-testing release 2019-12-11 14:49:26 +06:00
Nikolay Kim 9d84d14ef4 update deps 2019-12-11 14:47:30 +06:00
Nikolay Kim 60bfa1bfb1 prepare actix-server release 2019-12-11 14:43:26 +06:00
Nikolay Kim 2c81c22b3e refactor ioframe dispatcher 2019-12-11 14:36:11 +06:00
Nikolay Kim dded482514 allow to close mpsc sender 2019-12-11 14:36:00 +06:00
Nikolay Kim 631cb86947 refactor framed and stream dispatchers 2019-12-11 12:42:07 +06:00
Nikolay Kim 2e5e69c9ba Simplify oneshot and mpsc implementations 2019-12-11 11:28:09 +06:00
Nikolay Kim e315cf2893 prep actix-rt release; update deps 2019-12-11 10:34:50 +06:00
Nikolay Kim 13fd615966 actix-macros release 2019-12-11 10:32:01 +06:00
Nikolay Kim c094f84b85 prepare actix-service release 2019-12-11 10:29:34 +06:00
Nikolay Kim 25012d290a update actix-codec dependencies 2019-12-11 10:23:01 +06:00
Nikolay Kim 32202188cc prepare actix-codec release 2019-12-11 10:18:11 +06:00
Nikolay Kim bf734a31dc update docs 2019-12-10 21:34:51 +06:00
Nikolay Kim d29e7c4ba6 Merge branch 'master' of github.com:actix/actix-net 2019-12-10 21:14:18 +06:00
Nikolay Kim 7163e2c2a2 update doc strings 2019-12-10 21:14:06 +06:00
Nikolay Kim 1d810b4561 re-export AlpnError 2019-12-10 12:15:27 +06:00
daxpedda 0913badd61 Macro improvements. (#74)
* Macro improvements.

* Fix usage in `fn main`.
2019-12-10 08:47:35 +06:00
Nikolay Kim 8b3062cd6e Fix buffer remaining capacity calcualtion 2019-12-09 21:50:36 +06:00
Nikolay Kim 35218a4df1 add Clone impl for Apply service 2019-12-09 14:07:20 +06:00
Nikolay Kim d47f1fb730 prepare actix-service release 2019-12-08 19:49:35 +06:00
Nikolay Kim 1ad0bbfb7f rename fn service helpers 2019-12-08 19:05:05 +06:00
Nikolay Kim c38a25f102 fix hash impl 2019-12-07 11:51:47 +06:00
Nikolay Kim 110457477a update changes 2019-12-07 11:04:53 +06:00
Nikolay Kim a899b1e04d bump actix-ioframe version 2019-12-07 10:55:54 +06:00
Nikolay Kim 393cf1ab25 add unsafe from_bytes_unchecked 2019-12-07 10:48:22 +06:00
Nikolay Kim 40fbbb9c32 fix crate name 2019-12-07 10:39:33 +06:00
Nikolay Kim 99fef4f06b add helper conversions 2019-12-07 10:22:08 +06:00
Nikolay Kim fc0825fcdd update tokio to 0.2.4 2019-12-07 10:15:26 +06:00
Nikolay Kim 6c00ab8296 add string crate 2019-12-07 09:59:39 +06:00
Nikolay Kim cbdbc05dbd update tokio verion and prep alpha3 release 2019-12-07 09:57:43 +06:00
Yuki Okushi 5674840c01 Stop running tests for all features (#73) 2019-12-07 08:54:58 +06:00
Nikolay Kim 6f07c9d72a update trust-dns 2019-12-06 14:08:11 +06:00
Nikolay Kim fa48ddcfa1 fix non unix signals support 2019-12-06 14:06:14 +06:00
Max Gortman f89a992daf eager drop in then, and_then, and_then_apply_fn (#72) 2019-12-06 10:34:44 +06:00
Nikolay Kim e670a32ff3 inclide stream feature 2019-12-06 01:34:13 +06:00
Nikolay Kim 021c742d22 use string crate from master 2019-12-06 00:10:27 +06:00
Nikolay Kim 88a60ffa66 reexport ssl types 2019-12-05 23:09:44 +06:00
Nikolay Kim cb2845cb26 fix dependencies 2019-12-05 20:58:28 +06:00
Nikolay Kim b18fbc98d5 move rustls and nativetls acceptor services to actix-tls 2019-12-05 20:52:37 +06:00
Nikolay Kim 3a858feaec migrate to tokio 0.2.2 2019-12-05 16:40:24 +06:00
Nikolay Kim d49aca9595 use bitflags for internal flags; use tokio 0.2 2019-12-05 13:11:56 +06:00
Nikolay Kim 6f41b80cb4 optimize service combinators memory layout 2019-12-05 12:37:26 +06:00
Nikolay Kim c6eb318536 Fix low/high watermark for write/read buffers; fix oneshot impl 2019-12-05 01:36:31 +06:00
Nikolay Kim 21dcc22e53 refactor server configurations 2019-12-04 21:35:27 +06:00
Nikolay Kim de84663768 fix initial worker service state 2019-12-04 15:52:49 +06:00
Nikolay Kim c4e2051327 refactor server worker 2019-12-04 15:12:02 +06:00
Nikolay Kim 0a4fe22003 Restore Service/Factory::apply_fn() in form of Pipeline/Factory::and_then_apply_fn() 2019-12-03 19:59:28 +06:00
Nikolay Kim eb773c8b8c Merge branch 'master' of github.com:actix/actix-net 2019-12-03 18:34:32 +06:00
Nikolay Kim db0bc1e156 Restore Transform::map_init_err() combinator 2019-12-03 18:32:02 +06:00
Yuki Okushi 9eb12e0467
Use GitHub Actions (#71) 2019-12-03 20:00:16 +09:00
Nikolay Kim eb33f0ecbe add Clone for apply combinator 2019-12-03 16:15:06 +06:00
Nikolay Kim cbc5da8625 update changes 2019-12-03 14:10:36 +06:00
Nikolay Kim ec8dca8d69 Merge branch 'master' of github.com:actix/actix-net 2019-12-03 14:09:35 +06:00
Nikolay Kim 6a9df026e7 Add missing Clone impl for factory_fn_cfg 2019-12-03 14:05:23 +06:00
Aaron Housh 2756bedc3d Fix for non Unix OS (#69) 2019-12-03 10:07:54 +06:00
Nikolay Kim bd4c4cda8b update threadpool 2019-12-02 22:49:02 +06:00
Nikolay Kim c0ede65317 restore 0.1 behavior 2019-12-02 22:47:49 +06:00
Nikolay Kim 9f575418c1 clippy warnings 2019-12-02 22:30:09 +06:00
Nikolay Kim 9ed35cca7a use owned value for service factory config 2019-12-02 21:27:48 +06:00
Nikolay Kim 3385682e09 remove server feature 2019-12-02 17:04:42 +06:00
Nikolay Kim f55f96bc77 fix dependencies 2019-12-02 11:49:42 +06:00
Nikolay Kim a08b1eba87 update tests 2019-12-02 11:43:52 +06:00
Nikolay Kim d81e72cf06 remove deprecaed crate 2019-12-02 11:30:52 +06:00
Nikolay Kim 9fbe6a1f6d refactor server configuration and tls support 2019-12-02 11:30:27 +06:00
Nikolay Kim 16ff283fb2 add metadata 2019-12-01 20:30:24 +06:00
Nikolay Kim 503c2feb08 re-export net primitives 2019-12-01 10:56:25 +06:00
Nikolay Kim bec4efc699 add extra methods to pipeline 2019-11-29 13:51:00 +06:00
Nikolay Kim 5e5ae2ddec restore stream dispatcher 2019-11-29 10:41:09 +06:00
Nikolay Kim a02064592b disable rustls 2019-11-27 21:03:26 +06:00
Nikolay Kim af72005159 move BoxFuture to boxed mod 2019-11-27 20:59:36 +06:00
Nikolay Kim c254bb978c allow to wait on Server until server stops; restore signal handling 2019-11-26 17:03:52 +06:00
Nikolay Kim 009f8e2e7c allow to wait server exit 2019-11-26 16:33:45 +06:00
Nikolay Kim f5aecdee8f work around to rust#62127 2019-11-26 10:14:21 +06:00
Nikolay Kim 4546774f4e inclide fn ident to err message 2019-11-26 10:04:46 +06:00
Nikolay Kim 2cf140a869 inclide fn token to err message 2019-11-26 10:01:46 +06:00
Nikolay Kim e76ea8e80c re-export timeout 2019-11-26 09:04:14 +06:00
Nikolay Kim 52d03fa18c use actix deps instead of tokio 2019-11-26 08:26:22 +06:00
Nikolay Kim 5efac449b1 re-export time utils 2019-11-26 08:12:16 +06:00
Nikolay Kim 4ceac79f2c add test and main macros 2019-11-25 21:49:11 +06:00
Nikolay Kim 1fddd1e75b renamed boxed service 2019-11-25 18:18:00 +06:00
Nikolay Kim 905d058454 upgrade derive_more 2019-11-25 17:54:47 +06:00
Nikolay Kim 5265714f68 prep alpha.1 release 2019-11-21 19:58:55 +06:00
Nikolay Kim ae4394c0f2 fix uds server support 2019-11-21 00:35:44 +06:00
Nikolay Kim d3c5518646 fix rustls acceptor 2019-11-19 18:54:36 +06:00
Nikolay Kim 3bf83c1d98 cleanup Unpin constraint; simplify Framed impl 2019-11-19 14:51:40 +06:00
Nikolay Kim 617e40a7e9 fix framed_read 2019-11-19 11:06:55 +06:00
Nikolay Kim 3105cde168 add Service impl for RefCell<S> 2019-11-19 08:45:09 +06:00
Nikolay Kim 5b74c79cf9 Simplify transform trait, remove map_init_err 2019-11-19 06:51:43 +06:00
Nikolay Kim 8bf8ad86d6 add IntoServiceFactory impl for servie_fn 2019-11-18 20:46:49 +06:00
Nikolay Kim 877f89eeb7 use service types for ssl connectors 2019-11-18 20:20:56 +06:00
Nikolay Kim 1354946460 remove pin-project; update Unpin consrtaint 2019-11-18 18:28:54 +06:00
Nikolay Kim 7404d82a9b use concrete types 2019-11-18 14:30:04 +06:00
Nikolay Kim c1cdc9908a update deps and fix definitions 2019-11-15 16:06:44 +06:00
Yuki Okushi be7904fd57
Fix code style (#65)
* Fix clippy warnings

* cargo fmt

* Remove redundant lifetime
2019-11-15 00:28:29 +09:00
Nikolay Kim 13049b80ca
Migrate actix-net to std::future (#64)
* Migrate actix-codec, actix-rt, and actix-threadpool to std::future

* update to latest tokio alpha and futures-rs

* Migrate actix-service to std::future,

This is a squash of ~8 commits, since it included a lot of experimentation. To see the commits,
look into the semtexzv/std-future-service-tmp branch.

* update futures-rs and tokio

* Migrate actix-threadpool to std::future (#59)

* Migrate actix-threadpool to std::future

* Cosmetic refactor

- turn log::error! into log::warn! as it doesn't throw any error
- add Clone and Copy impls for Cancelled making it cheap to operate with
- apply rustfmt

* Bump up crate version to 0.2.0 and pre-fill its changelog

* Disable patching 'actix-threadpool' crate in global workspace as unnecessary

* Revert patching and fix 'actix-rt'

* Migrate actix-rt to std::future (#47)

* remove Pin from Service::poll_ready(); simplify combinators api; make code compile

* disable tests

* update travis config

* refactor naming

* drop IntoFuture trait

* Migrate actix-server to std::future (#50)

Still not finished, this is more WIP, this is an aggregation of several commits, which
can be found in semtexzv/std-future-server-tmp branch

* update actix-server

* rename Factor to ServiceFactory

* start server worker in start mehtod

* update actix-utils

* remove IntoTransform trait

* Migrate actix-server::ssl::nativetls to std futures (#61)

* Refactor 'nativetls' module

* Migrate 'actix-server-config' to std futures

- remove "uds" feature
- disable features by default

* Switch NativeTlsAcceptor to use 'tokio-tls' crate

* Bikeshed features names and remove unnecessary dependencies for 'actix-server-config' crate

* update openssl impl

* migrate actix-connect to std::future

* migrate actix-ioframe to std::future

* update version to alpha.1

* fix boxed service

* migrate server rustls support

* migratte openssl and rustls connecttors

* store the thread's handle with arbiter (#62)

* update ssl connect tests

* restore service tests

* update readme
2019-11-14 18:38:24 +06:00
Nikolay Kim 9fa2a36b4e prepare actix-rt release 2019-11-14 17:33:28 +06:00
Ivan Ladelshchikov ed5023128b store the thread's handle with arbiter (#60) 2019-11-14 15:07:33 +06:00
Nikolay Kim 2e8c2c7733 Re-register task on every future poll 2019-10-14 17:55:52 +06:00
Nikolay Kim 115e82329f fix arbiter thread panic message 2019-10-14 11:19:08 +06:00
Nikolay Kim 0b0060fe47 update deps 2019-10-14 10:37:48 +06:00
Nikolay Kim 35e32d8e55 prepare actix-testing release 2019-10-14 10:30:27 +06:00
Nikolay Kim 9982a9498d register current task in counters available method. 2019-10-08 15:02:43 +06:00
Nikolay Kim fa72975f34 extra trace logging 2019-10-08 14:46:22 +06:00
Sven-Hendrik Haase fe5de2510d
Merge pull request #56 from actix/fix-52
Add an error message if we receive a non-hostname-based dest
2019-10-04 13:48:20 +02:00
Yuki Okushi e3155957a8
Prepare actix-server release (#55) 2019-10-04 17:36:23 +09:00
Sven-Hendrik Haase f6f9e1fcdb Add an error message if we receive a non-hostname-based dest
This is more helpful than an unwrap and at least points users at the right location.
Upstream issue is https://github.com/briansmith/webpki/issues/54
2019-10-04 07:30:13 +02:00
Yuki Okushi 2667850d60 Prepare actix-server-config release (#54)
* Prepare actix-server-config release

* Bump up actix-server-config to 0.2.0
2019-10-04 06:13:33 +06:00
Yuki Okushi fba2002702
Prepare actix-connect release (#53) 2019-10-04 06:21:59 +09:00
Jerome Gravel-Niquet e733c562d9 Update rustls, tokio-rustls and webpki across the board (#42)
* Update rustls, tokio-rustls and webpki across the board

* bump minimum rust version to 1.37

* updated readme and changelogs to reflect changes and minimum required rust version
2019-10-04 03:32:32 +09:00
Yuki Okushi 8f05986a9f
Use `map()` instead of `and_then()` (#51) 2019-10-03 14:55:44 +09:00
Nikolay Kim aa9bbe2114 prepare actix-ioframe release 2019-09-25 10:47:06 +06:00
Nikolay Kim 4837a901e2 prepare actix-server release 2019-09-25 10:35:15 +06:00
Nikolay Kim a02ff17cb1 remove actix-tower from workspace 2019-09-25 10:11:17 +06:00
Nikolay Kim dbf566928c drop tower intergration 2019-09-25 10:01:08 +06:00
Nikolay Kim ca982b2467 update workspace deps for tests 2019-09-25 10:00:54 +06:00
Nikolay Kim c859d13e3b use actix-testing instead of test server 2019-09-25 09:51:28 +06:00
Nikolay Kim 41e49e8093 update changes 2019-09-25 09:32:33 +06:00
Nikolay Kim 715a770d7a deprecate test server 2019-09-25 09:31:52 +06:00
Nikolay Kim 5469d8c910 prep actix-testing release 2019-09-25 09:26:12 +06:00
Nikolay Kim 8be5f773f4 add actix-testing crate 2019-09-17 16:04:20 +06:00
karlri b686b4c34e Feature uds: Add listen_uds to ServerBuilder (#43)
Allows directly passing an Unix Listener instead of a path. Useful
for example when running as a daemon under systemd with the systemd
crate.
2019-09-16 11:07:46 +06:00
Nikolay Kim 34a7b7f05a add TcpStreamService 2019-09-05 16:34:48 -07:00
Nikolay Kim b1d9b06a87 Use arbiters storage for default async resolver 2019-09-02 15:15:55 -07:00
Nikolay Kim 94e673b50b Add arbiter specific storage 2019-09-02 15:03:03 -07:00
Nikolay Kim 1a644c6bb1 Check service readiness for new_apply_cfg combinator 2019-08-27 05:28:15 +06:00
Yuki Okushi aad013f559
Fix clippy warnings (#40)
Add explicit `dyn`s

Remove let binding

Use +=

Return false

Derive Default for TcpConnector

Squash if/else

Remove unnecessary return keywords

Use is_empty()

Fix clippy attribute

Allow mut_from_ref
2019-08-17 05:15:51 +09:00
Aron Heinecke 7a18d9da26 Add check for minimum rust version (#39) 2019-08-07 17:49:29 -07:00
Aron Heinecke d59b8ce62e Fix invalid minimum version (#38) 2019-08-07 17:48:31 -07:00
Nikolay Kim 3821d511d0 prep actix-threadpool release 2019-08-05 09:54:49 -07:00
Nikolay Kim 62e429cb0c Merge branch 'master' of github.com:actix/actix-net 2019-08-05 09:53:03 -07:00
Nikolay Kim a2643d475a Add ConnectService and OpensslConnectService 2019-08-05 09:52:50 -07:00
Sven-Hendrik Haase 34c259a8b5
Merge pull request #35 from ignatenkobrain/parking_lot
threadpool: Update parking_lot to 0.9
2019-08-05 17:30:19 +02:00
Igor Gnatenko 8b398c3386
threadpool: Update parking_lot to 0.9
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2019-08-04 15:46:14 +02:00
Neil Locketz 0baceb0e56 Fix typo in desc (#34) 2019-07-30 09:35:57 -07:00
Michael Snoyman 6be1f37f6c Minor typo corrections in docs (#33) 2019-07-25 11:46:11 +06:00
Nikolay Kim a742768feb bump version 2019-07-24 14:16:25 +06:00
Marat Safin f913872159 add rustls support for connect (#31) 2019-07-24 14:14:26 +06:00
Nikolay Kim 41145040e1 remove ClonableService 2019-07-19 11:03:16 +06:00
Nikolay Kim 311bb14d97 add unix domain sockets support #3 2019-07-18 17:05:40 +06:00
Nikolay Kim 2955e49d78 add unix domain sockets support 2019-07-18 16:43:42 +06:00
Nikolay Kim 9d1b428b34 undeprecate framed transport 2019-07-17 13:31:00 +06:00
Nikolay Kim 42d526bced mark some fn as unsafe 2019-07-17 11:16:38 +06:00
Nikolay Kim 23a230a83b deprecate ClonableService and FramedTransport 2019-07-17 10:57:52 +06:00
Nikolay Kim 411e31786f update actix-connect changes 2019-07-17 10:33:47 +06:00
Nikolay Kim b491d373b1 update actix-rt changes 2019-07-17 10:30:59 +06:00
Jeff Muizelaar 9271b95c87 Avoid a copy of the Future when initializing the Box. (#29)
Future's can be pretty big (> 1500 bytes) so this probably worth doing.

I confirmed with memcpy-find that this did infact eliminate two ~1500
byte copies from the actix-web basic example.
2019-07-17 10:29:22 +06:00
Jan Michael Auer 1b3cd0d88c Expose Connect addrs (#30) 2019-07-17 06:17:51 +06:00
Nikolay Kim da302d4b7a fix disconnect callback 2019-07-03 13:02:03 +06:00
Nikolay Kim 922a919572 simple callback 2019-07-02 12:35:27 +06:00
Nikolay Kim 5a62175b6e add disconnect callback 2019-07-02 12:10:05 +06:00
Nikolay Kim 5445e341c3 give access to io object during connect stage 2019-07-01 22:37:59 +06:00
Nikolay Kim 1b17d274a0 refactor connect stage 2019-07-01 11:20:24 +06:00
Nikolay Kim 9d8b3e6275 impl Stream and Sink for Connect 2019-06-30 22:58:23 +06:00
Nikolay Kim 27baf03f64 Do not block on sink drop for FramedTransport 2019-06-26 15:20:56 +06:00
Nikolay Kim 205cac82ce add custom framed dispatcher service 2019-06-26 15:19:40 +06:00
Nikolay Kim 07708c5e9a prepare rt release 2019-06-22 09:02:17 +06:00
Nikolay Kim 1c04ad3238
Merge pull request #22 from GeorgeHahn/with-external-runtime
Allow Actix to be started on an external CurrentThread runtime
2019-06-22 08:53:19 +06:00
Nikolay Kim 66aa21740c
Merge pull request #28 from ignatenkobrain/deps
chore: Update derive_more to 0.15
2019-06-18 22:26:37 +06:00
Igor Gnatenko b183cb3324
chore: Update derive_more to 0.15
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2019-06-18 10:25:01 +02:00
Nikolay Kim 158482cd2f Add new_apply_cfg function 2019-06-06 14:28:07 +06:00
George Hahn 9e61f62871 `new_async` -> `run_in_executor` and return future directly + builder cleanup 2019-06-05 12:51:59 -05:00
Nikolay Kim 7051888289 prepare actix-threadpool release 2019-06-05 08:09:46 +06:00
Nikolay Kim 0caa47fc47
Merge pull request #27 from ignatenkobrain/license
Include license files into all sub-crates
2019-06-01 16:48:42 +06:00
Nikolay Kim 6d1cbb2d2f
Merge pull request #26 from ignatenkobrain/master
chore: Update parking_lot to 0.8
2019-06-01 16:47:56 +06:00
Igor Gnatenko ca289ddf7f Include license files into all sub-crates
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2019-05-30 20:38:44 +02:00
Igor Gnatenko ad9a197916
chore: Update parking_lot to 0.8
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2019-05-30 20:30:43 +02:00
George Hahn c4f05e033f fixup: fix `new_async` doc comment 2019-05-24 10:29:52 -05:00
George Hahn 048314913c Enable System to be executed on an external CurrentThread runtime 2019-05-23 13:34:47 -05:00
Nikolay Kim c1b183e1ce Merge branch 'master' of github.com:actix/actix-net 2019-05-18 10:56:51 -07:00
Nikolay Kim 87bc3dacd9 use u64 for shutdown_timeout 2019-05-18 10:56:41 -07:00
Nikolay Kim 0156f479a0
Merge pull request #19 from pka/patch-1
Fix typo
2019-05-15 13:12:26 -07:00
Pirmin Kalberer 139fa3b9a2
Fix typo 2019-05-15 20:51:24 +02:00
Nikolay Kim a14f612382 remove debug prints 2019-05-15 10:29:10 -07:00
Nikolay Kim 059e2ad042 Fix checked resource match 2019-05-15 10:21:29 -07:00
Nikolay Kim fdf2a6f422 prepare actix-utils release 2019-05-15 08:31:40 -07:00
Nikolay Kim fc2631c852 merge remote 2019-05-14 17:37:14 -07:00
Nikolay Kim d51b210ae7 Merge branch 'master' of github.com:actix/actix-net 2019-05-14 17:36:18 -07:00
Nikolay Kim 0a6cded975 change Either constructor 2019-05-14 17:32:50 -07:00
Nikolay Kim 14e3933d8b
Merge pull request #17 from neoeinstein/tower-interop
Second iteration on tower interop
2019-05-12 20:03:42 -07:00
Nikolay Kim 837504c10f update deps 2019-05-12 08:40:42 -07:00
Nikolay Kim 802d808aca prepare actix-connect release 2019-05-12 08:15:18 -07:00
Nikolay Kim 7712de3d8e update deps 2019-05-12 08:10:30 -07:00
Nikolay Kim f1d0d5f6f9 prepare actix-server release 2019-05-12 08:03:16 -07:00
Nikolay Kim a76fcaf4d8 prepare actix-utils release 2019-05-12 08:00:23 -07:00
Nikolay Kim a2134035d6 prepare actix-service release 2019-05-12 07:53:26 -07:00
Nikolay Kim 5f8599faf1 merge master 2019-05-12 06:06:45 -07:00
Nikolay Kim f0776fca94 Use associated type for NewService config 2019-05-12 06:03:50 -07:00
Marcus Griep c7676df697
Add documentation and doctests 2019-05-03 10:08:49 -04:00
Marcus Griep ecf7a11a20
Add convenience methods to wrap with middleware 2019-05-02 17:47:37 -04:00
Marcus Griep 686958fe0c
Add reciprical compatibility layer for tower 2019-05-02 17:22:22 -04:00
Nikolay Kim 49ade171f6
Update CHANGES.md 2019-05-01 23:20:00 -07:00
Nikolay Kim 0a2a520c35
Merge pull request #16 from boustrophedon/derive_debug
Derive debug for Server and ServerCommand
2019-05-01 23:19:16 -07:00
Harry Stern b0c37dfc87
Derive debug for Server and ServerCommand 2019-05-02 01:31:04 -04:00
Nikolay Kim 91e28a4312
Merge pull request #15 from neoeinstein/tower-interop
Add compatibility layer for tower-service
2019-04-29 10:21:32 -07:00
Marcus Griep 508dce8bf1
Add compatibility crate for tower-service
Introduces a new crate `actix-tower`, which makes it easier to use
services built on the `tower-service` abstraction to be used with
`actix-service`.
2019-04-29 12:39:16 -04:00
Nikolay Kim 8ed1099a2e
Merge pull request #14 from Bobo1239/master
Increase compiler recursion limit
2019-04-23 13:04:32 -07:00
Boris-Chengbiao Zhou 83544bd971 Increase compiler recursion limit
Fixes `cargo doc` on Windows. (actix/actix#189)
2019-04-23 22:02:37 +02:00
Nikolay Kim 76c317e0b2 Added support for remainder match 2019-04-22 21:19:22 -07:00
Nikolay Kim 3b314e4c8c Connect::set_addr() 2019-04-19 17:43:52 -07:00
Nikolay Kim ae27b87641 IoStream trait and impls for TcpStream, SslStream and TlsStream 2019-04-16 08:32:12 -07:00
Nikolay Kim fc2dcadc7a use stable version of trust-dns-resolver 2019-04-14 20:46:36 -07:00
Nikolay Kim 54f62b5035 prep release 2019-04-12 12:30:55 -07:00
Nikolay Kim d3208bf7a8 Do not start default resolver immediately for default connector. 2019-04-12 12:28:18 -07:00
Nikolay Kim 21507d3da1 add TestServerRuntime::run_on() method 2019-04-12 12:26:47 -07:00
Nikolay Kim b9d8a215b4 Start trust-dns default resolver on first use 2019-04-11 09:57:21 -07:00
Nikolay Kim 51c4dfe5cb Allow to reset Path instance; export Quoter type 2019-04-07 22:48:18 -07:00
Nikolay Kim a60112c71e Poll boxed service call result immediately 2019-04-07 20:48:40 -07:00
Nikolay Kim bd814d6f80 re-export trust-dns types 2019-04-05 10:36:57 -07:00
Nikolay Kim a4e0c71baa Merge branch 'master' of github.com:actix/actix-net 2019-04-04 15:41:50 -07:00
Nikolay Kim b9ea445e70 Log error if dns system config could not be loaded 2019-04-04 15:41:05 -07:00
Nikolay Kim ba2901269d
Merge pull request #11 from Dowwie/master
added docs for trait Service, trait Transform
2019-04-04 11:06:02 -07:00
dowwie 5cbc29306a updated as per comments 2019-04-04 14:02:53 -04:00
Nikolay Kim 810fa869ae remove unneeded static 2019-04-04 10:04:19 -07:00
dowwie 33cd51aabf added docs for trait Service, trait Transform 2019-04-04 11:40:28 -04:00
Nikolay Kim 629ed05f82 Get dynamic segment by name instead of iterator 2019-04-03 21:40:21 -07:00
Nikolay Kim 5e8ae210f7 Rename connect Connector to TcpConnector #10 2019-03-31 19:14:13 -07:00
Nikolay Kim 3add90628f Fix SIGINT force shutdown 2019-03-30 12:09:02 -07:00
Nikolay Kim 02ab804e0b prepare actix-service release 2019-03-29 11:16:40 -07:00
Nikolay Kim feac0b43d9 add impl Service for Rc<RefCell<S>> 2019-03-29 10:21:17 -07:00
Nikolay Kim 1441355d4f use release 2019-03-28 04:02:39 -07:00
Nikolay Kim 7c5afc09a6 move threadpool to separate crate 2019-03-28 03:56:52 -07:00
Nikolay Kim 16856c7d3f Merge branch 'master' of github.com:actix/actix-net 2019-03-27 17:30:54 -07:00
Nikolay Kim 95d02659d5 Added Framed::map_io() method 2019-03-27 17:30:37 -07:00
Juan Aguilar Santillana bcbd7e6ddf Fix unnecessary arbiter clone at builder rt 2019-03-23 09:46:08 +03:00
Nikolay Kim e0d3581239 allow to send messages to framed transport via mpsc channel 2019-03-20 09:44:23 -07:00
Nikolay Kim ef1bdb2eb2 update travis config 2019-03-17 10:25:24 -07:00
Nikolay Kim 10301ff49d temp tarpaulin fix 2019-03-17 08:53:50 -07:00
Nikolay Kim 27c28d6597 Fix error handling for single address 2019-03-15 11:37:51 -07:00
Nikolay Kim b290273e81 prepare actix-connect release 2019-03-14 22:39:49 -07:00
Nikolay Kim 720230b852
Merge pull request #8 from Firstyear/2019-03-15-arbiter-docs
Improve Arbiter documentation
2019-03-14 20:58:33 -07:00
Nikolay Kim 44c2639fd6 prepare actix-server release 2019-03-14 20:55:55 -07:00
Nikolay Kim 9a5705d1b6 merge travis branch 2019-03-14 20:53:56 -07:00
Nikolay Kim 7ff923a58f stop tests threads 2019-03-14 20:52:17 -07:00
Nikolay Kim 6659b192d3 travis config 2019-03-14 20:52:13 -07:00
Nikolay Kim 1146d9cf30 fix init order 2019-03-14 20:48:58 -07:00
Nikolay Kim b7b76c47e5 rename method 2019-03-14 20:23:49 -07:00
Nikolay Kim d23dc6f6af Allow to run future before server service initialization 2019-03-14 20:09:34 -07:00
William Brown 9b6a955da4 Improve Arbiter documentation 2019-03-15 10:24:27 +10:00
Nikolay Kim f3aa48309f travis config 2019-03-14 11:55:39 -07:00
Nikolay Kim c9b86712e5 reinstall tarpaulin 2019-03-14 11:31:32 -07:00
Nikolay Kim 0f74f280f9 impl Address for http::Uri 2019-03-14 11:15:32 -07:00
Nikolay Kim eb37e15554 use specific version of nightly 2019-03-14 10:43:36 -07:00
Nikolay Kim ad007b8b42 Merge branch 'master' of github.com:actix/actix-net 2019-03-14 10:28:47 -07:00
Nikolay Kim 7c0d1f2273 update travis config 2019-03-14 10:25:34 -07:00
Nikolay Kim d82bc7c52b
Merge pull request #7 from najamelan/fix/compiler_warnings
Fix compiler warnings.
2019-03-14 07:24:37 -07:00
Nikolay Kim 265229b44b allow to override port 2019-03-13 22:55:01 -07:00
Nikolay Kim 38545dedc7 refactor Connect type and add tests 2019-03-13 22:51:31 -07:00
Nikolay Kim 6ebff22601 simplify name 2019-03-13 16:38:08 -07:00
Nikolay Kim 2c9b91b366 add specific constructors 2019-03-13 15:55:20 -07:00
Nikolay Kim b483200037 remove generic 2019-03-13 15:52:51 -07:00
Nikolay Kim a73600fbcd remove generic E 2019-03-13 15:51:21 -07:00
Nikolay Kim 084a28ca07 add Connect::with_request 2019-03-13 15:49:31 -07:00
Nikolay Kim a7c74c53ea store request in Connect request 2019-03-13 15:37:12 -07:00
Nikolay Kim 3e7d737e73 update travis 2019-03-13 14:39:02 -07:00
Nikolay Kim 87db4bf741 changes 2019-03-13 14:38:33 -07:00
Nikolay Kim 8b0fe6f796 rename crate 2019-03-13 12:41:41 -07:00
Nikolay Kim 52a45fda53 redesign actix-connector 2019-03-13 12:40:11 -07:00
Naja Melan 2c7de7e0fb Fix compiler warnings.
Compiles in stable and nightly
2019-03-13 08:41:26 +01:00
Nikolay Kim 1fcc0734b5 prep release 2019-03-12 17:01:02 -07:00
Nikolay Kim b6f952b036 remove constraint 2019-03-12 16:49:57 -07:00
Nikolay Kim 0fdac38307 add constraint 2019-03-12 16:48:29 -07:00
Nikolay Kim a3c4637372 prepare actix-server release 2019-03-12 16:40:22 -07:00
Nikolay Kim ae9bc5ae78 refactor ApplyConfig combinator 2019-03-12 16:32:10 -07:00
Nikolay Kim 21c289d7e4 fix InOrderService::poll_ready() nested service rediness check 2019-03-12 16:03:05 -07:00
Nikolay Kim 5e6eed905c fix InFlightService::poll_ready() nested service rediness check 2019-03-12 15:48:02 -07:00
Nikolay Kim 6801a38de5 check readiness for all services 2019-03-12 15:15:14 -07:00
Nikolay Kim 39356690b0 use ServerConfig for system configuration 2019-03-12 14:14:21 -07:00
Nikolay Kim f6f292a678 enforce constraint on OpensslAcceptor 2019-03-12 13:57:28 -07:00
Nikolay Kim b3366bc1af service response is not important 2019-03-12 13:55:31 -07:00
Nikolay Kim 2c1f8f0b96 enforce constraints on AndThenNewService type 2019-03-12 13:50:14 -07:00
Nikolay Kim e7465bfa2e fix map_err constraints 2019-03-12 13:45:05 -07:00
Nikolay Kim 755d4958c5 use IntoService types for transform services 2019-03-12 13:39:04 -07:00
Nikolay Kim 825117fd4c add Deref/DerefMut impls for Io 2019-03-12 13:12:22 -07:00
Nikolay Kim 7033b50fed add Io::set method for overriding param 2019-03-12 12:53:43 -07:00
Nikolay Kim ef9bfb8981 add helpers 2019-03-12 12:53:08 -07:00
Nikolay Kim bef199f831 add blocking mod support 2019-03-11 22:54:27 -07:00
Nikolay Kim f1d4bcef4b add Arbiter::exec_fn and exec functions 2019-03-11 22:51:17 -07:00
Nikolay Kim 8e13ba7bce update readme 2019-03-11 18:24:31 -07:00
Nikolay Kim 9a9b3e9ca9 update server tests 2019-03-11 15:19:28 -07:00
Nikolay Kim 5567fb41d2 add default type parameter 2019-03-11 13:48:55 -07:00
Nikolay Kim ad50595ece add PartialEq impl for Io 2019-03-11 13:37:30 -07:00
Nikolay Kim 2430c7247b update timing for travis 2019-03-11 12:53:16 -07:00
Nikolay Kim 1bf0f1e1a5 add Debug impl for Io; update examples 2019-03-11 12:46:12 -07:00
Nikolay Kim 9887aef6e8 add delay to test 2019-03-11 12:35:57 -07:00
Nikolay Kim 787255d030 add io parameters 2019-03-11 12:01:55 -07:00
Nikolay Kim f696914038 prepare router release 2019-03-09 14:38:08 -08:00
Nikolay Kim 3618f542fb prepare release actix-utils 2019-03-09 14:30:37 -08:00
Nikolay Kim 1f54ae9051 update deps 2019-03-09 14:23:08 -08:00
Nikolay Kim 86f57e5a4a prepare actix-service release 2019-03-09 14:10:02 -08:00
Nikolay Kim 43ad18ccb1 remove get_decoded 2019-03-09 13:58:07 -08:00
Nikolay Kim 34995a8ccf revert re-quoting change 2019-03-09 13:56:09 -08:00
Nikolay Kim 0ff300c40f export ApplyConfig 2019-03-09 09:05:51 -08:00
Nikolay Kim 629ef23371 add .apply_cfg new service combinator 2019-03-09 09:02:23 -08:00
Nikolay Kim d2b96ff877 add ServerConfig to server services 2019-03-09 07:31:22 -08:00
Nikolay Kim ac62e2dbf9 revert generic request in actix-utils 2019-03-09 07:27:35 -08:00
Nikolay Kim 6bbbdba921 revert generic Request change 2019-03-09 06:36:23 -08:00
Nikolay Kim 2099629fe3 cleanup ssl services 2019-03-08 22:41:30 -08:00
Nikolay Kim a4d4770462 remove server config 2019-03-08 22:38:39 -08:00
Nikolay Kim 70ead175b9 IntoService for fn_cfg_factory 2019-03-08 20:51:50 -08:00
Nikolay Kim 49867b5e9d fix IntoService 2019-03-08 20:50:29 -08:00
Nikolay Kim 0f064c43e9 remove uneeded code 2019-03-08 20:10:47 -08:00
Nikolay Kim 7db29544f9 add ServerConfig param for server service 2019-03-08 19:43:13 -08:00
Nikolay Kim 4850cf41ff rename module 2019-03-08 16:26:30 -08:00
Nikolay Kim 046142ffbc added is_prefix_match and resource_path 2019-03-08 15:34:40 -08:00
Nikolay Kim 49e6dbcda2 remove unused ResourceMap 2019-03-08 12:33:44 -08:00
Nikolay Kim 877614a494 add params decoding 2019-03-08 04:43:51 -08:00
Nikolay Kim ac0e8b9e53 re-enable examples 2019-03-06 23:33:35 -08:00
Nikolay Kim b407c65f4c add FramedParts::with_read_buf method 2019-03-06 22:53:55 -08:00
Nikolay Kim 51bd7d2721 update actix-rt 2019-03-06 10:39:53 -08:00
Nikolay Kim c03d869694 return io::Result from run method, remove Handle 2019-03-06 10:24:58 -08:00
Nikolay Kim 25f1eae51f add ResourceDef::root_prefix, insert slash to the beggining of the pattern 2019-03-05 21:03:53 -08:00
Nikolay Kim 1153715149 change generics order for Transform trait 2019-03-05 09:49:08 -08:00
Nikolay Kim aa2967c653 fix feature gated code 2019-03-05 07:41:41 -08:00
Nikolay Kim dfbb77f98d make service Request type generic 2019-03-05 07:35:26 -08:00
Nikolay Kim e8a49801eb revert IntoFuture change 2019-03-04 21:37:06 -08:00
Nikolay Kim 03f2046a42 add ApplyTransform new service 2019-03-04 21:25:50 -08:00
Nikolay Kim 2e18ca805c use IntoFuture 2019-03-04 20:40:38 -08:00
Nikolay Kim 15dafeff3d use IntoFuture instead of Future 2019-03-04 20:37:03 -08:00
Nikolay Kim ed14e6b8ea change to IntoFuture 2019-03-04 20:29:35 -08:00
Nikolay Kim 700abc997e prepare actix-utils release 2019-03-04 19:45:17 -08:00
Nikolay Kim 8c48bf4de7 simplify transform trait 2019-03-04 19:38:11 -08:00
Nikolay Kim 9bc492cf6c add SslError 2019-03-04 16:16:39 -08:00
Nikolay Kim d2a223e69e update changes 2019-03-04 15:42:25 -08:00
Nikolay Kim e9657a399a add maxconnrate 2019-03-04 15:41:16 -08:00
Nikolay Kim 9f25fdf929 rename StreamServiceFactory to ServiceFactory 2019-03-04 14:31:46 -08:00
Nikolay Kim 82930de8e7 use default type for RouterBuilder 2019-03-04 14:03:46 -08:00
Nikolay Kim 04a3e59bd5 update tests 2019-03-04 12:41:39 -08:00
Nikolay Kim 0ff0daa795 allow custom checks for resource selection 2019-03-04 11:47:03 -08:00
Nikolay Kim fb43940824 allow empty pattern 2019-03-03 21:00:58 -08:00
239 changed files with 20074 additions and 12452 deletions

View File

@ -1,41 +0,0 @@
environment:
global:
PROJECT_NAME: actix-net
matrix:
# Stable channel
- TARGET: i686-pc-windows-msvc
CHANNEL: stable
- TARGET: x86_64-pc-windows-gnu
CHANNEL: stable
- TARGET: x86_64-pc-windows-msvc
CHANNEL: stable
# Nightly channel
- TARGET: i686-pc-windows-msvc
CHANNEL: nightly
- TARGET: x86_64-pc-windows-gnu
CHANNEL: nightly
- TARGET: x86_64-pc-windows-msvc
CHANNEL: nightly
# Install Rust and Cargo
# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
install:
- ps: >-
If ($Env:TARGET -eq 'x86_64-pc-windows-gnu') {
$Env:PATH += ';C:\msys64\mingw64\bin'
} ElseIf ($Env:TARGET -eq 'i686-pc-windows-gnu') {
$Env:PATH += ';C:\MinGW\bin'
}
- curl -sSf -o rustup-init.exe https://win.rustup.rs
- rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -Vv
- cargo -V
# 'cargo test' takes care of building for us, so disable Appveyor's build stage.
build: false
# Equivalent to Travis' `script` phase
test_script:
- cargo clean
- cargo test

15
.cargo/config.toml Normal file
View File

@ -0,0 +1,15 @@
[alias]
lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
# just check the library (without dev deps)
ci-check-min = "hack --workspace check --no-default-features"
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 --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 --depth=2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

25
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,25 @@
## PR Type
<!-- What kind of change does this PR make? -->
<!-- Bug Fix / Feature / Refactor / Code Style / Other -->
INSERT_PR_TYPE
## PR Checklist
Check your PR fulfills the following:
<!-- For draft PRs check the boxes as you complete them. -->
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] A changelog entry has been made for the appropriate packages.
- [ ] Format code with the latest stable rustfmt
## Overview
<!-- Describe the current and new behavior. -->
<!-- Emphasize any breaking changes. -->
<!-- If this PR fixes or closes an issue, reference it here. -->
<!-- Closes #000 -->

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

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

@ -0,0 +1,129 @@
name: CI (post-merge)
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.2
- 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.11.0
with:
toolchain: ${{ matrix.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@v2.49.40
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.11.0
with:
toolchain: nightly
- name: Install cargo-hack & cargo-minimal-versions
uses: taiki-e/install-action@v2.49.40
with:
tool: cargo-hack,cargo-minimal-versions
- name: Check With Minimal Versions
run: cargo minimal-versions check

133
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,133 @@
name: CI
on:
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 }
version:
- { name: msrv, version: "${{ needs.read_msrv.outputs.msrv }}" }
- { name: stable, version: stable }
name: ${{ matrix.target.name }} / ${{ matrix.version.name }}
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.2
- 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.name }})
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
with:
toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
uses: taiki-e/install-action@v2.49.40
with:
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'
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
- name: CI cache clean
run: cargo-ci-cache-clean
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
with:
toolchain: nightly
- name: Install just
uses: taiki-e/install-action@v2.49.40
with:
tool: just
- name: doc tests
run: just test-docs

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.11.0
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2.49.40
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@v5.4.0
with:
files: codecov.json
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

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

@ -0,0 +1,69 @@
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.11.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.11.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:
if: false # rustdoc mismatch currently
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust (${{ vars.RUST_VERSION_EXTERNAL_TYPES }})
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
with:
toolchain: ${{ vars.RUST_VERSION_EXTERNAL_TYPES }}
- name: Install just
uses: taiki-e/install-action@v2.49.40
with:
tool: just
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v2.1.1
with:
tool: cargo-check-external-types
- name: check external types
run: just check-external-types-all +${{ vars.RUST_VERSION_EXTERNAL_TYPES }}

7
.gitignore vendored
View File

@ -1,4 +1,3 @@
Cargo.lock
target/ target/
guide/build/ guide/build/
/gh-pages /gh-pages
@ -12,3 +11,9 @@ guide/build/
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.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

29
.taplo.toml Normal file
View File

@ -0,0 +1,29 @@
exclude = ["target/*"]
include = ["**/*.toml"]
[formatting]
column_width = 110
[[rule]]
include = ["**/Cargo.toml"]
keys = [
"dependencies",
"*-dependencies",
"workspace.dependencies",
"workspace.*-dependencies",
"target.*.dependencies",
"target.*.*-dependencies",
]
formatting.reorder_keys = true
[[rule]]
include = ["**/Cargo.toml"]
keys = [
"dependencies.*",
"*-dependencies.*",
"workspace.dependencies.*",
"workspace.*-dependencies.*",
"target.*.dependencies",
"target.*.*-dependencies",
]
formatting.reorder_keys = false

View File

@ -1,57 +0,0 @@
language: rust
sudo: required
dist: trusty
cache:
cargo: true
apt: true
matrix:
include:
- rust: stable
- rust: beta
- rust: nightly
allow_failures:
- rust: nightly
env:
global:
- RUSTFLAGS="-C link-dead-code"
- OPENSSL_VERSION=openssl-1.0.2
before_install:
- sudo add-apt-repository -y ppa:0k53d-karl-f830m/openssl
- sudo apt-get update -qq
- sudo apt-get install -y openssl libssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev
# Add clippy
before_script:
- export PATH=$PATH:~/.cargo/bin
script:
- |
if [[ "$TRAVIS_RUST_VERSION" != "nightly" ]]; then
cargo clean
cargo test --features="ssl,tls,rust-tls" -- --nocapture
cd actix-codec && cargo test && cd ..
cd actix-service && cargo test && cd ..
cd actix-server && cargo test --features="ssl,tls,rust-tls" -- --nocapture && cd ..
cd actix-rt && cargo test && cd ..
cd actix-connector && cargo test && cd ..
cd actix-utils && cargo test && cd ..
cd router && cargo test && cd ..
fi
- |
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install -f cargo-tarpaulin
cargo tarpaulin --features="ssl,tls,rust-tls" --out Xml
bash <(curl -s https://codecov.io/bash)
echo "Uploaded code coverage"
cd actix-service && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd actix-rt && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd actix-connector && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd actix-codec && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd actix-server && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd actix-utils && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
cd router && cargo tarpaulin --out Xml && bash <(curl -s https://codecov.io/bash) && cd ..
fi

View File

@ -1,68 +0,0 @@
# Changes
## [0.3.0] - xxx
* Split `Service` trait to separate crate
* Use new `Service<Request>` trait
## [0.2.4] - 2018-11-21
### Added
* Allow to skip name resolution stage in Connector
## [0.2.3] - 2018-11-17
### Added
* Framed::is_write_buf_empty() checks if write buffer is flushed
## [0.2.2] - 2018-11-14
### Added
* Add low/high caps to Framed
### Changed
* Refactor Connector and Resolver services
### Fixed
* Fix wrong service to socket binding
## [0.2.0] - 2018-11-08
### Added
* Timeout service
* Added ServiceConfig and ServiceRuntime for server service configuration
### Changed
* Connector has been refactored
* timer and LowResTimer renamed to time and LowResTime
* Refactored `Server::configure()` method
## [0.1.1] - 2018-10-10
### Changed
- Set actix min version - 0.7.5
- Set trust-dns min version
## [0.1.0] - 2018-10-08
* Initial impl

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: Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language - Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences - Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism - Gracefully accepting constructive criticism
* Focusing on what is best for the community - Focusing on what is best for the community
* Showing empathy towards other community members - Showing empathy towards other community members
Examples of unacceptable behavior by participants include: Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances - The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks - Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment - Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission - 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 - Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities ## Our Responsibilities
@ -34,10 +34,13 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at fafhrd91@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at robjtede@icloud.com ([@robjtede]) or huyuumi@neet.club ([@JohnTitor]). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
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. 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
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

2941
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,44 @@
[workspace] [workspace]
resolver = "2"
members = [ members = [
"actix-codec", "actix-codec",
"actix-connector", "actix-macros",
"actix-rt", "actix-rt",
"actix-service",
"actix-server", "actix-server",
"actix-test-server", "actix-service",
"actix-tls",
"actix-tracing",
"actix-utils", "actix-utils",
"router", "bytestring",
"local-channel",
"local-waker",
] ]
[workspace.package]
license = "MIT OR Apache-2.0"
edition = "2021"
rust-version = "1.71.1"
[patch.crates-io]
actix-codec = { path = "actix-codec" }
actix-macros = { path = "actix-macros" }
actix-rt = { path = "actix-rt" }
actix-server = { path = "actix-server" }
actix-service = { path = "actix-service" }
actix-tls = { path = "actix-tls" }
actix-tracing = { path = "actix-tracing" }
actix-utils = { path = "actix-utils" }
bytestring = { path = "bytestring" }
local-channel = { path = "local-channel" }
local-waker = { path = "local-waker" }
[profile.release]
lto = true
opt-level = 3
codegen-units = 1
[workspace.lints.rust]
rust_2018_idioms = "deny"
nonstandard-style = "deny"
future_incompatible = "deny"
missing_docs = { level = "warn", priority = -1 }

View File

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2017-NOW Nikolay Kim Copyright 2017-NOW Actix Team
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
Copyright (c) 2017 Nikolay Kim Copyright (c) 2017-NOW Actix Team
Permission is hereby granted, free of charge, to any Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated person obtaining a copy of this software and associated

View File

@ -1,76 +1,30 @@
# Actix net [![Build Status](https://travis-ci.org/actix/actix-net.svg?branch=master)](https://travis-ci.org/actix/actix-net) [![codecov](https://codecov.io/gh/actix/actix-net/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-net) [![crates.io](https://meritbadge.herokuapp.com/actix-net)](https://crates.io/crates/actix-net) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # Actix Net
Actix net - framework for composable network services (experimental) > A collection of lower-level libraries for composable network services.
## Documentation & community resources [![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/graph/badge.svg?token=8rKIZKtLLm)](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-net/status.svg)](https://deps.rs/repo/github/actix/actix-net)
* [API Documentation (Development)](https://actix.rs/actix-net/actix_net/) ## Examples
* [Chat on gitter](https://gitter.im/actix/actix)
* Cargo package: [actix-net](https://crates.io/crates/actix-net)
* Minimum supported Rust version: 1.26 or later
## Example See example folders for [`actix-server`](./actix-server/examples) and [`actix-tls`](./actix-tls/examples).
```rust ## MSRV
fn main() {
let sys = actix_rt::System::new("test");
// load ssl keys 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.
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder.set_private_key_file("./examples/key.pem", SslFiletype::PEM).unwrap();
builder.set_certificate_chain_file("./examples/cert.pem").unwrap();
let acceptor = builder.build();
let num = Arc::new(AtomicUsize::new(0));
// bind socket address and start workers. By default server uses number of
// available logical cpu as threads count. actix net start separate
// instances of service pipeline in each worker.
actix_server::build()
.bind(
// configure service pipeline
"basic", "0.0.0.0:8443",
move || {
let num = num.clone();
let acceptor = acceptor.clone();
// service for converting incoming TcpStream to a SslStream<TcpStream>
(move |stream| {
SslAcceptorExt::accept_async(&acceptor, stream)
.map_err(|e| println!("Openssl error: {}", e))
})
// convert closure to a `NewService`
.into_new_service()
// .and_then() combinator uses other service to convert incoming `Request` to a `Response`
// and then uses that response as an input for next service.
// in this case, on success we use `logger` service
.and_then(logger)
// Next service counts number of connections
.and_then(move |req| {
let num = num.fetch_add(1, Ordering::Relaxed);
println!("processed {:?} connections", num);
future::ok(())
})
}).unwrap()
.start();
sys.run();
}
```
## License ## License
This project is licensed under either of The crates in repo are licensed under either of:
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
* MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) - MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
at your option. at your option.
## Code of Conduct ## Code of Conduct
Contribution to the actix-net crate is organized under the terms of the Contribution to the actix-net repo is organized under the terms of the Contributor Covenant.
Contributor Covenant, the maintainer of actix-net, @fafhrd91, promises to The Actix team promises to intervene to uphold that code of conduct.
intervene to uphold that code of conduct.

View File

@ -1,5 +1,85 @@
# Changes # Changes
## [0.1.0] - 2018-12-09 ## Unreleased
* Move codec to separate crate - Minimum supported Rust version (MSRV) is now 1.71.
## 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
- No significant changes since `0.4.1`.
## 0.4.1
- Added `LinesCodec`.
- `Framed::poll_ready` flushes when the buffer is full.
## 0.4.0
- No significant changes since v0.4.0-beta.1.
## 0.4.0-beta.1
- Replace `pin-project` with `pin-project-lite`.
- Upgrade `tokio` dependency to `1`.
- Upgrade `tokio-util` dependency to `0.6`.
- Upgrade `bytes` dependency to `1`.
## 0.3.0
- No changes from beta 2.
## 0.3.0-beta.2
- Remove unused type parameter from `Framed::replace_codec`.
## 0.3.0-beta.1
- Use `.advance()` instead of `.split_to()`.
- Upgrade `tokio-util` to `0.3`.
- Improve `BytesCodec::encode()` performance.
- Simplify `BytesCodec::decode()`.
- Rename methods on `Framed` to better describe their use.
- 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
- 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
- Added `Framed::map_io()` method.
## 0.1.1
- Added `FramedParts::with_read_buffer()` method.
## 0.1.0
- Move codec to separate crate.

View File

@ -1,25 +1,36 @@
[package] [package]
name = "actix-codec" name = "actix-codec"
version = "0.1.0" version = "0.5.2"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
description = "Utilities for encoding and decoding frames" description = "Codec utilities for working with framed protocols"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net"
repository = "https://github.com/actix/actix-net.git"
documentation = "https://docs.rs/actix-codec/"
categories = ["network-programming", "asynchronous"] categories = ["network-programming", "asynchronous"]
license = "MIT/Apache-2.0" license = "MIT OR Apache-2.0"
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] edition.workspace = true
edition = "2018" rust-version.workspace = true
workspace = "../"
[lib] [package.metadata.cargo_check_external_types]
name = "actix_codec" allowed_external_types = ["bytes::*", "futures_core::*", "futures_sink::*", "tokio::*", "tokio_util::*"]
path = "src/lib.rs"
[dependencies] [dependencies]
bytes = "0.4" bitflags = "2"
futures = "0.1.24" bytes = "1"
tokio-io = "0.1" futures-core = { version = "0.3.7", default-features = false }
tokio-codec = "0.1" futures-sink = { version = "0.3.7", default-features = false }
log = "0.4" memchr = "2.3"
pin-project-lite = "0.2"
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.5", features = ["html_reports"] }
tokio-test = "0.4.2"
[[bench]]
name = "lines"
harness = false
[lints]
workspace = true

1
actix-codec/LICENSE-APACHE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-APACHE

1
actix-codec/LICENSE-MIT Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-MIT

View File

@ -0,0 +1,59 @@
#![allow(missing_docs)]
use bytes::BytesMut;
use criterion::{criterion_group, criterion_main, Criterion};
const INPUT: &[u8] = include_bytes!("./lorem.txt");
fn bench_lines_codec(c: &mut Criterion) {
let mut decode_group = c.benchmark_group("lines decode");
decode_group.bench_function("actix", |b| {
b.iter(|| {
use actix_codec::Decoder as _;
let mut codec = actix_codec::LinesCodec::default();
let mut buf = BytesMut::from(INPUT);
while let Ok(Some(_bytes)) = codec.decode_eof(&mut buf) {}
});
});
decode_group.bench_function("tokio", |b| {
b.iter(|| {
use tokio_util::codec::Decoder as _;
let mut codec = tokio_util::codec::LinesCodec::new();
let mut buf = BytesMut::from(INPUT);
while let Ok(Some(_bytes)) = codec.decode_eof(&mut buf) {}
});
});
decode_group.finish();
let mut encode_group = c.benchmark_group("lines encode");
encode_group.bench_function("actix", |b| {
b.iter(|| {
use actix_codec::Encoder as _;
let mut codec = actix_codec::LinesCodec::default();
let mut buf = BytesMut::new();
codec.encode("123", &mut buf).unwrap();
});
});
encode_group.bench_function("tokio", |b| {
b.iter(|| {
use tokio_util::codec::Encoder as _;
let mut codec = tokio_util::codec::LinesCodec::new();
let mut buf = BytesMut::new();
codec.encode("123", &mut buf).unwrap();
});
});
encode_group.finish();
}
criterion_group!(benches, bench_lines_codec);
criterion_main!(benches);

View File

@ -0,0 +1,5 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In tortor quam, pulvinar sit amet vestibulum eget, tincidunt non urna. Sed eu sem in felis malesuada venenatis. Suspendisse volutpat aliquet nisi, in condimentum nibh convallis id. Quisque gravida felis scelerisque ipsum aliquam consequat. Praesent libero odio, malesuada vitae odio quis, aliquam aliquet enim. In fringilla ut turpis nec pharetra. Duis eu posuere metus. Sed a aliquet massa. Mauris non tempus mi, quis mattis libero. Vivamus ornare ex at semper cursus. Vestibulum sed facilisis erat, aliquet mollis est. In interdum, magna iaculis ultricies elementum, mi ante vestibulum mauris, nec viverra turpis lorem quis ante. Proin in auctor erat. Vivamus dictum congue massa, fermentum bibendum leo pretium quis. Integer dapibus sodales ligula, sit amet imperdiet felis suscipit eu. Phasellus non ornare enim.
Nam feugiat neque sit amet hendrerit rhoncus. Nunc suscipit molestie vehicula. Aenean vulputate porttitor augue, sit amet molestie dolor volutpat vitae. Nulla vitae condimentum eros. Aliquam tristique purus at metus lacinia egestas. Cras euismod lorem eu orci lobortis, sed tincidunt nisl laoreet. Ut suscipit fermentum mi, et euismod tortor. Pellentesque vitae tempor quam, sed dignissim mi. Suspendisse luctus lacus vitae ligula blandit vehicula. Quisque interdum iaculis tincidunt. Nunc elementum mi vitae tempor placerat. Suspendisse potenti. Donec blandit laoreet ipsum, quis rhoncus velit vulputate sed.
Aliquam suscipit lectus eros, at maximus dolor efficitur quis. Integer blandit tortor orci, nec mattis nunc eleifend ac. Mauris pharetra vel quam quis lacinia. Duis lobortis condimentum nunc ut facilisis. Praesent arcu nisi, porta sit amet viverra sit amet, pellentesque ut nisi. Nunc gravida tortor eu ligula tempus, in interdum magna pretium. Fusce eu ornare sapien. Nullam pellentesque cursus eros. Nam orci massa, faucibus eget leo eget, elementum vulputate erat. Fusce vehicula augue et dui hendrerit vulputate. Mauris neque lacus, porttitor ut condimentum id, efficitur ac neque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Donec accumsan, lectus fermentum elementum tristique, ipsum tortor mollis ante, non lacinia nibh ex quis sapien.
Donec pharetra, elit eget rutrum luctus, urna ligula facilisis lorem, sit amet rhoncus ante est eu mi. Vestibulum vestibulum ultricies interdum. Nulla tincidunt ante non hendrerit venenatis. Curabitur vestibulum turpis erat, id efficitur quam venenatis eu. Fusce nulla sem, dapibus vel quam feugiat, ornare fermentum ligula. Praesent tempus tincidunt mauris, non pellentesque felis varius in. Aenean eu arcu ligula. Morbi dapibus maximus nulla a pharetra. Fusce leo metus, luctus ut cursus non, sollicitudin non lectus. Integer pellentesque eleifend erat, vel gravida purus tempus a. Mauris id vestibulum quam. Nunc vitae ullamcorper metus, pharetra placerat enim. Fusce in ultrices nisl. Curabitur justo mauris, dignissim in aliquam sit amet, sollicitudin ut risus. Cras tempor rutrum justo, non tincidunt est maximus at.
Aliquam ac velit tincidunt, ullamcorper velit sit amet, pulvinar nisi. Nullam rhoncus rhoncus egestas. Cras ac luctus nisi. Mauris sit amet risus at magna volutpat ultrices quis ac dui. Aliquam condimentum tellus purus, vel sagittis odio vulputate at. Sed ut finibus tellus. Aliquam tincidunt vehicula diam.

View File

@ -1,20 +1,19 @@
use std::io; use std::io;
use bytes::{Bytes, BytesMut}; use bytes::{Buf, Bytes, BytesMut};
use tokio_codec::{Decoder, Encoder};
/// Bytes codec. use super::{Decoder, Encoder};
///
/// Reads/Writes chunks of bytes from a stream. /// Bytes codec. Reads/writes chunks of bytes from a stream.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct BytesCodec; pub struct BytesCodec;
impl Encoder for BytesCodec { impl Encoder<Bytes> for BytesCodec {
type Item = Bytes;
type Error = io::Error; type Error = io::Error;
#[inline]
fn encode(&mut self, item: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> { fn encode(&mut self, item: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
dst.extend_from_slice(&item[..]); dst.extend_from_slice(item.chunk());
Ok(()) Ok(())
} }
} }
@ -27,7 +26,7 @@ impl Decoder for BytesCodec {
if src.is_empty() { if src.is_empty() {
Ok(None) Ok(None)
} else { } else {
Ok(Some(src.take())) Ok(Some(src.split()))
} }
} }
} }

View File

@ -1,207 +1,281 @@
#![allow(deprecated)] use std::{
fmt, io,
pin::Pin,
task::{Context, Poll},
};
use std::fmt; use bitflags::bitflags;
use std::io::{self, Read, Write}; use bytes::{Buf, BytesMut};
use futures_core::{ready, Stream};
use futures_sink::Sink;
use pin_project_lite::pin_project;
use bytes::BytesMut; use crate::{AsyncRead, AsyncWrite, Decoder, Encoder};
use futures::{Poll, Sink, StartSend, Stream};
use tokio_codec::{Decoder, Encoder};
use tokio_io::{AsyncRead, AsyncWrite};
use super::framed_read::{framed_read2, framed_read2_with_buffer, FramedRead2};
use super::framed_write::{framed_write2, framed_write2_with_buffer, FramedWrite2};
/// Low-water mark
const LW: usize = 1024; const LW: usize = 1024;
/// High-water mark
const HW: usize = 8 * 1024; const HW: usize = 8 * 1024;
/// A unified `Stream` and `Sink` interface to an underlying I/O object, using bitflags! {
/// the `Encoder` and `Decoder` traits to encode and decode frames. #[derive(Debug, Clone, Copy)]
/// struct Flags: u8 {
/// You can create a `Framed` instance by using the `AsyncRead::framed` adapter. const EOF = 0b0001;
pub struct Framed<T, U> { const READABLE = 0b0010;
inner: FramedRead2<FramedWrite2<Fuse<T, U>>>, }
} }
pub struct Fuse<T, U>(pub T, pub U); pin_project! {
/// A unified `Stream` and `Sink` interface to an underlying I/O object, using the `Encoder` and
/// `Decoder` traits to encode and decode frames.
///
/// Raw I/O objects work with byte sequences, but higher-level code usually wants to batch these
/// into meaningful chunks, called "frames". This method layers framing on top of an I/O object,
/// by using the `Encoder`/`Decoder` traits to handle encoding and decoding of message frames.
/// Note that the incoming and outgoing frame types may be distinct.
pub struct Framed<T, U> {
#[pin]
io: T,
codec: U,
flags: Flags,
read_buf: BytesMut,
write_buf: BytesMut,
}
}
impl<T, U> Framed<T, U> impl<T, U> Framed<T, U>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
U: Decoder + Encoder, U: Decoder,
{ {
/// Provides a `Stream` and `Sink` interface for reading and writing to this /// This function returns a *single* object that is both `Stream` and `Sink`; grouping this into
/// `Io` object, using `Decode` and `Encode` to read and write the raw data. /// a single object is often useful for layering things like gzip or TLS, which require both
/// /// read and write access to the underlying object.
/// Raw I/O objects work with byte sequences, but higher-level code usually pub fn new(io: T, codec: U) -> Framed<T, U> {
/// wants to batch these into meaningful chunks, called "frames". This
/// method layers framing on top of an I/O object, by using the `Codec`
/// traits to handle encoding and decoding of messages frames. Note that
/// the incoming and outgoing frame types may be distinct.
///
/// This function returns a *single* object that is both `Stream` and
/// `Sink`; grouping this into a single object is often useful for layering
/// things like gzip or TLS, which require both read and write access to the
/// underlying object.
///
/// If you want to work more directly with the streams and sink, consider
/// calling `split` on the `Framed` returned by this method, which will
/// break them into separate objects, allowing them to interact more easily.
pub fn new(inner: T, codec: U) -> Framed<T, U> {
Framed { Framed {
inner: framed_read2(framed_write2(Fuse(inner, codec), LW, HW)), io,
codec,
flags: Flags::empty(),
read_buf: BytesMut::with_capacity(HW),
write_buf: BytesMut::with_capacity(HW),
} }
} }
/// Same as `Framed::new()` with ability to specify write buffer low/high capacity watermarks.
pub fn new_with_caps(inner: T, codec: U, lw: usize, hw: usize) -> Framed<T, U> {
debug_assert!((lw < hw) && hw != 0);
Framed {
inner: framed_read2(framed_write2(Fuse(inner, codec), lw, hw)),
}
}
/// Force send item
pub fn force_send(
&mut self,
item: <U as Encoder>::Item,
) -> Result<(), <U as Encoder>::Error> {
self.inner.get_mut().force_send(item)
}
} }
impl<T, U> Framed<T, U> { impl<T, U> Framed<T, U> {
/// Provides a `Stream` and `Sink` interface for reading and writing to this
/// `Io` object, using `Decode` and `Encode` to read and write the raw data.
///
/// Raw I/O objects work with byte sequences, but higher-level code usually
/// wants to batch these into meaningful chunks, called "frames". This
/// method layers framing on top of an I/O object, by using the `Codec`
/// traits to handle encoding and decoding of messages frames. Note that
/// the incoming and outgoing frame types may be distinct.
///
/// This function returns a *single* object that is both `Stream` and
/// `Sink`; grouping this into a single object is often useful for layering
/// things like gzip or TLS, which require both read and write access to the
/// underlying object.
///
/// This objects takes a stream and a readbuffer and a writebuffer. These
/// field can be obtained from an existing `Framed` with the
/// `into_parts` method.
///
/// If you want to work more directly with the streams and sink, consider
/// calling `split` on the `Framed` returned by this method, which will
/// break them into separate objects, allowing them to interact more easily.
pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
Framed {
inner: framed_read2_with_buffer(
framed_write2_with_buffer(
Fuse(parts.io, parts.codec),
parts.write_buf,
parts.write_buf_lw,
parts.write_buf_hw,
),
parts.read_buf,
),
}
}
/// Returns a reference to the underlying codec. /// Returns a reference to the underlying codec.
pub fn get_codec(&self) -> &U { pub fn codec_ref(&self) -> &U {
&self.inner.get_ref().get_ref().1 &self.codec
} }
/// Returns a mutable reference to the underlying codec. /// Returns a mutable reference to the underlying codec.
pub fn get_codec_mut(&mut self) -> &mut U { pub fn codec_mut(&mut self) -> &mut U {
&mut self.inner.get_mut().get_mut().1 &mut self.codec
} }
/// Returns a reference to the underlying I/O stream wrapped by /// Returns a reference to the underlying I/O stream wrapped by `Frame`.
/// `Frame`.
/// ///
/// Note that care should be taken to not tamper with the underlying stream /// Note that care should be taken to not tamper with the underlying stream of data coming in as
/// of data coming in as it may corrupt the stream of frames otherwise /// it may corrupt the stream of frames otherwise being worked with.
/// being worked with. pub fn io_ref(&self) -> &T {
pub fn get_ref(&self) -> &T { &self.io
&self.inner.get_ref().get_ref().0
} }
/// Returns a mutable reference to the underlying I/O stream wrapped by /// Returns a mutable reference to the underlying I/O stream.
/// `Frame`.
/// ///
/// Note that care should be taken to not tamper with the underlying stream /// Note that care should be taken to not tamper with the underlying stream of data coming in as
/// of data coming in as it may corrupt the stream of frames otherwise /// it may corrupt the stream of frames otherwise being worked with.
/// being worked with. pub fn io_mut(&mut self) -> &mut T {
pub fn get_mut(&mut self) -> &mut T { &mut self.io
&mut self.inner.get_mut().get_mut().0 }
/// Returns a `Pin` of a mutable reference to the underlying I/O stream.
pub fn io_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
self.project().io
}
/// Check if read buffer is empty.
pub fn is_read_buf_empty(&self) -> bool {
self.read_buf.is_empty()
} }
/// Check if write buffer is empty. /// Check if write buffer is empty.
pub fn is_write_buf_empty(&self) -> bool { pub fn is_write_buf_empty(&self) -> bool {
self.inner.get_ref().is_empty() self.write_buf.is_empty()
} }
/// Check if write buffer is full. /// Check if write buffer is full.
pub fn is_write_buf_full(&self) -> bool { pub fn is_write_buf_full(&self) -> bool {
self.inner.get_ref().is_full() self.write_buf.len() >= HW
} }
/// Consumes the `Frame`, returning its underlying I/O stream. /// Check if framed is able to write more data.
/// ///
/// Note that care should be taken to not tamper with the underlying stream /// `Framed` object considers ready if there is free space in write buffer.
/// of data coming in as it may corrupt the stream of frames otherwise pub fn is_write_ready(&self) -> bool {
/// being worked with. self.write_buf.len() < HW
pub fn into_inner(self) -> T {
self.inner.into_inner().into_inner().0
} }
/// Consume the `Frame`, returning `Frame` with different codec. /// Consume the `Frame`, returning `Frame` with different codec.
pub fn into_framed<U2>(self, codec: U2) -> Framed<T, U2> { pub fn replace_codec<U2>(self, codec: U2) -> Framed<T, U2> {
let (inner, read_buf) = self.inner.into_parts();
let (inner, write_buf, lw, hw) = inner.into_parts();
Framed { Framed {
inner: framed_read2_with_buffer( codec,
framed_write2_with_buffer(Fuse(inner.0, codec), write_buf, lw, hw), io: self.io,
read_buf, flags: self.flags,
), read_buf: self.read_buf,
write_buf: self.write_buf,
}
}
/// Consume the `Frame`, returning `Frame` with different io.
pub fn into_map_io<F, T2>(self, f: F) -> Framed<T2, U>
where
F: Fn(T) -> T2,
{
Framed {
io: f(self.io),
codec: self.codec,
flags: self.flags,
read_buf: self.read_buf,
write_buf: self.write_buf,
} }
} }
/// Consume the `Frame`, returning `Frame` with different codec. /// Consume the `Frame`, returning `Frame` with different codec.
pub fn map_codec<F, U2>(self, f: F) -> Framed<T, U2> pub fn into_map_codec<F, U2>(self, f: F) -> Framed<T, U2>
where where
F: Fn(U) -> U2, F: Fn(U) -> U2,
{ {
let (inner, read_buf) = self.inner.into_parts();
let (inner, write_buf, lw, hw) = inner.into_parts();
Framed { Framed {
inner: framed_read2_with_buffer( io: self.io,
framed_write2_with_buffer(Fuse(inner.0, f(inner.1)), write_buf, lw, hw), codec: f(self.codec),
read_buf, flags: self.flags,
), read_buf: self.read_buf,
write_buf: self.write_buf,
}
}
}
impl<T, U> Framed<T, U> {
/// Serialize item and write to the inner buffer
pub fn write<I>(mut self: Pin<&mut Self>, item: I) -> Result<(), <U as Encoder<I>>::Error>
where
T: AsyncWrite,
U: Encoder<I>,
{
let this = self.as_mut().project();
let remaining = this.write_buf.capacity() - this.write_buf.len();
if remaining < LW {
this.write_buf.reserve(HW - remaining);
}
this.codec.encode(item, this.write_buf)?;
Ok(())
}
/// Try to read underlying I/O stream and decode item.
pub fn next_item(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<<U as Decoder>::Item, U::Error>>>
where
T: AsyncRead,
U: Decoder,
{
loop {
let this = self.as_mut().project();
// Repeatedly call `decode` or `decode_eof` as long as it is "readable". Readable is
// defined as not having returned `None`. If the upstream has returned EOF, and the
// decoder is no longer readable, it can be assumed that the decoder will never become
// readable again, at which point the stream is terminated.
if this.flags.contains(Flags::READABLE) {
if this.flags.contains(Flags::EOF) {
match this.codec.decode_eof(this.read_buf) {
Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
Ok(None) => return Poll::Ready(None),
Err(err) => return Poll::Ready(Some(Err(err))),
}
}
tracing::trace!("attempting to decode a frame");
match this.codec.decode(this.read_buf) {
Ok(Some(frame)) => {
tracing::trace!("frame decoded from buffer");
return Poll::Ready(Some(Ok(frame)));
}
Err(err) => return Poll::Ready(Some(Err(err))),
_ => (), // Need more data
}
this.flags.remove(Flags::READABLE);
}
debug_assert!(!this.flags.contains(Flags::EOF));
// Otherwise, try to read more data and try again. Make sure we've got room.
let remaining = this.read_buf.capacity() - this.read_buf.len();
if remaining < LW {
this.read_buf.reserve(HW - remaining)
}
let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
Poll::Pending => return Poll::Pending,
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
Poll::Ready(Ok(cnt)) => cnt,
};
if cnt == 0 {
this.flags.insert(Flags::EOF);
}
this.flags.insert(Flags::READABLE);
} }
} }
/// Consumes the `Frame`, returning its underlying I/O stream, the buffer /// Flush write buffer to underlying I/O stream.
/// with unprocessed data, and the codec. pub fn flush<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
/// where
/// Note that care should be taken to not tamper with the underlying stream T: AsyncWrite,
/// of data coming in as it may corrupt the stream of frames otherwise U: Encoder<I>,
/// being worked with. {
pub fn into_parts(self) -> FramedParts<T, U> { let mut this = self.as_mut().project();
let (inner, read_buf) = self.inner.into_parts(); tracing::trace!("flushing framed transport");
let (inner, write_buf, write_buf_lw, write_buf_hw) = inner.into_parts();
FramedParts { while !this.write_buf.is_empty() {
io: inner.0, tracing::trace!("writing; remaining={}", this.write_buf.len());
codec: inner.1,
read_buf, let n = ready!(this.io.as_mut().poll_write(cx, this.write_buf))?;
write_buf,
write_buf_lw, if n == 0 {
write_buf_hw, return Poll::Ready(Err(io::Error::new(
_priv: (), io::ErrorKind::WriteZero,
"failed to write frame to transport",
)
.into()));
}
// remove written data
this.write_buf.advance(n);
} }
// Try flushing the underlying IO
ready!(this.io.poll_flush(cx))?;
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>>
where
T: AsyncWrite,
U: Encoder<I>,
{
let mut this = self.as_mut().project();
ready!(this.io.as_mut().poll_flush(cx))?;
ready!(this.io.as_mut().poll_shutdown(cx))?;
Poll::Ready(Ok(()))
} }
} }
@ -210,36 +284,39 @@ where
T: AsyncRead, T: AsyncRead,
U: Decoder, U: Decoder,
{ {
type Item = U::Item; type Item = Result<U::Item, U::Error>;
type Error = U::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.inner.poll() self.next_item(cx)
} }
} }
impl<T, U> Sink for Framed<T, U> impl<T, U, I> Sink<I> for Framed<T, U>
where where
T: AsyncWrite, T: AsyncWrite,
U: Encoder, U: Encoder<I>,
U::Error: From<io::Error>, U::Error: From<io::Error>,
{ {
type SinkItem = U::Item; type Error = U::Error;
type SinkError = U::Error;
fn start_send( fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
&mut self, if self.is_write_ready() {
item: Self::SinkItem, Poll::Ready(Ok(()))
) -> StartSend<Self::SinkItem, Self::SinkError> { } else {
self.inner.get_mut().start_send(item) self.flush(cx)
}
} }
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> {
self.inner.get_mut().poll_complete() self.write(item)
} }
fn close(&mut self) -> Poll<(), Self::SinkError> { fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.get_mut().close() self.flush(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.close(cx)
} }
} }
@ -248,75 +325,57 @@ where
T: fmt::Debug, T: fmt::Debug,
U: fmt::Debug, U: fmt::Debug,
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Framed") f.debug_struct("Framed")
.field("io", &self.inner.get_ref().get_ref().0) .field("io", &self.io)
.field("codec", &self.inner.get_ref().get_ref().1) .field("codec", &self.codec)
.finish() .finish()
} }
} }
// ===== impl Fuse ===== impl<T, U> Framed<T, U> {
/// This function returns a *single* object that is both `Stream` and `Sink`; grouping this into
impl<T: Read, U> Read for Fuse<T, U> { /// a single object is often useful for layering things like gzip or TLS, which require both
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> { /// read and write access to the underlying object.
self.0.read(dst) ///
} /// These objects take a stream, a read buffer and a write buffer. These fields can be obtained
} /// from an existing `Framed` with the `into_parts` method.
pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
impl<T: AsyncRead, U> AsyncRead for Fuse<T, U> { Framed {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { io: parts.io,
self.0.prepare_uninitialized_buffer(buf) codec: parts.codec,
} flags: parts.flags,
} write_buf: parts.write_buf,
read_buf: parts.read_buf,
impl<T: Write, U> Write for Fuse<T, U> { }
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
self.0.write(src)
} }
fn flush(&mut self) -> io::Result<()> { /// Consumes the `Frame`, returning its underlying I/O stream, the buffer with unprocessed data,
self.0.flush() /// and the codec.
} ///
} /// Note that care should be taken to not tamper with the underlying stream of data coming in as
/// it may corrupt the stream of frames otherwise being worked with.
impl<T: AsyncWrite, U> AsyncWrite for Fuse<T, U> { pub fn into_parts(self) -> FramedParts<T, U> {
fn shutdown(&mut self) -> Poll<(), io::Error> { FramedParts {
self.0.shutdown() io: self.io,
} codec: self.codec,
} flags: self.flags,
read_buf: self.read_buf,
impl<T, U: Decoder> Decoder for Fuse<T, U> { write_buf: self.write_buf,
type Item = U::Item; }
type Error = U::Error;
fn decode(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
self.1.decode(buffer)
}
fn decode_eof(&mut self, buffer: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
self.1.decode_eof(buffer)
}
}
impl<T, U: Encoder> Encoder for Fuse<T, U> {
type Item = U::Item;
type Error = U::Error;
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
self.1.encode(item, dst)
} }
} }
/// `FramedParts` contains an export of the data of a Framed transport. /// `FramedParts` contains an export of the data of a Framed transport.
/// It can be used to construct a new `Framed` with a different codec. ///
/// It contains all current buffers and the inner transport. /// It can be used to construct a new `Framed` with a different codec. It contains all current
/// buffers and the inner transport.
#[derive(Debug)] #[derive(Debug)]
pub struct FramedParts<T, U> { pub struct FramedParts<T, U> {
/// The inner transport used to read bytes to and write bytes to /// The inner transport used to read bytes to and write bytes to.
pub io: T, pub io: T,
/// The codec /// The codec object.
pub codec: U, pub codec: U,
/// The buffer with read but unprocessed data. /// The buffer with read but unprocessed data.
@ -325,28 +384,29 @@ pub struct FramedParts<T, U> {
/// A buffer with unprocessed data which are not written yet. /// A buffer with unprocessed data which are not written yet.
pub write_buf: BytesMut, pub write_buf: BytesMut,
/// A buffer low watermark capacity flags: Flags,
pub write_buf_lw: usize,
/// A buffer high watermark capacity
pub write_buf_hw: usize,
/// This private field allows us to add additional fields in the future in a
/// backwards compatible way.
_priv: (),
} }
impl<T, U> FramedParts<T, U> { impl<T, U> FramedParts<T, U> {
/// Create a new, default, `FramedParts` /// Creates a new default `FramedParts`.
pub fn new(io: T, codec: U) -> FramedParts<T, U> { pub fn new(io: T, codec: U) -> FramedParts<T, U> {
FramedParts { FramedParts {
io, io,
codec, codec,
flags: Flags::empty(),
read_buf: BytesMut::new(), read_buf: BytesMut::new(),
write_buf: BytesMut::new(), write_buf: BytesMut::new(),
write_buf_lw: LW, }
write_buf_hw: HW, }
_priv: (),
/// Creates a new `FramedParts` with read buffer.
pub fn with_read_buf(io: T, codec: U, read_buf: BytesMut) -> FramedParts<T, U> {
FramedParts {
io,
codec,
read_buf,
flags: Flags::empty(),
write_buf: BytesMut::new(),
} }
} }
} }

View File

@ -1,218 +0,0 @@
use std::fmt;
use bytes::BytesMut;
use futures::{try_ready, Async, Poll, Sink, StartSend, Stream};
use log::trace;
use tokio_codec::Decoder;
use tokio_io::AsyncRead;
use super::framed::Fuse;
/// A `Stream` of messages decoded from an `AsyncRead`.
pub struct FramedRead<T, D> {
inner: FramedRead2<Fuse<T, D>>,
}
pub struct FramedRead2<T> {
inner: T,
eof: bool,
is_readable: bool,
buffer: BytesMut,
}
const INITIAL_CAPACITY: usize = 8 * 1024;
// ===== impl FramedRead =====
impl<T, D> FramedRead<T, D>
where
T: AsyncRead,
D: Decoder,
{
/// Creates a new `FramedRead` with the given `decoder`.
pub fn new(inner: T, decoder: D) -> FramedRead<T, D> {
FramedRead {
inner: framed_read2(Fuse(inner, decoder)),
}
}
}
impl<T, D> FramedRead<T, D> {
/// Returns a reference to the underlying I/O stream wrapped by
/// `FramedRead`.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn get_ref(&self) -> &T {
&self.inner.inner.0
}
/// Returns a mutable reference to the underlying I/O stream wrapped by
/// `FramedRead`.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner.inner.0
}
/// Consumes the `FramedRead`, returning its underlying I/O stream.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn into_inner(self) -> T {
self.inner.inner.0
}
/// Returns a reference to the underlying decoder.
pub fn decoder(&self) -> &D {
&self.inner.inner.1
}
/// Returns a mutable reference to the underlying decoder.
pub fn decoder_mut(&mut self) -> &mut D {
&mut self.inner.inner.1
}
}
impl<T, D> Stream for FramedRead<T, D>
where
T: AsyncRead,
D: Decoder,
{
type Item = D::Item;
type Error = D::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.inner.poll()
}
}
impl<T, D> Sink for FramedRead<T, D>
where
T: Sink,
{
type SinkItem = T::SinkItem;
type SinkError = T::SinkError;
fn start_send(
&mut self,
item: Self::SinkItem,
) -> StartSend<Self::SinkItem, Self::SinkError> {
self.inner.inner.0.start_send(item)
}
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
self.inner.inner.0.poll_complete()
}
fn close(&mut self) -> Poll<(), Self::SinkError> {
self.inner.inner.0.close()
}
}
impl<T, D> fmt::Debug for FramedRead<T, D>
where
T: fmt::Debug,
D: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FramedRead")
.field("inner", &self.inner.inner.0)
.field("decoder", &self.inner.inner.1)
.field("eof", &self.inner.eof)
.field("is_readable", &self.inner.is_readable)
.field("buffer", &self.inner.buffer)
.finish()
}
}
// ===== impl FramedRead2 =====
pub fn framed_read2<T>(inner: T) -> FramedRead2<T> {
FramedRead2 {
inner,
eof: false,
is_readable: false,
buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
}
}
pub fn framed_read2_with_buffer<T>(inner: T, mut buf: BytesMut) -> FramedRead2<T> {
if buf.capacity() < INITIAL_CAPACITY {
let bytes_to_reserve = INITIAL_CAPACITY - buf.capacity();
buf.reserve(bytes_to_reserve);
}
FramedRead2 {
inner,
eof: false,
is_readable: !buf.is_empty(),
buffer: buf,
}
}
impl<T> FramedRead2<T> {
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
pub fn into_parts(self) -> (T, BytesMut) {
(self.inner, self.buffer)
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<T> Stream for FramedRead2<T>
where
T: AsyncRead + Decoder,
{
type Item = T::Item;
type Error = T::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
loop {
// Repeatedly call `decode` or `decode_eof` as long as it is
// "readable". Readable is defined as not having returned `None`. If
// the upstream has returned EOF, and the decoder is no longer
// readable, it can be assumed that the decoder will never become
// readable again, at which point the stream is terminated.
if self.is_readable {
if self.eof {
let frame = self.inner.decode_eof(&mut self.buffer)?;
return Ok(Async::Ready(frame));
}
trace!("attempting to decode a frame");
if let Some(frame) = self.inner.decode(&mut self.buffer)? {
trace!("frame decoded from buffer");
return Ok(Async::Ready(Some(frame)));
}
self.is_readable = false;
}
assert!(!self.eof);
// Otherwise, try to read more data and try again. Make sure we've
// got room for at least one byte to read to ensure that we don't
// get a spurious 0 that looks like EOF
self.buffer.reserve(1);
if 0 == try_ready!(self.inner.read_buf(&mut self.buffer)) {
self.eof = true;
}
self.is_readable = true;
}
}
}

View File

@ -1,303 +0,0 @@
use std::fmt;
use std::io::{self, Read};
use bytes::BytesMut;
use futures::{try_ready, Async, AsyncSink, Poll, Sink, StartSend, Stream};
use log::trace;
use tokio_codec::{Decoder, Encoder};
use tokio_io::{AsyncRead, AsyncWrite};
use super::framed::Fuse;
/// A `Sink` of frames encoded to an `AsyncWrite`.
pub struct FramedWrite<T, E> {
inner: FramedWrite2<Fuse<T, E>>,
}
pub struct FramedWrite2<T> {
inner: T,
buffer: BytesMut,
low_watermark: usize,
high_watermark: usize,
}
impl<T, E> FramedWrite<T, E>
where
T: AsyncWrite,
E: Encoder,
{
/// Creates a new `FramedWrite` with the given `encoder`.
pub fn new(inner: T, encoder: E, lw: usize, hw: usize) -> FramedWrite<T, E> {
FramedWrite {
inner: framed_write2(Fuse(inner, encoder), lw, hw),
}
}
}
impl<T, E> FramedWrite<T, E> {
/// Returns a reference to the underlying I/O stream wrapped by
/// `FramedWrite`.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn get_ref(&self) -> &T {
&self.inner.inner.0
}
/// Returns a mutable reference to the underlying I/O stream wrapped by
/// `FramedWrite`.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner.inner.0
}
/// Consumes the `FramedWrite`, returning its underlying I/O stream.
///
/// Note that care should be taken to not tamper with the underlying stream
/// of data coming in as it may corrupt the stream of frames otherwise
/// being worked with.
pub fn into_inner(self) -> T {
self.inner.inner.0
}
/// Returns a reference to the underlying decoder.
pub fn encoder(&self) -> &E {
&self.inner.inner.1
}
/// Returns a mutable reference to the underlying decoder.
pub fn encoder_mut(&mut self) -> &mut E {
&mut self.inner.inner.1
}
/// Check if write buffer is full
pub fn is_full(&self) -> bool {
self.inner.is_full()
}
/// Check if write buffer is empty.
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl<T, E> FramedWrite<T, E>
where
E: Encoder,
{
/// Force send item
pub fn force_send(&mut self, item: E::Item) -> Result<(), E::Error> {
self.inner.force_send(item)
}
}
impl<T, E> Sink for FramedWrite<T, E>
where
T: AsyncWrite,
E: Encoder,
{
type SinkItem = E::Item;
type SinkError = E::Error;
fn start_send(&mut self, item: E::Item) -> StartSend<E::Item, E::Error> {
self.inner.start_send(item)
}
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
self.inner.poll_complete()
}
fn close(&mut self) -> Poll<(), Self::SinkError> {
Ok(self.inner.close()?)
}
}
impl<T, D> Stream for FramedWrite<T, D>
where
T: Stream,
{
type Item = T::Item;
type Error = T::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.inner.inner.0.poll()
}
}
impl<T, U> fmt::Debug for FramedWrite<T, U>
where
T: fmt::Debug,
U: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FramedWrite")
.field("inner", &self.inner.get_ref().0)
.field("encoder", &self.inner.get_ref().1)
.field("buffer", &self.inner.buffer)
.finish()
}
}
// ===== impl FramedWrite2 =====
pub fn framed_write2<T>(
inner: T,
low_watermark: usize,
high_watermark: usize,
) -> FramedWrite2<T> {
FramedWrite2 {
inner,
low_watermark,
high_watermark,
buffer: BytesMut::with_capacity(high_watermark),
}
}
pub fn framed_write2_with_buffer<T>(
inner: T,
mut buffer: BytesMut,
low_watermark: usize,
high_watermark: usize,
) -> FramedWrite2<T> {
if buffer.capacity() < high_watermark {
let bytes_to_reserve = high_watermark - buffer.capacity();
buffer.reserve(bytes_to_reserve);
}
FramedWrite2 {
inner,
buffer,
low_watermark,
high_watermark,
}
}
impl<T> FramedWrite2<T> {
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
pub fn into_parts(self) -> (T, BytesMut, usize, usize) {
(
self.inner,
self.buffer,
self.low_watermark,
self.high_watermark,
)
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn is_full(&self) -> bool {
self.buffer.len() >= self.high_watermark
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
}
impl<T> FramedWrite2<T>
where
T: Encoder,
{
pub fn force_send(&mut self, item: T::Item) -> Result<(), T::Error> {
let len = self.buffer.len();
if len < self.low_watermark {
self.buffer.reserve(self.high_watermark - len)
}
self.inner.encode(item, &mut self.buffer)?;
Ok(())
}
}
impl<T> Sink for FramedWrite2<T>
where
T: AsyncWrite + Encoder,
{
type SinkItem = T::Item;
type SinkError = T::Error;
fn start_send(&mut self, item: T::Item) -> StartSend<T::Item, T::Error> {
// Check the buffer capacity
let len = self.buffer.len();
if len >= self.high_watermark {
return Ok(AsyncSink::NotReady(item));
}
if len < self.low_watermark {
self.buffer.reserve(self.high_watermark - len)
}
self.inner.encode(item, &mut self.buffer)?;
Ok(AsyncSink::Ready)
}
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
trace!("flushing framed transport");
while !self.buffer.is_empty() {
trace!("writing; remaining={}", self.buffer.len());
let n = try_ready!(self.inner.poll_write(&self.buffer));
if n == 0 {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to \
write frame to transport",
)
.into());
}
// TODO: Add a way to `bytes` to do this w/o returning the drained
// data.
let _ = self.buffer.split_to(n);
}
// Try flushing the underlying IO
try_ready!(self.inner.poll_flush());
trace!("framed transport flushed");
Ok(Async::Ready(()))
}
fn close(&mut self) -> Poll<(), Self::SinkError> {
try_ready!(self.poll_complete());
Ok(self.inner.shutdown()?)
}
}
impl<T: Decoder> Decoder for FramedWrite2<T> {
type Item = T::Item;
type Error = T::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
self.inner.decode(src)
}
fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
self.inner.decode_eof(src)
}
}
impl<T: Read> Read for FramedWrite2<T> {
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
self.inner.read(dst)
}
}
impl<T: AsyncRead> AsyncRead for FramedWrite2<T> {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
self.inner.prepare_uninitialized_buffer(buf)
}
}

View File

@ -1,24 +1,26 @@
//! Utilities for encoding and decoding frames. //! Codec utilities for working with framed protocols.
//! //!
//! Contains adapters to go from streams of bytes, [`AsyncRead`] and //! Contains adapters to go from streams of bytes, [`AsyncRead`] and [`AsyncWrite`], to framed
//! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`]. //! streams implementing [`Sink`] and [`Stream`]. Framed streams are also known as `transports`.
//! Framed streams are also known as [transports].
//! //!
//! [`AsyncRead`]: # //! [`Sink`]: futures_sink::Sink
//! [`AsyncWrite`]: # //! [`Stream`]: futures_core::Stream
//! [`Sink`]: #
//! [`Stream`]: # #![doc(html_logo_url = "https://actix.rs/img/logo.png")]
//! [transports]: # #![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 bcodec;
mod framed; mod framed;
mod framed_read; mod lines;
mod framed_write;
pub use self::bcodec::BytesCodec; pub use self::{
pub use self::framed::{Framed, FramedParts}; bcodec::BytesCodec,
pub use self::framed_read::FramedRead; framed::{Framed, FramedParts},
pub use self::framed_write::FramedWrite; lines::LinesCodec,
};
pub use tokio_codec::{Decoder, Encoder};
pub use tokio_io::{AsyncRead, AsyncWrite};

158
actix-codec/src/lines.rs Normal file
View File

@ -0,0 +1,158 @@
use std::io;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use memchr::memchr;
use super::{Decoder, Encoder};
/// Lines codec. Reads/writes line delimited strings.
///
/// 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;
impl<T: AsRef<str>> Encoder<T> for LinesCodec {
type Error = io::Error;
#[inline]
fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error> {
let item = item.as_ref();
dst.reserve(item.len() + 1);
dst.put_slice(item.as_bytes());
dst.put_u8(b'\n');
Ok(())
}
}
impl Decoder for LinesCodec {
type Item = String;
type Error = io::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
if src.is_empty() {
return Ok(None);
}
let len = match memchr(b'\n', src) {
Some(n) => n,
None => {
return Ok(None);
}
};
// split up to new line char
let mut buf = src.split_to(len);
debug_assert_eq!(len, buf.len());
// remove new line char from source
src.advance(1);
match buf.last() {
// remove carriage returns at the end of buf
Some(b'\r') => buf.truncate(len - 1),
// line is empty
None => return Ok(Some(String::new())),
_ => {}
}
try_into_utf8(buf.freeze())
}
fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match self.decode(src)? {
Some(frame) => Ok(Some(frame)),
None if src.is_empty() => Ok(None),
None => {
let buf = match src.last() {
// if last line ends in a CR then take everything up to it
Some(b'\r') => src.split_to(src.len() - 1),
// take all bytes from source
_ => src.split(),
};
if buf.is_empty() {
return Ok(None);
}
try_into_utf8(buf.freeze())
}
}
}
}
// Attempts to convert bytes into a `String`.
fn try_into_utf8(buf: Bytes) -> io::Result<Option<String>> {
String::from_utf8(buf.to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
.map(Some)
}
#[cfg(test)]
mod tests {
use bytes::BufMut as _;
use super::*;
#[test]
fn lines_decoder() {
let mut codec = LinesCodec::default();
let mut buf = BytesMut::from("\nline 1\nline 2\r\nline 3\n\r\n\r");
assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
assert_eq!("line 1", codec.decode(&mut buf).unwrap().unwrap());
assert_eq!("line 2", codec.decode(&mut buf).unwrap().unwrap());
assert_eq!("line 3", codec.decode(&mut buf).unwrap().unwrap());
assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
assert!(codec.decode(&mut buf).unwrap().is_none());
assert!(codec.decode_eof(&mut buf).unwrap().is_none());
buf.put_slice(b"k");
assert!(codec.decode(&mut buf).unwrap().is_none());
assert_eq!("\rk", codec.decode_eof(&mut buf).unwrap().unwrap());
assert!(codec.decode(&mut buf).unwrap().is_none());
assert!(codec.decode_eof(&mut buf).unwrap().is_none());
}
#[test]
fn lines_encoder() {
let mut codec = LinesCodec::default();
let mut buf = BytesMut::new();
codec.encode("", &mut buf).unwrap();
assert_eq!(&buf[..], b"\n");
codec.encode("test", &mut buf).unwrap();
assert_eq!(&buf[..], b"\ntest\n");
codec.encode("a\nb", &mut buf).unwrap();
assert_eq!(&buf[..], b"\ntest\na\nb\n");
}
#[test]
fn lines_encoder_no_overflow() {
let mut codec = LinesCodec::default();
let mut buf = BytesMut::new();
codec.encode("1234567", &mut buf).unwrap();
assert_eq!(&buf[..], b"1234567\n");
let mut buf = BytesMut::new();
codec.encode("12345678", &mut buf).unwrap();
assert_eq!(&buf[..], b"12345678\n");
let mut buf = BytesMut::new();
codec.encode("123456789111213", &mut buf).unwrap();
assert_eq!(&buf[..], b"123456789111213\n");
let mut buf = BytesMut::new();
codec.encode("1234567891112131", &mut buf).unwrap();
assert_eq!(&buf[..], b"1234567891112131\n");
}
}

View File

@ -0,0 +1,224 @@
#![allow(missing_docs)]
use std::{
collections::VecDeque,
io::{self, Write},
pin::Pin,
task::{
Context,
Poll::{self, Pending, Ready},
},
};
use actix_codec::*;
use bytes::{Buf as _, BufMut as _, BytesMut};
use futures_sink::Sink;
use tokio_test::{assert_ready, task};
macro_rules! bilateral {
($($x:expr,)*) => {{
let mut v = VecDeque::new();
v.extend(vec![$($x),*]);
Bilateral { calls: v }
}};
}
macro_rules! assert_ready {
($e:expr) => {{
use core::task::Poll::*;
match $e {
Ready(v) => v,
Pending => panic!("pending"),
}
}};
($e:expr, $($msg:tt),+) => {{
use core::task::Poll::*;
match $e {
Ready(v) => v,
Pending => {
let msg = format_args!($($msg),+);
panic!("pending; {}", msg)
}
}
}};
}
#[derive(Debug)]
pub struct Bilateral {
pub calls: VecDeque<io::Result<Vec<u8>>>,
}
impl Write for Bilateral {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
match self.calls.pop_front() {
Some(Ok(data)) => {
assert!(src.len() >= data.len());
assert_eq!(&data[..], &src[..data.len()]);
Ok(data.len())
}
Some(Err(err)) => Err(err),
None => panic!("unexpected write; {:?}", src),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl AsyncWrite for Bilateral {
fn poll_write(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
match Pin::get_mut(self).write(buf) {
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 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>> {
unimplemented!()
}
}
impl AsyncRead for Bilateral {
fn poll_read(
mut self: Pin<&mut Self>,
_: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<Result<(), std::io::Error>> {
use io::ErrorKind::WouldBlock;
match self.calls.pop_front() {
Some(Ok(data)) => {
debug_assert!(buf.remaining() >= data.len());
buf.put_slice(&data);
Ready(Ok(()))
}
Some(Err(ref err)) if err.kind() == WouldBlock => Pending,
Some(Err(err)) => Ready(Err(err)),
None => Ready(Ok(())),
}
}
}
pub struct U32;
impl Encoder<u32> for U32 {
type Error = io::Error;
fn encode(&mut self, item: u32, dst: &mut BytesMut) -> io::Result<()> {
// Reserve space
dst.reserve(4);
dst.put_u32(item);
Ok(())
}
}
impl Decoder for U32 {
type Item = u32;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<u32>> {
if buf.len() < 4 {
return Ok(None);
}
let n = buf.split_to(4).get_u32();
Ok(Some(n))
}
}
#[test]
fn test_write_hits_highwater_mark() {
// see here for what this test is based on:
// https://github.com/tokio-rs/tokio/blob/75c07770bfbfea4e5fd914af819c741ed9c3fc36/tokio-util/tests/framed_write.rs#L69
const ITER: usize = 2 * 1024;
let mut bi = bilateral! {
Err(io::Error::new(io::ErrorKind::WouldBlock, "not ready")),
Ok(b"".to_vec()),
};
for i in 0..=ITER {
let mut b = BytesMut::with_capacity(4);
b.put_u32(i as u32);
// Append to the end
match bi.calls.back_mut().unwrap() {
Ok(ref mut data) => {
// Write in 2kb chunks
if data.len() < ITER {
data.extend_from_slice(&b[..]);
continue;
} // else fall through and create a new buffer
}
_ => unreachable!(),
}
// Push a new new chunk
bi.calls.push_back(Ok(b[..].to_vec()));
}
assert_eq!(bi.calls.len(), 6);
let mut framed = Framed::new(bi, U32);
// Send 8KB. This fills up FramedWrite2 buffer
let mut task = task::spawn(());
task.enter(|cx, _| {
// Send 8KB. This fills up Framed buffer
for i in 0..ITER {
{
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
assert!(assert_ready!(framed.poll_ready(cx)).is_ok());
}
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
// write the buffer
assert!(framed.start_send(i as u32).is_ok());
}
{
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
// Now we poll_ready which forces a flush. The bilateral pops the front message
// and decides to block.
assert!(framed.poll_ready(cx).is_pending());
}
{
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
// We poll again, forcing another flush, which this time succeeds
// The whole 8KB buffer is flushed
assert!(assert_ready!(framed.poll_ready(cx)).is_ok());
}
{
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
// Send more data. This matches the final message expected by the bilateral
assert!(framed.start_send(ITER as u32).is_ok());
}
{
#[allow(unused_mut)]
let mut framed = Pin::new(&mut framed);
// Flush the rest of the buffer
assert!(assert_ready!(framed.poll_flush(cx)).is_ok());
}
// Ensure the mock is empty
assert_eq!(0, Pin::new(&framed).get_ref().io_ref().calls.len());
});
}

View File

@ -1,28 +0,0 @@
# Changes
## [0.3.0] - 2019-03-02
### Changed
* Migrate to actix-service 0.3
## [0.2.0] - 2019-02-01
### Changed
* Migrate to actix-service 0.2
* Upgrade trust-dns-resolver
* Use tokio-current-thread instead of direct actix-rt dipendency
## [0.1.1] - 2019-01-13
* Upgrade trust-dns-proto
## [0.1.0] - 2018-12-09
* Move server to separate crate

View File

@ -1,39 +0,0 @@
[package]
name = "actix-connector"
version = "0.3.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix Connector - tcp connector service"
keywords = ["network", "framework", "async", "futures"]
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git"
documentation = "https://docs.rs/actix-net/"
categories = ["network-programming", "asynchronous"]
license = "MIT/Apache-2.0"
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
edition = "2018"
workspace = ".."
[package.metadata.docs.rs]
features = ["ssl"]
[lib]
name = "actix_connector"
path = "src/lib.rs"
[features]
default = []
# openssl
ssl = ["openssl", "tokio-openssl"]
[dependencies]
actix-service = "0.3.0"
actix-codec = "0.1.0"
futures = "0.1"
tokio-tcp = "0.1"
tokio-current-thread = "0.1"
trust-dns-resolver = { version="0.11.0-alpha.2", default-features = false }
# openssl
openssl = { version="0.10", optional = true }
tokio-openssl = { version="0.3", optional = true }

View File

@ -1,386 +0,0 @@
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::net::{IpAddr, SocketAddr};
use std::time::Duration;
use std::{fmt, io};
use actix_service::{fn_factory, NewService, Service};
use futures::future::{ok, Either};
use futures::{try_ready, Async, Future, Poll};
use tokio_tcp::{ConnectFuture, TcpStream};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use trust_dns_resolver::system_conf::read_system_conf;
use super::resolver::{RequestHost, ResolveError, Resolver, ResolverFuture};
/// Port of the request
pub trait RequestPort {
fn port(&self) -> u16;
}
// #[derive(Fail, Debug)]
#[derive(Debug)]
pub enum ConnectorError {
/// Failed to resolve the hostname
// #[fail(display = "Failed resolving hostname: {}", _0)]
Resolver(ResolveError),
/// No dns records
// #[fail(display = "No dns records found for the input")]
NoRecords,
/// Connecting took too long
// #[fail(display = "Timeout out while establishing connection")]
Timeout,
/// Invalid input
InvalidInput,
/// Connection io error
// #[fail(display = "{}", _0)]
IoError(io::Error),
}
impl From<ResolveError> for ConnectorError {
fn from(err: ResolveError) -> Self {
ConnectorError::Resolver(err)
}
}
impl From<io::Error> for ConnectorError {
fn from(err: io::Error) -> Self {
ConnectorError::IoError(err)
}
}
/// Connect request
#[derive(Eq, PartialEq, Debug, Hash)]
pub struct Connect {
pub kind: ConnectKind,
pub timeout: Duration,
}
#[derive(Eq, PartialEq, Debug, Hash)]
pub enum ConnectKind {
Host { host: String, port: u16 },
Addr { host: String, addr: SocketAddr },
}
impl Connect {
/// Create new `Connect` instance.
pub fn new<T: AsRef<str>>(host: T, port: u16) -> Connect {
Connect {
kind: ConnectKind::Host {
host: host.as_ref().to_owned(),
port,
},
timeout: Duration::from_secs(1),
}
}
/// Create `Connect` instance by spliting the string by ':' and convert the second part to u16
pub fn with<T: AsRef<str>>(host: T) -> Result<Connect, ConnectorError> {
let mut parts_iter = host.as_ref().splitn(2, ':');
let host = parts_iter.next().ok_or(ConnectorError::InvalidInput)?;
let port_str = parts_iter.next().unwrap_or("");
let port = port_str
.parse::<u16>()
.map_err(|_| ConnectorError::InvalidInput)?;
Ok(Connect {
kind: ConnectKind::Host {
host: host.to_owned(),
port,
},
timeout: Duration::from_secs(1),
})
}
/// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages.
pub fn with_address<T: Into<String>>(host: T, addr: SocketAddr) -> Connect {
Connect {
kind: ConnectKind::Addr {
addr,
host: host.into(),
},
timeout: Duration::from_secs(1),
}
}
/// Set connect timeout
///
/// By default timeout is set to a 1 second.
pub fn timeout(mut self, timeout: Duration) -> Connect {
self.timeout = timeout;
self
}
}
impl RequestHost for Connect {
fn host(&self) -> &str {
match self.kind {
ConnectKind::Host { ref host, .. } => host,
ConnectKind::Addr { ref host, .. } => host,
}
}
}
impl RequestPort for Connect {
fn port(&self) -> u16 {
match self.kind {
ConnectKind::Host { port, .. } => port,
ConnectKind::Addr { addr, .. } => addr.port(),
}
}
}
impl fmt::Display for Connect {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.host(), self.port())
}
}
/// Tcp connector
pub struct Connector {
resolver: Resolver<Connect>,
}
impl Default for Connector {
fn default() -> Self {
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
(cfg, opts)
} else {
(ResolverConfig::default(), ResolverOpts::default())
};
Connector::new(cfg, opts)
}
}
impl Connector {
/// Create new connector with resolver configuration
pub fn new(cfg: ResolverConfig, opts: ResolverOpts) -> Self {
Connector {
resolver: Resolver::new(cfg, opts),
}
}
/// Create new connector with custom resolver
pub fn with_resolver(
resolver: Resolver<Connect>,
) -> impl Service<Request = Connect, Response = (Connect, TcpStream), Error = ConnectorError>
+ Clone {
Connector { resolver }
}
/// Create new default connector service
pub fn new_service_with_config<E>(
cfg: ResolverConfig,
opts: ResolverOpts,
) -> impl NewService<
(),
Request = Connect,
Response = (Connect, TcpStream),
Error = ConnectorError,
InitError = E,
> + Clone {
fn_factory(move || ok(Connector::new(cfg.clone(), opts)))
}
}
impl Clone for Connector {
fn clone(&self) -> Self {
Connector {
resolver: self.resolver.clone(),
}
}
}
impl Service for Connector {
type Request = Connect;
type Response = (Connect, TcpStream);
type Error = ConnectorError;
type Future = Either<ConnectorFuture, ConnectorTcpFuture>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: Connect) -> Self::Future {
match req.kind {
ConnectKind::Host { .. } => Either::A(ConnectorFuture {
fut: self.resolver.call(req),
fut2: None,
}),
ConnectKind::Addr { addr, .. } => {
let mut addrs = VecDeque::new();
addrs.push_back(addr.ip());
Either::B(ConnectorTcpFuture {
fut: TcpConnectorResponse::new(req, addrs),
})
}
}
}
}
#[doc(hidden)]
pub struct ConnectorFuture {
fut: ResolverFuture<Connect>,
fut2: Option<TcpConnectorResponse<Connect>>,
}
impl Future for ConnectorFuture {
type Item = (Connect, TcpStream);
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut2 {
return fut.poll().map_err(ConnectorError::from);
}
match self.fut.poll().map_err(ConnectorError::from)? {
Async::Ready((req, addrs)) => {
if addrs.is_empty() {
Err(ConnectorError::NoRecords)
} else {
self.fut2 = Some(TcpConnectorResponse::new(req, addrs));
self.poll()
}
}
Async::NotReady => Ok(Async::NotReady),
}
}
}
#[doc(hidden)]
pub struct ConnectorTcpFuture {
fut: TcpConnectorResponse<Connect>,
}
impl Future for ConnectorTcpFuture {
type Item = (Connect, TcpStream);
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(ConnectorError::IoError)
}
}
/// Tcp stream connector service
pub struct TcpConnector<T: RequestPort>(PhantomData<T>);
impl<T: RequestPort> Default for TcpConnector<T> {
fn default() -> TcpConnector<T> {
TcpConnector(PhantomData)
}
}
impl<T: RequestPort> Service for TcpConnector<T> {
type Request = (T, VecDeque<IpAddr>);
type Response = (T, TcpStream);
type Error = io::Error;
type Future = TcpConnectorResponse<T>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, (req, addrs): (T, VecDeque<IpAddr>)) -> Self::Future {
TcpConnectorResponse::new(req, addrs)
}
}
#[doc(hidden)]
/// Tcp stream connector response future
pub struct TcpConnectorResponse<T: RequestPort> {
port: u16,
req: Option<T>,
addr: Option<SocketAddr>,
addrs: VecDeque<IpAddr>,
stream: Option<ConnectFuture>,
}
impl<T: RequestPort> TcpConnectorResponse<T> {
pub fn new(req: T, addrs: VecDeque<IpAddr>) -> TcpConnectorResponse<T> {
TcpConnectorResponse {
addrs,
port: req.port(),
req: Some(req),
addr: None,
stream: None,
}
}
}
impl<T: RequestPort> Future for TcpConnectorResponse<T> {
type Item = (T, TcpStream);
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
// connect
loop {
if let Some(new) = self.stream.as_mut() {
match new.poll() {
Ok(Async::Ready(sock)) => {
return Ok(Async::Ready((self.req.take().unwrap(), sock)));
}
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(err) => {
if self.addrs.is_empty() {
return Err(err);
}
}
}
}
// try to connect
let addr = SocketAddr::new(self.addrs.pop_front().unwrap(), self.port);
self.stream = Some(TcpStream::connect(&addr));
self.addr = Some(addr)
}
}
}
#[derive(Clone)]
pub struct DefaultConnector(Connector);
impl Default for DefaultConnector {
fn default() -> Self {
DefaultConnector(Connector::default())
}
}
impl DefaultConnector {
pub fn new(cfg: ResolverConfig, opts: ResolverOpts) -> Self {
DefaultConnector(Connector::new(cfg, opts))
}
}
impl Service for DefaultConnector {
type Request = Connect;
type Response = TcpStream;
type Error = ConnectorError;
type Future = DefaultConnectorFuture;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.0.poll_ready()
}
fn call(&mut self, req: Connect) -> Self::Future {
DefaultConnectorFuture {
fut: self.0.call(req),
}
}
}
#[doc(hidden)]
pub struct DefaultConnectorFuture {
fut: Either<ConnectorFuture, ConnectorTcpFuture>,
}
impl Future for DefaultConnectorFuture {
type Item = TcpStream;
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::Ready(try_ready!(self.fut.poll()).1))
}
}

View File

@ -1,16 +0,0 @@
//! Actix Connector - tcp connector service
//!
//! ## Package feature
//!
//! * `tls` - enables ssl support via `native-tls` crate
//! * `ssl` - enables ssl support via `openssl` crate
//! * `rust-tls` - enables ssl support via `rustls` crate
mod connector;
mod resolver;
pub mod ssl;
pub use self::connector::{
Connect, Connector, ConnectorError, DefaultConnector, RequestPort, TcpConnector,
};
pub use self::resolver::{RequestHost, Resolver};

View File

@ -1,129 +0,0 @@
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::net::IpAddr;
use actix_service::Service;
use futures::{Async, Future, Poll};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
pub use trust_dns_resolver::error::ResolveError;
use trust_dns_resolver::lookup_ip::LookupIpFuture;
use trust_dns_resolver::system_conf::read_system_conf;
use trust_dns_resolver::{AsyncResolver, Background};
/// Host name of the request
pub trait RequestHost {
fn host(&self) -> &str;
}
impl RequestHost for String {
fn host(&self) -> &str {
self.as_ref()
}
}
pub struct Resolver<T = String> {
resolver: AsyncResolver,
req: PhantomData<T>,
}
impl<T: RequestHost> Default for Resolver<T> {
fn default() -> Self {
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
(cfg, opts)
} else {
(ResolverConfig::default(), ResolverOpts::default())
};
Resolver::new(cfg, opts)
}
}
impl<T: RequestHost> Resolver<T> {
/// Create new resolver instance with custom configuration and options.
pub fn new(cfg: ResolverConfig, opts: ResolverOpts) -> Self {
let (resolver, bg) = AsyncResolver::new(cfg, opts);
tokio_current_thread::spawn(bg);
Resolver {
resolver,
req: PhantomData,
}
}
/// Change type of resolver request.
pub fn into_request<T2: RequestHost>(&self) -> Resolver<T2> {
Resolver {
resolver: self.resolver.clone(),
req: PhantomData,
}
}
}
impl<T> Clone for Resolver<T> {
fn clone(&self) -> Self {
Resolver {
resolver: self.resolver.clone(),
req: PhantomData,
}
}
}
impl<T: RequestHost> Service for Resolver<T> {
type Request = T;
type Response = (T, VecDeque<IpAddr>);
type Error = ResolveError;
type Future = ResolverFuture<T>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: T) -> Self::Future {
if let Ok(ip) = req.host().parse() {
let mut addrs = VecDeque::new();
addrs.push_back(ip);
ResolverFuture::new(req, &self.resolver, Some(addrs))
} else {
ResolverFuture::new(req, &self.resolver, None)
}
}
}
#[doc(hidden)]
/// Resolver future
pub struct ResolverFuture<T> {
req: Option<T>,
lookup: Option<Background<LookupIpFuture>>,
addrs: Option<VecDeque<IpAddr>>,
}
impl<T: RequestHost> ResolverFuture<T> {
pub fn new(addr: T, resolver: &AsyncResolver, addrs: Option<VecDeque<IpAddr>>) -> Self {
// we need to do dns resolution
let lookup = Some(resolver.lookup_ip(addr.host()));
ResolverFuture {
lookup,
addrs,
req: Some(addr),
}
}
}
impl<T: RequestHost> Future for ResolverFuture<T> {
type Item = (T, VecDeque<IpAddr>);
type Error = ResolveError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(addrs) = self.addrs.take() {
Ok(Async::Ready((self.req.take().unwrap(), addrs)))
} else {
match self.lookup.as_mut().unwrap().poll() {
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(ips)) => Ok(Async::Ready((
self.req.take().unwrap(),
ips.iter().collect(),
))),
Err(err) => Err(err),
}
}
}
}

View File

@ -1,6 +0,0 @@
//! SSL Services
#[cfg(feature = "ssl")]
mod openssl;
#[cfg(feature = "ssl")]
pub use self::openssl::OpensslConnector;

View File

@ -1,107 +0,0 @@
use std::marker::PhantomData;
use actix_codec::{AsyncRead, AsyncWrite};
use actix_service::{NewService, Service};
use futures::{future::ok, future::FutureResult, Async, Future, Poll};
use openssl::ssl::{HandshakeError, SslConnector};
use tokio_openssl::{ConnectAsync, SslConnectorExt, SslStream};
use crate::resolver::RequestHost;
/// Openssl connector factory
pub struct OpensslConnector<R, T, E> {
connector: SslConnector,
_t: PhantomData<(R, T, E)>,
}
impl<R, T, E> OpensslConnector<R, T, E> {
pub fn new(connector: SslConnector) -> Self {
OpensslConnector {
connector,
_t: PhantomData,
}
}
}
impl<R: RequestHost, T: AsyncRead + AsyncWrite> OpensslConnector<R, T, ()> {
pub fn service(
connector: SslConnector,
) -> impl Service<Request = (R, T), Response = (R, SslStream<T>), Error = HandshakeError<T>>
{
OpensslConnectorService {
connector: connector,
_t: PhantomData,
}
}
}
impl<R, T, E> Clone for OpensslConnector<R, T, E> {
fn clone(&self) -> Self {
Self {
connector: self.connector.clone(),
_t: PhantomData,
}
}
}
impl<R: RequestHost, T: AsyncRead + AsyncWrite, E> NewService<()>
for OpensslConnector<R, T, E>
{
type Request = (R, T);
type Response = (R, SslStream<T>);
type Error = HandshakeError<T>;
type Service = OpensslConnectorService<R, T>;
type InitError = E;
type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future {
ok(OpensslConnectorService {
connector: self.connector.clone(),
_t: PhantomData,
})
}
}
pub struct OpensslConnectorService<R, T> {
connector: SslConnector,
_t: PhantomData<(R, T)>,
}
impl<R: RequestHost, T: AsyncRead + AsyncWrite> Service for OpensslConnectorService<R, T> {
type Request = (R, T);
type Response = (R, SslStream<T>);
type Error = HandshakeError<T>;
type Future = ConnectAsyncExt<R, T>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, (req, stream): (R, T)) -> Self::Future {
ConnectAsyncExt {
fut: SslConnectorExt::connect_async(&self.connector, req.host(), stream),
req: Some(req),
}
}
}
pub struct ConnectAsyncExt<R, T> {
req: Option<R>,
fut: ConnectAsync<T>,
}
impl<R, T> Future for ConnectAsyncExt<R, T>
where
R: RequestHost,
T: AsyncRead + AsyncWrite,
{
type Item = (R, SslStream<T>);
type Error = HandshakeError<T>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.fut.poll()? {
Async::Ready(stream) => Ok(Async::Ready((self.req.take().unwrap(), stream))),
Async::NotReady => Ok(Async::NotReady),
}
}
}

1
actix-macros/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/wip

53
actix-macros/CHANGES.md Normal file
View File

@ -0,0 +1,53 @@
# Changes
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.71.
## 0.2.4
- Update `syn` dependency to `2`.
- Minimum supported Rust version (MSRV) is now 1.65.
## 0.2.3
- Fix test macro in presence of other imports named "test". [#399]
[#399]: https://github.com/actix/actix-net/pull/399
## 0.2.2
- 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
- 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
- Update to latest `actix_rt::System::new` signature. [#261]
[#261]: https://github.com/actix/actix-net/pull/261
## 0.2.0-beta.1
- Remove `actix-reexport` feature. [#218]
[#218]: https://github.com/actix/actix-net/pull/218
## 0.1.3
- Add `actix-reexport` feature. [#218]
[#218]: https://github.com/actix/actix-net/pull/218
## 0.1.2
- Forward actix_rt::test arguments to test function [#127]
[#127]: https://github.com/actix/actix-net/pull/127

39
actix-macros/Cargo.toml Normal file
View File

@ -0,0 +1,39 @@
[package]
name = "actix-macros"
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"
categories = ["network-programming", "asynchronous"]
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"
syn = { version = "2", features = ["full"] }
# minimal versions compat
[target.'cfg(any())'.dependencies]
proc-macro2 = "1.0.60"
[dev-dependencies]
actix-rt = "2"
futures-util = { version = "0.3.17", default-features = false }
rustversion-msrv = "0.100"
trybuild = "1"
[lints]
workspace = true

1
actix-macros/LICENSE-APACHE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-APACHE

1
actix-macros/LICENSE-MIT Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-MIT

219
actix-macros/src/lib.rs Normal file
View File

@ -0,0 +1,219 @@
//! Macros for Actix system and runtime.
//!
//! The [`actix-rt`](https://docs.rs/actix-rt) crate must be available for macro output to compile.
//!
//! # Entry-point
//! See docs for the [`#[main]`](macro@main) macro.
//!
//! # Tests
//! See docs for the [`#[test]`](macro@test) macro.
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
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.
///
/// # Examples
/// ```
/// #[actix_rt::main]
/// async fn main() {
/// println!("Hello world");
/// }
/// ```
#[proc_macro_attribute]
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
Ok(input) => input,
// on parse err, make IDEs happy; see fn docs
Err(err) => return input_and_compile_error(item, err),
};
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;
let sig = &mut input.sig;
let body = &input.block;
if sig.asyncness.is_none() {
return syn::Error::new_spanned(
sig.fn_token,
"the async keyword is missing from the function declaration",
)
.to_compile_error()
.into();
}
let mut system = syn::parse_str::<syn::Path>("::actix_rt::System").unwrap();
for arg in &args {
match arg {
syn::Meta::NameValue(syn::MetaNameValue {
path,
value:
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit),
..
}),
..
}) => match path
.get_ident()
.map(|i| i.to_string().to_lowercase())
.as_deref()
{
Some("system") => match lit.parse() {
Ok(path) => system = path,
Err(_) => {
return syn::Error::new_spanned(lit, "Expected path")
.to_compile_error()
.into();
}
},
_ => {
return syn::Error::new_spanned(arg, "Unknown attribute specified")
.to_compile_error()
.into();
}
},
_ => {
return syn::Error::new_spanned(arg, "Unknown attribute specified")
.to_compile_error()
.into();
}
}
}
sig.asyncness = None;
(quote! {
#(#attrs)*
#vis #sig {
<#system>::new().block_on(async move { #body })
}
})
.into()
}
/// Marks async test function to be executed in an Actix system.
///
/// # Examples
/// ```
/// #[actix_rt::test]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
Ok(input) => input,
// on parse err, make IDEs happy; see fn docs
Err(err) => return input_and_compile_error(item, err),
};
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;
let sig = &mut input.sig;
let body = &input.block;
let mut has_test_attr = false;
for attr in attrs {
if attr.path().is_ident("test") {
has_test_attr = true;
}
}
if sig.asyncness.is_none() {
return syn::Error::new_spanned(
input.sig.fn_token,
"the async keyword is missing from the function declaration",
)
.to_compile_error()
.into();
}
sig.asyncness = None;
let missing_test_attr = if has_test_attr {
quote! {}
} else {
quote! { #[::core::prelude::v1::test] }
};
let mut system = syn::parse_str::<syn::Path>("::actix_rt::System").unwrap();
for arg in &args {
match arg {
syn::Meta::NameValue(syn::MetaNameValue {
path,
value:
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit),
..
}),
..
}) => match path
.get_ident()
.map(|i| i.to_string().to_lowercase())
.as_deref()
{
Some("system") => match lit.parse() {
Ok(path) => system = path,
Err(_) => {
return syn::Error::new_spanned(lit, "Expected path")
.to_compile_error()
.into();
}
},
_ => {
return syn::Error::new_spanned(arg, "Unknown attribute specified")
.to_compile_error()
.into();
}
},
_ => {
return syn::Error::new_spanned(arg, "Unknown attribute specified")
.to_compile_error()
.into();
}
}
}
(quote! {
#missing_test_attr
#(#attrs)*
#vis #sig {
<#system>::new().block_on(async { #body })
}
})
.into()
}
/// Converts the error to a token stream and appends it to the original input.
///
/// Returning the original input in addition to the error is good for IDEs which can gracefully
/// recover and show more precise errors within the macro body.
///
/// See <https://github.com/rust-analyzer/rust-analyzer/issues/10468> for more info.
fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream {
let compile_err = TokenStream::from(err.to_compile_error());
item.extend(compile_err);
item
}

View File

@ -0,0 +1,21 @@
#![allow(missing_docs)]
#[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");
t.pass("tests/trybuild/main-04-system-path.rs");
t.compile_fail("tests/trybuild/main-05-system-expect-path.rs");
t.compile_fail("tests/trybuild/main-06-unknown-attr.rs");
t.pass("tests/trybuild/test-01-basic.rs");
t.pass("tests/trybuild/test-02-keep-attrs.rs");
t.compile_fail("tests/trybuild/test-03-only-async.rs");
t.pass("tests/trybuild/test-04-system-path.rs");
t.compile_fail("tests/trybuild/test-05-system-expect-path.rs");
t.compile_fail("tests/trybuild/test-06-unknown-attr.rs");
}

View File

@ -0,0 +1,4 @@
#[actix_rt::main]
async fn main() {
println!("Hello world");
}

View File

@ -0,0 +1,4 @@
#[actix_rt::main]
fn main() {
futures_util::future::ready(()).await
}

View File

@ -0,0 +1,11 @@
error: the async keyword is missing from the function declaration
--> tests/trybuild/main-02-only-async.rs:2:1
|
2 | fn main() {
| ^^
error[E0601]: `main` function not found in crate `$CRATE`
--> tests/trybuild/main-02-only-async.rs:4:2
|
4 | }
| ^ consider adding a `main` function to `$DIR/tests/trybuild/main-02-only-async.rs`

View File

@ -0,0 +1,6 @@
#[actix_rt::main]
async fn main2(_param: bool) {
futures_util::future::ready(()).await
}
fn main() {}

View File

@ -0,0 +1,8 @@
mod system {
pub use actix_rt::System as MySystem;
}
#[actix_rt::main(system = "system::MySystem")]
async fn main() {
futures_util::future::ready(()).await
}

View File

@ -0,0 +1,4 @@
#[actix_rt::main(system = "!@#*&")]
async fn main2() {}
fn main() {}

View File

@ -0,0 +1,5 @@
error: Expected path
--> $DIR/main-05-system-expect-path.rs:1:27
|
1 | #[actix_rt::main(system = "!@#*&")]
| ^^^^^^^

View File

@ -0,0 +1,7 @@
#[actix_rt::main(foo = "bar")]
async fn async_main() {}
#[actix_rt::main(bar::baz)]
async fn async_main2() {}
fn main() {}

View File

@ -0,0 +1,11 @@
error: Unknown attribute specified
--> $DIR/main-06-unknown-attr.rs:1:18
|
1 | #[actix_rt::main(foo = "bar")]
| ^^^^^^^^^^^
error: Unknown attribute specified
--> $DIR/main-06-unknown-attr.rs:4:18
|
4 | #[actix_rt::main(bar::baz)]
| ^^^^^^^^

View File

@ -0,0 +1,6 @@
#[actix_rt::test]
async fn my_test() {
assert!(true);
}
fn main() {}

View File

@ -0,0 +1,7 @@
#[actix_rt::test]
#[should_panic]
async fn my_test() {
todo!()
}
fn main() {}

View File

@ -0,0 +1,6 @@
#[actix_rt::test]
fn my_test() {
futures_util::future::ready(()).await
}
fn main() {}

View File

@ -0,0 +1,5 @@
error: the async keyword is missing from the function declaration
--> $DIR/test-03-only-async.rs:2:1
|
2 | fn my_test() {
| ^^

View File

@ -0,0 +1,10 @@
mod system {
pub use actix_rt::System as MySystem;
}
#[actix_rt::test(system = "system::MySystem")]
async fn my_test() {
futures_util::future::ready(()).await
}
fn main() {}

View File

@ -0,0 +1,4 @@
#[actix_rt::test(system = "!@#*&")]
async fn my_test() {}
fn main() {}

View File

@ -0,0 +1,5 @@
error: Expected path
--> $DIR/test-05-system-expect-path.rs:1:27
|
1 | #[actix_rt::test(system = "!@#*&")]
| ^^^^^^^

View File

@ -0,0 +1,7 @@
#[actix_rt::test(foo = "bar")]
async fn my_test_1() {}
#[actix_rt::test(bar::baz)]
async fn my_test_2() {}
fn main() {}

View File

@ -0,0 +1,11 @@
error: Unknown attribute specified
--> $DIR/test-06-unknown-attr.rs:1:18
|
1 | #[actix_rt::test(foo = "bar")]
| ^^^^^^^^^^^
error: Unknown attribute specified
--> $DIR/test-06-unknown-attr.rs:4:18
|
4 | #[actix_rt::test(bar::baz)]
| ^^^^^^^^

View File

@ -1,5 +1,174 @@
# Changes # Changes
## [0.1.0] - 2018-12-09 ## Unreleased
* Initial release - Minimum supported Rust version (MSRV) is now 1.71.
## 2.10.0
- 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.
## 2.9.0
- Add `actix_rt::System::runtime()` method to retrieve the underlying `actix_rt::Runtime` runtime.
- Add `actix_rt::Runtime::tokio_runtime()` method to retrieve the underlying Tokio runtime.
- Minimum supported Rust version (MSRV) is now 1.65.
## 2.8.0
- Add `#[track_caller]` attribute to `spawn` functions and methods.
- Update `tokio-uring` dependency to `0.4`.
- Minimum supported Rust version (MSRV) is now 1.59.
## 2.7.0
- Update `tokio-uring` dependency to `0.3`.
- Minimum supported Rust version (MSRV) is now 1.49.
## 2.6.0
- Update `tokio-uring` dependency to `0.2`.
## 2.5.1
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`.
## 2.5.0
- Add `System::run_with_code` to allow retrieving the exit code on stop.
## 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.3.0
- 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
- **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.
## 2.1.0
- Add `ActixStream` extension trait to include readiness methods.
- Re-export `tokio::net::TcpSocket` in `net` module
## 2.0.2
- 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
- Expose `JoinError` from Tokio.
## 2.0.0
- Remove all Arbiter-local storage methods.
- Re-export `tokio::pin`.
## 2.0.0-beta.3
- 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
- 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`.
## 2.0.0-beta.1
- 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.
- 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.
## 1.1.1
- Fix memory leak due to
## 1.1.0 _(YANKED)_
- 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
- Update dependencies
## 1.0.0-alpha.3
- Migrate to tokio 0.2
- Fix compilation on non-unix platforms
## 1.0.0-alpha.2
- 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
- Migrate to std::future and tokio 0.2
## 0.2.6
- Allow to join arbiter's thread. #60
- Fix arbiter's thread panic message.
## 0.2.5
- Add arbiter specific storage
## 0.2.4
- Avoid a copy of the Future when initializing the Box. #29
## 0.2.3
- Allow to start System using existing CurrentThread Handle #22
## 0.2.2
- Moved `blocking` module to `actix-threadpool` crate
## 0.2.1
- 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
- `run` method returns `io::Result<()>`
- Removed `Handle`
## 0.1.0
- Initial release

View File

@ -1,27 +1,36 @@
[package] [package]
name = "actix-rt" name = "actix-rt"
version = "0.1.0" version = "2.10.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
description = "Actix runtime" description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
keywords = ["network", "framework", "async", "futures"] keywords = ["async", "futures", "io", "runtime"]
homepage = "https://actix.rs" homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git" repository = "https://github.com/actix/actix-net"
documentation = "https://docs.rs/actix-rt/"
categories = ["network-programming", "asynchronous"] categories = ["network-programming", "asynchronous"]
license = "MIT/Apache-2.0" license = "MIT OR Apache-2.0"
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] edition.workspace = true
edition = "2018" rust-version.workspace = true
workspace = "../"
[lib] [package.metadata.cargo_check_external_types]
name = "actix_rt" allowed_external_types = ["actix_macros::*", "tokio::*"]
path = "src/lib.rs"
[features]
default = ["macros"]
macros = ["actix-macros"]
io-uring = ["tokio-uring"]
[dependencies] [dependencies]
log = "0.4" actix-macros = { version = "0.2.3", optional = true }
bytes = "0.4"
futures = "0.1.24" futures-core = { version = "0.3", default-features = false }
tokio-current-thread = "0.1" tokio = { version = "1.23.1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
tokio-executor = "0.1.5"
tokio-reactor = "0.1.7" # runtime for `io-uring` feature
tokio-timer = "0.2.8" [target.'cfg(target_os = "linux")'.dependencies]
tokio-uring = { version = "0.5", optional = true }
[dev-dependencies]
tokio = { version = "1.23.1", features = ["full"] }
[lints]
workspace = true

1
actix-rt/LICENSE-APACHE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-APACHE

1
actix-rt/LICENSE-MIT Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-MIT

14
actix-rt/README.md Normal file
View File

@ -0,0 +1,14 @@
# actix-rt
> 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.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.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)
See crate documentation for more: https://docs.rs/actix-rt.

View File

@ -0,0 +1,60 @@
//! An example on how to build a multi-thread tokio runtime for Actix System.
//! Then spawn async task that can make use of work stealing of tokio runtime.
use actix_rt::System;
fn main() {
System::with_tokio_rt(|| {
// build system with a multi-thread tokio runtime.
tokio::runtime::Builder::new_multi_thread()
.worker_threads(2)
.enable_all()
.build()
.unwrap()
})
.block_on(async_main());
}
// async main function that acts like #[actix_web::main] or #[tokio::main]
async fn async_main() {
let (tx, rx) = tokio::sync::oneshot::channel();
// get a handle to system arbiter and spawn async task on it
System::current().arbiter().spawn(async {
// use tokio::spawn to get inside the context of multi thread tokio runtime
let h1 = tokio::spawn(async {
println!("thread id is {:?}", std::thread::current().id());
std::thread::sleep(std::time::Duration::from_secs(2));
});
// work stealing occurs for this task spawn
let h2 = tokio::spawn(async {
println!("thread id is {:?}", std::thread::current().id());
});
h1.await.unwrap();
h2.await.unwrap();
let _ = tx.send(());
});
rx.await.unwrap();
let (tx, rx) = tokio::sync::oneshot::channel();
let now = std::time::Instant::now();
// without additional tokio::spawn, all spawned tasks run on single thread
System::current().arbiter().spawn(async {
println!("thread id is {:?}", std::thread::current().id());
std::thread::sleep(std::time::Duration::from_secs(2));
let _ = tx.send(());
});
// previous spawn task has blocked the system arbiter thread
// so this task will wait for 2 seconds until it can be run
System::current().arbiter().spawn(async move {
println!("thread id is {:?}", std::thread::current().id());
assert!(now.elapsed() > std::time::Duration::from_secs(2));
});
rx.await.unwrap();
}

View File

@ -1,31 +1,31 @@
use std::cell::{Cell, RefCell}; use std::{
use std::collections::HashMap; cell::RefCell,
use std::sync::atomic::{AtomicUsize, Ordering}; fmt,
use std::{fmt, thread}; future::Future,
pin::Pin,
sync::atomic::{AtomicUsize, Ordering},
task::{Context, Poll},
thread,
};
use futures::sync::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; use futures_core::ready;
use futures::sync::oneshot::{channel, Sender}; use tokio::sync::mpsc;
use futures::{future, Async, Future, IntoFuture, Poll, Stream};
use tokio_current_thread::spawn;
use crate::builder::Builder; use crate::system::{System, SystemCommand};
use crate::system::System;
thread_local!(
static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None);
static RUNNING: Cell<bool> = Cell::new(false);
static Q: RefCell<Vec<Box<Future<Item = (), Error = ()>>>> = RefCell::new(Vec::new());
);
pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0); pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
thread_local!(
static HANDLE: RefCell<Option<ArbiterHandle>> = const { RefCell::new(None) };
);
pub(crate) enum ArbiterCommand { pub(crate) enum ArbiterCommand {
Stop, Stop,
Execute(Box<Future<Item = (), Error = ()> + Send>), Execute(Pin<Box<dyn Future<Output = ()> + Send>>),
} }
impl fmt::Debug for ArbiterCommand { impl fmt::Debug for ArbiterCommand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ArbiterCommand::Stop => write!(f, "ArbiterCommand::Stop"), ArbiterCommand::Stop => write!(f, "ArbiterCommand::Stop"),
ArbiterCommand::Execute(_) => write!(f, "ArbiterCommand::Execute"), ArbiterCommand::Execute(_) => write!(f, "ArbiterCommand::Execute"),
@ -33,235 +33,285 @@ impl fmt::Debug for ArbiterCommand {
} }
} }
/// A handle for sending spawn and stop messages to an [Arbiter].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Arbiter(UnboundedSender<ArbiterCommand>); pub struct ArbiterHandle {
tx: mpsc::UnboundedSender<ArbiterCommand>,
}
impl Default for Arbiter { impl ArbiterHandle {
fn default() -> Self { pub(crate) fn new(tx: mpsc::UnboundedSender<ArbiterCommand>) -> Self {
Self::new() Self { tx }
} }
/// Send a future to the [Arbiter]'s thread and spawn it.
///
/// 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.
pub fn spawn<Fut>(&self, future: Fut) -> bool
where
Fut: Future<Output = ()> + Send + 'static,
{
self.tx
.send(ArbiterCommand::Execute(Box::pin(future)))
.is_ok()
}
/// Send a function to the [Arbiter]'s thread and execute it.
///
/// Any result from the function is discarded. If you require a result, include a response
/// channel in the function.
///
/// Returns true if function was sent successfully and false if the [Arbiter] has died.
pub fn spawn_fn<F>(&self, f: F) -> bool
where
F: FnOnce() + Send + 'static,
{
self.spawn(async { f() })
}
/// Instruct [Arbiter] to stop processing it's event loop.
///
/// Returns true if stop message was sent successfully and false if the [Arbiter] has
/// been dropped.
pub fn stop(&self) -> bool {
self.tx.send(ArbiterCommand::Stop).is_ok()
}
}
/// An Arbiter represents a thread that provides an asynchronous execution environment for futures
/// and functions.
///
/// When an arbiter is created, it spawns a new [OS thread](thread), and hosts an event loop.
#[derive(Debug)]
pub struct Arbiter {
tx: mpsc::UnboundedSender<ArbiterCommand>,
thread_handle: thread::JoinHandle<()>,
} }
impl Arbiter { impl Arbiter {
pub(crate) fn new_system() -> Self { /// Spawn a new Arbiter thread and start its event loop.
let (tx, rx) = unbounded(); ///
/// # Panics
let arb = Arbiter(tx); /// Panics if a [System] is not registered on the current thread.
ADDR.with(|cell| *cell.borrow_mut() = Some(arb.clone())); #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
RUNNING.with(|cell| cell.set(false)); #[allow(clippy::new_without_default)]
Arbiter::spawn(ArbiterController { stop: None, rx }); pub fn new() -> Arbiter {
Self::with_tokio_rt(|| {
arb crate::runtime::default_tokio_runtime().expect("Cannot create new Arbiter's Runtime.")
}
/// Returns current arbiter's address
pub fn current() -> Arbiter {
ADDR.with(|cell| match *cell.borrow() {
Some(ref addr) => addr.clone(),
None => panic!("Arbiter is not running"),
}) })
} }
/// Stop arbiter /// Spawn a new Arbiter using the [Tokio Runtime](tokio-runtime) returned from a closure.
pub fn stop(&self) { ///
let _ = self.0.unbounded_send(ArbiterCommand::Stop); /// [tokio-runtime]: tokio::runtime::Runtime
} #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
/// Spawn new thread and run event loop in spawned thread. where
/// Returns address of newly created arbiter. F: FnOnce() -> tokio::runtime::Runtime + Send + 'static,
pub fn new() -> Arbiter { {
let id = COUNT.fetch_add(1, Ordering::Relaxed);
let name = format!("actix-rt:worker:{}", id);
let sys = System::current(); let sys = System::current();
let (arb_tx, arb_rx) = unbounded(); let system_id = sys.id();
let arb_tx2 = arb_tx.clone(); let arb_id = COUNT.fetch_add(1, Ordering::Relaxed);
let _ = thread::Builder::new().name(name.clone()).spawn(move || { let name = format!("actix-rt|system:{}|arbiter:{}", system_id, arb_id);
let mut rt = Builder::new().build_rt().expect("Can not create Runtime"); let (tx, rx) = mpsc::unbounded_channel();
let arb = Arbiter(arb_tx);
let (stop, stop_rx) = channel(); let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
RUNNING.with(|cell| cell.set(true));
System::set_current(sys); let thread_handle = thread::Builder::new()
.name(name.clone())
.spawn({
let tx = tx.clone();
move || {
let rt = crate::runtime::Runtime::from(runtime_factory());
let hnd = ArbiterHandle::new(tx);
// start arbiter controller System::set_current(sys);
rt.spawn(ArbiterController {
stop: Some(stop),
rx: arb_rx,
});
ADDR.with(|cell| *cell.borrow_mut() = Some(arb.clone()));
// register arbiter HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
let _ = System::current()
.sys()
.unbounded_send(SystemCommand::RegisterArbiter(id, arb.clone()));
// run loop // register arbiter
let _ = match rt.block_on(stop_rx) { let _ = System::current()
Ok(code) => code, .tx()
Err(_) => 1, .send(SystemCommand::RegisterArbiter(arb_id, hnd));
};
// unregister arbiter ready_tx.send(()).unwrap();
let _ = System::current()
.sys()
.unbounded_send(SystemCommand::UnregisterArbiter(id));
});
Arbiter(arb_tx2) // run arbiter event processing loop
rt.block_on(ArbiterRunner { rx });
// deregister arbiter
let _ = System::current()
.tx()
.send(SystemCommand::DeregisterArbiter(arb_id));
}
})
.unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
ready_rx.recv().unwrap();
Arbiter { tx, thread_handle }
} }
pub(crate) fn run_system() { /// Spawn a new Arbiter thread and start its event loop with `tokio-uring` runtime.
RUNNING.with(|cell| cell.set(true)); ///
Q.with(|cell| { /// # Panics
let mut v = cell.borrow_mut(); /// Panics if a [System] is not registered on the current thread.
for fut in v.drain(..) { #[cfg(all(target_os = "linux", feature = "io-uring"))]
spawn(fut); #[allow(clippy::new_without_default)]
} pub fn new() -> Arbiter {
}); let sys = System::current();
let system_id = sys.id();
let arb_id = COUNT.fetch_add(1, Ordering::Relaxed);
let name = format!("actix-rt|system:{}|arbiter:{}", system_id, arb_id);
let (tx, rx) = mpsc::unbounded_channel();
let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
let thread_handle = thread::Builder::new()
.name(name.clone())
.spawn({
let tx = tx.clone();
move || {
let hnd = ArbiterHandle::new(tx);
System::set_current(sys);
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
// register arbiter
let _ = System::current()
.tx()
.send(SystemCommand::RegisterArbiter(arb_id, hnd));
ready_tx.send(()).unwrap();
// run arbiter event processing loop
tokio_uring::start(ArbiterRunner { rx });
// deregister arbiter
let _ = System::current()
.tx()
.send(SystemCommand::DeregisterArbiter(arb_id));
}
})
.unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
ready_rx.recv().unwrap();
Arbiter { tx, thread_handle }
} }
pub(crate) fn stop_system() { /// Sets up an Arbiter runner in a new System using the environment's local set.
RUNNING.with(|cell| cell.set(false)); pub(crate) fn in_new_system() -> ArbiterHandle {
let (tx, rx) = mpsc::unbounded_channel();
let hnd = ArbiterHandle::new(tx);
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
crate::spawn(ArbiterRunner { rx });
hnd
} }
/// Spawn a future on the current thread. /// Return a handle to the this Arbiter's message sender.
pub fn spawn<F>(future: F) pub fn handle(&self) -> ArbiterHandle {
ArbiterHandle::new(self.tx.clone())
}
/// Return a handle to the current thread's Arbiter's message sender.
///
/// # Panics
/// Panics if no Arbiter is running on the current thread.
pub fn current() -> ArbiterHandle {
HANDLE.with(|cell| match *cell.borrow() {
Some(ref hnd) => hnd.clone(),
None => panic!("Arbiter is not running."),
})
}
/// Try to get current running arbiter handle.
///
/// Returns `None` if no Arbiter has been started.
///
/// Unlike [`current`](Self::current), this never panics.
pub fn try_current() -> Option<ArbiterHandle> {
HANDLE.with(|cell| cell.borrow().clone())
}
/// Stop Arbiter from continuing it's event loop.
///
/// Returns true if stop message was sent successfully and false if the Arbiter has been dropped.
pub fn stop(&self) -> bool {
self.tx.send(ArbiterCommand::Stop).is_ok()
}
/// Send a future to the Arbiter's thread and spawn it.
///
/// 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 where
F: Future<Item = (), Error = ()> + 'static, Fut: Future<Output = ()> + Send + 'static,
{ {
RUNNING.with(move |cell| { self.tx
if cell.get() { .send(ArbiterCommand::Execute(Box::pin(future)))
spawn(Box::new(future)); .is_ok()
} else {
Q.with(move |cell| cell.borrow_mut().push(Box::new(future)));
}
});
} }
/// Executes a future on the current thread. /// Send a function to the Arbiter's thread and execute it.
pub fn spawn_fn<F, R>(f: F) ///
/// Any result from the function is discarded. If you require a result, include a response
/// 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 where
F: FnOnce() -> R + 'static, F: FnOnce() + Send + 'static,
R: IntoFuture<Item = (), Error = ()> + 'static,
{ {
Arbiter::spawn(future::lazy(f)) self.spawn(async { f() })
} }
/// Send a future on the arbiter's thread and spawn. /// Wait for Arbiter's event loop to complete.
pub fn send<F>(&self, future: F) ///
where /// Joins the underlying OS thread handle. See [`JoinHandle::join`](thread::JoinHandle::join).
F: Future<Item = (), Error = ()> + Send + 'static, pub fn join(self) -> thread::Result<()> {
{ self.thread_handle.join()
let _ = self
.0
.unbounded_send(ArbiterCommand::Execute(Box::new(future)));
} }
} }
struct ArbiterController { /// A persistent future that processes [Arbiter] commands.
stop: Option<Sender<i32>>, struct ArbiterRunner {
rx: UnboundedReceiver<ArbiterCommand>, rx: mpsc::UnboundedReceiver<ArbiterCommand>,
} }
impl Drop for ArbiterController { impl Future for ArbiterRunner {
fn drop(&mut self) { type Output = ();
if thread::panicking() {
eprintln!("Panic in Arbiter thread, shutting down system.");
if System::current().stop_on_panic() {
System::current().stop_with_code(1)
}
}
}
}
impl Future for ArbiterController { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
type Item = (); // process all items currently buffered in channel
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop { loop {
match self.rx.poll() { match ready!(self.rx.poll_recv(cx)) {
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())), // channel closed; no more messages can be received
Ok(Async::Ready(Some(item))) => match item { None => return Poll::Ready(()),
// process arbiter command
Some(item) => match item {
ArbiterCommand::Stop => { ArbiterCommand::Stop => {
if let Some(stop) = self.stop.take() { return Poll::Ready(());
let _ = stop.send(0);
};
return Ok(Async::Ready(()));
} }
ArbiterCommand::Execute(fut) => { ArbiterCommand::Execute(task_fut) => {
spawn(fut); tokio::task::spawn_local(task_fut);
} }
}, },
Ok(Async::NotReady) => return Ok(Async::NotReady),
} }
} }
} }
} }
#[derive(Debug)]
pub(crate) enum SystemCommand {
Exit(i32),
RegisterArbiter(usize, Arbiter),
UnregisterArbiter(usize),
}
#[derive(Debug)]
pub(crate) struct SystemArbiter {
stop: Option<Sender<i32>>,
commands: UnboundedReceiver<SystemCommand>,
arbiters: HashMap<usize, Arbiter>,
}
impl SystemArbiter {
pub(crate) fn new(stop: Sender<i32>, commands: UnboundedReceiver<SystemCommand>) -> Self {
SystemArbiter {
commands,
stop: Some(stop),
arbiters: HashMap::new(),
}
}
}
impl Future for SystemArbiter {
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
match self.commands.poll() {
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())),
Ok(Async::Ready(Some(cmd))) => match cmd {
SystemCommand::Exit(code) => {
// stop arbiters
for arb in self.arbiters.values() {
arb.stop();
}
// stop event loop
if let Some(stop) = self.stop.take() {
let _ = stop.send(code);
}
}
SystemCommand::RegisterArbiter(name, hnd) => {
self.arbiters.insert(name, hnd);
}
SystemCommand::UnregisterArbiter(name) => {
self.arbiters.remove(&name);
}
},
Ok(Async::NotReady) => return Ok(Async::NotReady),
}
}
}
}
// /// Execute function in arbiter's thread
// impl<I: Send, E: Send> Handler<Execute<I, E>> for SystemArbiter {
// type Result = Result<I, E>;
// fn handle(&mut self, msg: Execute<I, E>, _: &mut Context<Self>) -> Result<I, E> {
// msg.exec()
// }
// }

View File

@ -1,175 +0,0 @@
use std::borrow::Cow;
use std::io;
use futures::future::{lazy, Future};
use futures::sync::mpsc::unbounded;
use futures::sync::oneshot::{channel, Receiver};
use tokio_current_thread::CurrentThread;
use tokio_reactor::Reactor;
use tokio_timer::clock::Clock;
use tokio_timer::timer::Timer;
use crate::arbiter::{Arbiter, SystemArbiter};
use crate::runtime::Runtime;
use crate::system::System;
/// Builder struct for a actix runtime.
///
/// Either use `Builder::build` to create a system and start actors.
/// Alternatively, use `Builder::run` to start the tokio runtime and
/// run a function in its context.
pub struct Builder {
/// Name of the System. Defaults to "actix" if unset.
name: Cow<'static, str>,
/// The clock to use
clock: Clock,
/// Whether the Arbiter will stop the whole System on uncaught panic. Defaults to false.
stop_on_panic: bool,
}
impl Builder {
pub(crate) fn new() -> Self {
Builder {
name: Cow::Borrowed("actix"),
clock: Clock::new(),
stop_on_panic: false,
}
}
/// Sets the name of the System.
pub fn name<T: Into<String>>(mut self, name: T) -> Self {
self.name = Cow::Owned(name.into());
self
}
/// Set the Clock instance that will be used by this System.
///
/// Defaults to the system clock.
pub fn clock(mut self, clock: Clock) -> Self {
self.clock = clock;
self
}
/// Sets the option 'stop_on_panic' which controls whether the System is stopped when an
/// uncaught panic is thrown from a worker thread.
///
/// Defaults to false.
pub fn stop_on_panic(mut self, stop_on_panic: bool) -> Self {
self.stop_on_panic = stop_on_panic;
self
}
/// Create new System.
///
/// This method panics if it can not create tokio runtime
pub fn build(self) -> SystemRunner {
self.create_runtime(|| {})
}
/// This function will start tokio runtime and will finish once the
/// `System::stop()` message get called.
/// Function `f` get called within tokio runtime context.
pub fn run<F>(self, f: F) -> i32
where
F: FnOnce() + 'static,
{
self.create_runtime(f).run()
}
fn create_runtime<F>(self, f: F) -> SystemRunner
where
F: FnOnce() + 'static,
{
let (stop_tx, stop) = channel();
let (sys_sender, sys_receiver) = unbounded();
let arbiter = Arbiter::new_system();
let system = System::construct(sys_sender, arbiter.clone(), self.stop_on_panic);
// system arbiter
let arb = SystemArbiter::new(stop_tx, sys_receiver);
let mut rt = self.build_rt().unwrap();
rt.spawn(arb);
// init system arbiter and run configuration method
let _ = rt.block_on(lazy(move || {
f();
Ok::<_, ()>(())
}));
SystemRunner { rt, stop, system }
}
pub(crate) fn build_rt(&self) -> io::Result<Runtime> {
// We need a reactor to receive events about IO objects from kernel
let reactor = Reactor::new()?;
let reactor_handle = reactor.handle();
// Place a timer wheel on top of the reactor. If there are no timeouts to fire, it'll let the
// reactor pick up some new external events.
let timer = Timer::new_with_now(reactor, self.clock.clone());
let timer_handle = timer.handle();
// And now put a single-threaded executor on top of the timer. When there are no futures ready
// to do something, it'll let the timer or the reactor to generate some new stimuli for the
// futures to continue in their life.
let executor = CurrentThread::new_with_park(timer);
Ok(Runtime::new2(
reactor_handle,
timer_handle,
self.clock.clone(),
executor,
))
}
}
/// Helper object that runs System's event loop
#[must_use = "SystemRunner must be run"]
#[derive(Debug)]
pub struct SystemRunner {
rt: Runtime,
stop: Receiver<i32>,
system: System,
}
impl SystemRunner {
/// This function will start event loop and will finish once the
/// `System::stop()` function is called.
pub fn run(self) -> i32 {
let SystemRunner { mut rt, stop, .. } = self;
// run loop
let _ = rt.block_on(lazy(move || {
Arbiter::run_system();
Ok::<_, ()>(())
}));
let code = match rt.block_on(stop) {
Ok(code) => code,
Err(_) => 1,
};
Arbiter::stop_system();
code
}
/// Execute a future and wait for result.
pub fn block_on<F, I, E>(&mut self, fut: F) -> Result<I, E>
where
F: Future<Item = I, Error = E>,
{
let _ = self.rt.block_on(lazy(move || {
Arbiter::run_system();
Ok::<_, ()>(())
}));
let res = self.rt.block_on(fut);
let _ = self.rt.block_on(lazy(move || {
Arbiter::stop_system();
Ok::<_, ()>(())
}));
res
}
}

View File

@ -1,27 +1,207 @@
//! A runtime implementation that runs everything on the current thread. //! Tokio-based single-threaded async runtime for the Actix ecosystem.
//!
//! In most parts of the the Actix ecosystem, it has been chosen to use !Send futures. For this
//! reason, a single-threaded runtime is appropriate since it is guaranteed that futures will not
//! be moved between threads. This can result in small performance improvements over cases where
//! atomics would otherwise be needed.
//!
//! To achieve similar performance to multi-threaded, work-stealing runtimes, applications
//! using `actix-rt` will create multiple, mostly disconnected, single-threaded runtimes.
//! This approach has good performance characteristics for workloads where the majority of tasks
//! have similar runtime expense.
//!
//! The disadvantage is that idle threads will not steal work from very busy, stuck or otherwise
//! backlogged threads. Tasks that are disproportionately expensive should be offloaded to the
//! blocking task thread-pool using [`task::spawn_blocking`].
//!
//! # Examples
//! ```no_run
//! use std::sync::mpsc;
//! use actix_rt::{Arbiter, System};
//!
//! let _ = System::new();
//!
//! let (tx, rx) = mpsc::channel::<u32>();
//!
//! let arbiter = Arbiter::new();
//! arbiter.spawn_fn(move || tx.send(42).unwrap());
//!
//! let num = rx.recv().unwrap();
//! assert_eq!(num, 42);
//!
//! arbiter.stop();
//! arbiter.join().unwrap();
//! ```
//!
//! # `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.
//!
//! Note that there are currently some unimplemented parts of using `actix-rt` with `io-uring`.
//! In particular, when running a `System`, only `System::block_on` is supported.
#![allow(clippy::type_complexity)]
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
#[cfg(all(not(target_os = "linux"), feature = "io-uring"))]
compile_error!("io_uring is a linux only feature.");
use std::future::Future;
// 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;
mod arbiter; mod arbiter;
mod builder;
mod runtime; mod runtime;
mod system; mod system;
pub use self::arbiter::Arbiter; pub use tokio::pin;
pub use self::builder::{Builder, SystemRunner}; use tokio::task::JoinHandle;
pub use self::runtime::{Handle, Runtime};
pub use self::system::System;
/// Spawns a future on the current arbiter. pub use self::{
/// arbiter::{Arbiter, ArbiterHandle},
/// # Panics runtime::Runtime,
/// system::{System, SystemRunner},
/// This function panics if actix system is not running. };
pub fn spawn<F>(f: F)
where pub mod signal {
F: futures::Future<Item = (), Error = ()> + 'static, //! Asynchronous signal handling (Tokio re-exports).
{
if !System::is_set() { #[cfg(unix)]
panic!("System is not running"); pub mod unix {
//! Unix specific signals (Tokio re-exports).
pub use tokio::signal::unix::*;
}
pub use tokio::signal::ctrl_c;
}
pub mod net {
//! TCP/UDP/Unix bindings (mostly Tokio re-exports).
use std::{
future::Future,
io,
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite, Interest};
#[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)]
pub trait ActixStream: AsyncRead + AsyncWrite + Unpin {
/// Poll stream and check read readiness of Self.
///
/// See [tokio::net::TcpStream::poll_read_ready] for detail on intended use.
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>>;
/// Poll stream and check write readiness of Self.
///
/// See [tokio::net::TcpStream::poll_write_ready] for detail on intended use.
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>>;
} }
Arbiter::spawn(f); impl ActixStream for TcpStream {
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
let ready = self.ready(Interest::READABLE);
tokio::pin!(ready);
ready.poll(cx)
}
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
let ready = self.ready(Interest::WRITABLE);
tokio::pin!(ready);
ready.poll(cx)
}
}
#[cfg(unix)]
impl ActixStream for UnixStream {
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
let ready = self.ready(Interest::READABLE);
tokio::pin!(ready);
ready.poll(cx)
}
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
let ready = self.ready(Interest::WRITABLE);
tokio::pin!(ready);
ready.poll(cx)
}
}
impl<Io: ActixStream + ?Sized> ActixStream for Box<Io> {
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
(**self).poll_read_ready(cx)
}
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
(**self).poll_write_ready(cx)
}
}
}
pub mod time {
//! Utilities for tracking time (Tokio re-exports).
pub use tokio::time::{
interval, interval_at, sleep, sleep_until, timeout, Instant, Interval, Sleep, Timeout,
};
}
pub mod task {
//! Task management (Tokio re-exports).
pub use tokio::task::{spawn_blocking, yield_now, JoinError, JoinHandle};
}
/// Spawns a future on the current thread as a new task.
///
/// If not immediately awaited, the task can be cancelled using [`JoinHandle::abort`].
///
/// The provided future is spawned as a new task; therefore, panics are caught.
///
/// # Panics
/// Panics if Actix system is not running.
///
/// # Examples
/// ```
/// # use std::time::Duration;
/// # actix_rt::Runtime::new().unwrap().block_on(async {
/// // task resolves successfully
/// assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
///
/// // task panics
/// assert!(actix_rt::spawn(async {
/// panic!("panic is caught at task boundary");
/// })
/// .await
/// .unwrap_err()
/// .is_panic());
///
/// // task is cancelled before completion
/// let handle = actix_rt::spawn(actix_rt::time::sleep(Duration::from_secs(100)));
/// handle.abort();
/// assert!(handle.await.unwrap_err().is_cancelled());
/// # });
/// ```
#[track_caller]
#[inline]
pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output>
where
Fut: Future + 'static,
Fut::Output: 'static,
{
tokio::task::spawn_local(f)
} }

View File

@ -1,92 +0,0 @@
//! A runtime implementation that runs everything on the current thread.
//!
//! [`current_thread::Runtime`][rt] is similar to the primary
//! [`Runtime`][concurrent-rt] except that it runs all components on the current
//! thread instead of using a thread pool. This means that it is able to spawn
//! futures that do not implement `Send`.
//!
//! Same as the default [`Runtime`][concurrent-rt], the
//! [`current_thread::Runtime`][rt] includes:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//! * A [timer] for scheduling work to run after a set period of time.
//!
//! Note that [`current_thread::Runtime`][rt] does not implement `Send` itself
//! and cannot be safely moved to other threads.
//!
//! # Spawning from other threads
//!
//! While [`current_thread::Runtime`][rt] does not implement `Send` and cannot
//! safely be moved to other threads, it provides a `Handle` that can be sent
//! to other threads and allows to spawn new tasks from there.
//!
//! For example:
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//! use std::thread;
//!
//! # fn main() {
//! let mut runtime = Runtime::new().unwrap();
//! let handle = runtime.handle();
//!
//! thread::spawn(move || {
//! handle.spawn(future::ok(()));
//! }).join().unwrap();
//!
//! # /*
//! runtime.run().unwrap();
//! # */
//! # }
//! ```
//!
//! # Examples
//!
//! Creating a new `Runtime` and running a future `f` until its completion and
//! returning its result.
//!
//! ```
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//!
//! let mut runtime = Runtime::new().unwrap();
//!
//! // Use the runtime...
//! // runtime.block_on(f); // where f is a future
//! ```
//!
//! [rt]: struct.Runtime.html
//! [concurrent-rt]: ../struct.Runtime.html
//! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html
//! [reactor]: ../../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [timer]: ../../timer/index.html
mod builder;
mod runtime;
pub use self::builder::Builder;
pub use self::runtime::{Runtime, Handle};
pub use tokio_current_thread::spawn;
pub use tokio_current_thread::TaskExecutor;
use futures::Future;
/// Run the provided future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
pub fn block_on_all<F>(future: F) -> Result<F::Item, F::Error>
where
F: Future,
{
let mut r = Runtime::new().expect("failed to start runtime on current thread");
let v = r.block_on(future)?;
r.run().expect("failed to resolve remaining futures");
Ok(v)
}

View File

@ -1,236 +1,149 @@
use std::error::Error; use std::{future::Future, io};
use std::fmt;
use std::io;
use futures::{future, Future}; use tokio::task::{JoinHandle, LocalSet};
use tokio_current_thread::Handle as ExecutorHandle;
use tokio_current_thread::{self as current_thread, CurrentThread};
use tokio_executor;
use tokio_reactor::{self, Reactor};
use tokio_timer::clock::{self, Clock};
use tokio_timer::timer::{self, Timer};
use crate::builder::Builder; /// A Tokio-based runtime proxy.
/// Single-threaded runtime provides a way to start reactor
/// and executor on the current thread.
/// ///
/// See [module level][mod] documentation for more details. /// All spawned futures will be executed on the current thread. Therefore, there is no `Send` bound
/// /// on submitted futures.
/// [mod]: index.html
#[derive(Debug)] #[derive(Debug)]
pub struct Runtime { pub struct Runtime {
reactor_handle: tokio_reactor::Handle, local: LocalSet,
timer_handle: timer::Handle, rt: tokio::runtime::Runtime,
clock: Clock,
executor: CurrentThread<Timer<Reactor>>,
} }
/// Handle to spawn a future on the corresponding `CurrentThread` runtime instance pub(crate) fn default_tokio_runtime() -> io::Result<tokio::runtime::Runtime> {
#[derive(Debug, Clone)] tokio::runtime::Builder::new_current_thread()
pub struct Handle(ExecutorHandle); .enable_io()
.enable_time()
impl Handle { .build()
/// Spawn a future onto the `CurrentThread` runtime instance corresponding to this handle
///
/// # Panics
///
/// This function panics if the spawn fails. Failure occurs if the `CurrentThread`
/// instance of the `Handle` does not exist anymore.
pub fn spawn<F>(&self, future: F) -> Result<(), tokio_executor::SpawnError>
where
F: Future<Item = (), Error = ()> + Send + 'static,
{
self.0.spawn(future)
}
/// Provides a best effort **hint** to whether or not `spawn` will succeed.
///
/// This function may return both false positives **and** false negatives.
/// If `status` returns `Ok`, then a call to `spawn` will *probably*
/// succeed, but may fail. If `status` returns `Err`, a call to `spawn` will
/// *probably* fail, but may succeed.
///
/// This allows a caller to avoid creating the task if the call to `spawn`
/// has a high likelihood of failing.
pub fn status(&self) -> Result<(), tokio_executor::SpawnError> {
self.0.status()
}
}
impl<T> future::Executor<T> for Handle
where
T: Future<Item = (), Error = ()> + Send + 'static,
{
fn execute(&self, future: T) -> Result<(), future::ExecuteError<T>> {
if let Err(e) = self.status() {
let kind = if e.is_at_capacity() {
future::ExecuteErrorKind::NoCapacity
} else {
future::ExecuteErrorKind::Shutdown
};
return Err(future::ExecuteError::new(kind, future));
}
let _ = self.spawn(future);
Ok(())
}
}
/// Error returned by the `run` function.
#[derive(Debug)]
pub struct RunError {
inner: current_thread::RunError,
}
impl fmt::Display for RunError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.inner)
}
}
impl Error for RunError {
fn description(&self) -> &str {
self.inner.description()
}
fn cause(&self) -> Option<&Error> {
self.inner.cause()
}
} }
impl Runtime { impl Runtime {
#[allow(clippy::new_ret_no_self)]
/// Returns a new runtime initialized with default configuration values. /// Returns a new runtime initialized with default configuration values.
pub fn new() -> io::Result<Runtime> { #[allow(clippy::new_ret_no_self)]
Builder::new().build_rt() pub fn new() -> io::Result<Self> {
let rt = default_tokio_runtime()?;
Ok(Runtime {
rt,
local: LocalSet::new(),
})
} }
pub(super) fn new2( /// Offload a future onto the single-threaded runtime.
reactor_handle: tokio_reactor::Handle,
timer_handle: timer::Handle,
clock: Clock,
executor: CurrentThread<Timer<Reactor>>,
) -> Runtime {
Runtime {
reactor_handle,
timer_handle,
clock,
executor,
}
}
/// Get a new handle to spawn futures on the single-threaded Tokio runtime
/// ///
/// Different to the runtime itself, the handle can be sent to different /// The returned join handle can be used to await the future's result.
/// threads.
pub fn handle(&self) -> Handle {
Handle(self.executor.handle().clone())
}
/// Spawn a future onto the single-threaded Tokio runtime.
/// ///
/// See [module level][mod] documentation for more details. /// See [crate root][crate] documentation for more details.
///
/// [mod]: index.html
/// ///
/// # Examples /// # Examples
/// /// ```
/// ```rust /// let rt = actix_rt::Runtime::new().unwrap();
/// # use futures::{future, Future, Stream};
/// use actix_rt::Runtime;
///
/// # fn dox() {
/// // Create the runtime
/// let mut rt = Runtime::new().unwrap();
/// ///
/// // Spawn a future onto the runtime /// // Spawn a future onto the runtime
/// rt.spawn(future::lazy(|| { /// let handle = rt.spawn(async {
/// println!("running on the runtime"); /// println!("running on the runtime");
/// Ok(()) /// 42
/// })); /// });
/// # } ///
/// # pub fn main() {} /// assert_eq!(rt.block_on(handle).unwrap(), 42);
/// ``` /// ```
/// ///
/// # Panics /// # Panics
/// /// This function panics if the spawn fails. Failure occurs if the executor is currently at
/// This function panics if the spawn fails. Failure occurs if the executor /// capacity and is unable to spawn a new future.
/// is currently at capacity and is unable to spawn a new future. #[track_caller]
pub fn spawn<F>(&mut self, future: F) -> &mut Self pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where where
F: Future<Item = (), Error = ()> + 'static, F: Future + 'static,
{ {
self.executor.spawn(future); self.local.spawn_local(future)
self
} }
/// Runs the provided future, blocking the current thread until the future /// Retrieves a reference to the underlying Tokio runtime associated with this instance.
/// completes.
/// ///
/// This function can be used to synchronously block the current thread /// The Tokio runtime is responsible for executing asynchronous tasks and managing
/// until the provided `future` has resolved either successfully or with an /// the event loop for an asynchronous Rust program. This method allows accessing
/// error. The result of the future is then returned from this function /// the runtime to interact with its features directly.
/// call.
/// ///
/// Note that this function will **also** execute any spawned futures on the /// In a typical use case, you might need to share the same runtime between different
/// current thread, but will **not** block until these other spawned futures /// modules of your project. For example, a module might require a `tokio::runtime::Handle`
/// have completed. Once the function returns, any uncompleted futures /// to spawn tasks on the same runtime, or the runtime itself to configure more complex
/// remain pending in the `Runtime` instance. These futures will not run /// 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
/// `future` has resolved either successfully or with an error. The result of the future is
/// then returned from this function call.
///
/// Note that this function will also execute any spawned futures on the current thread, but
/// will not block until these other spawned futures have completed. Once the function returns,
/// any uncompleted futures remain pending in the `Runtime` instance. These futures will not run
/// until `block_on` or `run` is called again. /// until `block_on` or `run` is called again.
/// ///
/// The caller is responsible for ensuring that other spawned futures /// The caller is responsible for ensuring that other spawned futures complete execution by
/// complete execution by calling `block_on` or `run`. /// calling `block_on` or `run`.
pub fn block_on<F>(&mut self, f: F) -> Result<F::Item, F::Error> #[track_caller]
pub fn block_on<F>(&self, f: F) -> F::Output
where where
F: Future, F: Future,
{ {
self.enter(|executor| { self.local.block_on(&self.rt, f)
// Run the provided future }
let ret = executor.block_on(f); }
ret.map_err(|e| e.into_inner().expect("unexpected execution error"))
}) impl From<tokio::runtime::Runtime> for Runtime {
} fn from(rt: tokio::runtime::Runtime) -> Self {
Self {
/// Run the executor to completion, blocking the thread until **all** local: LocalSet::new(),
/// spawned futures have completed. rt,
pub fn run(&mut self) -> Result<(), RunError> { }
self.enter(|executor| executor.run())
.map_err(|e| RunError { inner: e })
}
fn enter<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut current_thread::Entered<Timer<Reactor>>) -> R,
{
let Runtime {
ref reactor_handle,
ref timer_handle,
ref clock,
ref mut executor,
..
} = *self;
// Binds an executor to this thread
let mut enter = tokio_executor::enter().expect("Multiple executors at once");
// This will set the default handle and timer to use inside the closure
// and run the future.
tokio_reactor::with_default(&reactor_handle, &mut enter, |enter| {
clock::with_default(clock, enter, |enter| {
timer::with_default(&timer_handle, enter, |enter| {
// The TaskExecutor is a fake executor that looks into the
// current single-threaded executor when used. This is a trick,
// because we need two mutable references to the executor (one
// to run the provided future, another to install as the default
// one). We use the fake one here as the default one.
let mut default_executor = current_thread::TaskExecutor::current();
tokio_executor::with_default(&mut default_executor, enter, |enter| {
let mut executor = executor.enter(enter);
f(&mut executor)
})
})
})
})
} }
} }

View File

@ -1,55 +1,119 @@
use std::cell::RefCell; use std::{
cell::RefCell,
collections::HashMap,
future::Future,
io,
pin::Pin,
sync::atomic::{AtomicUsize, Ordering},
task::{Context, Poll},
};
use futures::sync::mpsc::UnboundedSender; use futures_core::ready;
use tokio::sync::{mpsc, oneshot};
use crate::arbiter::{Arbiter, SystemCommand}; use crate::{arbiter::ArbiterHandle, Arbiter};
use crate::builder::{Builder, SystemRunner};
/// System is a runtime manager. static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
#[derive(Clone, Debug)]
pub struct System {
sys: UnboundedSender<SystemCommand>,
arbiter: Arbiter,
stop_on_panic: bool,
}
thread_local!( 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.
#[derive(Clone, Debug)]
pub struct System {
id: usize,
sys_tx: mpsc::UnboundedSender<SystemCommand>,
/// Handle to the first [Arbiter] that is created with the System.
arbiter_handle: ArbiterHandle,
}
#[cfg(not(feature = "io-uring"))]
impl System { impl System {
/// Constructs new system and sets it as current /// Create a new system.
///
/// # Panics
/// Panics if underlying Tokio runtime can not be created.
#[allow(clippy::new_ret_no_self)]
pub fn new() -> SystemRunner {
Self::with_tokio_rt(|| {
crate::runtime::default_tokio_runtime()
.expect("Default Actix (Tokio) runtime could not be created.")
})
}
/// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
///
/// [tokio-runtime]: tokio::runtime::Runtime
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
where
F: FnOnce() -> tokio::runtime::Runtime,
{
let (stop_tx, stop_rx) = oneshot::channel();
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
let rt = crate::runtime::Runtime::from(runtime_factory());
let sys_arbiter = rt.block_on(async { Arbiter::in_new_system() });
let system = System::construct(sys_tx, sys_arbiter.clone());
system
.tx()
.send(SystemCommand::RegisterArbiter(usize::MAX, sys_arbiter))
.unwrap();
// init background system arbiter
let sys_ctrl = SystemController::new(sys_rx, stop_tx);
rt.spawn(sys_ctrl);
SystemRunner { rt, stop_rx }
}
}
#[cfg(feature = "io-uring")]
impl System {
/// Create a new system.
///
/// # Panics
/// Panics if underlying Tokio runtime can not be created.
#[allow(clippy::new_ret_no_self)]
pub fn new() -> SystemRunner {
SystemRunner
}
/// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
///
/// [tokio-runtime]: tokio::runtime::Runtime
#[doc(hidden)]
pub fn with_tokio_rt<F>(_: F) -> SystemRunner
where
F: FnOnce() -> tokio::runtime::Runtime,
{
unimplemented!("System::with_tokio_rt is not implemented for io-uring feature yet")
}
}
impl System {
/// Constructs new system and registers it on the current thread.
pub(crate) fn construct( pub(crate) fn construct(
sys: UnboundedSender<SystemCommand>, sys_tx: mpsc::UnboundedSender<SystemCommand>,
arbiter: Arbiter, arbiter_handle: ArbiterHandle,
stop_on_panic: bool,
) -> Self { ) -> Self {
let sys = System { let sys = System {
sys, sys_tx,
arbiter, arbiter_handle,
stop_on_panic, id: SYSTEM_COUNT.fetch_add(1, Ordering::SeqCst),
}; };
System::set_current(sys.clone()); System::set_current(sys.clone());
sys sys
} }
/// Build a new system with a customized tokio runtime.
///
/// This allows to customize the runtime. See struct level docs on
/// `Builder` for more information.
pub fn builder() -> Builder {
Builder::new()
}
#[allow(clippy::new_ret_no_self)]
/// Create new system.
///
/// This method panics if it can not create tokio runtime
pub fn new<T: Into<String>>(name: T) -> SystemRunner {
Self::builder().name(name).build()
}
/// Get current running system. /// Get current running system.
///
/// # Panics
/// Panics if no system is registered on the current thread.
pub fn current() -> System { pub fn current() -> System {
CURRENT.with(|cell| match *cell.borrow() { CURRENT.with(|cell| match *cell.borrow() {
Some(ref sys) => sys.clone(), Some(ref sys) => sys.clone(),
@ -57,62 +121,237 @@ impl System {
}) })
} }
/// Set current running system. /// Try to get current running system.
pub(crate) fn is_set() -> bool { ///
CURRENT.with(|cell| cell.borrow().is_some()) /// Returns `None` if no System has been started.
///
/// Unlike [`current`](Self::current), this never panics.
pub fn try_current() -> Option<System> {
CURRENT.with(|cell| cell.borrow().clone())
} }
/// Set current running system. /// Get handle to a the System's initial [Arbiter].
pub fn arbiter(&self) -> &ArbiterHandle {
&self.arbiter_handle
}
/// Check if there is a System registered on the current thread.
pub fn is_registered() -> bool {
CURRENT.with(|sys| sys.borrow().is_some())
}
/// Register given system on current thread.
#[doc(hidden)] #[doc(hidden)]
pub fn set_current(sys: System) { pub fn set_current(sys: System) {
CURRENT.with(|s| { CURRENT.with(|cell| {
*s.borrow_mut() = Some(sys); *cell.borrow_mut() = Some(sys);
}) })
} }
/// Execute function with system reference. /// Numeric system identifier.
pub fn with_current<F, R>(f: F) -> R ///
where /// Useful when using multiple Systems.
F: FnOnce(&System) -> R, pub fn id(&self) -> usize {
{ self.id
CURRENT.with(|cell| match *cell.borrow() {
Some(ref sys) => f(sys),
None => panic!("System is not running"),
})
} }
/// Stop the system /// Stop the system (with code 0).
pub fn stop(&self) { pub fn stop(&self) {
self.stop_with_code(0) self.stop_with_code(0)
} }
/// Stop the system with a particular exit code. /// Stop the system with a given exit code.
pub fn stop_with_code(&self, code: i32) { pub fn stop_with_code(&self, code: i32) {
let _ = self.sys.unbounded_send(SystemCommand::Exit(code)); let _ = self.sys_tx.send(SystemCommand::Exit(code));
} }
pub(crate) fn sys(&self) -> &UnboundedSender<SystemCommand> { pub(crate) fn tx(&self) -> &mpsc::UnboundedSender<SystemCommand> {
&self.sys &self.sys_tx
} }
}
/// Return status of 'stop_on_panic' option which controls whether the System is stopped when an
/// uncaught panic is thrown from a worker thread. /// Runner that keeps a [System]'s event loop alive until stop message is received.
pub fn stop_on_panic(&self) -> bool { #[cfg(not(feature = "io-uring"))]
self.stop_on_panic #[must_use = "A SystemRunner does nothing unless `run` is called."]
} #[derive(Debug)]
pub struct SystemRunner {
/// System arbiter rt: crate::runtime::Runtime,
pub fn arbiter(&self) -> &Arbiter { stop_rx: oneshot::Receiver<i32>,
&self.arbiter }
}
#[cfg(not(feature = "io-uring"))]
/// This function will start tokio runtime and will finish once the impl SystemRunner {
/// `System::stop()` message get called. /// Starts event loop and will return once [System] is [stopped](System::stop).
/// Function `f` get called within tokio runtime context. pub fn run(self) -> io::Result<()> {
pub fn run<F>(f: F) -> i32 let exit_code = self.run_with_code()?;
where
F: FnOnce() + 'static, match exit_code {
{ 0 => Ok(()),
Self::builder().run(f) nonzero => Err(io::Error::new(
io::ErrorKind::Other,
format!("Non-zero exit code: {}", nonzero),
)),
}
}
/// Runs the event loop until [stopped](System::stop_with_code), returning the exit code.
pub fn run_with_code(self) -> io::Result<i32> {
let SystemRunner { rt, stop_rx, .. } = self;
// run loop
rt.block_on(stop_rx)
.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)
}
}
/// Runner that keeps a [System]'s event loop alive until stop message is received.
#[cfg(feature = "io-uring")]
#[must_use = "A SystemRunner does nothing unless `run` is called."]
#[derive(Debug)]
pub struct SystemRunner;
#[cfg(feature = "io-uring")]
impl SystemRunner {
/// Starts event loop and will return once [System] is [stopped](System::stop).
pub fn run(self) -> io::Result<()> {
unimplemented!("SystemRunner::run is not implemented for io-uring feature yet");
}
/// 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");
}
/// Runs the provided future, blocking the current thread until the future completes.
#[inline]
pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
tokio_uring::start(async move {
let (stop_tx, stop_rx) = oneshot::channel();
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
let sys_arbiter = Arbiter::in_new_system();
let system = System::construct(sys_tx, sys_arbiter.clone());
system
.tx()
.send(SystemCommand::RegisterArbiter(usize::MAX, sys_arbiter))
.unwrap();
// init background system arbiter
let sys_ctrl = SystemController::new(sys_rx, stop_tx);
tokio_uring::spawn(sys_ctrl);
let res = fut.await;
drop(stop_rx);
res
})
}
}
#[derive(Debug)]
pub(crate) enum SystemCommand {
Exit(i32),
RegisterArbiter(usize, ArbiterHandle),
DeregisterArbiter(usize),
}
/// There is one `SystemController` per [System]. It runs in the background, keeping track of
/// [Arbiter]s and is able to distribute a system-wide stop command.
#[derive(Debug)]
pub(crate) struct SystemController {
stop_tx: Option<oneshot::Sender<i32>>,
cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
arbiters: HashMap<usize, ArbiterHandle>,
}
impl SystemController {
pub(crate) fn new(
cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
stop_tx: oneshot::Sender<i32>,
) -> Self {
SystemController {
cmd_rx,
stop_tx: Some(stop_tx),
arbiters: HashMap::with_capacity(4),
}
}
}
impl Future for SystemController {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// process all items currently buffered in channel
loop {
match ready!(self.cmd_rx.poll_recv(cx)) {
// channel closed; no more messages can be received
None => return Poll::Ready(()),
// process system command
Some(cmd) => match cmd {
SystemCommand::Exit(code) => {
// stop all arbiters
for arb in self.arbiters.values() {
arb.stop();
}
// stop event loop
// will only fire once
if let Some(stop_tx) = self.stop_tx.take() {
let _ = stop_tx.send(code);
}
}
SystemCommand::RegisterArbiter(id, arb) => {
self.arbiters.insert(id, arb);
}
SystemCommand::DeregisterArbiter(id) => {
self.arbiters.remove(&id);
}
},
}
}
} }
} }

View File

@ -0,0 +1,17 @@
//! Checks that test macro does not cause problems in the presence of imports named "test" that
//! could be either a module with test items or the "test with runtime" macro itself.
//!
//! Before actix/actix-net#399 was implemented, this macro was running twice. The first run output
//! `#[test]` and it got run again and since it was in scope.
//!
//! Prevented by using the fully-qualified test marker (`#[::core::prelude::v1::test]`).
#![cfg(feature = "macros")]
use actix_rt::time as test;
#[actix_rt::test]
async fn test_naming_conflict() {
use test as time;
time::sleep(std::time::Duration::from_millis(2)).await;
}

378
actix-rt/tests/tests.rs Normal file
View File

@ -0,0 +1,378 @@
#![allow(missing_docs)]
use std::{
future::Future,
time::{Duration, Instant},
};
use actix_rt::{task::JoinError, Arbiter, System};
#[cfg(not(feature = "io-uring"))]
use {
std::{sync::mpsc::channel, thread},
tokio::sync::oneshot,
};
#[test]
fn await_for_timer() {
let time = Duration::from_secs(1);
let instant = Instant::now();
System::new().block_on(async move {
tokio::time::sleep(time).await;
});
assert!(
instant.elapsed() >= time,
"Block on should poll awaited future to completion"
);
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn run_with_code() {
let sys = System::new();
System::current().stop_with_code(42);
let exit_code = sys.run_with_code().expect("system stop should not error");
assert_eq!(exit_code, 42);
}
#[test]
fn join_another_arbiter() {
let time = Duration::from_secs(1);
let instant = Instant::now();
System::new().block_on(async move {
let arbiter = Arbiter::new();
arbiter.spawn(Box::pin(async move {
tokio::time::sleep(time).await;
Arbiter::current().stop();
}));
arbiter.join().unwrap();
});
assert!(
instant.elapsed() >= time,
"Join on another arbiter should complete only when it calls stop"
);
let instant = Instant::now();
System::new().block_on(async move {
let arbiter = Arbiter::new();
arbiter.spawn_fn(move || {
actix_rt::spawn(async move {
tokio::time::sleep(time).await;
Arbiter::current().stop();
});
});
arbiter.join().unwrap();
});
assert!(
instant.elapsed() >= time,
"Join on an arbiter that has used actix_rt::spawn should wait for said future"
);
let instant = Instant::now();
System::new().block_on(async move {
let arbiter = Arbiter::new();
arbiter.spawn(Box::pin(async move {
tokio::time::sleep(time).await;
Arbiter::current().stop();
}));
arbiter.stop();
arbiter.join().unwrap();
});
assert!(
instant.elapsed() < time,
"Premature stop of arbiter should conclude regardless of it's current state"
);
}
#[test]
fn non_static_block_on() {
let string = String::from("test_str");
let string = string.as_str();
let sys = System::new();
sys.block_on(async {
actix_rt::time::sleep(Duration::from_millis(1)).await;
assert_eq!("test_str", string);
});
let rt = actix_rt::Runtime::new().unwrap();
rt.block_on(async {
actix_rt::time::sleep(Duration::from_millis(1)).await;
assert_eq!("test_str", string);
});
}
#[test]
fn wait_for_spawns() {
let rt = actix_rt::Runtime::new().unwrap();
let handle = rt.spawn(async {
println!("running on the runtime");
// panic is caught at task boundary
panic!("intentional test panic");
});
assert!(rt.block_on(handle).is_err());
}
// Temporary disabled tests for io-uring feature.
// They should be enabled when possible.
#[cfg(not(feature = "io-uring"))]
#[test]
fn arbiter_spawn_fn_runs() {
let _ = System::new();
let (tx, rx) = channel::<u32>();
let arbiter = Arbiter::new();
arbiter.spawn_fn(move || tx.send(42).unwrap());
let num = rx.recv().unwrap();
assert_eq!(num, 42);
arbiter.stop();
arbiter.join().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn arbiter_handle_spawn_fn_runs() {
let sys = System::new();
let (tx, rx) = channel::<u32>();
let arbiter = Arbiter::new();
let handle = arbiter.handle();
drop(arbiter);
handle.spawn_fn(move || {
tx.send(42).unwrap();
System::current().stop()
});
let num = rx.recv_timeout(Duration::from_secs(2)).unwrap();
assert_eq!(num, 42);
handle.stop();
sys.run().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn arbiter_drop_no_panic_fn() {
let _ = System::new();
let arbiter = Arbiter::new();
arbiter.spawn_fn(|| panic!("test"));
arbiter.stop();
arbiter.join().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn arbiter_drop_no_panic_fut() {
let _ = System::new();
let arbiter = Arbiter::new();
arbiter.spawn(async { panic!("test") });
arbiter.stop();
arbiter.join().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn system_arbiter_spawn() {
let runner = System::new();
let (tx, rx) = oneshot::channel();
let sys = System::current();
thread::spawn(|| {
// this thread will have no arbiter in it's thread local so call will panic
Arbiter::current();
})
.join()
.unwrap_err();
let thread = thread::spawn(|| {
// this thread will have no arbiter in it's thread local so use the system handle instead
System::set_current(sys);
let sys = System::current();
let arb = sys.arbiter();
arb.spawn(async move {
tx.send(42u32).unwrap();
System::current().stop();
});
});
assert_eq!(runner.block_on(rx).unwrap(), 42);
thread.join().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn system_stop_stops_arbiters() {
let sys = System::new();
let arb = Arbiter::new();
// arbiter should be alive to receive spawn msg
assert!(Arbiter::current().spawn_fn(|| {}));
assert!(arb.spawn_fn(|| {}));
System::current().stop();
sys.run().unwrap();
// account for slightly slow thread de-spawns
thread::sleep(Duration::from_millis(500));
// arbiter should be dead and return false
assert!(!Arbiter::current().spawn_fn(|| {}));
assert!(!arb.spawn_fn(|| {}));
arb.join().unwrap();
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn new_system_with_tokio() {
let (tx, rx) = channel();
let res = System::with_tokio_rt(move || {
tokio::runtime::Builder::new_multi_thread()
.enable_io()
.enable_time()
.thread_keep_alive(Duration::from_millis(1000))
.worker_threads(2)
.max_blocking_threads(2)
.on_thread_start(|| {})
.on_thread_stop(|| {})
.build()
.unwrap()
})
.block_on(async {
actix_rt::time::sleep(Duration::from_millis(1)).await;
tokio::task::spawn(async move {
tx.send(42).unwrap();
})
.await
.unwrap();
123usize
});
assert_eq!(res, 123);
assert_eq!(rx.recv().unwrap(), 42);
}
#[cfg(not(feature = "io-uring"))]
#[test]
fn new_arbiter_with_tokio() {
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
let _ = System::new();
let arb = Arbiter::with_tokio_rt(|| {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
});
let counter = Arc::new(AtomicBool::new(true));
let counter1 = counter.clone();
let did_spawn = arb.spawn(async move {
actix_rt::time::sleep(Duration::from_millis(1)).await;
counter1.store(false, Ordering::SeqCst);
Arbiter::current().stop();
});
assert!(did_spawn);
arb.join().unwrap();
assert!(!counter.load(Ordering::SeqCst));
}
#[test]
#[should_panic]
fn no_system_current_panic() {
System::current();
}
#[test]
#[should_panic]
fn no_system_arbiter_new_panic() {
Arbiter::new();
}
#[test]
fn try_current_no_system() {
assert!(System::try_current().is_none())
}
#[test]
fn try_current_with_system() {
System::new().block_on(async { assert!(System::try_current().is_some()) });
}
#[allow(clippy::unit_cmp)]
#[test]
fn spawn_local() {
System::new().block_on(async {
// demonstrate that spawn -> R is strictly more capable than spawn -> ()
assert_eq!(actix_rt::spawn(async {}).await.unwrap(), ());
assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
assert!(actix_rt::spawn(async { panic!("") }).await.is_err());
actix_rt::spawn(async { tokio::time::sleep(Duration::from_millis(50)).await })
.await
.unwrap();
fn g<F: Future<Output = Result<(), JoinError>>>(_f: F) {}
g(actix_rt::spawn(async {}));
// g(actix_rt::spawn(async { 1 })); // compile err
fn h<F: Future<Output = Result<R, JoinError>>, R>(_f: F) {}
h(actix_rt::spawn(async {}));
h(actix_rt::spawn(async { 1 }));
})
}
#[cfg(all(target_os = "linux", feature = "io-uring"))]
#[test]
fn tokio_uring_arbiter() {
System::new().block_on(async {
let (tx, rx) = std::sync::mpsc::channel();
Arbiter::new().spawn(async move {
let handle = actix_rt::spawn(async move {
let f = tokio_uring::fs::File::create("test.txt").await.unwrap();
let buf = b"Hello World!";
let (res, _) = f.write_all_at(&buf[..], 0).await;
assert!(res.is_ok());
f.sync_all().await.unwrap();
f.close().await.unwrap();
std::fs::remove_file("test.txt").unwrap();
});
handle.await.unwrap();
tx.send(true).unwrap();
});
assert!(rx.recv().unwrap());
})
}

View File

@ -1,52 +1,232 @@
# Changes # Changes
## [0.3.0] - 2019-03-02 ## Unreleased
### Changed ## 2.5.1
* Use new `NewService` trait - Fix panic in test server.
- Minimum supported Rust version (MSRV) is now 1.71.
## 2.5.0
## [0.2.1] - 2019-02-09 - Update `mio` dependency to `1`.
### Changed ## 2.4.0
* Drop service response - Update `tokio-uring` dependency to `0.5`.
- Minimum supported Rust version (MSRV) is now 1.70.
## 2.3.0
## [0.2.0] - 2019-02-01 - Add support for MultiPath TCP (MPTCP) with `MpTcp` enum and `ServerBuilder::mptcp()` method.
- Minimum supported Rust version (MSRV) is now 1.65.
### Changed ## 2.2.0
* Migrate to actix-service 0.2 - Minimum supported Rust version (MSRV) is now 1.59.
- Update `tokio-uring` dependency to `0.4`.
* Updated rustls dependency ## 2.1.1
- No significant changes since `2.1.0`.
## [0.1.3] - 2018-12-21 ## 2.1.0
### Fixed - 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.
* Fix max concurrent connections handling ## 2.0.0
- No significant changes since `2.0.0-rc.4`.
## [0.1.2] - 2018-12-12 ## 2.0.0-rc.4
### Changed - Update `tokio-uring` dependency to `0.2`.
* rename ServiceConfig::rt() to ServiceConfig::apply() ## 2.0.0-rc.3
- No significant changes since `2.0.0-rc.2`.
### Fixed ## 2.0.0-rc.2
* Fix back-pressure for concurrent ssl handshakes - Simplify `TestServer`.
## 2.0.0-rc.1
## [0.1.1] - 2018-12-11 - Hide implementation details of `Server`.
- `Server` now runs only after awaiting it.
* Fix signal handling on windows ## 2.0.0-beta.9
- Restore `Arbiter` support lost in `beta.8`.
## [0.1.0] - 2018-12-09 ## 2.0.0-beta.8
* Move server to separate crate - Fix non-unix signal handler.
## 2.0.0-beta.7
- 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.
## 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.5
- 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
- Prevent panic when `shutdown_timeout` is very large. [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.2
- Merge `actix-testing` to `actix-server` as `test_server` mod.
## 2.0.0-beta.1
- 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.
## 1.0.4
- Update actix-codec to 0.3.0.
- Workers must be greater than 0.
## 1.0.3
- Replace deprecated `net2` crate with `socket2`.
## 1.0.2
- Avoid error by calling `reregister()` on Windows.
## 1.0.1
- Rename `.start()` method to `.run()`
## 1.0.0
- Use actix-net releases
## 1.0.0-alpha.4
- Use actix-service 1.0.0-alpha.4
## 1.0.0-alpha.3
- Migrate to tokio 0.2
- Fix compilation on non-unix platforms
- Better handling server configuration
## 1.0.0-alpha.2
- Simplify server service (remove actix-server-config)
- Allow to wait on `Server` until server stops
## 0.8.0-alpha.1
- Migrate to `std::future`
## 0.7.0
- Update `rustls` to 0.16
- Minimum required Rust version upped to 1.37.0
## 0.6.1
- Add UDS listening support to `ServerBuilder`
## 0.6.0
- Support Unix domain sockets #3
## 0.5.1
- ServerBuilder::shutdown_timeout() accepts u64
## 0.5.0
- Add `Debug` impl for `SslError`
- Derive debug for `Server` and `ServerCommand`
- Upgrade to actix-service 0.4
## 0.4.3
- Re-export `IoStream` trait
- Depend on `ssl` and `rust-tls` features from actix-server-config
## 0.4.2
- Fix SIGINT force shutdown
## 0.4.1
- `SystemRuntime::on_start()` - allow to run future before server service initialization
## 0.4.0
- Use `ServerConfig` for service factory
- Wrap tcp socket to `Io` type
- Upgrade actix-service
## 0.3.1
- Add `ServerBuilder::maxconnrate` sets the maximum per-worker number of concurrent connections
- Add helper ssl error `SslError`
- Rename `StreamServiceFactory` to `ServiceFactory`
- Deprecate `StreamServiceFactory`
## 0.3.0
- Use new `NewService` trait
## 0.2.1
- Drop service response
## 0.2.0
- Migrate to actix-service 0.2
- Updated rustls dependency
## 0.1.3
- Fix max concurrent connections handling
## 0.1.2
- rename ServiceConfig::rt() to ServiceConfig::apply()
- Fix back-pressure for concurrent ssl handshakes
## 0.1.1
- Fix signal handling on windows
## 0.1.0
- Move server to separate crate

View File

@ -1,67 +1,50 @@
[package] [package]
name = "actix-server" name = "actix-server"
version = "0.3.0" version = "2.5.1"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = [
description = "Actix server - General purpose tcp server" "Nikolay Kim <fafhrd91@gmail.com>",
keywords = ["network", "framework", "async", "futures"] "Rob Ede <robjtede@icloud.com>",
homepage = "https://actix.rs" "Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
repository = "https://github.com/actix/actix-net.git" ]
documentation = "https://docs.rs/actix-server/" description = "General purpose TCP server built for the Actix ecosystem"
keywords = ["network", "tcp", "server", "framework", "async"]
categories = ["network-programming", "asynchronous"] categories = ["network-programming", "asynchronous"]
license = "MIT/Apache-2.0" homepage = "https://actix.rs"
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] repository = "https://github.com/actix/actix-net/tree/master/actix-server"
edition = "2018" license = "MIT OR Apache-2.0"
workspace = ".." edition.workspace = true
rust-version.workspace = true
[package.metadata.docs.rs] [package.metadata.cargo_check_external_types]
features = ["ssl", "tls", "rust-tls"] allowed_external_types = ["tokio::*"]
[lib]
name = "actix_server"
path = "src/lib.rs"
[features] [features]
default = [] default = []
io-uring = ["tokio-uring", "actix-rt/io-uring"]
# tls
tls = ["native-tls"]
# openssl
ssl = ["openssl", "tokio-openssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]
[dependencies] [dependencies]
actix-service = "0.3.0" actix-rt = { version = "2.10", default-features = false }
actix-rt = "0.1.0" actix-service = "2"
actix-utils = "3"
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
mio = { version = "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"] }
log = "0.4" # runtime for `io-uring` feature
num_cpus = "1.0" [target.'cfg(target_os = "linux")'.dependencies]
tokio-uring = { version = "0.5", optional = true }
mio = "^0.6.13"
net2 = "0.2"
futures = "0.1"
slab = "0.4"
tokio-io = "0.1"
tokio-tcp = "0.1"
tokio-timer = "0.2.8"
tokio-reactor = "0.1"
tokio-signal = "0.2"
# native-tls
native-tls = { version="0.2", optional = true }
# openssl
openssl = { version="0.10", optional = true }
tokio-openssl = { version="0.3", optional = true }
#rustls
rustls = { version = "^0.15", optional = true }
tokio-rustls = { version = "^0.9", optional = true }
webpki = { version = "0.19", optional = true }
webpki-roots = { version = "0.16", optional = true }
[dev-dependencies] [dev-dependencies]
env_logger = "0.6" actix-codec = "0.5"
actix-codec = "0.1.0" actix-rt = "2.8"
bytes = "1"
futures-util = { version = "0.3.17", default-features = false, features = ["sink", "async-await-macro"] }
pretty_env_logger = "0.5"
tokio = { version = "1.23.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
[lints]
workspace = true

1
actix-server/LICENSE-APACHE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-APACHE

1
actix-server/LICENSE-MIT Symbolic link
View File

@ -0,0 +1 @@
../LICENSE-MIT

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.1)](https://docs.rs/actix-server/2.5.1)
[![Version](https://img.shields.io/badge/rustc-1.52+-ab6000.svg)](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-server.svg)
<br />
[![Dependency Status](https://deps.rs/crate/actix-server/2.5.1/status.svg)](https://deps.rs/crate/actix-server/2.5.1)
![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

@ -0,0 +1,98 @@
//! Simple file-reader TCP server with framed stream.
//!
//! Using the following command:
//!
//! ```sh
//! nc 127.0.0.1 8080
//! ```
//!
//! Follow the prompt and enter a file path, relative or absolute.
#![allow(missing_docs)]
use std::io;
use actix_codec::{Framed, LinesCodec};
use actix_rt::net::TcpStream;
use actix_server::Server;
use actix_service::{fn_service, ServiceFactoryExt as _};
use futures_util::{SinkExt as _, StreamExt as _};
use tokio::{fs::File, io::AsyncReadExt as _};
async fn run() -> io::Result<()> {
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);
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
// a service *factory*; so it can be created once per worker.
Server::build()
.bind("file-reader", addr, move || {
fn_service(move |stream: TcpStream| async move {
// set up codec to use with I/O resource
let mut framed = Framed::new(stream, LinesCodec::default());
loop {
// prompt for file name
framed.send("Type file name to return:").await?;
// wait for next line
match framed.next().await {
Some(Ok(line)) => {
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?;
// send String into framed object
framed.send(buf).await?;
// break out of loop and
break;
}
Err(err) => {
tracing::error!("{}", err);
framed
.send("File not found or not readable. Try again.")
.await?;
continue;
}
};
}
// not being able to read a line from the stream is unrecoverable
Some(Err(err)) => return Err(err),
// This EOF won't be hit.
None => continue,
}
}
// close connection after file has been copied to TCP stream
Ok(())
})
.map_err(|err| tracing::error!("service error: {:?}", err))
})?
.workers(2)
.run()
.await
}
#[tokio::main]
async fn main() -> io::Result<()> {
run().await?;
Ok(())
}
// alternatively:
// #[actix_rt::main]
// async fn main() -> io::Result<()> {
// run().await?;
// Ok(())
// }

View File

@ -0,0 +1,101 @@
//! Simple composite-service TCP echo server.
//!
//! Using the following command:
//!
//! ```sh
//! nc 127.0.0.1 8080
//! ```
//!
//! Start typing. When you press enter the typed line will be echoed back. The server will log
//! the length of each line it echos and the total size of data sent when the connection is closed.
use std::{
io,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
};
use actix_rt::net::TcpStream;
use actix_server::Server;
use actix_service::{fn_service, ServiceFactoryExt as _};
use bytes::BytesMut;
use futures_util::future::ok;
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
async fn run() -> io::Result<()> {
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);
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
// a service *factory*; so it can be created once per worker.
Server::build()
.bind("echo", addr, move || {
let count = Arc::clone(&count);
let num2 = Arc::clone(&count);
fn_service(move |mut stream: TcpStream| {
let count = Arc::clone(&count);
async move {
let num = count.fetch_add(1, Ordering::SeqCst);
let num = num + 1;
let mut size = 0;
let mut buf = BytesMut::new();
loop {
match stream.read_buf(&mut buf).await {
// end of stream; bail from loop
Ok(0) => break,
// more bytes to process
Ok(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) => {
tracing::error!("stream error: {:?}", err);
return Err(());
}
}
}
// send data down service pipeline
Ok((buf.freeze(), size))
}
})
.map_err(|err| tracing::error!("service error: {:?}", err))
.and_then(move |(_, size)| {
let num = num2.load(Ordering::SeqCst);
tracing::info!("[{}] total bytes read: {}", num, size);
ok(size)
})
})?
.workers(2)
.run()
.await
}
#[tokio::main]
async fn main() -> io::Result<()> {
run().await?;
Ok(())
}
// alternatively:
// #[actix_rt::main]
// async fn main() -> io::Result<()> {
// run().await?;
// Ok(())
// }

View File

@ -1,461 +1,462 @@
use std::sync::mpsc as sync_mpsc; use std::{io, thread, time::Duration};
use std::time::{Duration, Instant};
use std::{io, net, thread};
use actix_rt::System; use actix_rt::time::Instant;
use futures::future::{lazy, Future}; use mio::{Interest, Poll, Token as MioToken};
use log::{error, info}; use tracing::{debug, error, info};
use mio;
use slab::Slab;
use tokio_timer::Delay;
use super::server::Server; use crate::{
use super::worker::{Conn, WorkerClient}; availability::Availability,
use super::Token; socket::MioListener,
waker_queue::{WakerInterest, WakerQueue, WAKER_TOKEN},
worker::{Conn, ServerWorker, WorkerHandleAccept, WorkerHandleServer},
ServerBuilder, ServerHandle,
};
pub(crate) enum Command { const TIMEOUT_DURATION_ON_ERROR: Duration = Duration::from_millis(510);
Pause,
Resume,
Stop,
Worker(WorkerClient),
}
struct ServerSocketInfo { struct ServerSocketInfo {
addr: net::SocketAddr, token: usize,
token: Token,
sock: mio::net::TcpListener, lst: MioListener,
timeout: Option<Instant>,
/// Timeout is used to mark the deadline when this socket's listener should be registered again
/// after an error.
timeout: Option<actix_rt::time::Instant>,
} }
#[derive(Clone)] /// Poll instance of the server.
pub(crate) struct AcceptNotify(mio::SetReadiness); pub(crate) struct Accept {
poll: Poll,
impl AcceptNotify { waker_queue: WakerQueue,
pub(crate) fn new(ready: mio::SetReadiness) -> Self { handles: Vec<WorkerHandleAccept>,
AcceptNotify(ready) srv: ServerHandle,
}
pub(crate) fn notify(&self) {
let _ = self.0.set_readiness(mio::Ready::readable());
}
}
impl Default for AcceptNotify {
fn default() -> Self {
AcceptNotify::new(mio::Registration::new2().1)
}
}
pub(crate) struct AcceptLoop {
cmd_reg: Option<mio::Registration>,
cmd_ready: mio::SetReadiness,
notify_reg: Option<mio::Registration>,
notify_ready: mio::SetReadiness,
tx: sync_mpsc::Sender<Command>,
rx: Option<sync_mpsc::Receiver<Command>>,
srv: Option<Server>,
}
impl AcceptLoop {
pub fn new(srv: Server) -> AcceptLoop {
let (tx, rx) = sync_mpsc::channel();
let (cmd_reg, cmd_ready) = mio::Registration::new2();
let (notify_reg, notify_ready) = mio::Registration::new2();
AcceptLoop {
tx,
cmd_ready,
cmd_reg: Some(cmd_reg),
notify_ready,
notify_reg: Some(notify_reg),
rx: Some(rx),
srv: Some(srv),
}
}
pub fn send(&self, msg: Command) {
let _ = self.tx.send(msg);
let _ = self.cmd_ready.set_readiness(mio::Ready::readable());
}
pub fn get_notify(&self) -> AcceptNotify {
AcceptNotify::new(self.notify_ready.clone())
}
pub(crate) fn start(
&mut self,
socks: Vec<(Token, net::TcpListener)>,
workers: Vec<WorkerClient>,
) {
let srv = self.srv.take().expect("Can not re-use AcceptInfo");
Accept::start(
self.rx.take().expect("Can not re-use AcceptInfo"),
self.cmd_reg.take().expect("Can not re-use AcceptInfo"),
self.notify_reg.take().expect("Can not re-use AcceptInfo"),
socks,
srv,
workers,
);
}
}
struct Accept {
poll: mio::Poll,
rx: sync_mpsc::Receiver<Command>,
sockets: Slab<ServerSocketInfo>,
workers: Vec<WorkerClient>,
srv: Server,
timer: (mio::Registration, mio::SetReadiness),
next: usize, next: usize,
backpressure: bool, avail: Availability,
} /// use the smallest duration from sockets timeout.
timeout: Option<Duration>,
const DELTA: usize = 100; paused: bool,
const CMD: mio::Token = mio::Token(0);
const TIMER: mio::Token = mio::Token(1);
const NOTIFY: mio::Token = mio::Token(2);
/// This function defines errors that are per-connection. Which basically
/// means that if we get this error from `accept()` system call it means
/// next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` is performed.
/// The timeout is useful to handle resource exhaustion errors like ENFILE
/// and EMFILE. Otherwise, could enter into tight loop.
fn connection_error(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::ConnectionRefused
|| e.kind() == io::ErrorKind::ConnectionAborted
|| e.kind() == io::ErrorKind::ConnectionReset
} }
impl Accept { impl Accept {
#![allow(clippy::too_many_arguments)]
pub(crate) fn start( pub(crate) fn start(
rx: sync_mpsc::Receiver<Command>, sockets: Vec<(usize, MioListener)>,
cmd_reg: mio::Registration, builder: &ServerBuilder,
notify_reg: mio::Registration, ) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>, thread::JoinHandle<()>)> {
socks: Vec<(Token, net::TcpListener)>, let handle_server = ServerHandle::new(builder.cmd_tx.clone());
srv: Server,
workers: Vec<WorkerClient>,
) {
let sys = System::current();
// start accept thread // construct poll instance and its waker
let _ = thread::Builder::new() let poll = Poll::new()?;
.name("actix-server accept loop".to_owned()) let waker_queue = WakerQueue::new(poll.registry())?;
.spawn(move || {
System::set_current(sys);
let mut accept = Accept::new(rx, socks, workers, srv);
// Start listening for incoming commands // start workers and collect handles
if let Err(err) = accept.poll.register( let (handles_accept, handles_server) = (0..builder.threads)
&cmd_reg, .map(|idx| {
CMD, // clone service factories
mio::Ready::readable(), let factories = builder
mio::PollOpt::edge(), .factories
) { .iter()
panic!("Can not register Registration: {}", err); .map(|f| f.clone_factory())
} .collect::<Vec<_>>();
// Start listening for notify updates // start worker using service factories
if let Err(err) = accept.poll.register( ServerWorker::start(idx, factories, waker_queue.clone(), builder.worker_config)
&notify_reg, })
NOTIFY, .collect::<io::Result<Vec<_>>>()?
mio::Ready::readable(), .into_iter()
mio::PollOpt::edge(), .unzip();
) {
panic!("Can not register Registration: {}", err);
}
accept.poll(); let (mut accept, mut sockets) = Accept::new_with_sockets(
}); poll,
waker_queue.clone(),
sockets,
handles_accept,
handle_server,
)?;
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, accept_handle))
} }
fn new( fn new_with_sockets(
rx: sync_mpsc::Receiver<Command>, poll: Poll,
socks: Vec<(Token, net::TcpListener)>, waker_queue: WakerQueue,
workers: Vec<WorkerClient>, sockets: Vec<(usize, MioListener)>,
srv: Server, accept_handles: Vec<WorkerHandleAccept>,
) -> Accept { server_handle: ServerHandle,
// Create a poll instance ) -> io::Result<(Accept, Box<[ServerSocketInfo]>)> {
let poll = match mio::Poll::new() { let sockets = sockets
Ok(poll) => poll, .into_iter()
Err(err) => panic!("Can not create mio::Poll: {}", err), .map(|(token, mut lst)| {
// Start listening for incoming connections
poll.registry()
.register(&mut lst, MioToken(token), Interest::READABLE)?;
Ok(ServerSocketInfo {
token,
lst,
timeout: None,
})
})
.collect::<io::Result<_>>()?;
let mut avail = Availability::default();
// Assume all handles are avail at construct time.
avail.set_available_all(&accept_handles);
let accept = Accept {
poll,
waker_queue,
handles: accept_handles,
srv: server_handle,
next: 0,
avail,
timeout: None,
paused: false,
}; };
// Start accept Ok((accept, sockets))
let mut sockets = Slab::new();
for (hnd_token, lst) in socks.into_iter() {
let addr = lst.local_addr().unwrap();
let server = mio::net::TcpListener::from_std(lst)
.expect("Can not create mio::net::TcpListener");
let entry = sockets.vacant_entry();
let token = entry.key();
// Start listening for incoming connections
if let Err(err) = poll.register(
&server,
mio::Token(token + DELTA),
mio::Ready::readable(),
mio::PollOpt::edge(),
) {
panic!("Can not register io: {}", err);
}
entry.insert(ServerSocketInfo {
addr,
token: hnd_token,
sock: server,
timeout: None,
});
}
// Timer
let (tm, tmr) = mio::Registration::new2();
if let Err(err) =
poll.register(&tm, TIMER, mio::Ready::readable(), mio::PollOpt::edge())
{
panic!("Can not register Registration: {}", err);
}
Accept {
poll,
rx,
sockets,
workers,
srv,
next: 0,
timer: (tm, tmr),
backpressure: false,
}
} }
fn poll(&mut self) { /// blocking wait for readiness events triggered by mio
// Create storage for events fn poll_with(&mut self, sockets: &mut [ServerSocketInfo]) {
let mut events = mio::Events::with_capacity(128); let mut events = mio::Events::with_capacity(256);
loop { loop {
if let Err(err) = self.poll.poll(&mut events, None) { if let Err(err) = self.poll.poll(&mut events, self.timeout) {
panic!("Poll error: {}", err); match err.kind() {
io::ErrorKind::Interrupted => {}
_ => panic!("Poll error: {}", err),
}
} }
for event in events.iter() { for event in events.iter() {
let token = event.token(); let token = event.token();
match token { match token {
CMD => { WAKER_TOKEN => {
if !self.process_cmd() { let exit = self.handle_waker(sockets);
if exit {
info!("accept thread stopped");
return; return;
} }
} }
TIMER => self.process_timer(),
NOTIFY => self.backpressure(false),
_ => { _ => {
let token = usize::from(token); let token = usize::from(token);
if token < DELTA { self.accept(sockets, token);
continue;
}
self.accept(token - DELTA);
} }
} }
} }
// check for timeout and re-register sockets
self.process_timeout(sockets);
} }
} }
fn process_timer(&mut self) { fn handle_waker(&mut self, sockets: &mut [ServerSocketInfo]) -> bool {
let now = Instant::now(); // This is a loop because interests for command from previous version was
for (token, info) in self.sockets.iter_mut() { // a loop that would try to drain the command channel. It's yet unknown
if let Some(inst) = info.timeout.take() { // if it's necessary/good practice to actively drain the waker queue.
if now > inst {
if let Err(err) = self.poll.register(
&info.sock,
mio::Token(token + DELTA),
mio::Ready::readable(),
mio::PollOpt::edge(),
) {
error!("Can not register server socket {}", err);
} else {
info!("Resume accepting connections on {}", info.addr);
}
} else {
info.timeout = Some(inst);
}
}
}
}
fn process_cmd(&mut self) -> bool {
loop { loop {
match self.rx.try_recv() { // Take guard with every iteration so no new interests can be added until the current
Ok(cmd) => match cmd { // task is done. Take care not to take the guard again inside this loop.
Command::Pause => { let mut guard = self.waker_queue.guard();
for (_, info) in self.sockets.iter_mut() {
if let Err(err) = self.poll.deregister(&info.sock) {
error!("Can not deregister server socket {}", err);
} else {
info!("Paused accepting connections on {}", info.addr);
}
}
}
Command::Resume => {
for (token, info) in self.sockets.iter() {
if let Err(err) = self.poll.register(
&info.sock,
mio::Token(token + DELTA),
mio::Ready::readable(),
mio::PollOpt::edge(),
) {
error!("Can not resume socket accept process: {}", err);
} else {
info!(
"Accepting connections on {} has been resumed",
info.addr
);
}
}
}
Command::Stop => {
for (_, info) in self.sockets.iter() {
let _ = self.poll.deregister(&info.sock);
}
return false;
}
Command::Worker(worker) => {
self.backpressure(false);
self.workers.push(worker);
}
},
Err(err) => match err {
sync_mpsc::TryRecvError::Empty => break,
sync_mpsc::TryRecvError::Disconnected => {
for (_, info) in self.sockets.iter() {
let _ = self.poll.deregister(&info.sock);
}
return false;
}
},
}
}
true
}
fn backpressure(&mut self, on: bool) { #[allow(clippy::significant_drop_in_scrutinee)]
if self.backpressure { match guard.pop_front() {
if !on { // Worker notified it became available.
self.backpressure = false; Some(WakerInterest::WorkerAvailable(idx)) => {
for (token, info) in self.sockets.iter() { drop(guard);
if let Err(err) = self.poll.register(
&info.sock, self.avail.set_available(idx, true);
mio::Token(token + DELTA),
mio::Ready::readable(), if !self.paused {
mio::PollOpt::edge(), self.accept_all(sockets);
) {
error!("Can not resume socket accept process: {}", err);
} else {
info!("Accepting connections on {} has been resumed", info.addr);
} }
} }
}
} else if on { // A new worker thread has been created so store its handle.
self.backpressure = true; Some(WakerInterest::Worker(handle)) => {
for (_, info) in self.sockets.iter() { drop(guard);
let _ = self.poll.deregister(&info.sock);
self.avail.set_available(handle.idx(), true);
self.handles.push(handle);
if !self.paused {
self.accept_all(sockets);
}
}
Some(WakerInterest::Pause) => {
drop(guard);
if !self.paused {
self.paused = true;
self.deregister_all(sockets);
}
}
Some(WakerInterest::Resume) => {
drop(guard);
if self.paused {
self.paused = false;
sockets.iter_mut().for_each(|info| {
self.register_logged(info);
});
self.accept_all(sockets);
}
}
Some(WakerInterest::Stop) => {
if !self.paused {
self.deregister_all(sockets);
}
return true;
}
// waker queue is drained
None => {
// Reset the WakerQueue before break so it does not grow infinitely
WakerQueue::reset(&mut guard);
return false;
}
} }
} }
} }
fn accept_one(&mut self, mut msg: Conn) { fn process_timeout(&mut self, sockets: &mut [ServerSocketInfo]) {
if self.backpressure { // always remove old timeouts
while !self.workers.is_empty() { if self.timeout.take().is_some() {
match self.workers[self.next].send(msg) { let now = Instant::now();
Ok(_) => (),
Err(tmp) => { sockets
self.srv.worker_died(self.workers[self.next].idx); .iter_mut()
msg = tmp; // Only sockets that had an associated timeout were deregistered.
self.workers.swap_remove(self.next); .filter(|info| info.timeout.is_some())
if self.workers.is_empty() { .for_each(|info| {
error!("No workers"); let inst = info.timeout.take().unwrap();
return;
} else if self.workers.len() <= self.next { if now < inst {
self.next = 0; // still timed out; try to set new timeout
} info.timeout = Some(inst);
continue; self.set_timeout(inst - now);
} else if !self.paused {
// timeout expired; register socket again
self.register_logged(info);
} }
}
self.next = (self.next + 1) % self.workers.len(); // Drop the timeout if server is paused and socket timeout is expired.
break; // When server recovers from pause it will register all sockets without
} // a timeout value so this socket register will be delayed till then.
} else { });
let mut idx = 0;
while idx < self.workers.len() {
idx += 1;
if self.workers[self.next].available() {
match self.workers[self.next].send(msg) {
Ok(_) => {
self.next = (self.next + 1) % self.workers.len();
return;
}
Err(tmp) => {
self.srv.worker_died(self.workers[self.next].idx);
msg = tmp;
self.workers.swap_remove(self.next);
if self.workers.is_empty() {
error!("No workers");
self.backpressure(true);
return;
} else if self.workers.len() <= self.next {
self.next = 0;
}
continue;
}
}
}
self.next = (self.next + 1) % self.workers.len();
}
// enable backpressure
self.backpressure(true);
self.accept_one(msg);
} }
} }
fn accept(&mut self, token: usize) { /// Update accept timeout with `duration` if it is shorter than current timeout.
fn set_timeout(&mut self, duration: Duration) {
match self.timeout {
Some(ref mut timeout) => {
if *timeout > duration {
*timeout = duration;
}
}
None => self.timeout = Some(duration),
}
}
#[cfg(not(target_os = "windows"))]
fn register(&self, info: &mut ServerSocketInfo) -> io::Result<()> {
let token = MioToken(info.token);
self.poll
.registry()
.register(&mut info.lst, token, Interest::READABLE)
}
#[cfg(target_os = "windows")]
fn register(&self, info: &mut ServerSocketInfo) -> io::Result<()> {
// On windows, calling register without deregister cause an error.
// See https://github.com/actix/actix-web/issues/905
// Calling reregister seems to fix the issue.
let token = MioToken(info.token);
self.poll
.registry()
.register(&mut info.lst, token, Interest::READABLE)
.or_else(|_| {
self.poll
.registry()
.reregister(&mut info.lst, token, Interest::READABLE)
})
}
fn register_logged(&self, info: &mut ServerSocketInfo) {
match self.register(info) {
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(err) => {
error!("can not deregister server socket {}", err)
}
}
}
fn deregister_all(&self, sockets: &mut [ServerSocketInfo]) {
// This is a best effort implementation with following limitation:
//
// Every ServerSocketInfo with associated timeout will be skipped and it's timeout is
// removed in the process.
//
// Therefore WakerInterest::Pause followed by WakerInterest::Resume in a very short gap
// (less than 500ms) would cause all timing out ServerSocketInfos be re-registered before
// expected timing.
sockets
.iter_mut()
// Take all timeout.
// This is to prevent Accept::process_timer method re-register a socket afterwards.
.map(|info| (info.timeout.take(), info))
// Socket info with a timeout is already deregistered so skip them.
.filter(|(timeout, _)| timeout.is_none())
.for_each(|(_, info)| self.deregister_logged(info));
}
// Send connection to worker and handle error.
fn send_connection(&mut self, conn: Conn) -> Result<(), Conn> {
let next = self.next();
match next.send(conn) {
Ok(_) => {
// Increment counter of WorkerHandle.
// Set worker to unavailable with it hit max (Return false).
if !next.inc_counter() {
let idx = next.idx();
self.avail.set_available(idx, false);
}
self.set_next();
Ok(())
}
Err(conn) => {
// Worker thread is error and could be gone.
// Remove worker handle and notify `ServerBuilder`.
self.remove_next();
if self.handles.is_empty() {
error!("no workers");
// All workers are gone and Conn is nowhere to be sent.
// Treat this situation as Ok and drop Conn.
return Ok(());
} else if self.handles.len() <= self.next {
self.next = 0;
}
Err(conn)
}
}
}
fn accept_one(&mut self, mut conn: Conn) {
loop { loop {
let msg = if let Some(info) = self.sockets.get_mut(token) { let next = self.next();
match info.sock.accept_std() { let idx = next.idx();
Ok((io, addr)) => Conn {
io,
token: info.token,
peer: Some(addr),
},
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);
if let Err(err) = self.poll.deregister(&info.sock) {
error!("Can not deregister server socket {}", err);
}
// sleep after error if self.avail.get_available(idx) {
info.timeout = Some(Instant::now() + Duration::from_millis(500)); match self.send_connection(conn) {
Ok(_) => return,
let r = self.timer.1.clone(); Err(c) => conn = c,
System::current().arbiter().send(lazy(move || {
Delay::new(Instant::now() + Duration::from_millis(510))
.map_err(|_| ())
.and_then(move |_| {
let _ = r.set_readiness(mio::Ready::readable());
Ok(())
})
}));
return;
}
} }
} else { } else {
return; self.avail.set_available(idx, false);
}; self.set_next();
self.accept_one(msg); if !self.avail.available() {
while let Err(c) = self.send_connection(conn) {
conn = c;
}
return;
}
}
} }
} }
fn accept(&mut self, sockets: &mut [ServerSocketInfo], token: usize) {
while self.avail.available() {
let info = &mut sockets[token];
match info.lst.accept() {
Ok(io) => {
let conn = Conn { io, token };
self.accept_one(conn);
}
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);
// sleep after error. write the timeout to socket info as later
// the poll would need it mark which socket and when it's
// listener should be registered
info.timeout = Some(Instant::now() + Duration::from_millis(500));
self.set_timeout(TIMEOUT_DURATION_ON_ERROR);
return;
}
};
}
}
fn accept_all(&mut self, sockets: &mut [ServerSocketInfo]) {
sockets
.iter_mut()
.map(|info| info.token)
.collect::<Vec<_>>()
.into_iter()
.for_each(|idx| self.accept(sockets, idx))
}
#[inline(always)]
fn next(&self) -> &WorkerHandleAccept {
&self.handles[self.next]
}
/// Set next worker handle that would accept connection.
#[inline(always)]
fn set_next(&mut self) {
self.next = (self.next + 1) % self.handles.len();
}
/// Remove next worker handle that fail to accept connection.
fn remove_next(&mut self) {
let handle = self.handles.swap_remove(self.next);
let idx = handle.idx();
// A message is sent to `ServerBuilder` future to notify it a new worker
// should be made.
self.srv.worker_faulted(idx);
self.avail.set_available(idx, false);
}
}
/// This function defines errors that are per-connection; if we get this error from the `accept()`
/// system call it means the next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` call is attempted. The timeout is
/// useful to handle resource exhaustion errors like `ENFILE` and `EMFILE`. Otherwise, it could
/// enter into a temporary spin loop.
fn connection_error(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::ConnectionRefused
|| e.kind() == io::ErrorKind::ConnectionAborted
|| e.kind() == io::ErrorKind::ConnectionReset
} }

View File

@ -0,0 +1,121 @@
use crate::worker::WorkerHandleAccept;
/// Array of u128 with every bit as marker for a worker handle's availability.
#[derive(Debug, Default)]
pub(crate) struct Availability([u128; 4]);
impl Availability {
/// Check if any worker handle is available
#[inline(always)]
pub(crate) fn available(&self) -> bool {
self.0.iter().any(|a| *a != 0)
}
/// Check if worker handle is available by index
#[inline(always)]
pub(crate) fn get_available(&self, idx: usize) -> bool {
let (offset, idx) = Self::offset(idx);
self.0[offset] & (1 << idx as u128) != 0
}
/// Set worker handle available state by index.
pub(crate) fn set_available(&mut self, idx: usize, avail: bool) {
let (offset, idx) = Self::offset(idx);
let off = 1 << idx as u128;
if avail {
self.0[offset] |= off;
} else {
self.0[offset] &= !off
}
}
/// Set all worker handle to available state.
/// This would result in a re-check on all workers' availability.
pub(crate) fn set_available_all(&mut self, handles: &[WorkerHandleAccept]) {
handles.iter().for_each(|handle| {
self.set_available(handle.idx(), true);
})
}
/// Get offset and adjusted index of given worker handle index.
pub(crate) fn offset(idx: usize) -> (usize, usize) {
if idx < 128 {
(0, idx)
} else if idx < 128 * 2 {
(1, idx - 128)
} else if idx < 128 * 3 {
(2, idx - 128 * 2)
} else if idx < 128 * 4 {
(3, idx - 128 * 3)
} else {
panic!("Max WorkerHandle count is 512")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn single(aval: &mut Availability, idx: usize) {
aval.set_available(idx, true);
assert!(aval.available());
aval.set_available(idx, true);
aval.set_available(idx, false);
assert!(!aval.available());
aval.set_available(idx, false);
assert!(!aval.available());
}
fn multi(aval: &mut Availability, mut idx: Vec<usize>) {
idx.iter().for_each(|idx| aval.set_available(*idx, true));
assert!(aval.available());
while let Some(idx) = idx.pop() {
assert!(aval.available());
aval.set_available(idx, false);
}
assert!(!aval.available());
}
#[test]
fn availability() {
let mut aval = Availability::default();
single(&mut aval, 1);
single(&mut aval, 128);
single(&mut aval, 256);
single(&mut aval, 511);
let idx = (0..511).filter(|i| i % 3 == 0 && i % 5 == 0).collect();
multi(&mut aval, idx);
multi(&mut aval, (0..511).collect())
}
#[test]
#[should_panic]
fn overflow() {
let mut aval = Availability::default();
single(&mut aval, 512);
}
#[test]
fn pin_point() {
let mut aval = Availability::default();
aval.set_available(438, true);
aval.set_available(479, true);
assert_eq!(aval.0[3], 1 << (438 - 384) | 1 << (479 - 384));
}
}

View File

@ -1,37 +1,47 @@
use std::time::Duration; use std::{io, num::NonZeroUsize, time::Duration};
use std::{io, mem, net};
use actix_rt::{spawn, Arbiter, System}; use actix_rt::net::TcpStream;
use futures::future::{lazy, ok}; use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
use futures::stream::futures_unordered;
use futures::sync::mpsc::{unbounded, UnboundedReceiver};
use futures::{Async, Future, Poll, Stream};
use log::{error, info};
use net2::TcpBuilder;
use num_cpus;
use tokio_timer::sleep;
use crate::accept::{AcceptLoop, AcceptNotify, Command}; use crate::{
use crate::config::{ConfiguredService, ServiceConfig}; server::ServerCommand,
use crate::server::{Server, ServerCommand}; service::{InternalServiceFactory, ServerServiceFactory, StreamNewService},
use crate::services::{InternalServiceFactory, StreamNewService, StreamServiceFactory}; socket::{create_mio_tcp_listener, MioListener, MioTcpListener, StdTcpListener, ToSocketAddrs},
use crate::signals::{Signal, Signals}; worker::ServerWorkerConfig,
use crate::worker::{self, Worker, WorkerAvailability, WorkerClient}; Server,
use crate::Token; };
/// Server builder /// 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 struct ServerBuilder {
threads: usize, pub(crate) threads: usize,
token: Token, pub(crate) token: usize,
workers: Vec<(usize, WorkerClient)>, pub(crate) backlog: u32,
services: Vec<Box<InternalServiceFactory>>, pub(crate) factories: Vec<Box<dyn InternalServiceFactory>>,
sockets: Vec<(Token, net::TcpListener)>, pub(crate) sockets: Vec<(usize, String, MioListener)>,
accept: AcceptLoop, pub(crate) mptcp: MpTcp,
exit: bool, pub(crate) exit: bool,
shutdown_timeout: Duration, pub(crate) listen_os_signals: bool,
no_signals: bool, pub(crate) cmd_tx: UnboundedSender<ServerCommand>,
cmd: UnboundedReceiver<ServerCommand>, pub(crate) cmd_rx: UnboundedReceiver<ServerCommand>,
server: Server, pub(crate) worker_config: ServerWorkerConfig,
} }
impl Default for ServerBuilder { impl Default for ServerBuilder {
@ -43,381 +53,326 @@ impl Default for ServerBuilder {
impl ServerBuilder { impl ServerBuilder {
/// Create new Server builder instance /// Create new Server builder instance
pub fn new() -> ServerBuilder { pub fn new() -> ServerBuilder {
let (tx, rx) = unbounded(); let (cmd_tx, cmd_rx) = unbounded_channel();
let server = Server::new(tx);
ServerBuilder { ServerBuilder {
threads: num_cpus::get(), threads: std::thread::available_parallelism().map_or(2, NonZeroUsize::get),
token: Token(0), token: 0,
workers: Vec::new(), factories: Vec::new(),
services: Vec::new(),
sockets: Vec::new(), sockets: Vec::new(),
accept: AcceptLoop::new(server.clone()), backlog: 2048,
mptcp: MpTcp::Disabled,
exit: false, exit: false,
shutdown_timeout: Duration::from_secs(30), listen_os_signals: true,
no_signals: false, cmd_tx,
cmd: rx, cmd_rx,
server, worker_config: ServerWorkerConfig::default(),
} }
} }
/// Set number of workers to start. /// Sets number of workers to start.
/// ///
/// By default server uses number of available logical cpu as workers /// See [`bind()`](Self::bind()) for more details on how worker count affects the number of
/// count. /// 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.
///
/// # Panics
///
/// Panics if `num` is 0.
pub fn workers(mut self, num: usize) -> Self { pub fn workers(mut self, num: usize) -> Self {
assert_ne!(num, 0, "workers must be greater than 0");
self.threads = num; self.threads = num;
self self
} }
/// Set max number of threads for each worker's blocking task thread pool.
///
/// One thread pool is set up **per worker**; not shared across workers.
///
/// # Examples:
/// ```
/// # use actix_server::ServerBuilder;
/// let builder = ServerBuilder::new()
/// .workers(4) // server has 4 worker thread.
/// .worker_max_blocking_threads(4); // every worker has 4 max blocking threads.
/// ```
///
/// See [tokio::runtime::Builder::max_blocking_threads] for behavior reference.
pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
self.worker_config.max_blocking_threads(num);
self
}
/// Set the maximum number of pending connections.
///
/// This refers to the number of clients that can be waiting to be served. Exceeding this number
/// results in the client getting an error when attempting to connect. It should only affect
/// servers under significant load.
///
/// Generally set in the 64-2048 range. Default value is 2048.
///
/// This method should be called before `bind()` method call.
pub fn backlog(mut self, num: u32) -> Self {
self.backlog = num;
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. /// Sets the maximum per-worker number of concurrent connections.
/// ///
/// All socket listeners will stop accepting connections when this limit is /// All socket listeners will stop accepting connections when this limit is reached for
/// reached for each worker. /// each worker.
/// ///
/// By default max connections is set to a 25k per worker. /// By default max connections is set to a 25k per worker.
pub fn maxconn(self, num: usize) -> Self { pub fn max_concurrent_connections(mut self, num: usize) -> Self {
worker::max_concurrent_connections(num); self.worker_config.max_concurrent_connections(num);
self self
} }
/// Stop actix system. #[doc(hidden)]
#[deprecated(since = "2.0.0", note = "Renamed to `max_concurrent_connections`.")]
pub fn maxconn(self, num: usize) -> Self {
self.max_concurrent_connections(num)
}
/// Sets flag to stop Actix `System` after server shutdown.
/// ///
/// `SystemExit` message stops currently running system. /// This has no effect when server is running in a Tokio-only runtime.
pub fn system_exit(mut self) -> Self { pub fn system_exit(mut self) -> Self {
self.exit = true; self.exit = true;
self self
} }
/// Disable signal handling /// Disables OS signal handling.
pub fn disable_signals(mut self) -> Self { pub fn disable_signals(mut self) -> Self {
self.no_signals = true; self.listen_os_signals = false;
self self
} }
/// Timeout for graceful workers shutdown in seconds. /// Timeout for graceful workers shutdown in seconds.
/// ///
/// After receiving a stop signal, workers have this much time to finish /// After receiving a stop signal, workers have this much time to finish serving requests.
/// serving requests. Workers still alive after the timeout are force /// Workers still alive after the timeout are force dropped.
/// dropped.
/// ///
/// By default shutdown timeout sets to 30 seconds. /// By default shutdown timeout sets to 30 seconds.
pub fn shutdown_timeout(mut self, sec: u16) -> Self { pub fn shutdown_timeout(mut self, sec: u64) -> Self {
self.shutdown_timeout = Duration::from_secs(u64::from(sec)); self.worker_config
.shutdown_timeout(Duration::from_secs(sec));
self self
} }
/// Execute external configuration as part of the server building /// Adds new service to the server.
/// process.
/// ///
/// This function is useful for moving parts of configuration to a /// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
/// different module or even library. ///
pub fn configure<F>(mut self, f: F) -> io::Result<ServerBuilder> /// # 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 where
F: Fn(&mut ServiceConfig) -> io::Result<()>, F: ServerServiceFactory<TcpStream>,
U: ToSocketAddrs,
N: AsRef<str>,
{ {
let mut cfg = ServiceConfig::new(self.threads); let sockets = bind_addr(addrs, self.backlog, &self.mptcp)?;
f(&mut cfg)?; tracing::trace!("binding server to: {sockets:?}");
if let Some(apply) = cfg.apply {
let mut srv = ConfiguredService::new(apply);
for (name, lst) in cfg.services {
let token = self.token.next();
srv.stream(token, name);
self.sockets.push((token, lst));
}
self.services.push(Box::new(srv));
}
self.threads = cfg.threads;
Ok(self)
}
/// Add new service to the server.
pub fn bind<F, U, N: AsRef<str>>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
where
F: StreamServiceFactory,
U: net::ToSocketAddrs,
{
let sockets = bind_addr(addr)?;
let token = self.token.next();
self.services.push(StreamNewService::create(
name.as_ref().to_string(),
token,
factory,
));
for lst in sockets { for lst in sockets {
self.sockets.push((token, lst)); 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)));
} }
Ok(self) 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>>( pub fn listen<F, N: AsRef<str>>(
mut self, mut self,
name: N, name: N,
lst: net::TcpListener, lst: StdTcpListener,
factory: F, factory: F,
) -> Self ) -> io::Result<Self>
where where
F: StreamServiceFactory, F: ServerServiceFactory<TcpStream>,
{ {
let token = self.token.next(); lst.set_nonblocking(true)?;
self.services.push(StreamNewService::create( let addr = lst.local_addr()?;
let token = self.next_token();
self.factories.push(StreamNewService::create(
name.as_ref().to_string(), name.as_ref().to_string(),
token, token,
factory, factory,
addr,
)); ));
self.sockets.push((token, lst));
self
}
/// Spawn new thread and start listening for incoming connections. self.sockets
/// .push((token, name.as_ref().to_string(), MioListener::from(lst)));
/// This method spawns new thread and starts new actix system. Other than
/// that it is similar to `start()` method. This method blocks. Ok(self)
///
/// This methods panics if no socket addresses get bound.
///
/// ```rust,ignore
/// use actix_web::*;
///
/// fn main() {
/// Server::new().
/// .service(
/// HttpServer::new(|| App::new().resource("/", |r| r.h(|_| HttpResponse::Ok())))
/// .bind("127.0.0.1:0")
/// .expect("Can not bind to 127.0.0.1:0"))
/// .run();
/// }
/// ```
pub fn run(self) {
let sys = System::new("http-server");
self.start();
sys.run();
} }
/// Starts processing incoming connections and return server controller. /// Starts processing incoming connections and return server controller.
pub fn start(mut self) -> Server { pub fn run(self) -> Server {
if self.sockets.is_empty() { if self.sockets.is_empty() {
panic!("Server should have at least one bound socket"); panic!("Server should have at least one bound socket");
} else { } else {
info!("Starting {} workers", self.threads); tracing::info!("starting {} workers", self.threads);
Server::new(self)
// start workers
let mut workers = Vec::new();
for idx in 0..self.threads {
let worker = self.start_worker(idx, self.accept.get_notify());
workers.push(worker.clone());
self.workers.push((idx, worker));
}
// start accept thread
for sock in &self.sockets {
info!("Starting server on {}", sock.1.local_addr().ok().unwrap());
}
self.accept
.start(mem::replace(&mut self.sockets, Vec::new()), workers);
// handle signals
if !self.no_signals {
Signals::start(self.server.clone());
}
// start http server actor
let server = self.server.clone();
spawn(self);
server
} }
} }
fn start_worker(&self, idx: usize, notify: AcceptNotify) -> WorkerClient { fn next_token(&mut self) -> usize {
let (tx1, rx1) = unbounded(); let token = self.token;
let (tx2, rx2) = unbounded(); self.token += 1;
let timeout = self.shutdown_timeout; token
let avail = WorkerAvailability::new(notify);
let worker = WorkerClient::new(idx, tx1, tx2, avail.clone());
let services: Vec<Box<InternalServiceFactory>> =
self.services.iter().map(|v| v.clone_factory()).collect();
Arbiter::new().send(lazy(move || {
Worker::start(rx1, rx2, services, avail, timeout);
Ok::<_, ()>(())
}));
worker
}
fn handle_cmd(&mut self, item: ServerCommand) {
match item {
ServerCommand::Pause(tx) => {
self.accept.send(Command::Pause);
let _ = tx.send(());
}
ServerCommand::Resume(tx) => {
self.accept.send(Command::Resume);
let _ = tx.send(());
}
ServerCommand::Signal(sig) => {
// Signals support
// Handle `SIGINT`, `SIGTERM`, `SIGQUIT` signals and stop actix system
match sig {
Signal::Int => {
info!("SIGINT received, exiting");
self.exit = true;
self.handle_cmd(ServerCommand::Stop {
graceful: false,
completion: None,
})
}
Signal::Term => {
info!("SIGTERM received, stopping");
self.exit = true;
self.handle_cmd(ServerCommand::Stop {
graceful: true,
completion: None,
})
}
Signal::Quit => {
info!("SIGQUIT received, exiting");
self.exit = true;
self.handle_cmd(ServerCommand::Stop {
graceful: false,
completion: None,
})
}
_ => (),
}
}
ServerCommand::Stop {
graceful,
completion,
} => {
let exit = self.exit;
// stop accept thread
self.accept.send(Command::Stop);
// stop workers
if !self.workers.is_empty() {
spawn(
futures_unordered(
self.workers
.iter()
.map(move |worker| worker.1.stop(graceful)),
)
.collect()
.then(move |_| {
if let Some(tx) = completion {
let _ = tx.send(());
}
if exit {
spawn(sleep(Duration::from_millis(300)).then(|_| {
System::current().stop();
ok(())
}));
}
ok(())
}),
)
} else {
// we need to stop system if server was spawned
if self.exit {
spawn(sleep(Duration::from_millis(300)).then(|_| {
System::current().stop();
ok(())
}));
}
if let Some(tx) = completion {
let _ = tx.send(());
}
}
}
ServerCommand::WorkerDied(idx) => {
let mut found = false;
for i in 0..self.workers.len() {
if self.workers[i].0 == idx {
self.workers.swap_remove(i);
found = true;
break;
}
}
if found {
error!("Worker has died {:?}, restarting", idx);
let mut new_idx = self.workers.len();
'found: loop {
for i in 0..self.workers.len() {
if self.workers[i].0 == new_idx {
new_idx += 1;
continue 'found;
}
}
break;
}
let worker = self.start_worker(new_idx, self.accept.get_notify());
self.workers.push((new_idx, worker.clone()));
self.accept.send(Command::Worker(worker));
}
}
}
} }
} }
impl Future for ServerBuilder { #[cfg(unix)]
type Item = (); impl ServerBuilder {
type Error = (); /// Adds new service to the server using a UDS (unix domain socket) address.
///
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { /// # Worker Count
loop { ///
match self.cmd.poll() { /// The `factory` will be instantiated multiple times in most scenarios. The number of
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())), /// instantiations is: number of [`workers`](Self::workers()).
Ok(Async::NotReady) => return Ok(Async::NotReady), pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
Ok(Async::Ready(Some(item))) => self.handle_cmd(item), where
F: ServerServiceFactory<actix_rt::net::UnixStream>,
N: AsRef<str>,
U: AsRef<std::path::Path>,
{
// The path must not exist when we try to bind.
// Try to remove it to avoid bind error.
if let Err(err) = std::fs::remove_file(addr.as_ref()) {
// NotFound is expected and not an issue. Anything else is.
if err.kind() != std::io::ErrorKind::NotFound {
return Err(err);
} }
} }
let lst = crate::socket::StdUnixListener::bind(addr)?;
self.listen_uds(name, lst, factory)
}
/// 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,
lst: crate::socket::StdUnixListener,
factory: F,
) -> io::Result<Self>
where
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);
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)
} }
} }
pub(super) fn bind_addr<S: net::ToSocketAddrs>(addr: S) -> io::Result<Vec<net::TcpListener>> { pub(super) fn bind_addr<S: ToSocketAddrs>(
let mut err = None; addr: S,
let mut succ = false; backlog: u32,
mptcp: &MpTcp,
) -> io::Result<Vec<MioTcpListener>> {
let mut opt_err = None;
let mut success = false;
let mut sockets = Vec::new(); let mut sockets = Vec::new();
for addr in addr.to_socket_addrs()? { for addr in addr.to_socket_addrs()? {
match create_tcp_listener(addr) { match create_mio_tcp_listener(addr, backlog, mptcp) {
Ok(lst) => { Ok(lst) => {
succ = true; success = true;
sockets.push(lst); sockets.push(lst);
} }
Err(e) => err = Some(e), Err(err) => opt_err = Some(err),
} }
} }
if !succ { if success {
if let Some(e) = err.take() {
Err(e)
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"Can not bind to address.",
))
}
} else {
Ok(sockets) Ok(sockets)
} else if let Some(err) = opt_err.take() {
Err(err)
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"Can not bind to address.",
))
} }
} }
fn create_tcp_listener(addr: net::SocketAddr) -> io::Result<net::TcpListener> {
let builder = match addr {
net::SocketAddr::V4(_) => TcpBuilder::new_v4()?,
net::SocketAddr::V6(_) => TcpBuilder::new_v6()?,
};
builder.reuse_address(true)?;
builder.bind(addr)?;
Ok(builder.listen(1024)?)
}

View File

@ -1,228 +0,0 @@
use std::collections::HashMap;
use std::{fmt, io, net};
use actix_service::{IntoNewService, NewService};
use futures::future::{join_all, Future};
use log::error;
use tokio_tcp::TcpStream;
use crate::counter::CounterGuard;
use super::builder::bind_addr;
use super::services::{
BoxedServerService, InternalServiceFactory, ServerMessage, StreamService,
};
use super::Token;
pub struct ServiceConfig {
pub(crate) services: Vec<(String, net::TcpListener)>,
pub(crate) apply: Option<Box<ServiceRuntimeConfiguration>>,
pub(crate) threads: usize,
}
impl ServiceConfig {
pub(super) fn new(threads: usize) -> ServiceConfig {
ServiceConfig {
threads,
services: Vec::new(),
apply: None,
}
}
/// Set number of workers to start.
///
/// By default server uses number of available logical cpu as workers
/// count.
pub fn workers(&mut self, num: usize) {
self.threads = num;
}
/// Add new service to server
pub fn bind<U, N: AsRef<str>>(&mut self, name: N, addr: U) -> io::Result<&mut Self>
where
U: net::ToSocketAddrs,
{
let sockets = bind_addr(addr)?;
for lst in sockets {
self.listen(name.as_ref(), lst);
}
Ok(self)
}
/// Add new service to server
pub fn listen<N: AsRef<str>>(&mut self, name: N, lst: net::TcpListener) -> &mut Self {
if self.apply.is_none() {
self.apply = Some(Box::new(not_configured));
}
self.services.push((name.as_ref().to_string(), lst));
self
}
/// Register service configuration function. This function get called
/// during worker runtime configuration. It get executed in worker thread.
pub fn apply<F>(&mut self, f: F) -> io::Result<()>
where
F: Fn(&mut ServiceRuntime) + Send + Clone + 'static,
{
self.apply = Some(Box::new(f));
Ok(())
}
}
pub(super) struct ConfiguredService {
rt: Box<ServiceRuntimeConfiguration>,
names: HashMap<Token, String>,
services: HashMap<String, Token>,
}
impl ConfiguredService {
pub(super) fn new(rt: Box<ServiceRuntimeConfiguration>) -> Self {
ConfiguredService {
rt,
names: HashMap::new(),
services: HashMap::new(),
}
}
pub(super) fn stream(&mut self, token: Token, name: String) {
self.names.insert(token, name.clone());
self.services.insert(name, token);
}
}
impl InternalServiceFactory for ConfiguredService {
fn name(&self, token: Token) -> &str {
&self.names[&token]
}
fn clone_factory(&self) -> Box<InternalServiceFactory> {
Box::new(Self {
rt: self.rt.clone(),
names: self.names.clone(),
services: self.services.clone(),
})
}
fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>> {
// configure services
let mut rt = ServiceRuntime::new(self.services.clone());
self.rt.configure(&mut rt);
rt.validate();
// construct services
let mut fut = Vec::new();
for (token, ns) in rt.services {
fut.push(ns.new_service(&()).map(move |service| (token, service)));
}
Box::new(join_all(fut).map_err(|e| {
error!("Can not construct service: {:?}", e);
}))
}
}
pub(super) trait ServiceRuntimeConfiguration: Send {
fn clone(&self) -> Box<ServiceRuntimeConfiguration>;
fn configure(&self, rt: &mut ServiceRuntime);
}
impl<F> ServiceRuntimeConfiguration for F
where
F: Fn(&mut ServiceRuntime) + Send + Clone + 'static,
{
fn clone(&self) -> Box<ServiceRuntimeConfiguration> {
Box::new(self.clone())
}
fn configure(&self, rt: &mut ServiceRuntime) {
(self)(rt)
}
}
fn not_configured(_: &mut ServiceRuntime) {
error!("Service is not configured");
}
pub struct ServiceRuntime {
names: HashMap<String, Token>,
services: HashMap<Token, BoxedNewService>,
}
impl ServiceRuntime {
fn new(names: HashMap<String, Token>) -> Self {
ServiceRuntime {
names,
services: HashMap::new(),
}
}
fn validate(&self) {
for (name, token) in &self.names {
if !self.services.contains_key(&token) {
error!("Service {:?} is not configured", name);
}
}
}
pub fn service<T, F>(&mut self, name: &str, service: F)
where
F: IntoNewService<T>,
T: NewService<Request = TcpStream, Response = ()> + 'static,
T::Future: 'static,
T::Service: 'static,
T::InitError: fmt::Debug,
{
// let name = name.to_owned();
if let Some(token) = self.names.get(name) {
self.services.insert(
token.clone(),
Box::new(ServiceFactory {
inner: service.into_new_service(),
}),
);
} else {
panic!("Unknown service: {:?}", name);
}
}
}
type BoxedNewService = Box<
NewService<
Request = (Option<CounterGuard>, ServerMessage),
Response = (),
Error = (),
InitError = (),
Service = BoxedServerService,
Future = Box<Future<Item = BoxedServerService, Error = ()>>,
>,
>;
struct ServiceFactory<T> {
inner: T,
}
impl<T> NewService for ServiceFactory<T>
where
T: NewService<Request = TcpStream, Response = ()>,
T::Future: 'static,
T::Service: 'static,
T::Error: 'static,
T::InitError: fmt::Debug + 'static,
{
type Request = (Option<CounterGuard>, ServerMessage);
type Response = ();
type Error = ();
type InitError = ();
type Service = BoxedServerService;
type Future = Box<Future<Item = BoxedServerService, Error = ()>>;
fn new_service(&self, _: &()) -> Self::Future {
Box::new(self.inner.new_service(&()).map_err(|_| ()).map(|s| {
let service: BoxedServerService = Box::new(StreamService::new(s));
service
}))
}
}

View File

@ -1,80 +0,0 @@
use std::cell::Cell;
use std::rc::Rc;
use futures::task::AtomicTask;
#[derive(Clone)]
/// Simple counter with ability to notify task on reaching specific number
///
/// Counter could be cloned, total ncount is shared across all clones.
pub struct Counter(Rc<CounterInner>);
#[derive(Debug)]
struct CounterInner {
count: Cell<usize>,
capacity: usize,
task: AtomicTask,
}
impl Counter {
/// Create `Counter` instance and set max value.
pub fn new(capacity: usize) -> Self {
Counter(Rc::new(CounterInner {
capacity,
count: Cell::new(0),
task: AtomicTask::new(),
}))
}
pub fn get(&self) -> CounterGuard {
CounterGuard::new(self.0.clone())
}
/// Check if counter is not at capacity
pub fn available(&self) -> bool {
self.0.available()
}
/// Get total number of acquired counts
pub fn total(&self) -> usize {
self.0.count.get()
}
}
#[derive(Debug)]
pub struct CounterGuard(Rc<CounterInner>);
impl CounterGuard {
fn new(inner: Rc<CounterInner>) -> Self {
inner.inc();
CounterGuard(inner)
}
}
impl Drop for CounterGuard {
fn drop(&mut self) {
self.0.dec();
}
}
impl CounterInner {
fn inc(&self) {
self.count.set(self.count.get() + 1);
}
fn dec(&self) {
let num = self.count.get();
self.count.set(num - 1);
if num == self.capacity {
self.task.notify();
}
}
fn available(&self) -> bool {
let avail = self.count.get() < self.capacity;
if !avail {
self.task.register();
}
avail
}
}

View File

@ -0,0 +1,56 @@
use std::future::Future;
use tokio::sync::{mpsc::UnboundedSender, oneshot};
use crate::server::ServerCommand;
/// Server handle.
#[derive(Debug, Clone)]
pub struct ServerHandle {
cmd_tx: UnboundedSender<ServerCommand>,
}
impl ServerHandle {
pub(crate) fn new(cmd_tx: UnboundedSender<ServerCommand>) -> Self {
ServerHandle { cmd_tx }
}
pub(crate) fn worker_faulted(&self, idx: usize) {
let _ = self.cmd_tx.send(ServerCommand::WorkerFaulted(idx));
}
/// Pause accepting incoming connections.
///
/// May drop socket pending connection. All open connections remain active.
pub fn pause(&self) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.cmd_tx.send(ServerCommand::Pause(tx));
async {
let _ = rx.await;
}
}
/// Resume accepting incoming connections.
pub fn resume(&self) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.cmd_tx.send(ServerCommand::Resume(tx));
async {
let _ = rx.await;
}
}
/// Stop incoming connection processing, stop all workers and exit.
pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.cmd_tx.send(ServerCommand::Stop {
graceful,
completion: Some(tx),
force_system_stop: false,
});
async {
let _ = rx.await;
}
}
}

View File

@ -0,0 +1,78 @@
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use futures_core::future::BoxFuture;
// a poor man's join future. joined future is only used when starting/stopping the server.
// pin_project and pinned futures are overkill for this task.
pub(crate) struct JoinAll<T> {
fut: Vec<JoinFuture<T>>,
}
pub(crate) fn join_all<T>(fut: Vec<impl Future<Output = T> + Send + 'static>) -> JoinAll<T> {
let fut = fut
.into_iter()
.map(|f| JoinFuture::Future(Box::pin(f)))
.collect();
JoinAll { fut }
}
enum JoinFuture<T> {
Future(BoxFuture<'static, T>),
Result(Option<T>),
}
impl<T> Unpin for JoinAll<T> {}
impl<T> Future for JoinAll<T> {
type Output = Vec<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut ready = true;
let this = self.get_mut();
for fut in this.fut.iter_mut() {
if let JoinFuture::Future(f) = fut {
match f.as_mut().poll(cx) {
Poll::Ready(t) => {
*fut = JoinFuture::Result(Some(t));
}
Poll::Pending => ready = false,
}
}
}
if ready {
let mut res = Vec::new();
for fut in this.fut.iter_mut() {
if let JoinFuture::Result(f) = fut {
res.push(f.take().unwrap());
}
}
Poll::Ready(res)
} else {
Poll::Pending
}
}
}
#[cfg(test)]
mod test {
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))];
let mut res = join_all(futs).await.into_iter();
assert_eq!(Ok(1), res.next().unwrap());
assert_eq!(Err(3), res.next().unwrap());
assert_eq!(Ok(9), res.next().unwrap());
}
}

View File

@ -1,33 +1,34 @@
//! General purpose tcp server //! General purpose TCP server.
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
mod accept; mod accept;
mod availability;
mod builder; mod builder;
mod config; mod handle;
mod counter; mod join_all;
mod server; mod server;
mod services; mod service;
mod signals; mod signals;
pub mod ssl; mod socket;
mod test_server;
mod waker_queue;
mod worker; mod worker;
pub use self::builder::ServerBuilder; #[doc(hidden)]
pub use self::config::{ServiceConfig, ServiceRuntime}; pub use self::socket::FromStream;
pub use self::server::Server; pub use self::{
pub use self::services::StreamServiceFactory; builder::{MpTcp, ServerBuilder},
handle::ServerHandle,
/// Socket id token server::Server,
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] service::ServerServiceFactory,
pub(crate) struct Token(usize); test_server::TestServer,
};
impl Token {
pub(crate) fn next(&mut self) -> Token {
let token = Token(self.0 + 1);
self.0 += 1;
token
}
}
/// Start server building process /// Start server building process
#[doc(hidden)]
#[deprecated(since = "2.0.0", note = "Use `Server::build()`.")]
pub fn new() -> ServerBuilder { pub fn new() -> ServerBuilder {
ServerBuilder::default() ServerBuilder::default()
} }

View File

@ -1,69 +1,368 @@
use futures::sync::mpsc::UnboundedSender; use std::{
use futures::sync::oneshot; future::Future,
use futures::Future; io, mem,
pin::Pin,
task::{Context, Poll},
thread,
time::Duration,
};
use crate::builder::ServerBuilder; use actix_rt::{time::sleep, System};
use crate::signals::Signal; use futures_core::{future::BoxFuture, Stream};
use futures_util::stream::StreamExt as _;
use tokio::sync::{mpsc::UnboundedReceiver, oneshot};
use tracing::{error, info};
use crate::{
accept::Accept,
builder::ServerBuilder,
join_all::join_all,
service::InternalServiceFactory,
signals::{SignalKind, Signals},
waker_queue::{WakerInterest, WakerQueue},
worker::{ServerWorker, ServerWorkerConfig, WorkerHandleServer},
ServerHandle,
};
#[derive(Debug)]
pub(crate) enum ServerCommand { pub(crate) enum ServerCommand {
WorkerDied(usize), /// Worker failed to accept connection, indicating a probable panic.
///
/// Contains index of faulted worker.
WorkerFaulted(usize),
/// Pause accepting connections.
///
/// Contains return channel to notify caller of successful state change.
Pause(oneshot::Sender<()>), Pause(oneshot::Sender<()>),
/// Resume accepting connections.
///
/// Contains return channel to notify caller of successful state change.
Resume(oneshot::Sender<()>), Resume(oneshot::Sender<()>),
Signal(Signal),
/// Whether to try and shut down gracefully /// Stop accepting connections and begin shutdown procedure.
Stop { Stop {
/// True if shut down should be graceful.
graceful: bool, graceful: bool,
/// Return channel to notify caller that shutdown is complete.
completion: Option<oneshot::Sender<()>>, completion: Option<oneshot::Sender<()>>,
/// Force System exit when true, overriding `ServerBuilder::system_exit()` if it is false.
force_system_stop: bool,
}, },
} }
#[derive(Clone)] /// General purpose TCP server that runs services receiving Tokio `TcpStream`s.
pub struct Server(UnboundedSender<ServerCommand>); ///
/// Handles creating worker threads, restarting faulted workers, connection accepting, and
/// back-pressure logic.
///
/// Creates a worker per CPU core (or the number specified in [`ServerBuilder::workers`]) and
/// distributes connections with a round-robin strategy.
///
/// The [Server] must be awaited or polled in order to start running. It will resolve when the
/// server has fully shut down.
///
/// # Shutdown Signals
/// 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.
///
/// # Examples
/// The following is a TCP echo server. Test using `telnet 127.0.0.1 8080`.
///
/// ```no_run
/// use std::io;
///
/// use actix_rt::net::TcpStream;
/// use actix_server::Server;
/// use actix_service::{fn_service, ServiceFactoryExt as _};
/// use bytes::BytesMut;
/// use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
///
/// #[actix_rt::main]
/// async fn main() -> io::Result<()> {
/// let bind_addr = ("127.0.0.1", 8080);
///
/// Server::build()
/// .bind("echo", bind_addr, move || {
/// fn_service(move |mut stream: TcpStream| {
/// async move {
/// let mut size = 0;
/// let mut buf = BytesMut::new();
///
/// loop {
/// match stream.read_buf(&mut buf).await {
/// // end of stream; bail from loop
/// Ok(0) => break,
///
/// // write bytes back to stream
/// Ok(bytes_read) => {
/// stream.write_all(&buf[size..]).await.unwrap();
/// size += bytes_read;
/// }
///
/// Err(err) => {
/// eprintln!("Stream Error: {:?}", err);
/// return Err(());
/// }
/// }
/// }
///
/// Ok(())
/// }
/// })
/// .map_err(|err| eprintln!("Service Error: {:?}", err))
/// })?
/// .run()
/// .await
/// }
/// ```
#[must_use = "Server does nothing unless you `.await` or poll it"]
pub struct Server {
handle: ServerHandle,
fut: BoxFuture<'static, io::Result<()>>,
}
impl Server { impl Server {
pub(crate) fn new(tx: UnboundedSender<ServerCommand>) -> Self { /// Create server build.
Server(tx)
}
/// Start server building process
pub fn build() -> ServerBuilder { pub fn build() -> ServerBuilder {
ServerBuilder::default() ServerBuilder::default()
} }
pub(crate) fn signal(&self, sig: Signal) { pub(crate) fn new(builder: ServerBuilder) -> Self {
let _ = self.0.unbounded_send(ServerCommand::Signal(sig)); Server {
handle: ServerHandle::new(builder.cmd_tx.clone()),
fut: Box::pin(ServerInner::run(builder)),
}
} }
pub(crate) fn worker_died(&self, idx: usize) { /// Get a `Server` handle that can be used issue commands and change it's state.
let _ = self.0.unbounded_send(ServerCommand::WorkerDied(idx));
}
/// Pause accepting incoming connections
/// ///
/// If socket contains some pending connection, they might be dropped. /// See [ServerHandle](ServerHandle) for usage.
/// All opened connection remains active. pub fn handle(&self) -> ServerHandle {
pub fn pause(&self) -> impl Future<Item = (), Error = ()> { self.handle.clone()
let (tx, rx) = oneshot::channel(); }
let _ = self.0.unbounded_send(ServerCommand::Pause(tx)); }
rx.map_err(|_| ())
} impl Future for Server {
type Output = io::Result<()>;
/// Resume accepting incoming connections
pub fn resume(&self) -> impl Future<Item = (), Error = ()> { #[inline]
let (tx, rx) = oneshot::channel(); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let _ = self.0.unbounded_send(ServerCommand::Resume(tx)); Pin::new(&mut Pin::into_inner(self).fut).poll(cx)
rx.map_err(|_| ()) }
} }
/// Stop incoming connection processing, stop all workers and exit. pub struct ServerInner {
/// worker_handles: Vec<WorkerHandleServer>,
/// If server starts with `spawn()` method, then spawned thread get terminated. accept_handle: Option<thread::JoinHandle<()>>,
pub fn stop(&self, graceful: bool) -> impl Future<Item = (), Error = ()> { worker_config: ServerWorkerConfig,
let (tx, rx) = oneshot::channel(); services: Vec<Box<dyn InternalServiceFactory>>,
let _ = self.0.unbounded_send(ServerCommand::Stop { waker_queue: WakerQueue,
graceful, system_stop: bool,
completion: Some(tx), stopping: bool,
}); }
rx.map_err(|_| ())
impl ServerInner {
async fn run(builder: ServerBuilder) -> io::Result<()> {
let (mut this, mut mux) = Self::run_sync(builder)?;
while let Some(cmd) = mux.next().await {
this.handle_cmd(cmd).await;
if this.stopping {
break;
}
}
Ok(())
}
fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
// 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();
match (is_actix, is_tokio) {
(true, _) => info!("Actix runtime found; starting in Actix runtime"),
(_, true) => info!("Tokio runtime found; starting in existing Tokio runtime"),
(_, false) => panic!("Actix or Tokio runtime not found; halting"),
}
for (_, name, lst) in &builder.sockets {
info!(
r#"starting service: "{}", workers: {}, listening on: {}"#,
name,
builder.threads,
lst.local_addr()
);
}
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),
cmd_rx: builder.cmd_rx,
};
let server = ServerInner {
waker_queue,
accept_handle: Some(accept_handle),
worker_handles,
worker_config: builder.worker_config,
services: builder.factories,
system_stop: builder.exit,
stopping: false,
};
Ok((server, mux))
}
async fn handle_cmd(&mut self, item: ServerCommand) {
match item {
ServerCommand::Pause(tx) => {
self.waker_queue.wake(WakerInterest::Pause);
let _ = tx.send(());
}
ServerCommand::Resume(tx) => {
self.waker_queue.wake(WakerInterest::Resume);
let _ = tx.send(());
}
ServerCommand::Stop {
graceful,
completion,
force_system_stop,
} => {
self.stopping = true;
// 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
let workers_stop = self
.worker_handles
.iter()
.map(|worker| worker.stop(graceful))
.collect::<Vec<_>>();
if graceful {
// wait for all workers to shut down
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(());
}
if self.system_stop || force_system_stop {
sleep(Duration::from_millis(300)).await;
System::try_current().as_ref().map(System::stop);
}
}
ServerCommand::WorkerFaulted(idx) => {
// 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);
let factories = self
.services
.iter()
.map(|service| service.clone_factory())
.collect();
match ServerWorker::start(
idx,
factories,
self.waker_queue.clone(),
self.worker_config,
) {
Ok((handle_accept, handle_server)) => {
*self
.worker_handles
.iter_mut()
.find(|wrk| wrk.idx == idx)
.unwrap() = handle_server;
self.waker_queue.wake(WakerInterest::Worker(handle_accept));
}
Err(err) => error!("can not restart worker {}: {}", idx, err),
};
}
}
}
fn map_signal(signal: SignalKind) -> ServerCommand {
match signal {
SignalKind::Int => {
info!("SIGINT received; starting forced shutdown");
ServerCommand::Stop {
graceful: false,
completion: None,
force_system_stop: true,
}
}
SignalKind::Term => {
info!("SIGTERM received; starting graceful shutdown");
ServerCommand::Stop {
graceful: true,
completion: None,
force_system_stop: true,
}
}
SignalKind::Quit => {
info!("SIGQUIT received; starting forced shutdown");
ServerCommand::Stop {
graceful: false,
completion: None,
force_system_stop: true,
}
}
}
}
}
struct ServerEventMultiplexer {
cmd_rx: UnboundedReceiver<ServerCommand>,
signal_fut: Option<Signals>,
}
impl Stream for ServerEventMultiplexer {
type Item = ServerCommand;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = Pin::into_inner(self);
if let Some(signal_fut) = &mut this.signal_fut {
if let Poll::Ready(signal) = Pin::new(signal_fut).poll(cx) {
this.signal_fut = None;
return Poll::Ready(Some(ServerInner::map_signal(signal)));
}
}
this.cmd_rx.poll_recv(cx)
} }
} }

162
actix-server/src/service.rs Normal file
View File

@ -0,0 +1,162 @@
use std::{
marker::PhantomData,
net::SocketAddr,
task::{Context, Poll},
};
use actix_service::{Service, ServiceFactory as BaseServiceFactory};
use actix_utils::future::{ready, Ready};
use futures_core::future::LocalBoxFuture;
use tracing::error;
use crate::{
socket::{FromStream, MioStream},
worker::WorkerCounterGuard,
};
#[doc(hidden)]
pub trait ServerServiceFactory<Stream: FromStream>: Send + Clone + 'static {
type Factory: BaseServiceFactory<Stream, Config = ()>;
fn create(&self) -> Self::Factory;
}
pub(crate) trait InternalServiceFactory: Send {
fn name(&self, token: usize) -> &str;
fn clone_factory(&self) -> Box<dyn InternalServiceFactory>;
fn create(&self) -> LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>>;
}
pub(crate) type BoxedServerService = Box<
dyn Service<
(WorkerCounterGuard, MioStream),
Response = (),
Error = (),
Future = Ready<Result<(), ()>>,
>,
>;
pub(crate) struct StreamService<S, I> {
service: S,
_phantom: PhantomData<I>,
}
impl<S, I> StreamService<S, I> {
pub(crate) fn new(service: S) -> Self {
StreamService {
service,
_phantom: PhantomData,
}
}
}
impl<S, I> Service<(WorkerCounterGuard, MioStream)> for StreamService<S, I>
where
S: Service<I>,
S::Future: 'static,
S::Error: 'static,
I: FromStream,
{
type Response = ();
type Error = ();
type Future = Ready<Result<(), ()>>;
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(ctx).map_err(|_| ())
}
fn call(&self, (guard, req): (WorkerCounterGuard, MioStream)) -> Self::Future {
ready(match FromStream::from_mio(req) {
Ok(stream) => {
let f = self.service.call(stream);
actix_rt::spawn(async move {
let _ = f.await;
drop(guard);
});
Ok(())
}
Err(err) => {
error!("can not convert to an async TCP stream: {err}");
Err(())
}
})
}
}
pub(crate) struct StreamNewService<F: ServerServiceFactory<Io>, Io: FromStream> {
name: String,
inner: F,
token: usize,
addr: SocketAddr,
_t: PhantomData<Io>,
}
impl<F, Io> StreamNewService<F, Io>
where
F: ServerServiceFactory<Io>,
Io: FromStream + Send + 'static,
{
pub(crate) fn create(
name: String,
token: usize,
inner: F,
addr: SocketAddr,
) -> Box<dyn InternalServiceFactory> {
Box::new(Self {
name,
token,
inner,
addr,
_t: PhantomData,
})
}
}
impl<F, Io> InternalServiceFactory for StreamNewService<F, Io>
where
F: ServerServiceFactory<Io>,
Io: FromStream + Send + 'static,
{
fn name(&self, _: usize) -> &str {
&self.name
}
fn clone_factory(&self) -> Box<dyn InternalServiceFactory> {
Box::new(Self {
name: self.name.clone(),
inner: self.inner.clone(),
token: self.token,
addr: self.addr,
_t: PhantomData,
})
}
fn create(&self) -> LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>> {
let token = self.token;
let fut = self.inner.create().new_service(());
Box::pin(async move {
match fut.await {
Ok(inner) => {
let service = Box::new(StreamService::new(inner)) as _;
Ok((token, service))
}
Err(_) => Err(()),
}
})
}
}
impl<F, T, I> ServerServiceFactory<I> for F
where
F: Fn() -> T + Send + Clone + 'static,
T: BaseServiceFactory<I, Config = ()>,
I: FromStream,
{
type Factory = T;
fn create(&self) -> T {
(self)()
}
}

View File

@ -1,165 +0,0 @@
use std::net;
use std::time::Duration;
use actix_rt::spawn;
use actix_service::{NewService, Service};
use futures::future::{err, ok, FutureResult};
use futures::{Future, Poll};
use log::error;
use tokio_reactor::Handle;
use tokio_tcp::TcpStream;
use super::Token;
use crate::counter::CounterGuard;
/// Server message
pub(crate) enum ServerMessage {
/// New stream
Connect(net::TcpStream),
/// Gracefull shutdown
Shutdown(Duration),
/// Force shutdown
ForceShutdown,
}
pub trait StreamServiceFactory: Send + Clone + 'static {
type NewService: NewService<Request = TcpStream>;
fn create(&self) -> Self::NewService;
}
pub(crate) trait InternalServiceFactory: Send {
fn name(&self, token: Token) -> &str;
fn clone_factory(&self) -> Box<InternalServiceFactory>;
fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>>;
}
pub(crate) type BoxedServerService = Box<
Service<
Request = (Option<CounterGuard>, ServerMessage),
Response = (),
Error = (),
Future = FutureResult<(), ()>,
>,
>;
pub(crate) struct StreamService<T> {
service: T,
}
impl<T> StreamService<T> {
pub(crate) fn new(service: T) -> Self {
StreamService { service }
}
}
impl<T> Service for StreamService<T>
where
T: Service<Request = TcpStream>,
T::Future: 'static,
T::Error: 'static,
{
type Request = (Option<CounterGuard>, ServerMessage);
type Response = ();
type Error = ();
type Future = FutureResult<(), ()>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready().map_err(|_| ())
}
fn call(&mut self, (guard, req): (Option<CounterGuard>, ServerMessage)) -> Self::Future {
match req {
ServerMessage::Connect(stream) => {
let stream = TcpStream::from_std(stream, &Handle::default()).map_err(|e| {
error!("Can not convert to an async tcp stream: {}", e);
});
if let Ok(stream) = stream {
spawn(self.service.call(stream).then(move |res| {
drop(guard);
res.map_err(|_| ()).map(|_| ())
}));
ok(())
} else {
err(())
}
}
_ => ok(()),
}
}
}
pub(crate) struct StreamNewService<F: StreamServiceFactory> {
name: String,
inner: F,
token: Token,
}
impl<F> StreamNewService<F>
where
F: StreamServiceFactory,
{
pub(crate) fn create(name: String, token: Token, inner: F) -> Box<InternalServiceFactory> {
Box::new(Self { name, token, inner })
}
}
impl<F> InternalServiceFactory for StreamNewService<F>
where
F: StreamServiceFactory,
{
fn name(&self, _: Token) -> &str {
&self.name
}
fn clone_factory(&self) -> Box<InternalServiceFactory> {
Box::new(Self {
name: self.name.clone(),
inner: self.inner.clone(),
token: self.token,
})
}
fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>> {
let token = self.token;
Box::new(
self.inner
.create()
.new_service(&())
.map_err(|_| ())
.map(move |inner| {
let service: BoxedServerService = Box::new(StreamService::new(inner));
vec![(token, service)]
}),
)
}
}
impl InternalServiceFactory for Box<InternalServiceFactory> {
fn name(&self, token: Token) -> &str {
self.as_ref().name(token)
}
fn clone_factory(&self) -> Box<InternalServiceFactory> {
self.as_ref().clone_factory()
}
fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>> {
self.as_ref().create()
}
}
impl<F, T> StreamServiceFactory for F
where
F: Fn() -> T + Send + Clone + 'static,
T: NewService<Request = TcpStream>,
{
type NewService = T;
fn create(&self) -> T {
(self)()
}
}

View File

@ -1,118 +1,108 @@
use std::io; use std::{
fmt,
future::Future,
pin::Pin,
task::{Context, Poll},
};
use actix_rt::spawn; use tracing::trace;
use futures::stream::futures_unordered;
use futures::{Async, Future, Poll, Stream};
use crate::server::Server; /// Types of process signals.
// #[allow(dead_code)]
/// Different types of process signals #[derive(Debug, Clone, Copy, PartialEq)]
#[derive(PartialEq, Clone, Copy, Debug)] #[allow(dead_code)] // variants are never constructed on non-unix
pub(crate) enum Signal { pub(crate) enum SignalKind {
/// SIGHUP /// `SIGINT`
Hup,
/// SIGINT
Int, Int,
/// SIGTERM
/// `SIGTERM`
Term, Term,
/// SIGQUIT
/// `SIGQUIT`
Quit, Quit,
} }
pub(crate) struct Signals { impl fmt::Display for SignalKind {
srv: Server, fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(not(unix))] f.write_str(match self {
stream: SigStream, SignalKind::Int => "SIGINT",
#[cfg(unix)] SignalKind::Term => "SIGTERM",
streams: Vec<SigStream>, SignalKind::Quit => "SIGQUIT",
})
}
} }
type SigStream = Box<Stream<Item = Signal, Error = io::Error>>; /// Process signal listener.
pub(crate) struct Signals {
#[cfg(not(unix))]
signals: futures_core::future::BoxFuture<'static, std::io::Result<()>>,
#[cfg(unix)]
signals: Vec<(SignalKind, actix_rt::signal::unix::Signal)>,
}
impl Signals { impl Signals {
pub(crate) fn start(srv: Server) { /// Constructs an OS signal listening future.
let fut = { pub(crate) fn new() -> Self {
#[cfg(not(unix))] trace!("setting up OS signal listener");
{
tokio_signal::ctrl_c()
.map_err(|_| ())
.and_then(move |stream| Signals {
srv,
stream: Box::new(stream.map(|_| Signal::Int)),
})
}
#[cfg(unix)] #[cfg(not(unix))]
{ {
use tokio_signal::unix; Signals {
signals: Box::pin(actix_rt::signal::ctrl_c()),
let mut sigs: Vec<Box<Future<Item = SigStream, Error = io::Error>>> =
Vec::new();
sigs.push(Box::new(
tokio_signal::unix::Signal::new(tokio_signal::unix::SIGINT).map(|stream| {
let s: SigStream = Box::new(stream.map(|_| Signal::Int));
s
}),
));
sigs.push(Box::new(
tokio_signal::unix::Signal::new(tokio_signal::unix::SIGHUP).map(
|stream: unix::Signal| {
let s: SigStream = Box::new(stream.map(|_| Signal::Hup));
s
},
),
));
sigs.push(Box::new(
tokio_signal::unix::Signal::new(tokio_signal::unix::SIGTERM).map(
|stream| {
let s: SigStream = Box::new(stream.map(|_| Signal::Term));
s
},
),
));
sigs.push(Box::new(
tokio_signal::unix::Signal::new(tokio_signal::unix::SIGQUIT).map(
|stream| {
let s: SigStream = Box::new(stream.map(|_| Signal::Quit));
s
},
),
));
futures_unordered(sigs)
.collect()
.map_err(|_| ())
.and_then(move |streams| Signals { srv, streams })
} }
}; }
spawn(fut);
#[cfg(unix)]
{
use actix_rt::signal::unix;
let sig_map = [
(unix::SignalKind::interrupt(), SignalKind::Int),
(unix::SignalKind::terminate(), SignalKind::Term),
(unix::SignalKind::quit(), SignalKind::Quit),
];
let signals = sig_map
.iter()
.filter_map(|(kind, sig)| {
unix::signal(*kind)
.map(|tokio_sig| (*sig, tokio_sig))
.map_err(|e| {
tracing::error!(
"can not initialize stream handler for {:?} err: {}",
sig,
e
)
})
.ok()
})
.collect::<Vec<_>>();
Signals { signals }
}
} }
} }
impl Future for Signals { impl Future for Signals {
type Item = (); type Output = SignalKind;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
#[cfg(not(unix))] #[cfg(not(unix))]
loop { {
match self.stream.poll() { self.signals.as_mut().poll(cx).map(|_| SignalKind::Int)
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())),
Ok(Async::Ready(Some(sig))) => self.srv.signal(sig),
Ok(Async::NotReady) => return Ok(Async::NotReady),
}
} }
#[cfg(unix)] #[cfg(unix)]
{ {
for s in &mut self.streams { for (sig, fut) in self.signals.iter_mut() {
loop { if fut.poll_recv(cx).is_ready() {
match s.poll() { trace!("{} received", sig);
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())), return Poll::Ready(*sig);
Ok(Async::NotReady) => break,
Ok(Async::Ready(Some(sig))) => self.srv.signal(sig),
}
} }
} }
Ok(Async::NotReady)
Poll::Pending
} }
} }
} }

294
actix-server/src/socket.rs Normal file
View File

@ -0,0 +1,294 @@
pub(crate) use std::net::{
SocketAddr as StdSocketAddr, TcpListener as StdTcpListener, ToSocketAddrs,
};
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,
};
use crate::builder::MpTcp;
pub(crate) enum MioListener {
Tcp(MioTcpListener),
#[cfg(unix)]
Uds(MioUnixListener),
}
impl MioListener {
pub(crate) fn local_addr(&self) -> SocketAddr {
match *self {
MioListener::Tcp(ref lst) => lst
.local_addr()
.map(SocketAddr::Tcp)
.unwrap_or(SocketAddr::Unknown),
#[cfg(unix)]
MioListener::Uds(ref lst) => lst
.local_addr()
.map(SocketAddr::Uds)
.unwrap_or(SocketAddr::Unknown),
}
}
pub(crate) fn accept(&self) -> io::Result<MioStream> {
match *self {
MioListener::Tcp(ref lst) => lst.accept().map(|(stream, _)| MioStream::Tcp(stream)),
#[cfg(unix)]
MioListener::Uds(ref lst) => lst.accept().map(|(stream, _)| MioStream::Uds(stream)),
}
}
}
impl Source for MioListener {
fn register(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
match *self {
MioListener::Tcp(ref mut lst) => lst.register(registry, token, interests),
#[cfg(unix)]
MioListener::Uds(ref mut lst) => lst.register(registry, token, interests),
}
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
match *self {
MioListener::Tcp(ref mut lst) => lst.reregister(registry, token, interests),
#[cfg(unix)]
MioListener::Uds(ref mut lst) => lst.reregister(registry, token, interests),
}
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
match *self {
MioListener::Tcp(ref mut lst) => lst.deregister(registry),
#[cfg(unix)]
MioListener::Uds(ref mut lst) => {
let res = lst.deregister(registry);
// cleanup file path
if let Ok(addr) = lst.local_addr() {
if let Some(path) = addr.as_pathname() {
let _ = std::fs::remove_file(path);
}
}
res
}
}
}
}
impl From<StdTcpListener> for MioListener {
fn from(lst: StdTcpListener) -> Self {
MioListener::Tcp(MioTcpListener::from_std(lst))
}
}
#[cfg(unix)]
impl From<StdUnixListener> for MioListener {
fn from(lst: StdUnixListener) -> Self {
MioListener::Uds(MioUnixListener::from_std(lst))
}
}
impl fmt::Debug for MioListener {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MioListener::Tcp(ref lst) => write!(f, "{:?}", lst),
#[cfg(unix)]
MioListener::Uds(ref lst) => write!(f, "{:?}", lst),
}
}
}
impl fmt::Display for MioListener {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MioListener::Tcp(ref lst) => write!(f, "{:?}", lst),
#[cfg(unix)]
MioListener::Uds(ref lst) => write!(f, "{:?}", lst),
}
}
}
pub(crate) enum SocketAddr {
Unknown,
Tcp(StdSocketAddr),
#[cfg(unix)]
Uds(std::os::unix::net::SocketAddr),
}
impl fmt::Display for SocketAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Unknown => write!(f, "Unknown SocketAddr"),
Self::Tcp(ref addr) => write!(f, "{}", addr),
#[cfg(unix)]
Self::Uds(ref addr) => write!(f, "{:?}", addr),
}
}
}
impl fmt::Debug for SocketAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Unknown => write!(f, "Unknown SocketAddr"),
Self::Tcp(ref addr) => write!(f, "{:?}", addr),
#[cfg(unix)]
Self::Uds(ref addr) => write!(f, "{:?}", addr),
}
}
}
#[derive(Debug)]
pub enum MioStream {
Tcp(mio::net::TcpStream),
#[cfg(unix)]
Uds(mio::net::UnixStream),
}
/// Helper trait for converting a Mio stream into a Tokio stream.
pub trait FromStream: Sized {
/// Creates stream from a `mio` stream.
fn from_mio(sock: MioStream) -> io::Result<Self>;
}
#[cfg(windows)]
mod win_impl {
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
use super::*;
// TODO: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
impl FromStream for TcpStream {
fn from_mio(sock: MioStream) -> io::Result<Self> {
match sock {
MioStream::Tcp(mio) => {
let raw = IntoRawSocket::into_raw_socket(mio);
// SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
TcpStream::from_std(unsafe { FromRawSocket::from_raw_socket(raw) })
}
}
}
}
}
#[cfg(unix)]
mod unix_impl {
use std::os::unix::io::{FromRawFd, IntoRawFd};
use actix_rt::net::UnixStream;
use super::*;
// HACK: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
impl FromStream for TcpStream {
fn from_mio(sock: MioStream) -> io::Result<Self> {
match sock {
MioStream::Tcp(mio) => {
let raw = IntoRawFd::into_raw_fd(mio);
// SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
TcpStream::from_std(unsafe { FromRawFd::from_raw_fd(raw) })
}
MioStream::Uds(_) => {
panic!("Should not happen, bug in server impl");
}
}
}
}
// HACK: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
impl FromStream for UnixStream {
fn from_mio(sock: MioStream) -> io::Result<Self> {
match sock {
MioStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
MioStream::Uds(mio) => {
let raw = IntoRawFd::into_raw_fd(mio);
// SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
UnixStream::from_std(unsafe { FromRawFd::from_raw_fd(raw) })
}
}
}
}
}
pub(crate) fn create_mio_tcp_listener(
addr: StdSocketAddr,
backlog: u32,
mptcp: &MpTcp,
) -> io::Result<MioTcpListener> {
use socket2::{Domain, Protocol, Socket, Type};
#[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)?;
socket.bind(&addr.into())?;
socket.listen(backlog as i32)?;
Ok(MioTcpListener::from_std(StdTcpListener::from(socket)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn socket_addr() {
let addr = SocketAddr::Tcp("127.0.0.1:8080".parse().unwrap());
assert!(format!("{:?}", addr).contains("127.0.0.1:8080"));
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, &MpTcp::Disabled).unwrap();
let lst = MioListener::Tcp(lst);
assert!(format!("{:?}", lst).contains("TcpListener"));
assert!(format!("{}", lst).contains("127.0.0.1"));
}
#[test]
#[cfg(unix)]
fn uds() {
let _ = std::fs::remove_file("/tmp/sock.xxxxx");
if let Ok(socket) = MioUnixListener::bind("/tmp/sock.xxxxx") {
let addr = socket.local_addr().expect("Couldn't get local address");
let a = SocketAddr::Uds(addr);
assert!(format!("{:?}", a).contains("/tmp/sock.xxxxx"));
assert!(format!("{}", a).contains("/tmp/sock.xxxxx"));
let lst = MioListener::Uds(socket);
assert!(format!("{:?}", lst).contains("/tmp/sock.xxxxx"));
assert!(format!("{}", lst).contains("/tmp/sock.xxxxx"));
}
}
}

View File

@ -1,35 +0,0 @@
//! SSL Services
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::counter::Counter;
#[cfg(feature = "ssl")]
mod openssl;
#[cfg(feature = "ssl")]
pub use self::openssl::OpensslAcceptor;
#[cfg(feature = "tls")]
mod nativetls;
#[cfg(feature = "tls")]
pub use self::nativetls::{NativeTlsAcceptor, TlsStream};
#[cfg(feature = "rust-tls")]
mod rustls;
#[cfg(feature = "rust-tls")]
pub use self::rustls::RustlsAcceptor;
/// Sets the maximum per-worker concurrent ssl connection establish process.
///
/// All listeners will stop accepting connections when this limit is
/// reached. It can be used to limit the global SSL CPU usage.
///
/// By default max connections is set to a 256.
pub fn max_concurrent_ssl_connect(num: usize) {
MAX_CONN.store(num, Ordering::Relaxed);
}
pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
thread_local! {
static MAX_CONN_COUNTER: Counter = Counter::new(MAX_CONN.load(Ordering::Relaxed));
}

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