Merge branch 'master' into master

This commit is contained in:
Ibraheem Ahmed 2022-01-31 21:36:22 -05:00 committed by GitHub
commit 1b757ad214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 167 additions and 75 deletions

View File

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

View File

@ -193,7 +193,7 @@ impl<T, U> Framed<T, U> {
match this.codec.decode_eof(this.read_buf) {
Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
Ok(None) => return Poll::Ready(None),
Err(e) => return Poll::Ready(Some(Err(e))),
Err(err) => return Poll::Ready(Some(Err(err))),
}
}
@ -204,7 +204,7 @@ impl<T, U> Framed<T, U> {
log::trace!("frame decoded from buffer");
return Poll::Ready(Some(Ok(frame)));
}
Err(e) => return Poll::Ready(Some(Err(e))),
Err(err) => return Poll::Ready(Some(Err(err))),
_ => (), // Need more data
}
@ -221,7 +221,7 @@ impl<T, U> Framed<T, U> {
let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
Poll::Pending => return Poll::Pending,
Poll::Ready(Err(e)) => return Poll::Ready(Some(Err(e.into()))),
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
Poll::Ready(Ok(cnt)) => cnt,
};

View File

@ -50,7 +50,7 @@ impl Write for Bilateral {
assert_eq!(&data[..], &src[..data.len()]);
Ok(data.len())
}
Some(Err(e)) => Err(e),
Some(Err(err)) => Err(err),
None => panic!("unexpected write; {:?}", src),
}
}
@ -67,13 +67,13 @@ impl AsyncWrite for Bilateral {
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
match Pin::get_mut(self).write(buf) {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
other => Ready(other),
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
match Pin::get_mut(self).flush() {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
other => Ready(other),
}
}
@ -99,8 +99,8 @@ impl AsyncRead for Bilateral {
buf.put_slice(&data);
Ready(Ok(()))
}
Some(Err(ref e)) if e.kind() == WouldBlock => Pending,
Some(Err(e)) => Ready(Err(e)),
Some(Err(ref err)) if err.kind() == WouldBlock => Pending,
Some(Err(err)) => Ready(Err(err)),
None => Ready(Ok(())),
}
}

View File

@ -35,4 +35,4 @@ tokio-uring = { version = "0.2", optional = true }
[dev-dependencies]
tokio = { version = "1.13.1", features = ["full"] }
hyper = { version = "0.14", default-features = false, features = ["server", "tcp", "http1"] }
hyper = { version = "0.14.10", default-features = false, features = ["server", "tcp", "http1"] }

View File

@ -21,8 +21,8 @@ fn main() {
let server =
Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
if let Err(err) = server.await {
eprintln!("server error: {}", err);
}
})
}

View File

@ -127,10 +127,10 @@ impl Accept {
let mut events = mio::Events::with_capacity(256);
loop {
if let Err(e) = self.poll.poll(&mut events, self.timeout) {
match e.kind() {
if let Err(err) = self.poll.poll(&mut events, self.timeout) {
match err.kind() {
io::ErrorKind::Interrupted => {}
_ => panic!("Poll error: {}", e),
_ => panic!("Poll error: {}", err),
}
}
@ -298,15 +298,15 @@ impl Accept {
fn register_logged(&self, info: &mut ServerSocketInfo) {
match self.register(info) {
Ok(_) => debug!("Resume accepting connections on {}", info.lst.local_addr()),
Err(e) => error!("Can not register server socket {}", e),
Err(err) => error!("Can not register server socket {}", err),
}
}
fn deregister_logged(&self, info: &mut ServerSocketInfo) {
match self.poll.registry().deregister(&mut info.lst) {
Ok(_) => debug!("Paused accepting connections on {}", info.lst.local_addr()),
Err(e) => {
error!("Can not deregister server socket {}", e)
Err(err) => {
error!("Can not deregister server socket {}", err)
}
}
}
@ -396,10 +396,10 @@ impl Accept {
let conn = Conn { io, token };
self.accept_one(conn);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return,
Err(ref e) if connection_error(e) => continue,
Err(e) => {
error!("Error accepting connection: {}", e);
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return,
Err(ref err) if connection_error(err) => continue,
Err(err) => {
error!("Error accepting connection: {}", err);
// deregister listener temporary
self.deregister_logged(info);

View File

@ -220,10 +220,10 @@ impl ServerBuilder {
{
// The path must not exist when we try to bind.
// Try to remove it to avoid bind error.
if let Err(e) = std::fs::remove_file(addr.as_ref()) {
if let Err(err) = std::fs::remove_file(addr.as_ref()) {
// NotFound is expected and not an issue. Anything else is.
if e.kind() != std::io::ErrorKind::NotFound {
return Err(e);
if err.kind() != std::io::ErrorKind::NotFound {
return Err(err);
}
}
@ -264,22 +264,23 @@ pub(super) fn bind_addr<S: ToSocketAddrs>(
addr: S,
backlog: u32,
) -> io::Result<Vec<MioTcpListener>> {
let mut err = None;
let mut opt_err = None;
let mut success = false;
let mut sockets = Vec::new();
for addr in addr.to_socket_addrs()? {
match create_mio_tcp_listener(addr, backlog) {
Ok(lst) => {
success = true;
sockets.push(lst);
}
Err(e) => err = Some(e),
Err(err) => opt_err = Some(err),
}
}
if success {
Ok(sockets)
} else if let Some(err) = err.take() {
} else if let Some(err) = opt_err.take() {
Err(err)
} else {
Err(io::Error::new(

View File

@ -77,8 +77,8 @@ where
});
Ok(())
}
Err(e) => {
error!("Can not convert to an async tcp stream: {}", e);
Err(err) => {
error!("Can not convert to an async tcp stream: {}", err);
Err(())
}
})

View File

@ -97,7 +97,7 @@ where
match this.fut.poll(cx) {
Poll::Ready(Ok(resp)) => Poll::Ready(Ok((this.f)(resp))),
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
Poll::Pending => Poll::Pending,
}
}

View File

@ -3,6 +3,12 @@
## Unreleased - 2021-xx-xx
## 3.0.2 - 2022-01-28
- Expose `connect::Connection::new`. [#439]
[#439]: https://github.com/actix/actix-net/pull/439
## 3.0.1 - 2022-01-11
- No significant changes since `3.0.0`.
@ -16,6 +22,7 @@
[#429]: https://github.com/actix/actix-net/pull/429
## 3.0.0-rc.1 - 2021-11-29
### Added
- Derive `Debug` for `connect::Connection`. [#422]

View File

@ -1,6 +1,6 @@
[package]
name = "actix-tls"
version = "3.0.1"
version = "3.0.2"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@ -47,7 +47,6 @@ actix-rt = { version = "2.2.0", default-features = false }
actix-service = "2.0.0"
actix-utils = "3.0.0"
derive_more = "0.99.5"
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
log = "0.4"
pin-project-lite = "0.2.7"

View File

@ -2,11 +2,12 @@
use std::{
convert::Infallible,
error::Error,
fmt,
sync::atomic::{AtomicUsize, Ordering},
};
use actix_utils::counter::Counter;
use derive_more::{Display, Error};
#[cfg(feature = "openssl")]
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
@ -43,23 +44,45 @@ pub fn max_concurrent_tls_connect(num: usize) {
/// TLS handshake error, TLS timeout, or inner service error.
///
/// All TLS acceptors from this crate will return the `SvcErr` type parameter as [`Infallible`],
/// which can be cast to your own service type, inferred or otherwise,
/// using [`into_service_error`](Self::into_service_error).
#[derive(Debug, Display, Error)]
/// which can be cast to your own service type, inferred or otherwise, using [`into_service_error`].
///
/// [`into_service_error`]: Self::into_service_error
#[derive(Debug)]
pub enum TlsError<TlsErr, SvcErr> {
/// TLS handshake has timed-out.
#[display(fmt = "TLS handshake has timed-out")]
Timeout,
/// Wraps TLS service errors.
#[display(fmt = "TLS handshake error")]
Tls(TlsErr),
/// Wraps service errors.
#[display(fmt = "Service error")]
Service(SvcErr),
}
impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Timeout => f.write_str("TLS handshake has timed-out"),
Self::Tls(_) => f.write_str("TLS handshake error"),
Self::Service(_) => f.write_str("Service error"),
}
}
}
impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
where
TlsErr: Error + 'static,
SvcErr: Error + 'static,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
TlsError::Tls(err) => Some(err),
TlsError::Service(err) => Some(err),
TlsError::Timeout => None,
}
}
}
impl<TlsErr> TlsError<TlsErr, Infallible> {
/// Casts the infallible service error type returned from acceptors into caller's type.
///

View File

@ -20,11 +20,11 @@ use actix_utils::{
counter::Counter,
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
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.
@ -33,9 +33,12 @@ pub mod reexports {
}
/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
impl_more::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<IO: ActixStream> AsyncRead for TlsStream<IO> {
fn poll_read(
self: Pin<&mut Self>,

View File

@ -21,11 +21,11 @@ use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
use openssl::ssl::{Error, Ssl, SslAcceptor};
use pin_project_lite::pin_project;
use 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.
@ -36,9 +36,12 @@ pub mod reexports {
}
/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
impl_more::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<IO: ActixStream> AsyncRead for TlsStream<IO> {
fn poll_read(
self: Pin<&mut Self>,

View File

@ -22,12 +22,12 @@ use actix_utils::{
counter::{Counter, CounterGuard},
future::{ready, Ready as FutReady},
};
use derive_more::{Deref, DerefMut, From};
use pin_project_lite::pin_project;
use tokio_rustls::rustls::ServerConfig;
use tokio_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.
@ -36,9 +36,12 @@ pub mod reexports {
}
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
#[derive(Deref, DerefMut, From)]
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
impl_more::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<IO: ActixStream> AsyncRead for TlsStream<IO> {
fn poll_read(
self: Pin<&mut Self>,

View File

@ -1,20 +1,19 @@
use derive_more::{Deref, DerefMut};
use super::Host;
use crate::impl_more;
/// Wraps underlying I/O and the connection request that initiated it.
#[derive(Debug, Deref, DerefMut)]
#[derive(Debug)]
pub struct Connection<R, IO> {
pub(crate) req: R,
#[deref]
#[deref_mut]
pub(crate) io: IO,
}
impl_more::deref! { Connection<R, IO> => io: IO }
impl_more::deref_mut! { Connection<R, IO> => io }
impl<R, IO> Connection<R, IO> {
/// Construct new `Connection` from request and IO parts.
pub(crate) fn new(req: R, io: IO) -> Self {
pub fn new(req: R, io: IO) -> Self {
Self { req, io }
}
}

View File

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

View File

@ -141,9 +141,12 @@ where
trace!("SSL Handshake success: {:?}", stream.hostname());
Poll::Ready(Ok(stream.replace_io(this.io.take().unwrap()).1))
}
Err(e) => {
trace!("SSL Handshake error: {:?}", e);
Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, format!("{}", e))))
Err(err) => {
trace!("SSL Handshake error: {:?}", err);
Poll::Ready(Err(io::Error::new(
io::ErrorKind::Other,
format!("{}", err),
)))
}
}
}

View File

@ -164,8 +164,8 @@ impl<R: Host> Future for ResolverFut<R> {
Self::LookUp(fut, req) => {
let res = match ready!(Pin::new(fut).poll(cx)) {
Ok(Ok(res)) => Ok(res),
Ok(Err(e)) => Err(ConnectError::Resolver(Box::new(e))),
Err(e) => Err(ConnectError::Io(e.into())),
Ok(Err(err)) => Err(ConnectError::Resolver(Box::new(err))),
Err(err) => Err(ConnectError::Io(err.into())),
};
let req = req.take().unwrap();

View File

@ -0,0 +1,40 @@
/// 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};

View File

@ -18,3 +18,5 @@ pub mod accept;
#[cfg(feature = "connect")]
#[cfg_attr(docsrs, doc(cfg(feature = "connect")))]
pub mod connect;
mod impl_more;