From 0819fd9fa76d3dbd94f0c1728cad06614ca9fa5e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 20 Jul 2022 14:01:07 +0100 Subject: [PATCH 1/5] Make TcpIncoming public --- tonic/src/transport/server/incoming.rs | 4 ++-- tonic/src/transport/server/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tonic/src/transport/server/incoming.rs b/tonic/src/transport/server/incoming.rs index 686aef197..358ec18d7 100644 --- a/tonic/src/transport/server/incoming.rs +++ b/tonic/src/transport/server/incoming.rs @@ -127,12 +127,12 @@ enum SelectOutput { Done, } -pub(crate) struct TcpIncoming { +pub struct TcpIncoming { inner: AddrIncoming, } impl TcpIncoming { - pub(crate) fn new( + pub fn new( addr: SocketAddr, nodelay: bool, keepalive: Option, diff --git a/tonic/src/transport/server/mod.rs b/tonic/src/transport/server/mod.rs index 8754b6e2e..b05f78049 100644 --- a/tonic/src/transport/server/mod.rs +++ b/tonic/src/transport/server/mod.rs @@ -24,7 +24,7 @@ use super::service::TlsAcceptor; #[cfg(unix)] pub use unix::UdsConnectInfo; -use incoming::TcpIncoming; +pub use incoming::TcpIncoming; #[cfg(feature = "tls")] pub(crate) use tokio_rustls::server::TlsStream; From 9b02ebc453cf2a938f80678717f4b5c66edf8de6 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 25 Jul 2022 15:38:32 +0100 Subject: [PATCH 2/5] Add some docs --- tonic/src/transport/server/incoming.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tonic/src/transport/server/incoming.rs b/tonic/src/transport/server/incoming.rs index 358ec18d7..7a44c3c2b 100644 --- a/tonic/src/transport/server/incoming.rs +++ b/tonic/src/transport/server/incoming.rs @@ -127,11 +127,19 @@ enum SelectOutput { Done, } +/// Binds a socket address for a [Router](super::Router) +/// +/// An incoming stream, usable with [Router::serve_with_incoming](super::Router::serve_with_incoming), +/// of `AsyncRead + AsyncWrite` that communicate with clients that connect to a socket address. +#[derive(Debug)] pub struct TcpIncoming { inner: AddrIncoming, } impl TcpIncoming { + /// Creates an instance by binding (opening) the specified socket address + /// to which the specified TCP 'nodelay' and 'keepalive' parameters are applied. + /// Returns a TcpIncoming if the socket address was successfully bound. pub fn new( addr: SocketAddr, nodelay: bool, From 2991b1baee6a28b6c9e3abf25e3615a733d1e80b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 25 Jul 2022 17:21:19 +0100 Subject: [PATCH 3/5] add no_run doc-test --- tonic/src/transport/server/incoming.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tonic/src/transport/server/incoming.rs b/tonic/src/transport/server/incoming.rs index 7a44c3c2b..757e8fc43 100644 --- a/tonic/src/transport/server/incoming.rs +++ b/tonic/src/transport/server/incoming.rs @@ -140,6 +140,27 @@ impl TcpIncoming { /// Creates an instance by binding (opening) the specified socket address /// to which the specified TCP 'nodelay' and 'keepalive' parameters are applied. /// Returns a TcpIncoming if the socket address was successfully bound. + /// + /// # Examples + /// ```no_run + /// # use tower_service::Service; + /// # use http::{request::Request, response::Response}; + /// # use tonic::{body::BoxBody, transport::{Body, NamedService, Server, server::TcpIncoming}}; + /// # use core::convert::Infallible; + /// # use std::error::Error; + /// # fn main() { } // Cannot have type parameters, hence instead define: + /// # fn run(some_service: S) -> Result<(), Box> + /// # where + /// # S: Service, Response = Response, Error = Infallible> + NamedService + Clone + Send + 'static, + /// # S::Future: Send + 'static, + /// # { + /// let addr = "127.0.0.1:8123".parse().unwrap(); + /// let tinc = TcpIncoming::new(addr, true, None)?; + /// Server::builder() + /// .add_service(some_service) + /// .serve_with_incoming(tinc); + /// # Ok(()) + /// # } pub fn new( addr: SocketAddr, nodelay: bool, From 043d3b13eda147edaf2b73d90f708153da86d221 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 25 Jul 2022 18:51:39 +0100 Subject: [PATCH 4/5] Add a tiny unit test of TcpIncoming only --- tonic/src/transport/server/incoming.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tonic/src/transport/server/incoming.rs b/tonic/src/transport/server/incoming.rs index 757e8fc43..3289799be 100644 --- a/tonic/src/transport/server/incoming.rs +++ b/tonic/src/transport/server/incoming.rs @@ -180,3 +180,17 @@ impl Stream for TcpIncoming { Pin::new(&mut self.inner).poll_accept(cx) } } + +#[cfg(test)] +mod tests { + use crate::transport::server::TcpIncoming; + #[tokio::test] + async fn one_tcpincoming_at_a_time() { + let addr = "127.0.0.1:1322".parse().unwrap(); + { + let _t1 = TcpIncoming::new(addr, true, None).unwrap(); + let _t2 = TcpIncoming::new(addr, true, None).unwrap_err(); + } + let _t3 = TcpIncoming::new(addr, true, None).unwrap(); + } +} From 0aaa6dc8e632d572cd315ce7257c64986ef7fd1f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Jul 2022 09:11:44 +0100 Subject: [PATCH 5/5] Doctest: loop to find a free port --- tonic/src/transport/server/incoming.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tonic/src/transport/server/incoming.rs b/tonic/src/transport/server/incoming.rs index 3289799be..c8434fd34 100644 --- a/tonic/src/transport/server/incoming.rs +++ b/tonic/src/transport/server/incoming.rs @@ -154,8 +154,15 @@ impl TcpIncoming { /// # S: Service, Response = Response, Error = Infallible> + NamedService + Clone + Send + 'static, /// # S::Future: Send + 'static, /// # { - /// let addr = "127.0.0.1:8123".parse().unwrap(); - /// let tinc = TcpIncoming::new(addr, true, None)?; + /// // Find a free port + /// let mut port = 1322; + /// let tinc = loop { + /// let addr = format!("127.0.0.1:{}", port).parse().unwrap(); + /// match TcpIncoming::new(addr, true, None) { + /// Ok(t) => break t, + /// Err(_) => port += 1 + /// } + /// }; /// Server::builder() /// .add_service(some_service) /// .serve_with_incoming(tinc);