experimental h3

This commit is contained in:
Jun Kurihara 2022-07-05 19:17:35 +09:00
commit 981a81abb2
No known key found for this signature in database
GPG key ID: 48ADFD173ED22B03
2 changed files with 47 additions and 31 deletions

View file

@ -38,7 +38,7 @@ where
while let Some((req, stream)) = h3_conn while let Some((req, stream)) = h3_conn
.accept() .accept()
.await .await
.map_err(|e| anyhow!("HTTP/3 accept failed (likely timeout): {}", e))? .map_err(|e| anyhow!("HTTP/3 accept failed: {}", e))?
{ {
info!("HTTP/3 new request received"); info!("HTTP/3 new request received");

View file

@ -79,6 +79,7 @@ where
#[cfg(feature = "h3")] #[cfg(feature = "h3")]
let listener_service_h3 = async { let listener_service_h3 = async {
// TODO: Work around to initially serve incoming connection // TODO: Work around to initially serve incoming connection
// かなり適当。エラーが出たり出なかったり。原因がわからない…
let tls_app_names: Vec<String> = self let tls_app_names: Vec<String> = self
.backends .backends
.apps .apps
@ -95,40 +96,55 @@ where
let server_crypto = backend_serve.get_tls_server_config().unwrap(); let server_crypto = backend_serve.get_tls_server_config().unwrap();
let server_config_h3 = quinn::ServerConfig::with_crypto(Arc::new(server_crypto)); let server_config_h3 = quinn::ServerConfig::with_crypto(Arc::new(server_crypto));
let (endpoint, mut incoming) = let (endpoint, incoming) =
quinn::Endpoint::server(server_config_h3, self.listening_on).unwrap(); quinn::Endpoint::server(server_config_h3, self.listening_on).unwrap();
debug!("HTTP/3 UDP listening on {}", endpoint.local_addr().unwrap()); debug!("HTTP/3 UDP listening on {}", endpoint.local_addr().unwrap());
// let peekable_incoming = incoming.peekable(); let mut p = incoming.peekable();
loop {
while let Some(mut conn) = incoming.next().await { // TODO: Not sure if this properly works to handle multiple "server_name"s to host multiple hosts.
let hsd = conn.handshake_data().await; // peek() should work for that.
if let Some(peeked_conn) = std::pin::Pin::new(&mut p).peek_mut().await {
let hsd = peeked_conn.handshake_data().await;
let hsd_downcast = hsd? let hsd_downcast = hsd?
.downcast::<quinn::crypto::rustls::HandshakeData>() .downcast::<quinn::crypto::rustls::HandshakeData>()
.unwrap(); .unwrap();
let svn = if let Some(sni) = hsd_downcast.server_name { let svn = if let Some(sni) = hsd_downcast.server_name {
info!("HTTP/3 connection incoming (SNI {:?})", sni);
sni sni
} else { } else {
debug!("HTTP/3 no SNI is given"); debug!("HTTP/3 no SNI is given");
continue; continue;
}; };
let new_server_crypto = if let Some(p) = self.fetch_server_crypto(&svn) { let new_server_crypto = if let Some(p) = self.fetch_server_crypto(&svn) {
p p
} else { } else {
continue; continue;
}; };
// Set ServerConfig::set_server_config for given SNI // Set ServerConfig::set_server_config for given SNI
let new_server_config_h3 = quinn::ServerConfig::with_crypto(Arc::new(new_server_crypto)); let mut new_server_config_h3 =
quinn::ServerConfig::with_crypto(Arc::new(new_server_crypto));
if svn == "localhost" {
new_server_config_h3.concurrent_connections(512);
}
info!(
"HTTP/3 connection incoming (SNI {:?}): Overwrite ServerConfig",
svn
);
endpoint.set_server_config(Some(new_server_config_h3)); endpoint.set_server_config(Some(new_server_config_h3));
}
// Then acquire actual connection
let peekable_incoming = std::pin::Pin::new(&mut p);
if let Some(conn) = peekable_incoming.get_mut().next().await {
let fut = self.clone().client_serve_h3(conn); let fut = self.clone().client_serve_h3(conn);
self.globals.runtime_handle.spawn(async { self.globals.runtime_handle.spawn(async {
if let Err(e) = fut.await { if let Err(e) = fut.await {
warn!("QUIC or HTTP/3 connection failed: {}", e) warn!("QUIC or HTTP/3 connection failed: {}", e)
} }
}); });
} else {
break;
}
} }
endpoint.wait_idle().await; endpoint.wait_idle().await;
Ok(()) as Result<()> Ok(()) as Result<()>