diff --git a/tonic/Cargo.toml b/tonic/Cargo.toml index 39b0276cc..5dc34a591 100644 --- a/tonic/Cargo.toml +++ b/tonic/Cargo.toml @@ -26,6 +26,15 @@ keywords = ["rpc", "grpc", "async", "futures", "protobuf"] default = ["transport", "codegen", "prost"] codegen = ["async-trait"] transport = [ + "hyper/default", + "hyper/stream", + "tokio", + "tower", + "tower-balance", + "tower-load", + "tracing-futures", +] +client = [ "hyper", "tokio", "tower", @@ -64,8 +73,8 @@ prost-derive = { version = "0.6", optional = true } async-trait = { version = "0.1.13", optional = true } # transport -hyper = { version = "0.13.4", features = ["stream"], optional = true } -tokio = { version = "0.2.13", features = ["tcp"], optional = true } +hyper = { version = "0.13.4", default-features = false, optional = true } +tokio = { version = "0.2.13", optional = true } tower = { version = "0.3", optional = true} tower-make = { version = "0.3", features = ["connect"] } tower-balance = { version = "0.3", optional = true } @@ -76,6 +85,9 @@ tracing-futures = { version = "0.2", optional = true } tokio-rustls = { version = "0.14", optional = true } rustls-native-certs = { version = "0.4", optional = true } +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen-futures = "0.4.18" + [dev-dependencies] tokio = { version = "0.2", features = ["rt-core", "macros"] } static_assertions = "1.0" diff --git a/tonic/src/lib.rs b/tonic/src/lib.rs index a765e6acf..95670df27 100644 --- a/tonic/src/lib.rs +++ b/tonic/src/lib.rs @@ -82,7 +82,7 @@ pub mod codec; pub mod metadata; pub mod server; -#[cfg(feature = "transport")] +#[cfg(any(feature = "transport", feature = "client"))] #[cfg_attr(docsrs, doc(cfg(feature = "transport")))] pub mod transport; diff --git a/tonic/src/request.rs b/tonic/src/request.rs index f2f047ffc..fbdf48b3e 100644 --- a/tonic/src/request.rs +++ b/tonic/src/request.rs @@ -1,10 +1,10 @@ use crate::metadata::MetadataMap; -#[cfg(feature = "transport")] +#[cfg(any(feature = "transport", feature = "client"))] use crate::transport::Certificate; use futures_core::Stream; use http::Extensions; use std::net::SocketAddr; -#[cfg(feature = "transport")] +#[cfg(any(feature = "transport", feature = "client"))] use std::sync::Arc; /// A gRPC request and metadata from an RPC call. @@ -18,7 +18,7 @@ pub struct Request { #[derive(Clone)] pub(crate) struct ConnectionInfo { pub(crate) remote_addr: Option, - #[cfg(feature = "transport")] + #[cfg(any(feature = "transport", feature = "client"))] pub(crate) peer_certs: Option>>, } diff --git a/tonic/src/transport/channel/endpoint.rs b/tonic/src/transport/channel/endpoint.rs index b7bf1ae6d..8c9fc8b35 100644 --- a/tonic/src/transport/channel/endpoint.rs +++ b/tonic/src/transport/channel/endpoint.rs @@ -39,6 +39,7 @@ impl Endpoint { // FIXME: determine if we want to expose this or not. This is really // just used in codegen for a shortcut. #[doc(hidden)] + #[cfg(feature = "transport")] pub fn new(dst: D) -> Result where D: TryInto, @@ -203,6 +204,7 @@ impl Endpoint { } /// Create a channel from this config. + #[cfg(feature = "transport")] pub async fn connect(&self) -> Result { let mut http = hyper::client::connect::HttpConnector::new(); http.enforce_http(false); @@ -223,6 +225,7 @@ impl Endpoint { /// /// The channel returned by this method does not attempt to connect to the endpoint until first /// use. + #[cfg(feature = "transport")] pub fn connect_lazy(&self) -> Result { let mut http = hyper::client::connect::HttpConnector::new(); http.enforce_http(false); diff --git a/tonic/src/transport/channel/mod.rs b/tonic/src/transport/channel/mod.rs index ac47a225b..134d6ba73 100644 --- a/tonic/src/transport/channel/mod.rs +++ b/tonic/src/transport/channel/mod.rs @@ -108,6 +108,7 @@ impl Channel { /// /// This creates a [`Channel`] that will load balance accross all the /// provided endpoints. + #[cfg(feature = "transport")] pub fn balance_list(list: impl Iterator) -> Self { let (channel, mut tx) = Self::balance_channel(DEFAULT_BUFFER_SIZE); list.for_each(|endpoint| { @@ -121,6 +122,7 @@ impl Channel { /// Balance a list of [`Endpoint`]'s. /// /// This creates a [`Channel`] that will listen to a stream of change events and will add or remove provided endpoints. + #[cfg(feature = "transport")] pub fn balance_channel(capacity: usize) -> (Self, Sender>) where K: Hash + Eq + Send + Clone + 'static, diff --git a/tonic/src/transport/mod.rs b/tonic/src/transport/mod.rs index 40bd7b110..79e626d58 100644 --- a/tonic/src/transport/mod.rs +++ b/tonic/src/transport/mod.rs @@ -87,8 +87,26 @@ //! [rustls]: https://docs.rs/rustls/0.16.0/rustls/ pub mod channel; +#[cfg(feature = "transport")] pub mod server; +/// Trait that connected IO resources implement. +/// +/// The goal for this trait is to allow users to implement +/// custom IO types that can still provide the same connection +/// metadata. +pub trait Connected { + /// Return the remote address this IO resource is connected too. + fn remote_addr(&self) -> Option { + None + } + + /// Return the set of connected peer TLS certificates. + fn peer_certs(&self) -> Option> { + None + } +} + mod error; mod service; mod tls; @@ -96,6 +114,7 @@ mod tls; #[doc(inline)] pub use self::channel::{Channel, Endpoint}; pub use self::error::Error; +#[cfg(feature = "transport")] #[doc(inline)] pub use self::server::{NamedService, Server}; pub use self::tls::{Certificate, Identity}; @@ -105,5 +124,6 @@ pub use hyper::{Body, Uri}; #[cfg_attr(docsrs, doc(cfg(feature = "tls")))] pub use self::channel::ClientTlsConfig; #[cfg(feature = "tls")] +#[cfg(feature = "transport")] #[cfg_attr(docsrs, doc(cfg(feature = "tls")))] pub use self::server::ServerTlsConfig; diff --git a/tonic/src/transport/server/conn.rs b/tonic/src/transport/server/conn.rs index d7d458840..8ddc11236 100644 --- a/tonic/src/transport/server/conn.rs +++ b/tonic/src/transport/server/conn.rs @@ -1,29 +1,12 @@ +use super::super::Connected; #[cfg(feature = "tls")] use super::TlsStream; -use crate::transport::Certificate; use hyper::server::conn::AddrStream; use std::net::SocketAddr; use tokio::net::TcpStream; #[cfg(feature = "tls")] use tokio_rustls::rustls::Session; -/// Trait that connected IO resources implement. -/// -/// The goal for this trait is to allow users to implement -/// custom IO types that can still provide the same connection -/// metadata. -pub trait Connected { - /// Return the remote address this IO resource is connected too. - fn remote_addr(&self) -> Option { - None - } - - /// Return the set of connected peer TLS certificates. - fn peer_certs(&self) -> Option> { - None - } -} - impl Connected for AddrStream { fn remote_addr(&self) -> Option { Some(self.remote_addr()) diff --git a/tonic/src/transport/server/mod.rs b/tonic/src/transport/server/mod.rs index e83ff073b..da3a5a278 100644 --- a/tonic/src/transport/server/mod.rs +++ b/tonic/src/transport/server/mod.rs @@ -6,7 +6,7 @@ mod incoming; #[cfg_attr(docsrs, doc(cfg(feature = "tls")))] mod tls; -pub use conn::Connected; +pub use super::Connected; #[cfg(feature = "tls")] pub use tls::ServerTlsConfig; diff --git a/tonic/src/transport/service/connection.rs b/tonic/src/transport/service/connection.rs index 83d79d8d4..b56993ca0 100644 --- a/tonic/src/transport/service/connection.rs +++ b/tonic/src/transport/service/connection.rs @@ -28,6 +28,22 @@ pub(crate) struct Connection { inner: BoxService, } +#[cfg(target_arch = "wasm32")] +mod wasm { + use std::future::Future; + use std::pin::Pin; + + type BoxSendFuture = Pin + Send>>; + + pub struct Executor; + + impl hyper::rt::Executor for Executor { + fn execute(&self, fut: BoxSendFuture) { + wasm_bindgen_futures::spawn_local(fut) + } + } +} + impl Connection { pub(crate) fn new( connector: C, @@ -44,16 +60,21 @@ impl Connection { .http2_initial_stream_window_size(endpoint.init_stream_window_size) .http2_initial_connection_window_size(endpoint.init_connection_window_size) .http2_only(true) - .http2_keep_alive_interval(endpoint.http2_keep_alive_interval) + // .http2_keep_alive_interval(endpoint.http2_keep_alive_interval) .clone(); - if let Some(val) = endpoint.http2_keep_alive_timeout { - settings.http2_keep_alive_timeout(val); + #[cfg(target_arch = "wasm32")] + { + settings.executor(wasm::Executor); } - if let Some(val) = endpoint.http2_keep_alive_while_idle { - settings.http2_keep_alive_while_idle(val); - } + // if let Some(val) = endpoint.http2_keep_alive_timeout { + // settings.http2_keep_alive_timeout(val); + // } + + // if let Some(val) = endpoint.http2_keep_alive_while_idle { + // settings.http2_keep_alive_while_idle(val); + // } let settings = settings.clone(); diff --git a/tonic/src/transport/service/discover.rs b/tonic/src/transport/service/discover.rs index 572e7adef..d8a6a6c3d 100644 --- a/tonic/src/transport/service/discover.rs +++ b/tonic/src/transport/service/discover.rs @@ -29,6 +29,7 @@ impl DynamicServiceStream { } } +#[cfg(feature = "transport")] impl Discover for DynamicServiceStream { type Key = K; type Service = Connection; diff --git a/tonic/src/transport/service/io.rs b/tonic/src/transport/service/io.rs index 98961507d..a0e633381 100644 --- a/tonic/src/transport/service/io.rs +++ b/tonic/src/transport/service/io.rs @@ -1,4 +1,4 @@ -use crate::transport::{server::Connected, Certificate}; +use crate::transport::{Certificate, Connected}; use hyper::client::connect::{Connected as HyperConnected, Connection}; use std::io; use std::net::SocketAddr;