Skip to content

Commit ec48b04

Browse files
authored
transport: Make TCP_NODELAY configurable (#146)
Allow configuring `TCP_NODELAY` through TCP/WebSocket configurations. Polkadot configures it to `true` btw: https://github.com/paritytech/polkadot-sdk/blob/b65313e81465dd730e48d4ce00deb76922618375/substrate/client/network/src/transport.rs#L58
1 parent 70f94b1 commit ec48b04

File tree

7 files changed

+58
-11
lines changed

7 files changed

+58
-11
lines changed

src/transport/tcp/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ pub struct Config {
4141
/// Defaults to `true`.
4242
pub reuse_port: bool,
4343

44+
/// Enable `TCP_NODELAY`.
45+
///
46+
/// Defaults to `false`.
47+
pub nodelay: bool,
48+
4449
/// Yamux configuration.
4550
pub yamux_config: crate::yamux::Config,
4651

@@ -85,6 +90,7 @@ impl Default for Config {
8590
"/ip6/::/tcp/0".parse().expect("valid address"),
8691
],
8792
reuse_port: true,
93+
nodelay: false,
8894
yamux_config: Default::default(),
8995
noise_read_ahead_frame_count: MAX_READ_AHEAD_FACTOR,
9096
noise_write_buffer_size: MAX_WRITE_BUFFER_SIZE,

src/transport/tcp/connection.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ mod tests {
681681
.with(Protocol::Tcp(address.port())),
682682
Default::default(),
683683
Duration::from_secs(10),
684+
false,
684685
)
685686
.await
686687
.unwrap();
@@ -775,6 +776,7 @@ mod tests {
775776
.with(Protocol::Tcp(address.port())),
776777
Default::default(),
777778
Duration::from_secs(10),
779+
false,
778780
)
779781
.await
780782
.unwrap();
@@ -916,6 +918,7 @@ mod tests {
916918
.with(Protocol::Tcp(address.port())),
917919
Default::default(),
918920
Duration::from_secs(10),
921+
false,
919922
)
920923
.await
921924
.unwrap();
@@ -961,6 +964,7 @@ mod tests {
961964
.with(Protocol::Tcp(address.port())),
962965
Default::default(),
963966
Duration::from_secs(10),
967+
false,
964968
)
965969
.await
966970
.unwrap();
@@ -1115,6 +1119,7 @@ mod tests {
11151119
.with(Protocol::Tcp(address.port())),
11161120
Default::default(),
11171121
Duration::from_secs(10),
1122+
false,
11181123
)
11191124
.await
11201125
.unwrap();
@@ -1224,6 +1229,7 @@ mod tests {
12241229
.with(Protocol::Tcp(address.port())),
12251230
Default::default(),
12261231
Duration::from_secs(10),
1232+
false,
12271233
)
12281234
.await
12291235
.unwrap();

src/transport/tcp/listener.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl TcpListener {
106106
pub fn new(
107107
addresses: Vec<Multiaddr>,
108108
reuse_port: bool,
109+
nodelay: bool,
109110
) -> (Self, Vec<Multiaddr>, DialAddresses) {
110111
let (listeners, listen_addresses): (_, Vec<Vec<_>>) = addresses
111112
.into_iter()
@@ -131,6 +132,7 @@ impl TcpListener {
131132
},
132133
};
133134

135+
socket.set_nodelay(nodelay).ok()?;
134136
socket.set_nonblocking(true).ok()?;
135137
socket.set_reuse_address(true).ok()?;
136138
#[cfg(unix)]
@@ -339,7 +341,7 @@ mod tests {
339341

340342
#[tokio::test]
341343
async fn no_listeners() {
342-
let (mut listener, _, _) = TcpListener::new(Vec::new(), true);
344+
let (mut listener, _, _) = TcpListener::new(Vec::new(), true, false);
343345

344346
futures::future::poll_fn(|cx| match listener.poll_next_unpin(cx) {
345347
Poll::Pending => Poll::Ready(()),
@@ -351,7 +353,8 @@ mod tests {
351353
#[tokio::test]
352354
async fn one_listener() {
353355
let address: Multiaddr = "/ip6/::1/tcp/0".parse().unwrap();
354-
let (mut listener, listen_addresses, _) = TcpListener::new(vec![address.clone()], true);
356+
let (mut listener, listen_addresses, _) =
357+
TcpListener::new(vec![address.clone()], true, false);
355358
let Some(Protocol::Tcp(port)) =
356359
listen_addresses.iter().next().unwrap().clone().iter().skip(1).next()
357360
else {
@@ -368,7 +371,8 @@ mod tests {
368371
async fn two_listeners() {
369372
let address1: Multiaddr = "/ip6/::1/tcp/0".parse().unwrap();
370373
let address2: Multiaddr = "/ip4/127.0.0.1/tcp/0".parse().unwrap();
371-
let (mut listener, listen_addresses, _) = TcpListener::new(vec![address1, address2], true);
374+
let (mut listener, listen_addresses, _) =
375+
TcpListener::new(vec![address1, address2], true, false);
372376
let Some(Protocol::Tcp(port1)) =
373377
listen_addresses.iter().next().unwrap().clone().iter().skip(1).next()
374378
else {
@@ -421,7 +425,7 @@ mod tests {
421425
async fn show_all_addresses() {
422426
let address1: Multiaddr = "/ip6/::/tcp/0".parse().unwrap();
423427
let address2: Multiaddr = "/ip4/0.0.0.0/tcp/0".parse().unwrap();
424-
let (_, listen_addresses, _) = TcpListener::new(vec![address1, address2], true);
428+
let (_, listen_addresses, _) = TcpListener::new(vec![address1, address2], true, false);
425429

426430
println!("{listen_addresses:#?}");
427431
}

src/transport/tcp/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl TcpTransport {
137137
address: Multiaddr,
138138
dial_addresses: DialAddresses,
139139
connection_open_timeout: Duration,
140+
nodelay: bool,
140141
) -> crate::Result<(Multiaddr, TcpStream)> {
141142
let (socket_address, _) = TcpListener::get_socket_address(&address)?;
142143
let remote_address = match socket_address {
@@ -198,6 +199,7 @@ impl TcpTransport {
198199
socket.set_only_v6(true)?;
199200
}
200201
socket.set_nonblocking(true)?;
202+
socket.set_nodelay(nodelay)?;
201203

202204
match dial_addresses.local_dial_address(&remote_address.ip()) {
203205
Ok(Some(dial_address)) => {
@@ -261,6 +263,7 @@ impl TransportBuilder for TcpTransport {
261263
let (listener, listen_addresses, dial_addresses) = TcpListener::new(
262264
std::mem::take(&mut config.listen_addresses),
263265
config.reuse_port,
266+
config.nodelay,
264267
);
265268

266269
Ok((
@@ -293,11 +296,12 @@ impl Transport for TcpTransport {
293296
let substream_open_timeout = self.config.substream_open_timeout;
294297
let dial_addresses = self.dial_addresses.clone();
295298
let keypair = self.context.keypair.clone();
299+
let nodelay = self.config.nodelay;
296300

297301
self.pending_dials.insert(connection_id, address.clone());
298302
self.pending_connections.push(Box::pin(async move {
299303
let (_, stream) =
300-
TcpTransport::dial_peer(address, dial_addresses, connection_open_timeout)
304+
TcpTransport::dial_peer(address, dial_addresses, connection_open_timeout, nodelay)
301305
.await
302306
.map_err(|error| (connection_id, error))?;
303307

@@ -370,9 +374,16 @@ impl Transport for TcpTransport {
370374
.map(|address| {
371375
let dial_addresses = self.dial_addresses.clone();
372376
let connection_open_timeout = self.config.connection_open_timeout;
377+
let nodelay = self.config.nodelay;
373378

374379
async move {
375-
TcpTransport::dial_peer(address, dial_addresses, connection_open_timeout).await
380+
TcpTransport::dial_peer(
381+
address,
382+
dial_addresses,
383+
connection_open_timeout,
384+
nodelay,
385+
)
386+
.await
376387
}
377388
})
378389
.collect();

src/transport/websocket/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ pub struct Config {
4141
/// Defaults to `true`.
4242
pub reuse_port: bool,
4343

44+
/// Enable `TCP_NODELAY`.
45+
///
46+
/// Defaults to `false`.
47+
pub nodelay: bool,
48+
4449
/// Yamux configuration.
4550
pub yamux_config: crate::yamux::Config,
4651

@@ -85,6 +90,7 @@ impl Default for Config {
8590
"/ip6/::/tcp/0/ws".parse().expect("valid address"),
8691
],
8792
reuse_port: true,
93+
nodelay: false,
8894
yamux_config: Default::default(),
8995
noise_read_ahead_frame_count: MAX_READ_AHEAD_FACTOR,
9096
noise_write_buffer_size: MAX_WRITE_BUFFER_SIZE,

src/transport/websocket/listener.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl WebSocketListener {
105105
pub fn new(
106106
addresses: Vec<Multiaddr>,
107107
reuse_port: bool,
108+
nodelay: bool,
108109
) -> (Self, Vec<Multiaddr>, DialAddresses) {
109110
let (listeners, listen_addresses): (_, Vec<Vec<_>>) = addresses
110111
.into_iter()
@@ -135,6 +136,7 @@ impl WebSocketListener {
135136
.ok()?,
136137
};
137138

139+
socket.set_nodelay(nodelay).ok()?;
138140
socket.set_nonblocking(true).ok()?;
139141
socket.set_reuse_address(true).ok()?;
140142
#[cfg(unix)]
@@ -398,7 +400,7 @@ mod tests {
398400

399401
#[tokio::test]
400402
async fn no_listeners() {
401-
let (mut listener, _, _) = WebSocketListener::new(Vec::new(), true);
403+
let (mut listener, _, _) = WebSocketListener::new(Vec::new(), true, false);
402404

403405
futures::future::poll_fn(|cx| match listener.poll_next_unpin(cx) {
404406
Poll::Pending => Poll::Ready(()),
@@ -411,7 +413,7 @@ mod tests {
411413
async fn one_listener() {
412414
let address: Multiaddr = "/ip6/::1/tcp/0/ws".parse().unwrap();
413415
let (mut listener, listen_addresses, _) =
414-
WebSocketListener::new(vec![address.clone()], true);
416+
WebSocketListener::new(vec![address.clone()], true, false);
415417
let Some(Protocol::Tcp(port)) =
416418
listen_addresses.iter().next().unwrap().clone().iter().skip(1).next()
417419
else {
@@ -429,7 +431,7 @@ mod tests {
429431
let address1: Multiaddr = "/ip6/::1/tcp/0/ws".parse().unwrap();
430432
let address2: Multiaddr = "/ip4/127.0.0.1/tcp/0/ws".parse().unwrap();
431433
let (mut listener, listen_addresses, _) =
432-
WebSocketListener::new(vec![address1, address2], true);
434+
WebSocketListener::new(vec![address1, address2], true, false);
433435

434436
let Some(Protocol::Tcp(port1)) =
435437
listen_addresses.iter().next().unwrap().clone().iter().skip(1).next()

src/transport/websocket/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ impl WebSocketTransport {
182182
address: Multiaddr,
183183
dial_addresses: DialAddresses,
184184
connection_open_timeout: Duration,
185+
nodelay: bool,
185186
) -> crate::Result<(Multiaddr, WebSocketStream<MaybeTlsStream<TcpStream>>)> {
186187
let (url, _) = Self::multiaddr_into_url(address.clone())?;
187188
let (socket_address, _) = WebSocketListener::get_socket_address(&address)?;
@@ -245,6 +246,7 @@ impl WebSocketTransport {
245246
socket.set_only_v6(true)?;
246247
}
247248
socket.set_nonblocking(true)?;
249+
socket.set_nodelay(nodelay)?;
248250

249251
match dial_addresses.local_dial_address(&remote_address.ip()) {
250252
Ok(Some(dial_address)) => {
@@ -315,6 +317,7 @@ impl TransportBuilder for WebSocketTransport {
315317
let (listener, listen_addresses, dial_addresses) = WebSocketListener::new(
316318
std::mem::take(&mut config.listen_addresses),
317319
config.reuse_port,
320+
config.nodelay,
318321
);
319322

320323
Ok((
@@ -344,6 +347,8 @@ impl Transport for WebSocketTransport {
344347
let max_read_ahead_factor = self.config.noise_read_ahead_frame_count;
345348
let max_write_buffer_size = self.config.noise_write_buffer_size;
346349
let dial_addresses = self.dial_addresses.clone();
350+
let nodelay = self.config.nodelay;
351+
347352
self.pending_dials.insert(connection_id, address.clone());
348353

349354
tracing::debug!(target: LOG_TARGET, ?connection_id, ?address, "open connection");
@@ -353,6 +358,7 @@ impl Transport for WebSocketTransport {
353358
address.clone(),
354359
dial_addresses,
355360
connection_open_timeout,
361+
nodelay,
356362
)
357363
.await
358364
.map_err(|error| WebSocketError::new(error, Some(connection_id)))?;
@@ -437,10 +443,16 @@ impl Transport for WebSocketTransport {
437443
.map(|address| {
438444
let connection_open_timeout = self.config.connection_open_timeout;
439445
let dial_addresses = self.dial_addresses.clone();
446+
let nodelay = self.config.nodelay;
440447

441448
async move {
442-
WebSocketTransport::dial_peer(address, dial_addresses, connection_open_timeout)
443-
.await
449+
WebSocketTransport::dial_peer(
450+
address,
451+
dial_addresses,
452+
connection_open_timeout,
453+
nodelay,
454+
)
455+
.await
444456
}
445457
})
446458
.collect();

0 commit comments

Comments
 (0)