v0.34.0_1
This commit is contained in:
1 parent
9b3d6731cc
commit
00f29f92c8
68 files changed
+2599
-513
No files matched your search
+20
-199
@@ -134,6 +134,7 @@ async fn serve_inner(
|
||||
stop,
|
||||
grace,
|
||||
http2_settings,
|
||||
Default::default(),
|
||||
)
|
||||
.await;
|
||||
},
|
||||
@@ -178,6 +179,7 @@ async fn serve_inner(
|
||||
stop,
|
||||
grace,
|
||||
Http2Connections::default(),
|
||||
Default::default(),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
@@ -208,6 +210,7 @@ async fn serve_inner(
|
||||
stop,
|
||||
grace,
|
||||
Http2Connections::default(),
|
||||
Default::default(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -242,6 +245,22 @@ async fn serve_inner(
|
||||
&& frontend_state
|
||||
.as_ref()
|
||||
.is_some_and(|state| state.config.load().websocket_rfc8441_on(local, false));
|
||||
// The existing Hyper transport remains untouched when the
|
||||
// option is disabled. Connections opened after a hot config
|
||||
// change acquire a new bridge automatically.
|
||||
#[cfg(target_os = "linux")]
|
||||
if !prior_h2 && frontend_state.as_ref().is_some_and(|state| {
|
||||
state.config.load().web_php_services.values()
|
||||
.any(|service| service.sendfile == crate::web_server::SendfileMode::Auto)
|
||||
}) {
|
||||
let (io, slots) = sendfile::SendfileIo::new(stream);
|
||||
connection(
|
||||
io, router, peer, local, Transport { tls: false }, None,
|
||||
false, false, h2c, frontend_state, lease, stop, grace,
|
||||
http2_settings, Some(slots),
|
||||
).await;
|
||||
return;
|
||||
}
|
||||
connection(
|
||||
stream,
|
||||
router,
|
||||
@@ -257,6 +276,7 @@ async fn serve_inner(
|
||||
stop,
|
||||
grace,
|
||||
http2_settings,
|
||||
Default::default(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -273,205 +293,6 @@ async fn serve_inner(
|
||||
while tasks.join_next().await.is_some() {}
|
||||
Ok(())
|
||||
}
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn connection<I>(
|
||||
stream: I,
|
||||
router: Router,
|
||||
peer: SocketAddr,
|
||||
local: SocketAddr,
|
||||
transport: Transport,
|
||||
tls_sni: Option<String>,
|
||||
h2: bool,
|
||||
extended_connect: bool,
|
||||
h2c_upgrade: bool,
|
||||
frontend_state: Option<Arc<App>>,
|
||||
lease: Arc<ConnectionLease>,
|
||||
stop: CancellationToken,
|
||||
grace: Duration,
|
||||
http2_settings: Http2Connections,
|
||||
) where
|
||||
I: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
{
|
||||
if h2 {
|
||||
http2_connection(
|
||||
stream,
|
||||
router,
|
||||
peer,
|
||||
local,
|
||||
transport,
|
||||
tls_sni.clone(),
|
||||
extended_connect,
|
||||
frontend_state.clone(),
|
||||
lease,
|
||||
stop,
|
||||
grace,
|
||||
http2_settings,
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
let request_stop = stop.clone();
|
||||
let service_frontend_state = frontend_state.clone();
|
||||
let service = service_fn(move |mut request: Request<Incoming>| {
|
||||
let router = router.clone();
|
||||
let request_stop = request_stop.clone();
|
||||
let request_lease = lease.clone();
|
||||
let upgrade_state = service_frontend_state.clone();
|
||||
async move {
|
||||
request.extensions_mut().insert(PeerAddr(peer));
|
||||
request.extensions_mut().insert(LocalAddr(local));
|
||||
request.extensions_mut().insert(transport);
|
||||
request.extensions_mut().insert(request_lease.clone());
|
||||
request
|
||||
.extensions_mut()
|
||||
.insert(ServerShutdown(request_stop.clone()));
|
||||
|
||||
if h2c_attempt(&request) {
|
||||
if !h2c_upgrade {
|
||||
let (authority, host) = request_log_identity(&request);
|
||||
log_protocol_error_with_identity(
|
||||
upgrade_state.as_ref(),
|
||||
"h2c_upgrade_rejected",
|
||||
"h2c upgrade is disabled on this listener",
|
||||
peer,
|
||||
local,
|
||||
"tcp",
|
||||
"1.1",
|
||||
400,
|
||||
authority,
|
||||
host,
|
||||
None,
|
||||
);
|
||||
return Ok::<_, Infallible>(
|
||||
Response::builder()
|
||||
.status(http::StatusCode::BAD_REQUEST)
|
||||
.header(http::header::CACHE_CONTROL, "no-store")
|
||||
.body(Body::from("h2c upgrade is disabled on this listener"))
|
||||
.expect("static h2c disabled response"),
|
||||
);
|
||||
}
|
||||
let injected_headers = match h2_headers_frame(&request) {
|
||||
Ok(frame) => frame,
|
||||
Err(message) => {
|
||||
let (authority, host) = request_log_identity(&request);
|
||||
log_protocol_error_with_identity(
|
||||
upgrade_state.as_ref(),
|
||||
"h2c_upgrade_invalid",
|
||||
message,
|
||||
peer,
|
||||
local,
|
||||
"tcp",
|
||||
"1.1",
|
||||
400,
|
||||
authority,
|
||||
host,
|
||||
None,
|
||||
);
|
||||
return Ok::<_, Infallible>(
|
||||
Response::builder()
|
||||
.status(http::StatusCode::BAD_REQUEST)
|
||||
.header(http::header::CACHE_CONTROL, "no-store")
|
||||
.body(Body::from(message))
|
||||
.expect("static h2c validation response"),
|
||||
);
|
||||
}
|
||||
};
|
||||
let on_upgrade = hyper::upgrade::on(&mut request);
|
||||
let upgrade_router = router.clone();
|
||||
let upgrade_stop = request_stop.clone();
|
||||
let upgrade_lease = request_lease.clone();
|
||||
let upgrade_state_for_task = upgrade_state.clone();
|
||||
let task = async move {
|
||||
match on_upgrade.await {
|
||||
Ok(upgraded) => {
|
||||
if let Some(state) = &upgrade_state_for_task {
|
||||
state
|
||||
.metrics
|
||||
.http2_connections
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
let extended_connect =
|
||||
upgrade_state_for_task.as_ref().is_some_and(|state| {
|
||||
state.config.load().websocket_rfc8441_on(local, false)
|
||||
});
|
||||
let io = H2cUpgradeIo::new(TokioIo::new(upgraded), injected_headers);
|
||||
http2_connection(
|
||||
io,
|
||||
upgrade_router,
|
||||
peer,
|
||||
local,
|
||||
Transport { tls: false },
|
||||
None,
|
||||
extended_connect,
|
||||
upgrade_state_for_task.clone(),
|
||||
upgrade_lease,
|
||||
upgrade_stop,
|
||||
grace,
|
||||
http2_settings,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(error) => {
|
||||
log_protocol_error(
|
||||
upgrade_state_for_task.as_ref(),
|
||||
"h2c_transport_error",
|
||||
&error,
|
||||
peer,
|
||||
local,
|
||||
"tcp",
|
||||
"2",
|
||||
0,
|
||||
None,
|
||||
);
|
||||
tracing::debug!(%error, "h2c upgrade transport failed");
|
||||
}
|
||||
}
|
||||
};
|
||||
if let Some(state) = upgrade_state {
|
||||
state.tunnels.spawn(task);
|
||||
} else {
|
||||
tokio::spawn(task);
|
||||
}
|
||||
return Ok::<_, Infallible>(
|
||||
Response::builder()
|
||||
.status(http::StatusCode::SWITCHING_PROTOCOLS)
|
||||
.header(http::header::CONNECTION, "Upgrade")
|
||||
.header(http::header::UPGRADE, "h2c")
|
||||
.body(Body::empty())
|
||||
.expect("static h2c switching response"),
|
||||
);
|
||||
}
|
||||
|
||||
router.oneshot(request.map(Body::new)).await
|
||||
}
|
||||
});
|
||||
let mut builder = http1::Builder::new();
|
||||
builder
|
||||
.timer(TokioTimer::new())
|
||||
.keep_alive(true)
|
||||
.max_headers(64)
|
||||
.max_buf_size(65_536)
|
||||
.header_read_timeout(Duration::from_secs(10));
|
||||
let conn = builder
|
||||
.serve_connection(TokioIo::new(stream), service)
|
||||
.with_upgrades();
|
||||
tokio::pin!(conn);
|
||||
tokio::select! {
|
||||
result = &mut conn => {
|
||||
if let Err(error) = result {
|
||||
log_protocol_error(
|
||||
frontend_state.as_ref(), "http1_connection_error", &error, peer, local,
|
||||
if transport.tls { "tls" } else { "tcp" }, "1.1", 400, tls_sni.clone(),
|
||||
);
|
||||
tracing::debug!(%error, "HTTP/1 connection closed");
|
||||
}
|
||||
},
|
||||
_ = stop.cancelled() => {
|
||||
conn.as_mut().graceful_shutdown(); let _ = tokio::time::timeout(grace, &mut conn).await;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum H2ShutdownCause {
|
||||
Idle,
|
||||
|
||||
Reference in new issue
Block a user