From c1ac6de53cdef6eb006e89a04bc6684f29b616f3 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 09:19:51 -0700 Subject: [PATCH 1/4] commonize HTTP/HTTPS paths and use more structured errors internally --- Cargo.lock | 9 +- dropshot/Cargo.toml | 1 + dropshot/src/server.rs | 484 +++++++++++++++++------------------------ 3 files changed, 203 insertions(+), 291 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06d7bcfb9..bb3458144 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,7 @@ dependencies = [ "slog-term", "subprocess", "tempfile", + "thiserror", "tokio", "tokio-rustls", "tokio-tungstenite", @@ -1838,18 +1839,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index 21c908a87..f41d22a01 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -42,6 +42,7 @@ slog-async = "2.8.0" slog-bunyan = "2.5.0" slog-json = "2.6.1" slog-term = "2.9.1" +thiserror = "1.0.64" tokio-rustls = "0.25.0" toml = "0.8.19" waitgroup = "0.1.2" diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 8816c9f77..8272a64d6 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -43,6 +43,7 @@ use waitgroup::WaitGroup; use crate::config::HandlerTaskMode; use crate::RequestInfo; use slog::Logger; +use thiserror::Error; // TODO Replace this with something else? type GenericError = Box; @@ -106,8 +107,9 @@ pub struct ServerConfig { pub struct HttpServerStarter { app_state: Arc>, local_addr: SocketAddr, - wrapped: WrappedHttpServerStarter, handler_waitgroup: WaitGroup, + incoming: HttpAcceptor, + tls_acceptor: Option>>, } impl HttpServerStarter { @@ -127,6 +129,17 @@ impl HttpServerStarter { log: &Logger, tls: Option, ) -> Result, GenericError> { + HttpServerStarter::new_internal(config, api, private, log, tls) + .map_err(|e| Box::new(e) as GenericError) + } + + fn new_internal( + config: &ConfigDropshot, + api: ApiDescription, + private: C, + log: &Logger, + tls: Option, + ) -> Result, BuildError> { let server_config = ServerConfig { // We start aggressively to ensure test coverage. request_body_max_bytes: config.request_body_max_bytes, @@ -135,68 +148,150 @@ impl HttpServerStarter { default_handler_task_mode: config.default_handler_task_mode, log_headers: config.log_headers.clone(), }; - let handler_waitgroup = WaitGroup::new(); - let starter = match &tls { - Some(tls) => { - let (starter, app_state, local_addr) = - InnerHttpsServerStarter::new( - config, - server_config, - api, - private, - log, - tls, - handler_waitgroup.worker(), - )?; - HttpServerStarter { - app_state, - local_addr, - wrapped: WrappedHttpServerStarter::Https(starter), - handler_waitgroup, - } - } - None => { - let (starter, app_state, local_addr) = - InnerHttpServerStarter::new( - config, - server_config, - api, - private, - log, - handler_waitgroup.worker(), - )?; - HttpServerStarter { - app_state, - local_addr, - wrapped: WrappedHttpServerStarter::Http(starter), - handler_waitgroup, - } - } - }; - for (path, method, _) in &starter.app_state.router { - debug!(starter.app_state.log, "registered endpoint"; + let std_listener = std::net::TcpListener::bind(&config.bind_address) + .map_err(|e| BuildError::bind_error(e, config.bind_address))?; + std_listener.set_nonblocking(true).map_err(|e| { + BuildError::generic_system(e, "setting non-blocking") + })?; + // We use `from_std` instead of just calling `bind` here directly + // to avoid invoking an async function. + let tcp = TcpListener::from_std(std_listener).map_err(|e| { + BuildError::generic_system(e, "creating TCP listener") + })?; + let local_addr = tcp.local_addr().map_err(|e| { + BuildError::generic_system(e, "getting local TCP address") + })?; + let incoming = HttpAcceptor { tcp, log: log.clone() }; + + let log = log.new(o!("local_addr" => local_addr)); + + let tls_acceptor = tls + .as_ref() + .map(|tls| { + Ok(Arc::new(Mutex::new(TlsAcceptor::from(Arc::new( + rustls::ServerConfig::try_from(tls)?, + ))))) + }) + .transpose()?; + + let app_state = Arc::new(DropshotState { + private, + config: server_config, + router: api.into_router(), + log: log.clone(), + local_addr, + tls_acceptor: tls_acceptor.clone(), + handler_waitgroup_worker: DebugIgnore(handler_waitgroup.worker()), + }); + + for (path, method, _) in &app_state.router { + debug!(&log, "registered endpoint"; "method" => &method, "path" => &path ); } - Ok(starter) + Ok(HttpServerStarter { + app_state, + local_addr, + handler_waitgroup, + incoming, + tls_acceptor, + }) } pub fn start(self) -> HttpServer { - let (tx, rx) = tokio::sync::oneshot::channel::<()>(); - let log_close = self.app_state.log.new(o!()); - let join_handle = match self.wrapped { - WrappedHttpServerStarter::Http(http) => http.start(rx, log_close), - WrappedHttpServerStarter::Https(https) => { - https.start(rx, log_close) - } - }; - info!(self.app_state.log, "listening"); + let HttpServerStarter { + app_state, + local_addr, + handler_waitgroup, + tls_acceptor, + incoming, // XXX-dap rename + } = self; + + let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); + + let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); + + let log = &app_state.log; + let log_close = log.clone(); + let join_handle = tokio::spawn(async move { + use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; + use hyper_util::server::conn::auto; + + let mut builder = auto::Builder::new(TokioExecutor::new()); + // http/1 settings + builder.http1().timer(TokioTimer::new()); + // XXX-dap previously, the TLS one did NOT do this http2 step + // http/2 settings + builder.http2().timer(TokioTimer::new()); + + // Use a graceful watcher to keep track of all existing connections, + // and when the close_signal is trigger, force all known conns + // to start a graceful shutdown. + let graceful = + hyper_util::server::graceful::GracefulShutdown::new(); + + // The following code looks superficially similar between the HTTP + // and HTTPS paths. However, the concrete types of various objects + // are different and so it's not easy to actually share the code. + let log = log_close; + match tls_acceptor { + Some(tls_acceptor) => { + let mut https_acceptor = + HttpsAcceptor::new(log.clone(), tls_acceptor, incoming); + loop { + tokio::select! { + Some(Ok(sock)) = https_acceptor.accept() => { + let remote_addr = sock.remote_addr(); + let handler = make_service + .make_http_request_handler(remote_addr); + let fut = builder + .serve_connection_with_upgrades( + TokioIo::new(sock), + handler, + ); + let fut = graceful.watch(fut.into_owned()); + tokio::spawn(fut); + }, + + _ = &mut rx => { + info!(log, "beginning graceful shutdown"); + break; + } + } + } + } + None => loop { + tokio::select! { + (sock, remote_addr) = incoming.accept() => { + let handler = make_service + .make_http_request_handler(remote_addr); + let fut = builder + .serve_connection_with_upgrades( + TokioIo::new(sock), + handler, + ); + let fut = graceful.watch(fut.into_owned()); + tokio::spawn(fut); + }, + + _ = &mut rx => { + info!(log, "beginning graceful shutdown"); + break; + } + } + }, + }; + + // optional: could use another select on a timeout + graceful.shutdown().await + }); + + info!(log, "listening"); - let handler_waitgroup = self.handler_waitgroup; let join_handle = async move { // After the server shuts down, we also want to wait for any // detached handler futures to complete. @@ -210,139 +305,31 @@ impl HttpServerStarter { #[cfg(feature = "usdt-probes")] let probe_registration = match usdt::register_probes() { Ok(_) => { - debug!( - self.app_state.log, - "successfully registered DTrace USDT probes" - ); + debug!(&log, "successfully registered DTrace USDT probes"); ProbeRegistration::Succeeded } Err(e) => { let msg = e.to_string(); - error!( - self.app_state.log, - "failed to register DTrace USDT probes: {}", msg - ); + error!(&log, "failed to register DTrace USDT probes: {}", msg); ProbeRegistration::Failed(msg) } }; #[cfg(not(feature = "usdt-probes"))] let probe_registration = { - debug!( - self.app_state.log, - "DTrace USDT probes compiled out, not registering" - ); + debug!(&log, "DTrace USDT probes compiled out, not registering"); ProbeRegistration::Disabled }; HttpServer { probe_registration, - app_state: self.app_state, - local_addr: self.local_addr, + app_state, + local_addr, closer: CloseHandle { close_channel: Some(tx) }, join_future: join_handle.boxed().shared(), } } } -enum WrappedHttpServerStarter { - Http(InnerHttpServerStarter), - Https(InnerHttpsServerStarter), -} - -struct InnerHttpServerStarter( - HttpAcceptor, - ServerConnectionHandler, -); - -type InnerHttpServerStarterNewReturn = - (InnerHttpServerStarter, Arc>, SocketAddr); - -impl InnerHttpServerStarter { - /// Begins execution of the underlying Http server. - fn start( - self, - mut close_signal: tokio::sync::oneshot::Receiver<()>, - log_close: Logger, - ) -> tokio::task::JoinHandle<()> { - use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; - use hyper_util::server::conn::auto; - - tokio::spawn(async move { - let mut builder = auto::Builder::new(TokioExecutor::new()); - // http/1 settings - builder.http1().timer(TokioTimer::new()); - // http/2 settings - builder.http2().timer(TokioTimer::new()); - - // Use a graceful watcher to keep track of all existing connections, - // and when the close_signal is trigger, force all known conns - // to start a graceful shutdown. - let graceful = - hyper_util::server::graceful::GracefulShutdown::new(); - - loop { - tokio::select! { - (sock, remote_addr) = self.0.accept() => { - let fut = builder.serve_connection_with_upgrades( - TokioIo::new(sock), - self.1.make_http_request_handler(remote_addr), - ); - let fut = graceful.watch(fut.into_owned()); - tokio::spawn(fut); - }, - - _ = &mut close_signal => { - info!(log_close, "received request to begin graceful shutdown"); - break; - } - } - } - - // optional: could use another select on a timeout - graceful.shutdown().await - }) - } - - /// Set up an HTTP server bound on the specified address that runs - /// registered handlers. You must invoke `start()` on the returned instance - /// of `HttpServerStarter` (and await the result) to actually start the - /// server. - fn new( - config: &ConfigDropshot, - server_config: ServerConfig, - api: ApiDescription, - private: C, - log: &Logger, - handler_waitgroup_worker: waitgroup::Worker, - ) -> Result, std::io::Error> { - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function. - let std_listener = std::net::TcpListener::bind(&config.bind_address)?; - std_listener.set_nonblocking(true)?; - let tcp = TcpListener::from_std(std_listener)?; - let local_addr = tcp.local_addr()?; - let incoming = - HttpAcceptor { tcp, log: log.new(o!("local_addr" => local_addr)) }; - - let app_state = Arc::new(DropshotState { - private, - config: server_config, - router: api.into_router(), - log: log.new(o!("local_addr" => local_addr)), - local_addr, - tls_acceptor: None, - handler_waitgroup_worker: DebugIgnore(handler_waitgroup_worker), - }); - - let make_service = ServerConnectionHandler::new(app_state.clone()); - Ok(( - InnerHttpServerStarter(incoming, make_service), - app_state, - local_addr, - )) - } -} - /// Accepts TCP connections like a `TcpListener`, but ignores transient errors rather than propagating them to the caller struct HttpAcceptor { tcp: TcpListener, @@ -508,16 +495,11 @@ impl HttpsAcceptor { } } -struct InnerHttpsServerStarter( - HttpsAcceptor, - ServerConnectionHandler, -); - /// Create a TLS configuration from the Dropshot config structure. impl TryFrom<&ConfigTls> for rustls::ServerConfig { - type Error = std::io::Error; + type Error = BuildError; - fn try_from(config: &ConfigTls) -> std::io::Result { + fn try_from(config: &ConfigTls) -> Result { let (mut cert_reader, mut key_reader): ( Box, Box, @@ -532,25 +514,17 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { ConfigTls::AsFile { cert_file, key_file } => { let certfile = Box::new(std::io::BufReader::new( std::fs::File::open(cert_file).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "failed to open {}: {}", - cert_file.display(), - e - ), + BuildError::generic_system( + e, + format!("opening {}", cert_file.display()), ) })?, )); let keyfile = Box::new(std::io::BufReader::new( std::fs::File::open(key_file).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "failed to open {}: {}", - key_file.display(), - e - ), + BuildError::generic_system( + e, + format!("opening {}", key_file.display()), ) })?, )); @@ -561,17 +535,17 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { let certs = rustls_pemfile::certs(&mut cert_reader) .collect::, _>>() .map_err(|err| { - io_error(format!("failed to load certificate: {err}")) + BuildError::generic_system(err, "loading TLS certificates") })?; let keys = rustls_pemfile::pkcs8_private_keys(&mut key_reader) .collect::, _>>() .map_err(|err| { - io_error(format!("failed to load private key: {err}")) + BuildError::generic_system(err, "loading TLS private key") })?; let mut keys_iter = keys.into_iter(); let (Some(private_key), None) = (keys_iter.next(), keys_iter.next()) else { - return Err(io_error("expected a single private key".into())); + return Err(BuildError::NotOnePrivateKey); }; let mut cfg = rustls::ServerConfig::builder() @@ -583,102 +557,6 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { } } -type InnerHttpsServerStarterNewReturn = - (InnerHttpsServerStarter, Arc>, SocketAddr); - -impl InnerHttpsServerStarter { - /// Begins execution of the underlying Http server. - fn start( - mut self, - mut close_signal: tokio::sync::oneshot::Receiver<()>, - log_close: Logger, - ) -> tokio::task::JoinHandle<()> { - use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; - use hyper_util::server::conn::auto; - - tokio::spawn(async move { - let mut builder = auto::Builder::new(TokioExecutor::new()); - // http/1 settings - builder.http1().timer(TokioTimer::new()); - - // Use a graceful watcher to keep track of all existing connections, - // and when the close_signal is trigger, force all known conns - // to start a graceful shutdown. - let graceful = - hyper_util::server::graceful::GracefulShutdown::new(); - - loop { - tokio::select! { - Some(Ok(sock)) = self.0.accept() => { - let remote_addr = sock.remote_addr(); - let fut = builder.serve_connection_with_upgrades( - TokioIo::new(sock), - self.1.make_http_request_handler(remote_addr), - ); - let fut = graceful.watch(fut.into_owned()); - tokio::spawn(fut); - }, - - _ = &mut close_signal => { - info!(log_close, "received request to begin graceful shutdown"); - break; - } - } - } - - // optional: could use another select on a timeout - graceful.shutdown().await - }) - } - - fn new( - config: &ConfigDropshot, - server_config: ServerConfig, - api: ApiDescription, - private: C, - log: &Logger, - tls: &ConfigTls, - handler_waitgroup_worker: waitgroup::Worker, - ) -> Result, GenericError> { - let acceptor = Arc::new(Mutex::new(TlsAcceptor::from(Arc::new( - rustls::ServerConfig::try_from(tls)?, - )))); - - let tcp = { - let listener = std::net::TcpListener::bind(&config.bind_address)?; - listener.set_nonblocking(true)?; - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function, to match the interface - // provided by `HttpServerStarter::new`. - TcpListener::from_std(listener)? - }; - - let local_addr = tcp.local_addr()?; - let logger = log.new(o!("local_addr" => local_addr)); - let tcp = HttpAcceptor { tcp, log: logger.clone() }; - let https_acceptor = - HttpsAcceptor::new(logger.clone(), acceptor.clone(), tcp); - - let app_state = Arc::new(DropshotState { - private, - config: server_config, - router: api.into_router(), - log: logger, - local_addr, - tls_acceptor: Some(acceptor), - handler_waitgroup_worker: DebugIgnore(handler_waitgroup_worker), - }); - - let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); - - Ok(( - InnerHttpsServerStarter(https_acceptor, make_service), - app_state, - local_addr, - )) - } -} - type SharedBoxFuture = Shared + Send>>>; /// Future returned by [`HttpServer::wait_for_shutdown()`]. @@ -1142,8 +1020,40 @@ impl Service> } } -fn io_error(err: String) -> std::io::Error { - std::io::Error::new(std::io::ErrorKind::Other, err) +/// Errors encountered while configuring a Dropshot server +#[derive(Debug, Error)] +pub enum BuildError { + #[error("failed to bind to {address}")] + BindError { + address: SocketAddr, + #[source] + error: std::io::Error, + }, + #[error("expected exactly one TLS private key")] + NotOnePrivateKey, + #[error("must register an API")] + MissingApi, + #[error("only one API can be registered with a server")] + TooManyApis, + #[error("{context}")] + SystemError { + context: String, + #[source] + error: std::io::Error, + }, +} + +impl BuildError { + fn bind_error(error: std::io::Error, address: SocketAddr) -> BuildError { + BuildError::BindError { address, error } + } + + fn generic_system>( + error: std::io::Error, + context: S, + ) -> BuildError { + BuildError::SystemError { context: context.into(), error } + } } #[cfg(test)] From eb0685dad04753060012d2f057e8512ecb545d8d Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 10:04:25 -0700 Subject: [PATCH 2/4] nits --- dropshot/src/server.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 8272a64d6..52c89807f 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -108,7 +108,7 @@ pub struct HttpServerStarter { app_state: Arc>, local_addr: SocketAddr, handler_waitgroup: WaitGroup, - incoming: HttpAcceptor, + http_acceptor: HttpAcceptor, tls_acceptor: Option>>, } @@ -197,7 +197,7 @@ impl HttpServerStarter { app_state, local_addr, handler_waitgroup, - incoming, + http_acceptor: incoming, tls_acceptor, }) } @@ -208,7 +208,7 @@ impl HttpServerStarter { local_addr, handler_waitgroup, tls_acceptor, - incoming, // XXX-dap rename + http_acceptor, } = self; let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); @@ -240,8 +240,11 @@ impl HttpServerStarter { let log = log_close; match tls_acceptor { Some(tls_acceptor) => { - let mut https_acceptor = - HttpsAcceptor::new(log.clone(), tls_acceptor, incoming); + let mut https_acceptor = HttpsAcceptor::new( + log.clone(), + tls_acceptor, + http_acceptor, + ); loop { tokio::select! { Some(Ok(sock)) = https_acceptor.accept() => { @@ -266,7 +269,7 @@ impl HttpServerStarter { } None => loop { tokio::select! { - (sock, remote_addr) = incoming.accept() => { + (sock, remote_addr) = http_acceptor.accept() => { let handler = make_service .make_http_request_handler(remote_addr); let fut = builder From 979bdbaa432735da5aaddac05e44338ef830cc35 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 10:09:15 -0700 Subject: [PATCH 3/4] more cleanup --- dropshot/src/server.rs | 49 ++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 52c89807f..6ec5fbf4a 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -140,6 +140,27 @@ impl HttpServerStarter { log: &Logger, tls: Option, ) -> Result, BuildError> { + let tcp = { + let std_listener = std::net::TcpListener::bind( + &config.bind_address, + ) + .map_err(|e| BuildError::bind_error(e, config.bind_address))?; + std_listener.set_nonblocking(true).map_err(|e| { + BuildError::generic_system(e, "setting non-blocking") + })?; + // We use `from_std` instead of just calling `bind` here directly + // to avoid invoking an async function. + TcpListener::from_std(std_listener).map_err(|e| { + BuildError::generic_system(e, "creating TCP listener") + })? + }; + + let local_addr = tcp.local_addr().map_err(|e| { + BuildError::generic_system(e, "getting local TCP address") + })?; + + let log = log.new(o!("local_addr" => local_addr)); + let server_config = ServerConfig { // We start aggressively to ensure test coverage. request_body_max_bytes: config.request_body_max_bytes, @@ -148,24 +169,6 @@ impl HttpServerStarter { default_handler_task_mode: config.default_handler_task_mode, log_headers: config.log_headers.clone(), }; - let handler_waitgroup = WaitGroup::new(); - - let std_listener = std::net::TcpListener::bind(&config.bind_address) - .map_err(|e| BuildError::bind_error(e, config.bind_address))?; - std_listener.set_nonblocking(true).map_err(|e| { - BuildError::generic_system(e, "setting non-blocking") - })?; - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function. - let tcp = TcpListener::from_std(std_listener).map_err(|e| { - BuildError::generic_system(e, "creating TCP listener") - })?; - let local_addr = tcp.local_addr().map_err(|e| { - BuildError::generic_system(e, "getting local TCP address") - })?; - let incoming = HttpAcceptor { tcp, log: log.clone() }; - - let log = log.new(o!("local_addr" => local_addr)); let tls_acceptor = tls .as_ref() @@ -175,7 +178,7 @@ impl HttpServerStarter { ))))) }) .transpose()?; - + let handler_waitgroup = WaitGroup::new(); let app_state = Arc::new(DropshotState { private, config: server_config, @@ -193,11 +196,13 @@ impl HttpServerStarter { ); } + let http_acceptor = HttpAcceptor { tcp, log: log.clone() }; + Ok(HttpServerStarter { app_state, local_addr, handler_waitgroup, - http_acceptor: incoming, + http_acceptor, tls_acceptor, }) } @@ -211,10 +216,8 @@ impl HttpServerStarter { http_acceptor, } = self; - let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); - let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); - + let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); let log = &app_state.log; let log_close = log.clone(); let join_handle = tokio::spawn(async move { From 87c77b5635ae814ad8aa67dd3953da8a19b2dfbe Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 11:18:12 -0700 Subject: [PATCH 4/4] remove unnecessary XXX --- dropshot/src/server.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 6ec5fbf4a..339c3db3b 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -227,7 +227,6 @@ impl HttpServerStarter { let mut builder = auto::Builder::new(TokioExecutor::new()); // http/1 settings builder.http1().timer(TokioTimer::new()); - // XXX-dap previously, the TLS one did NOT do this http2 step // http/2 settings builder.http2().timer(TokioTimer::new());