/// Creates a new `AddrIncoming` binding to provided socket address. pubfn bind(addr: &SocketAddr) -> crate::Result<Self> {
AddrIncoming::new(addr)
}
/// Creates a new `AddrIncoming` from an existing `tokio::net::TcpListener`. pubfn from_listener(listener: TcpListener) -> crate::Result<Self> { let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
Ok(AddrIncoming {
listener,
addr,
sleep_on_errors: true,
tcp_keepalive_config: TcpKeepaliveConfig::default(),
tcp_nodelay: false,
timeout: None,
})
}
/// Get the local address bound to this listener. pubfn local_addr(&self) -> SocketAddr { self.addr
}
/// Set the duration to remain idle before sending TCP keepalive probes. /// /// If `None` is specified, keepalive is disabled. pubfn set_keepalive(&mutself, time: Option<Duration>) -> &e='color:red'>mutSelf { self.tcp_keepalive_config.time = time; self
}
/// Set the duration between two successive TCP keepalive retransmissions, /// if acknowledgement to the previous keepalive transmission is not received. pubfn set_keepalive_interval(&mutself, interval: Option<Duration>) -> &mutSelf { self.tcp_keepalive_config.interval = interval; self
}
/// Set the number of retransmissions to be carried out before declaring that remote end is not available. pubfn set_keepalive_retries(&mutself, retries: Option<u32>) -> &n style='color:red'>mut Self { self.tcp_keepalive_config.retries = retries; self
}
/// Set the value of `TCP_NODELAY` option for accepted connections. pubfn set_nodelay(&mutself, enabled: bool) -> &mutSelf { self.tcp_nodelay = enabled; self
}
/// Set whether to sleep on accept errors. /// /// A possible scenario is that the process has hit the max open files /// allowed, and so trying to accept a new connection will fail with /// `EMFILE`. In some cases, it's preferable to just wait for some time, if /// the application will likely close some files (or connections), and try /// to accept the connection again. If this option is `true`, the error /// will be logged at the `error` level, since it is still a big deal, /// and then the listener will sleep for 1 second. /// /// In other cases, hitting the max open files should be treat similarly /// to being out-of-memory, and simply error (and shutdown). Setting /// this option to `false` will allow that. /// /// Default is `true`. pubfn set_sleep_on_errors(&mutself, val: bool) { self.sleep_on_errors = val;
}
fn poll_next_(&mutself, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> { // Check if a previous timeout is active that was set by IO errors. iflet Some(refmut to) = self.timeout {
ready!(Pin::new(to).poll(cx));
} self.timeout = None;
loop { match ready!(self.listener.poll_accept(cx)) {
Ok((socket, remote_addr)) => { iflet Some(tcp_keepalive) = &self.tcp_keepalive_config.into_socket2() { let sock_ref = socket2::SockRef::from(&socket); iflet Err(e) = sock_ref.set_tcp_keepalive(tcp_keepalive) {
trace!("error trying to set TCP keepalive: {}", e);
}
} iflet Err(e) = socket.set_nodelay(self.tcp_nodelay) {
trace!("error trying to set TCP nodelay: {}", e);
} let local_addr = socket.local_addr()?; return Poll::Ready(Ok(AddrStream::new(socket, remote_addr, local_addr)));
}
Err(e) => { // Connection errors can be ignored directly, continue by // accepting the next request. if is_connection_error(&e) {
debug!("accepted connection already errored: {}", e); continue;
}
match timeout.as_mut().poll(cx) {
Poll::Ready(()) => { // Wow, it's been a second already? Ok then... continue;
}
Poll::Pending => { self.timeout = Some(timeout); return Poll::Pending;
}
}
} else { return Poll::Ready(Err(e));
}
}
}
}
}
}
impl Accept for AddrIncoming { type Conn = AddrStream; type Error = io::Error;
fn poll_accept( mutself: Pin<&mutSelf>,
cx: &mut task::Context<'_>,
) -> Poll<Option<Result<Self::Conn, Self::Error>>> { let result = ready!(self.poll_next_(cx));
Poll::Ready(Some(result))
}
}
/// 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 is_connection_error(e: &io::Error) -> bool {
matches!(
e.kind(),
io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionReset
)
}
mod addr_stream { use std::io; use std::net::SocketAddr; #[cfg(unix)] use std::os::unix::io::{AsRawFd, RawFd}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use tokio::net::TcpStream;
usecrate::common::{task, Pin, Poll};
pin_project_lite::pin_project! { /// A transport returned yieled by `AddrIncoming`. #[derive(Debug)] pubstruct AddrStream { #[pin]
inner: TcpStream, pub(super) remote_addr: SocketAddr, pub(super) local_addr: SocketAddr
}
}
/// Returns the remote (peer) address of this connection. #[inline] pubfn remote_addr(&self) -> SocketAddr { self.remote_addr
}
/// Returns the local address of this connection. #[inline] pubfn local_addr(&self) -> SocketAddr { self.local_addr
}
/// Consumes the AddrStream and returns the underlying IO object #[inline] pubfn into_inner(self) -> TcpStream { self.inner
}
/// Attempt to receive data on the socket, without removing that data /// from the queue, registering the current task for wakeup if data is /// not yet available. pubfn poll_peek(
&mutself,
cx: &mut task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<io::Result<usize>> { self.inner.poll_peek(cx, buf)
}
}
#[inline] fn is_write_vectored(&self) -> bool { // Note that since `self.inner` is a `TcpStream`, this could // *probably* be hard-coded to return `true`...but it seems more // correct to ask it anyway (maybe we're on some platform without // scatter-gather IO?) self.inner.is_write_vectored()
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.