mirror of
https://github.com/fafhrd91/actix-net
synced 2025-08-12 14:27:05 +02:00
Compare commits
12 Commits
local-chan
...
utils-v3.0
Author | SHA1 | Date | |
---|---|---|---|
|
d5a9a6a1c5 | ||
|
ade71b7bd3 | ||
|
cb83922b29 | ||
|
25209f5bd8 | ||
|
c4a0f37d0c | ||
|
0e649329b9 | ||
|
66756bc448 | ||
|
126ed4c2e3 | ||
|
283974f3e6 | ||
|
bf2aa3902c | ||
|
71b4e55c92 | ||
|
eb5fa30ada |
@@ -14,13 +14,10 @@ ci-check = "hack --workspace --feature-powerset --exclude-features=io-uring chec
|
||||
ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
|
||||
|
||||
# tests avoiding io-uring feature
|
||||
ci-test = " hack --feature-powerset --exclude=actix-rt --exclude=actix-server --exclude-features=io-uring test --workspace --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-rt = " hack --feature-powerset --exclude-features=io-uring test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-server = "hack --feature-powerset --exclude-features=io-uring test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# tests avoiding io-uring feature on Windows
|
||||
ci-test-win = "hack --feature-powerset --depth 2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# test with io-uring feature
|
||||
ci-test-rt-linux = " hack --feature-powerset test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-server-linux = "hack --feature-powerset test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# test lower msrv
|
||||
ci-test-lower-msrv = "hack --workspace --exclude=actix-server --exclude=actix-tls --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-linux = " hack --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
7
.github/workflows/ci-master.yml
vendored
7
.github/workflows/ci-master.yml
vendored
@@ -101,14 +101,11 @@ jobs:
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: |
|
||||
cargo ci-test
|
||||
cargo ci-test-rt
|
||||
cargo ci-test-server
|
||||
run: cargo ci-test
|
||||
- name: tests
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rt-linux && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-server-linux"
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
|
55
.github/workflows/ci.yml
vendored
55
.github/workflows/ci.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- 1.52.0 # MSRV for -server and -tls
|
||||
- 1.57.0
|
||||
- stable
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
@@ -77,10 +77,6 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
|
||||
- name: Tweak lockfile
|
||||
run: |
|
||||
cargo update -p=native-tls --precise=0.2.8
|
||||
|
||||
- name: check lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
@@ -108,55 +104,18 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-linux }
|
||||
|
||||
- name: tests
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: cargo ci-test
|
||||
- name: tests
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
matrix.target.os == 'windows-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: |
|
||||
cargo ci-test
|
||||
cargo ci-test-rt
|
||||
cargo ci-test-server
|
||||
run: cargo ci-test-win
|
||||
- name: tests
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rt-linux && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-server-linux"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
build_and_test_lower_msrv:
|
||||
name: Linux / 1.49 (lower MSRV)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install 1.49.0 # MSRV for all but -server and -tls
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.49.0-x86_64-unknown-linux-gnu
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
|
||||
- name: Tweak lockfile
|
||||
run: |
|
||||
cargo update -p=rustls --precise=0.20.2
|
||||
cargo update -p=native-tls --precise=0.2.8
|
||||
|
||||
- name: tests
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=1.49 cargo ci-test-lower-msrv"
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.5.1 - 2022-03-15
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.2.3 - 2021-10-19
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Add `#[track_caller]` attribute to `spawn` functions and methods. [#454]
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
[#454]: https://github.com/actix/actix-net/pull/454
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 2.1.1 - 2022-03-09
|
||||
|
@@ -74,7 +74,7 @@ async fn run() -> io::Result<()> {
|
||||
// close connection after file has been copied to TCP stream
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|err| tracing::error!("Service Error: {:?}", err))
|
||||
.map_err(|err| tracing::error!("service error: {:?}", err))
|
||||
})?
|
||||
.workers(2)
|
||||
.run()
|
||||
|
@@ -64,7 +64,7 @@ async fn run() -> io::Result<()> {
|
||||
|
||||
// stream error; bail from loop with error
|
||||
Err(err) => {
|
||||
tracing::error!("Stream Error: {:?}", err);
|
||||
tracing::error!("stream error: {:?}", err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ async fn run() -> io::Result<()> {
|
||||
Ok((buf.freeze(), size))
|
||||
}
|
||||
})
|
||||
.map_err(|err| tracing::error!("Service Error: {:?}", err))
|
||||
.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);
|
||||
|
@@ -24,7 +24,7 @@ struct ServerSocketInfo {
|
||||
timeout: Option<actix_rt::time::Instant>,
|
||||
}
|
||||
|
||||
/// poll instance of the server.
|
||||
/// Poll instance of the server.
|
||||
pub(crate) struct Accept {
|
||||
poll: Poll,
|
||||
waker_queue: WakerQueue,
|
||||
@@ -140,7 +140,7 @@ impl Accept {
|
||||
WAKER_TOKEN => {
|
||||
let exit = self.handle_waker(sockets);
|
||||
if exit {
|
||||
info!("Accept thread stopped");
|
||||
info!("accept thread stopped");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -161,11 +161,13 @@ impl Accept {
|
||||
// a loop that would try to drain the command channel. It's yet unknown
|
||||
// if it's necessary/good practice to actively drain the waker queue.
|
||||
loop {
|
||||
// take guard with every iteration so no new interest can be added
|
||||
// until the current task is done.
|
||||
// Take guard with every iteration so no new interests can be added until the current
|
||||
// task is done. Take care not to take the guard again inside this loop.
|
||||
let mut guard = self.waker_queue.guard();
|
||||
|
||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||
match guard.pop_front() {
|
||||
// worker notify it becomes available.
|
||||
// Worker notified it became available.
|
||||
Some(WakerInterest::WorkerAvailable(idx)) => {
|
||||
drop(guard);
|
||||
|
||||
@@ -176,7 +178,7 @@ impl Accept {
|
||||
}
|
||||
}
|
||||
|
||||
// a new worker thread is made and it's handle would be added to Accept
|
||||
// A new worker thread has been created so store its handle.
|
||||
Some(WakerInterest::Worker(handle)) => {
|
||||
drop(guard);
|
||||
|
||||
@@ -297,16 +299,16 @@ impl Accept {
|
||||
|
||||
fn register_logged(&self, info: &mut ServerSocketInfo) {
|
||||
match self.register(info) {
|
||||
Ok(_) => debug!("Resume accepting connections on {}", info.lst.local_addr()),
|
||||
Err(err) => error!("Can not register server socket {}", err),
|
||||
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()),
|
||||
Ok(_) => debug!("paused accepting connections on {}", info.lst.local_addr()),
|
||||
Err(err) => {
|
||||
error!("Can not deregister server socket {}", err)
|
||||
error!("can not deregister server socket {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,7 +352,7 @@ impl Accept {
|
||||
self.remove_next();
|
||||
|
||||
if self.handles.is_empty() {
|
||||
error!("No workers");
|
||||
error!("no workers");
|
||||
// All workers are gone and Conn is nowhere to be sent.
|
||||
// Treat this situation as Ok and drop Conn.
|
||||
return Ok(());
|
||||
@@ -399,7 +401,7 @@ impl Accept {
|
||||
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);
|
||||
error!("error accepting connection: {}", err);
|
||||
|
||||
// deregister listener temporary
|
||||
self.deregister_logged(info);
|
||||
|
@@ -197,7 +197,7 @@ impl ServerBuilder {
|
||||
if self.sockets.is_empty() {
|
||||
panic!("Server should have at least one bound socket");
|
||||
} else {
|
||||
info!("Starting {} workers", self.threads);
|
||||
info!("starting {} workers", self.threads);
|
||||
Server::new(self)
|
||||
}
|
||||
}
|
||||
|
@@ -200,7 +200,7 @@ impl ServerInner {
|
||||
|
||||
for (_, name, lst) in &builder.sockets {
|
||||
info!(
|
||||
r#"Starting service: "{}", workers: {}, listening on: {}"#,
|
||||
r#"starting service: "{}", workers: {}, listening on: {}"#,
|
||||
name,
|
||||
builder.threads,
|
||||
lst.local_addr()
|
||||
@@ -283,7 +283,7 @@ impl ServerInner {
|
||||
// TODO: maybe just return with warning log if not found ?
|
||||
assert!(self.worker_handles.iter().any(|wrk| wrk.idx == idx));
|
||||
|
||||
error!("Worker {} has died; restarting", idx);
|
||||
error!("worker {} has died; restarting", idx);
|
||||
|
||||
let factories = self
|
||||
.services
|
||||
|
@@ -78,7 +78,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Can not convert to an async tcp stream: {}", err);
|
||||
error!("can not convert to an async TCP stream: {}", err);
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
|
@@ -70,7 +70,7 @@ impl Signals {
|
||||
.map(|tokio_sig| (*sig, tokio_sig))
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
"Can not initialize stream handler for {:?} err: {}",
|
||||
"can not initialize stream handler for {:?} err: {}",
|
||||
sig,
|
||||
e
|
||||
)
|
||||
|
@@ -337,7 +337,7 @@ impl ServerWorker {
|
||||
Ok((token, svc)) => services.push((idx, token, svc)),
|
||||
|
||||
Err(err) => {
|
||||
error!("Can not start worker: {:?}", err);
|
||||
error!("can not start worker: {:?}", err);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("can not start server service {}", idx),
|
||||
@@ -436,7 +436,7 @@ impl ServerWorker {
|
||||
Ok((token, svc)) => services.push((idx, token, svc)),
|
||||
|
||||
Err(err) => {
|
||||
error!("Can not start worker: {:?}", err);
|
||||
error!("can not start worker: {:?}", err);
|
||||
Arbiter::current().stop();
|
||||
factory_tx
|
||||
.send(Err(io::Error::new(
|
||||
@@ -476,7 +476,7 @@ impl ServerWorker {
|
||||
|
||||
fn restart_service(&mut self, idx: usize, factory_id: usize) {
|
||||
let factory = &self.factories[factory_id];
|
||||
trace!("Service {:?} failed, restarting", factory.name(idx));
|
||||
trace!("service {:?} failed, restarting", factory.name(idx));
|
||||
self.services[idx].status = WorkerServiceStatus::Restarting;
|
||||
self.state = WorkerState::Restarting(Restart {
|
||||
factory_id,
|
||||
@@ -508,7 +508,7 @@ impl ServerWorker {
|
||||
Poll::Ready(Ok(_)) => {
|
||||
if srv.status == WorkerServiceStatus::Unavailable {
|
||||
trace!(
|
||||
"Service {:?} is available",
|
||||
"service {:?} is available",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Available;
|
||||
@@ -519,7 +519,7 @@ impl ServerWorker {
|
||||
|
||||
if srv.status == WorkerServiceStatus::Available {
|
||||
trace!(
|
||||
"Service {:?} is unavailable",
|
||||
"service {:?} is unavailable",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Unavailable;
|
||||
@@ -527,7 +527,7 @@ impl ServerWorker {
|
||||
}
|
||||
Poll::Ready(Err(_)) => {
|
||||
error!(
|
||||
"Service {:?} readiness check returned error, restarting",
|
||||
"service {:?} readiness check returned error, restarting",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Failed;
|
||||
@@ -590,11 +590,11 @@ impl Future for ServerWorker {
|
||||
{
|
||||
let num = this.counter.total();
|
||||
if num == 0 {
|
||||
info!("Shutting down idle worker");
|
||||
info!("shutting down idle worker");
|
||||
let _ = tx.send(true);
|
||||
return Poll::Ready(());
|
||||
} else if graceful {
|
||||
info!("Graceful worker shutdown; finishing {} connections", num);
|
||||
info!("graceful worker shutdown; finishing {} connections", num);
|
||||
this.shutdown(false);
|
||||
|
||||
this.state = WorkerState::Shutdown(Shutdown {
|
||||
@@ -603,7 +603,7 @@ impl Future for ServerWorker {
|
||||
tx,
|
||||
});
|
||||
} else {
|
||||
info!("Force shutdown worker, closing {} connections", num);
|
||||
info!("force shutdown worker, closing {} connections", num);
|
||||
this.shutdown(true);
|
||||
|
||||
let _ = tx.send(false);
|
||||
@@ -638,7 +638,7 @@ impl Future for ServerWorker {
|
||||
assert_eq!(token, token_new);
|
||||
|
||||
trace!(
|
||||
"Service {:?} has been restarted",
|
||||
"service {:?} has been restarted",
|
||||
this.factories[factory_id].name(token)
|
||||
);
|
||||
|
||||
@@ -685,7 +685,7 @@ impl Future for ServerWorker {
|
||||
match this.check_readiness(cx) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
trace!("Worker is unavailable");
|
||||
trace!("worker is unavailable");
|
||||
this.state = WorkerState::Unavailable;
|
||||
return self.poll(cx);
|
||||
}
|
||||
|
@@ -186,9 +186,9 @@ fn test_start() {
|
||||
#[actix_rt::test]
|
||||
async fn test_max_concurrent_connections() {
|
||||
// Note:
|
||||
// A tcp listener would accept connects based on it's backlog setting.
|
||||
// A TCP listener would accept connects based on it's backlog setting.
|
||||
//
|
||||
// The limit test on the other hand is only for concurrent tcp stream limiting a work
|
||||
// The limit test on the other hand is only for concurrent TCP stream limiting a work
|
||||
// thread accept.
|
||||
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 2.0.2 - 2021-12-18
|
||||
|
@@ -23,6 +23,6 @@ paste = "1"
|
||||
pin-project-lite = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-rt = "2"
|
||||
actix-utils = "3"
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
|
@@ -25,6 +25,8 @@
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`forward_ready!`]: crate::forward_ready
|
||||
#[macro_export]
|
||||
macro_rules! always_ready {
|
||||
() => {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 3.0.4 - 2022-03-15
|
||||
|
@@ -30,24 +30,25 @@ accept = []
|
||||
connect = []
|
||||
|
||||
# use openssl impls
|
||||
openssl = ["tls-openssl", "tokio-openssl"]
|
||||
openssl = ["tls-openssl", "tokio-openssl", "actix-codec"]
|
||||
|
||||
# use rustls impls
|
||||
rustls = ["tokio-rustls", "webpki-roots"]
|
||||
rustls = ["tokio-rustls", "webpki-roots", "actix-codec"]
|
||||
|
||||
# use native-tls impls
|
||||
native-tls = ["tokio-native-tls"]
|
||||
native-tls = ["tokio-native-tls", "actix-codec"]
|
||||
|
||||
# support http::Uri as connect address
|
||||
uri = ["http"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.5.0"
|
||||
actix-codec = { version = "0.5.0", optional = true }
|
||||
actix-rt = { version = "2.2.0", default-features = false }
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
impl-more = "0.1"
|
||||
pin-project-lite = "0.2.7"
|
||||
tokio-util = "0.7"
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
@@ -67,8 +68,9 @@ webpki-roots = { version = "0.22", optional = true }
|
||||
tokio-native-tls = { version = "0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-codec = "0.5.0"
|
||||
actix-rt = "2.2.0"
|
||||
actix-server = "2.0.0"
|
||||
actix-server = "2"
|
||||
bytes = "1"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
|
||||
@@ -76,7 +78,7 @@ log = "0.4"
|
||||
rcgen = "0.8"
|
||||
rustls-pemfile = "0.2.1"
|
||||
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"] }
|
||||
trust-dns-resolver = "0.20.0"
|
||||
trust-dns-resolver = "0.20"
|
||||
|
||||
[[example]]
|
||||
name = "accept-rustls"
|
||||
|
@@ -24,7 +24,6 @@ use futures_core::future::LocalBoxFuture;
|
||||
use tokio_native_tls::{native_tls::Error, TlsAcceptor};
|
||||
|
||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||
use crate::impl_more;
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `native-tls` that are useful for acceptors.
|
||||
@@ -35,9 +34,8 @@ pub mod reexports {
|
||||
/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
|
||||
pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_native_tls::TlsStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_native_tls::TlsStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
impl_more::impl_from!(<IO> in tokio_native_tls::TlsStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
|
@@ -25,7 +25,6 @@ use openssl::ssl::{Error, Ssl, SslAcceptor};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||
use crate::impl_more;
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `openssl` that are useful for acceptors.
|
||||
@@ -38,9 +37,8 @@ pub mod reexports {
|
||||
/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
|
||||
pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_openssl::SslStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_openssl::SslStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
impl_more::impl_from!(<IO> in tokio_openssl::SslStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
|
@@ -27,7 +27,6 @@ use tokio_rustls::rustls::ServerConfig;
|
||||
use tokio_rustls::{Accept, TlsAcceptor};
|
||||
|
||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||
use crate::impl_more;
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `rustls` that are useful for acceptors.
|
||||
@@ -38,9 +37,8 @@ pub mod reexports {
|
||||
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
||||
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
|
||||
|
||||
impl_more::from! { tokio_rustls::server::TlsStream<IO> => TlsStream<IO> }
|
||||
impl_more::deref! { TlsStream<IO> => 0: tokio_rustls::server::TlsStream<IO> }
|
||||
impl_more::deref_mut! { TlsStream<IO> => 0 }
|
||||
impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
|
@@ -1,5 +1,4 @@
|
||||
use super::Host;
|
||||
use crate::impl_more;
|
||||
|
||||
/// Wraps underlying I/O and the connection request that initiated it.
|
||||
#[derive(Debug)]
|
||||
@@ -8,8 +7,7 @@ pub struct Connection<R, IO> {
|
||||
pub(crate) io: IO,
|
||||
}
|
||||
|
||||
impl_more::deref! { Connection<R, IO> => io: IO }
|
||||
impl_more::deref_mut! { Connection<R, IO> => io }
|
||||
impl_more::impl_deref_and_mut!(<R, IO> in Connection<R, IO> => io: IO);
|
||||
|
||||
impl<R, IO> Connection<R, IO> {
|
||||
/// Construct new `Connection` from request and IO parts.
|
||||
|
@@ -27,25 +27,25 @@ pub trait Host: Unpin + 'static {
|
||||
|
||||
impl Host for String {
|
||||
fn hostname(&self) -> &str {
|
||||
str_split_once(self, ':')
|
||||
self.split_once(':')
|
||||
.map(|(hostname, _)| hostname)
|
||||
.unwrap_or(self)
|
||||
}
|
||||
|
||||
fn port(&self) -> Option<u16> {
|
||||
str_split_once(self, ':').and_then(|(_, port)| port.parse().ok())
|
||||
self.split_once(':').and_then(|(_, port)| port.parse().ok())
|
||||
}
|
||||
}
|
||||
|
||||
impl Host for &'static str {
|
||||
fn hostname(&self) -> &str {
|
||||
str_split_once(self, ':')
|
||||
self.split_once(':')
|
||||
.map(|(hostname, _)| hostname)
|
||||
.unwrap_or(self)
|
||||
}
|
||||
|
||||
fn port(&self) -> Option<u16> {
|
||||
str_split_once(self, ':').and_then(|(_, port)| port.parse().ok())
|
||||
self.split_once(':').and_then(|(_, port)| port.parse().ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,3 @@ mod tests {
|
||||
assert_connection_info_eq!("example.com:false:false", "example.com", None);
|
||||
}
|
||||
}
|
||||
|
||||
// `str::split_once` is stabilized in 1.52.0
|
||||
fn str_split_once(str: &str, delimiter: char) -> Option<(&str, &str)> {
|
||||
let mut splitn = str.splitn(2, delimiter);
|
||||
let prefix = splitn.next()?;
|
||||
let suffix = splitn.next()?;
|
||||
Some((prefix, suffix))
|
||||
}
|
||||
|
@@ -74,16 +74,16 @@ where
|
||||
let connector = self.connector.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
trace!("SSL Handshake start for: {:?}", stream.hostname());
|
||||
trace!("TLS handshake start for: {:?}", stream.hostname());
|
||||
connector
|
||||
.connect(stream.hostname(), io)
|
||||
.await
|
||||
.map(|res| {
|
||||
trace!("SSL Handshake success: {:?}", stream.hostname());
|
||||
trace!("TLS handshake success: {:?}", stream.hostname());
|
||||
stream.replace_io(res).1
|
||||
})
|
||||
.map_err(|e| {
|
||||
trace!("SSL Handshake error: {:?}", e);
|
||||
trace!("TLS handshake error: {:?}", e);
|
||||
io::Error::new(io::ErrorKind::Other, format!("{}", e))
|
||||
})
|
||||
})
|
||||
|
@@ -97,7 +97,8 @@ where
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, stream: Connection<R, IO>) -> Self::Future {
|
||||
trace!("SSL Handshake start for: {:?}", stream.hostname());
|
||||
trace!("TLS handshake start for: {:?}", stream.hostname());
|
||||
|
||||
let (io, stream) = stream.replace_io(());
|
||||
let host = stream.hostname();
|
||||
|
||||
@@ -137,11 +138,11 @@ where
|
||||
match ready!(Pin::new(this.io.as_mut().unwrap()).poll_connect(cx)) {
|
||||
Ok(_) => {
|
||||
let stream = this.stream.take().unwrap();
|
||||
trace!("SSL Handshake success: {:?}", stream.hostname());
|
||||
trace!("TLS handshake success: {:?}", stream.hostname());
|
||||
Poll::Ready(Ok(stream.replace_io(this.io.take().unwrap()).1))
|
||||
}
|
||||
Err(err) => {
|
||||
trace!("SSL Handshake error: {:?}", err);
|
||||
trace!("TLS handshake error: {:?}", err);
|
||||
Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{}", err),
|
||||
|
@@ -101,7 +101,7 @@ where
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||
trace!("SSL Handshake start for: {:?}", connection.hostname());
|
||||
trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||
let (stream, connection) = connection.replace_io(());
|
||||
|
||||
match ServerName::try_from(connection.hostname()) {
|
||||
@@ -140,7 +140,7 @@ where
|
||||
Self::Future { connect, connection } => {
|
||||
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||
let connection = connection.take().unwrap();
|
||||
trace!("SSL Handshake success: {:?}", connection.hostname());
|
||||
trace!("TLS handshake success: {:?}", connection.hostname());
|
||||
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||
}
|
||||
}
|
||||
|
@@ -114,8 +114,8 @@ impl<R: Host> TcpConnectorFut<R> {
|
||||
stream: ReusableBoxFuture::new(connect(addr, local_addr)),
|
||||
},
|
||||
|
||||
// when resolver returns multiple socket addr for request they would be popped from
|
||||
// front end of queue and returns with the first successful tcp connection.
|
||||
// When resolver returns multiple socket addr for request they would be popped from
|
||||
// front end of queue and returns with the first successful TCP connection.
|
||||
ConnectAddrs::Multi(mut addrs) => {
|
||||
let addr = addrs.pop_front().unwrap();
|
||||
|
||||
|
@@ -1,40 +0,0 @@
|
||||
/// A helper to implement `Deref` for a type.
|
||||
#[macro_export]
|
||||
macro_rules! deref {
|
||||
($ty:ident $(<$($generic:ident),*>)? => $field:tt: $target:ty) => {
|
||||
impl $(<$($generic),*>)? ::core::ops::Deref for $ty $(<$($generic),*>)? {
|
||||
type Target = $target;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.$field
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A helper to implement `DerefMut` for a type.
|
||||
#[macro_export]
|
||||
macro_rules! deref_mut {
|
||||
($ty:ident $(<$($generic:ident),*>)? => $field:tt) => {
|
||||
impl $(<$($generic),*>)? ::core::ops::DerefMut for $ty $(<$($generic),*>)? {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.$field
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A helper to implement `From` for a unit struct.
|
||||
#[macro_export]
|
||||
macro_rules! from {
|
||||
($from:ty => $ty:ident $(<$($generic:ident),*>)?) => {
|
||||
impl $(<$($generic),*>)? ::core::convert::From<$from> for $ty $(<$($generic),*>)? {
|
||||
fn from(from: $from) -> Self {
|
||||
Self(from)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use crate::{deref, deref_mut, from};
|
@@ -18,5 +18,3 @@ pub mod accept;
|
||||
#[cfg(feature = "connect")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "connect")))]
|
||||
pub mod connect;
|
||||
|
||||
mod impl_more;
|
||||
|
@@ -143,6 +143,9 @@ async fn test_local_addr() {
|
||||
})
|
||||
});
|
||||
|
||||
// if you've arrived here because of a failing test on macOS run this in your terminal:
|
||||
// sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
let conn = Connector::default().service();
|
||||
let local = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3));
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.1.0 - 2020-01-15
|
||||
|
@@ -16,12 +16,12 @@ name = "actix_tracing"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
tracing = "0.1"
|
||||
tracing = "0.1.35"
|
||||
tracing-futures = "0.2"
|
||||
|
||||
[dev_dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-rt = "2"
|
||||
slab = "0.4"
|
||||
|
@@ -1,7 +1,10 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
|
||||
## 3.0.1 - 2022-10-21
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 3.0.0 - 2021-04-16
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-utils"
|
||||
version = "3.0.0"
|
||||
version = "3.0.1"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
|
@@ -1,4 +1,4 @@
|
||||
//! Asynchronous values.
|
||||
//! Helpers for constructing futures.
|
||||
|
||||
mod either;
|
||||
mod poll_fn;
|
||||
|
@@ -8,6 +8,31 @@ use core::{
|
||||
};
|
||||
|
||||
/// Creates a future driven by the provided function that receives a task context.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::task::Poll;
|
||||
/// # use actix_utils::future::poll_fn;
|
||||
/// # async fn test_poll_fn() {
|
||||
/// let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
/// assert_eq!(res, 42);
|
||||
///
|
||||
/// let mut i = 5;
|
||||
/// let res = poll_fn(|cx| {
|
||||
/// i -= 1;
|
||||
///
|
||||
/// if i > 0 {
|
||||
/// cx.waker().wake_by_ref();
|
||||
/// Poll::Pending
|
||||
/// } else {
|
||||
/// Poll::Ready(42)
|
||||
/// }
|
||||
/// })
|
||||
/// .await;
|
||||
/// assert_eq!(res, 42);
|
||||
/// # }
|
||||
/// # actix_rt::Runtime::new().unwrap().block_on(test_poll_fn());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn poll_fn<F, T>(f: F) -> PollFn<F>
|
||||
where
|
||||
@@ -16,13 +41,11 @@ where
|
||||
PollFn { f }
|
||||
}
|
||||
|
||||
/// A Future driven by the inner function.
|
||||
/// Future for the [`poll_fn`] function.
|
||||
pub struct PollFn<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
impl<F> fmt::Debug for PollFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PollFn").finish()
|
||||
@@ -36,15 +59,22 @@ where
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
(self.f)(cx)
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// SAFETY: we are not moving out of the pinned field
|
||||
// see https://github.com/rust-lang/rust/pull/102737
|
||||
(unsafe { &mut self.get_unchecked_mut().f })(cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::marker::PhantomPinned;
|
||||
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_impl_all!(PollFn<()>: Unpin);
|
||||
static_assertions::assert_not_impl_all!(PollFn<PhantomPinned>: Unpin);
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_poll_fn() {
|
||||
let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
@@ -64,4 +94,29 @@ mod tests {
|
||||
.await;
|
||||
assert_eq!(res, 42);
|
||||
}
|
||||
|
||||
// following soundness tests taken from https://github.com/tokio-rs/tokio/pull/5087
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn require_send<T: Send>(_t: &T) {}
|
||||
#[allow(dead_code)]
|
||||
fn require_sync<T: Sync>(_t: &T) {}
|
||||
|
||||
trait AmbiguousIfUnpin<A> {
|
||||
fn some_item(&self) {}
|
||||
}
|
||||
impl<T: ?Sized> AmbiguousIfUnpin<()> for T {}
|
||||
impl<T: ?Sized + Unpin> AmbiguousIfUnpin<[u8; 0]> for T {}
|
||||
|
||||
const _: fn() = || {
|
||||
let pinned = std::marker::PhantomPinned;
|
||||
let f = poll_fn(move |_| {
|
||||
// Use `pinned` to take ownership of it.
|
||||
let _ = &pinned;
|
||||
std::task::Poll::Pending::<()>
|
||||
});
|
||||
require_send(&f);
|
||||
require_sync(&f);
|
||||
AmbiguousIfUnpin::some_item(&f);
|
||||
};
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
//! When MSRV is 1.48, replace with `core::future::Ready` and `core::future::ready()`.
|
||||
//! When `core::future::Ready` has a `into_inner()` method, this can be deprecated.
|
||||
|
||||
use core::{
|
||||
future::Future,
|
||||
@@ -6,7 +6,7 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Future for the [`ready`](ready()) function.
|
||||
/// Future for the [`ready`] function.
|
||||
///
|
||||
/// Panic will occur if polled more than once.
|
||||
///
|
||||
|
@@ -1,8 +1,16 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 1.1.0 - 2022-06-11
|
||||
- Implement `From<Box<str>>` for `ByteString`. [#458]
|
||||
- Implement `Into<String>` for `ByteString`. [#458]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#458]: https://github.com/actix/actix-net/pull/458
|
||||
|
||||
|
||||
## 1.0.0 - 2020-12-31
|
||||
- Update `bytes` dependency to `1`.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bytestring"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -18,7 +18,7 @@ name = "bytestring"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1"
|
||||
bytes = "1.2"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -6,7 +6,11 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
@@ -68,7 +72,7 @@ impl AsRef<[u8]> for ByteString {
|
||||
|
||||
impl AsRef<str> for ByteString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +96,7 @@ impl ops::Deref for ByteString {
|
||||
|
||||
impl borrow::Borrow<str> for ByteString {
|
||||
fn borrow(&self) -> &str {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +114,20 @@ impl From<&str> for ByteString {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<str>> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: Box<str>) -> Self {
|
||||
Self(Bytes::from(value.into_boxed_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ByteString> for String {
|
||||
#[inline]
|
||||
fn from(value: ByteString) -> Self {
|
||||
value.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
msrv = "1.48"
|
||||
msrv = "1.57"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.1.3 - 2022-05-03
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.1.3 - 2022-05-03
|
||||
|
Reference in New Issue
Block a user