Add tcp_nodelay for Builder

This commit is contained in:
quininer
2019-03-19 11:56:45 +08:00
committed by Sean McArthur
parent f5e7e883c7
commit 47640170bb
3 changed files with 43 additions and 22 deletions

View File

@@ -81,6 +81,7 @@ struct Config {
http2_only: bool,
http1_title_case_headers: bool,
local_address: Option<IpAddr>,
nodelay: bool,
}
impl ClientBuilder {
@@ -115,6 +116,7 @@ impl ClientBuilder {
http2_only: false,
http1_title_case_headers: false,
local_address: None,
nodelay: false
},
}
}
@@ -146,7 +148,7 @@ impl ClientBuilder {
id.add_to_native_tls(&mut tls)?;
}
Connector::new_default_tls(tls, proxies.clone(), config.local_address)?
Connector::new_default_tls(tls, proxies.clone(), config.local_address, config.nodelay)?
},
#[cfg(feature = "rustls-tls")]
TlsBackend::Rustls => {
@@ -175,12 +177,12 @@ impl ClientBuilder {
id.add_to_rustls(&mut tls)?;
}
Connector::new_rustls_tls(tls, proxies.clone(), config.local_address)?
Connector::new_rustls_tls(tls, proxies.clone(), config.local_address, config.nodelay)?
}
}
#[cfg(not(feature = "tls"))]
Connector::new(proxies.clone(), config.local_address)?
Connector::new(proxies.clone(), config.local_address, config.nodelay)?
};
connector.set_timeout(config.connect_timeout);
@@ -215,6 +217,12 @@ impl ClientBuilder {
})
}
/// Set that all sockets have `SO_NODELAY` set to `true`.
pub fn tcp_nodelay(mut self) -> ClientBuilder {
self.config.nodelay = true;
self
}
/// Use native TLS backend.
#[cfg(feature = "default-tls")]
pub fn use_default_tls(mut self) -> ClientBuilder {

View File

@@ -84,6 +84,11 @@ impl ClientBuilder {
})
}
/// Set that all sockets have `SO_NODELAY` set to `true`.
pub fn tcp_nodelay(self) -> ClientBuilder {
self.with_inner(move |inner| inner.tcp_nodelay())
}
/// Use native TLS backend.
#[cfg(feature = "default-tls")]
pub fn use_default_tls(self) -> ClientBuilder {

View File

@@ -31,6 +31,8 @@ pub(crate) struct Connector {
inner: Inner,
proxies: Arc<Vec<Proxy>>,
timeout: Option<Duration>,
#[cfg(feature = "tls")]
nodelay: bool
}
enum Inner {
@@ -48,13 +50,14 @@ enum Inner {
impl Connector {
#[cfg(not(feature = "tls"))]
pub(crate) fn new<T>(proxies: Arc<Vec<Proxy>>, local_addr: T) -> ::Result<Connector>
pub(crate) fn new<T>(proxies: Arc<Vec<Proxy>>, local_addr: T, nodelay: bool) -> ::Result<Connector>
where
T: Into<Option<IpAddr>>
{
let mut http = http_connector()?;
http.set_local_address(local_addr.into());
http.set_nodelay(nodelay);
Ok(Connector {
inner: Inner::Http(http),
proxies,
@@ -66,7 +69,8 @@ impl Connector {
pub(crate) fn new_default_tls<T>(
tls: TlsConnectorBuilder,
proxies: Arc<Vec<Proxy>>,
local_addr: T) -> ::Result<Connector>
local_addr: T,
nodelay: bool) -> ::Result<Connector>
where
T: Into<Option<IpAddr>>,
{
@@ -80,6 +84,7 @@ impl Connector {
inner: Inner::DefaultTls(http, tls),
proxies,
timeout: None,
nodelay
})
}
@@ -87,7 +92,8 @@ impl Connector {
pub(crate) fn new_rustls_tls<T>(
tls: rustls::ClientConfig,
proxies: Arc<Vec<Proxy>>,
local_addr: T) -> ::Result<Connector>
local_addr: T,
nodelay: bool) -> ::Result<Connector>
where
T: Into<Option<IpAddr>>,
{
@@ -108,6 +114,7 @@ impl Connector {
inner: Inner::RustlsTls { http, tls, tls_proxy },
proxies,
timeout: None,
nodelay
})
}
@@ -134,6 +141,9 @@ impl Connect for Connector {
type Future = Connecting;
fn connect(&self, dst: Destination) -> Self::Future {
#[cfg(feature = "tls")]
let nodelay = self.nodelay;
macro_rules! timeout {
($future:expr) => {
if let Some(dur) = self.timeout {
@@ -163,33 +173,27 @@ impl Connect for Connector {
Inner::Http(http) => connect!(http, $dst, $proxy),
#[cfg(feature = "default-tls")]
Inner::DefaultTls(http, tls) => {
let http = ::hyper_tls::HttpsConnector::from((http.clone(), tls.clone()));
let mut http = http.clone();
http.set_nodelay(nodelay);
let http = ::hyper_tls::HttpsConnector::from((http, tls.clone()));
connect!(http, $dst, $proxy)
},
#[cfg(feature = "rustls-tls")]
Inner::RustlsTls { http, tls, .. } => {
use ::rustls::Session;
let mut http = http.clone();
// Disable Nagle's algorithm for TLS handshake
//
// https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES
if $dst.scheme() == "https" {
http.set_nodelay(true);
}
http.set_nodelay(nodelay || ($dst.scheme() == "https"));
let http = ::hyper_rustls::HttpsConnector::from((http, tls.clone()));
timeout!(http.connect($dst)
.and_then(|(mut io, connected)| {
if let ::hyper_rustls::MaybeHttpsStream::Https(stream) = &mut io {
let (io, session) = stream.get_mut();
.and_then(move |(io, connected)| {
if let ::hyper_rustls::MaybeHttpsStream::Https(stream) = &io {
let (io, _) = stream.get_ref();
// keep nodelay for h2
//
// https://http2.github.io/faq/#will-i-need-tcp_nodelay-for-my-http2-connections
if session.get_alpn_protocol() != Some(b"h2") {
if !nodelay {
io.set_nodelay(false)?;
}
}
@@ -227,7 +231,9 @@ impl Connect for Connector {
let host = dst.host().to_owned();
let port = dst.port().unwrap_or(443);
let http = ::hyper_tls::HttpsConnector::from((http.clone(), tls.clone()));
let mut http = http.clone();
http.set_nodelay(nodelay);
let http = ::hyper_tls::HttpsConnector::from((http, tls.clone()));
let tls = tls.clone();
return timeout!(http.connect(ndst).and_then(move |(conn, connected)| {
trace!("tunneling HTTPS over proxy");
@@ -247,7 +253,9 @@ impl Connect for Connector {
let host = dst.host().to_owned();
let port = dst.port().unwrap_or(443);
let http = ::hyper_rustls::HttpsConnector::from((http.clone(), tls_proxy.clone()));
let mut http = http.clone();
http.set_nodelay(nodelay);
let http = ::hyper_rustls::HttpsConnector::from((http, tls_proxy.clone()));
let tls = tls.clone();
return timeout!(http.connect(ndst).and_then(move |(conn, connected)| {
trace!("tunneling HTTPS over proxy");