From 3c3a0042227b6fa5fc94b6d34ea3d4d4f3b76696 Mon Sep 17 00:00:00 2001 From: Alcibiades Athens Date: Sat, 21 Dec 2024 23:32:16 -0500 Subject: [PATCH] fix: prep for tonic example --- Cargo.toml | 12 ++- examples/tonic.rs | 108 ++++++++++++++++++++++ examples/{full.rs => tower_service_fn.rs} | 8 +- src/lib.rs | 8 -- src/test.rs | 1 - 5 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 examples/tonic.rs rename examples/{full.rs => tower_service_fn.rs} (96%) diff --git a/Cargo.toml b/Cargo.toml index 412224a..3f3c371 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,14 +45,24 @@ once_cell = "1.20.2" rcgen = "0.13.1" reqwest = { version = "0.12.9", features = ["rustls-tls", "http2"] } ring = "0.17.8" -tokio = { version = "1.42", features = ["rt-multi-thread", "net", "test-util", "time"] } +tokio = { version = "1.42", features = ["rt-multi-thread", "net", "test-util", "time", "signal"] } tokio-util = { version = "0.7.13", features = ["compat"] } +tonic = "0.12.3" +tonic-health = "0.12.3" tracing-subscriber = "0.3.19" [[bench]] name = "hello_world_tower_hyper_tls_tcp" harness = false +[[example]] +name = "tower_service_fn" +path = "examples/tower_service_fn.rs" + +[[example]] +name = "tonic" +path = "examples/tonic.rs" + [features] default = [] jemalloc = ["tikv-jemallocator"] diff --git a/examples/tonic.rs b/examples/tonic.rs new file mode 100644 index 0000000..5da3b68 --- /dev/null +++ b/examples/tonic.rs @@ -0,0 +1,108 @@ +use std::net::SocketAddr; +use std::sync::Arc; + +use bytes::Bytes; +use http::Request; +use http_body_util::{Full}; +use hyper::body::Incoming; +use hyper::Response; +use hyper_util::rt::TokioExecutor; +use hyper_util::server::conn::auto::Builder as HttpConnectionBuilder; +use hyper_util::service::TowerToHyperService; +use rustls::ServerConfig; +use tokio::net::TcpListener; +use tokio_stream::wrappers::TcpListenerStream; +use tonic::server::NamedService; +use tonic::service::AxumRouter; +use tonic::transport::Server; +use tower::ServiceExt; +use tracing::{info, Level}; + +use postel::{load_certs, load_private_key, serve_http_with_shutdown}; + +// Define a service for demonstration purposes +pub struct GreeterService; + +impl NamedService for GreeterService { + const NAME: &'static str = "greeter"; +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Initialize logging + tracing_subscriber::fmt() + .with_max_level(Level::INFO) + .init(); + + // Configure server address + let addr = SocketAddr::from(([127, 0, 0, 1], 8443)); + + // Set up gRPC health service + let (mut health_reporter, health_service) = tonic_health::server::health_reporter(); + health_reporter.set_serving::().await; + + // Set up TCP listener + let listener = TcpListener::bind(addr).await?; + info!("Server listening on https://{}", addr); + let incoming = TcpListenerStream::new(listener); + + // Create HTTP connection builder + let builder = HttpConnectionBuilder::new(TokioExecutor::new()); + + // Set up TLS configuration + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); + + let certs = load_certs("examples/sample.pem")?; + let key = load_private_key("examples/sample.rsa")?; + + let mut config = ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(certs, key)?; + + // Configure ALPN protocols - required for gRPC + config.alpn_protocols = vec![b"h2".to_vec()]; + let tls_config = Arc::new(config); + + // Create a shutdown signal + let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel(); + + // Start server in the background + let server = tokio::spawn(async move { + info!("Server starting up..."); + + let svc = >>::map_response::<_, Response>>(Server::builder() + .add_service(health_service) + .into_service() + .into_axum_router(), |res| { + // TODO the issue here is that streams are not sync + res.map(|_| Full::new(Bytes::from("placeholder"))) + }); + + let hyper_svc = TowerToHyperService::new(svc); + + serve_http_with_shutdown( + hyper_svc, + incoming, + builder, + Some(tls_config), + Some(async { + shutdown_rx.await.ok(); + info!("Shutdown signal received"); + }), + ) + .await + .expect("Server failed unexpectedly"); + }); + + // Keep the main thread running until Ctrl+C + tokio::signal::ctrl_c().await?; + info!("Initiating graceful shutdown"); + let _ = shutdown_tx.send(()); + + // Wait for server to shutdown + server.await?; + + Ok(()) +} \ No newline at end of file diff --git a/examples/full.rs b/examples/tower_service_fn.rs similarity index 96% rename from examples/full.rs rename to examples/tower_service_fn.rs index 62aacc1..ac5f158 100644 --- a/examples/full.rs +++ b/examples/tower_service_fn.rs @@ -71,8 +71,9 @@ where #[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Box> { - let addr = SocketAddr::from(([127, 0, 0, 1], 8443)); // 1. Set up the TCP listener + let addr = SocketAddr::from(([127, 0, 0, 1], 8443)); + let listener = TcpListener::bind(addr).await?; info!("Listening on https://{}", addr); let incoming = TcpListenerStream::new(listener); @@ -90,6 +91,10 @@ async fn main() -> Result<(), Box> { let svc = TowerToHyperService::new(svc); // 5. Set up TLS config + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); + let certs = load_certs("examples/sample.pem")?; let key = load_private_key("examples/sample.rsa")?; @@ -97,6 +102,7 @@ async fn main() -> Result<(), Box> { .with_no_client_auth() .with_single_cert(certs, key) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; let tls_config = Arc::new(config); diff --git a/src/lib.rs b/src/lib.rs index 8d20065..ab2a5c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,3 @@ -// Optional alternative to the default global allocator. -// faster in some scenarios, but not always. -#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] -use tikv_jemallocator::Jemalloc; - -#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] -#[global_allocator] -static GLOBAL: Jemalloc = Jemalloc; pub use error::{Error as TransportError, Kind as TransportErrorKind}; pub use http::serve_http_connection; diff --git a/src/test.rs b/src/test.rs index f6add1a..7af9e4f 100644 --- a/src/test.rs +++ b/src/test.rs @@ -2,7 +2,6 @@ pub(crate) mod helper { use once_cell::sync::Lazy; - #[allow(dead_code)] pub(crate) static RUSTLS: Lazy<()> = Lazy::new(|| { rustls::crypto::aws_lc_rs::default_provider() .install_default()