use std::error::Error as StdError; use std::marker::Unpin; #[cfg(feature = "runtime")] use std::time::Duration;
use bytes::Bytes; use h2::server::{Connection, Handshake, SendResponse}; use h2::{Reason, RecvStream}; use http::{Method, Request}; use pin_project_lite::pin_project; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::{debug, trace, warn};
// Our defaults are chosen for the "majority" case, which usually are not // resource constrained, and so the spec default of 64kb can be too limiting // for performance. // // At the same time, a server more often has multiple clients connected, and // so is more likely to use more resources than a client would. const DEFAULT_CONN_WINDOW: u32 = 1024 * 1024; // 1mb const DEFAULT_STREAM_WINDOW: u32 = 1024 * 1024; // 1mb const DEFAULT_MAX_FRAME_SIZE: u32 = 1024 * 16; // 16kb const DEFAULT_MAX_SEND_BUF_SIZE: usize = 1024 * 400; // 400kb // 16 MB "sane default" taken from golang http2 const DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: u32 = 16 << 20;
let bdp = if config.adaptive_window {
Some(config.initial_stream_window_size)
} else {
None
};
let ping_config = ping::Config {
bdp_initial_window: bdp, #[cfg(feature = "runtime")]
keep_alive_interval: config.keep_alive_interval, #[cfg(feature = "runtime")]
keep_alive_timeout: config.keep_alive_timeout, // If keep-alive is enabled for servers, always enabled while // idle, so it can more aggressively close dead connections. #[cfg(feature = "runtime")]
keep_alive_while_idle: true,
};
// Check that the service is ready to accept a new request. // // - If not, just drive the connection some. // - If ready, try to accept a new request from the connection. match service.poll_ready(cx) {
Poll::Ready(Ok(())) => (),
Poll::Pending => { // use `poll_closed` instead of `poll_accept`, // in order to avoid accepting a request.
ready!(self.conn.poll_closed(cx).map_err(crate::Error::new_h2))?;
trace!("incoming connection complete"); return Poll::Ready(Ok(()));
}
Poll::Ready(Err(err)) => { let err = crate::Error::new_user_service(err);
debug!("service closed: {}", err);
let reason = err.h2_reason(); if reason == Reason::NO_ERROR { // NO_ERROR is only used for graceful shutdowns...
trace!("interpreting NO_ERROR user error as graceful_shutdown"); self.conn.graceful_shutdown();
} else {
trace!("abruptly shutting down with {:?}", reason); self.conn.abrupt_shutdown(reason);
} self.closing = Some(err); break;
}
}
// When the service is ready, accepts an incoming request. match ready!(self.conn.poll_accept(cx)) {
Some(Ok((req, mut respond))) => {
trace!("incoming request"); let content_length = headers::content_length_parse_all(req.headers()); let ping = self
.ping
.as_ref()
.map(|ping| ping.0.clone())
.unwrap_or_else(ping::disabled);
// Record the headers received
ping.record_non_data();
let is_connect = req.method() == Method::CONNECT; let (mut parts, stream) = req.into_parts(); let (mut req, connect_parts) = if !is_connect {
(
Request::from_parts(
parts, crate::Body::h2(stream, content_length.into(), ping),
),
None,
)
} else { if content_length.map_or(false, |len| len != 0) {
warn!("h2 connect request with non-zero body not supported");
respond.send_reset(h2::Reason::INTERNAL_ERROR); return Poll::Ready(Ok(()));
} let (pending, upgrade) = crate::upgrade::pending();
debug_assert!(parts.extensions.get::<OnUpgrade>().is_none());
parts.extensions.insert(upgrade);
(
Request::from_parts(parts, crate::Body::empty()),
Some(ConnectParts {
pending,
ping,
recv_stream: stream,
}),
)
};
¤ 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.0.14Bemerkung:
(vorverarbeitet am 2026-06-21)
¤
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.