Skip to content

Commit 9f8fa3b

Browse files
shashank-bairyvietj
authored andcommitted
Tcp user timeout fixes for server
Motivation: - Configures TCP_USER_TIMEOUT for EpollTransport and IoUringTransport - Fixes fluent api pattern for the same in client and server configs - Related tests
1 parent e334587 commit 9f8fa3b

9 files changed

Lines changed: 65 additions & 1 deletion

File tree

vertx-core/src/main/java/examples/CoreExamples.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,14 @@ public void configureTransport() {
501501
.build();
502502
}
503503

504-
public void configureLinuxOptions(Vertx vertx, boolean fastOpen, boolean cork, boolean quickAck, boolean reusePort) {
504+
public void configureLinuxOptions(Vertx vertx, boolean fastOpen, boolean cork, boolean quickAck, boolean reusePort, int tcpUserTimeout) {
505505
// Available on Linux
506506
vertx.createHttpServer(new HttpServerOptions()
507507
.setTcpFastOpen(fastOpen)
508508
.setTcpCork(cork)
509509
.setTcpQuickAck(quickAck)
510510
.setReusePort(reusePort)
511+
.setTcpUserTimeout(tcpUserTimeout)
511512
);
512513
}
513514

vertx-core/src/main/java/io/vertx/core/http/HttpServerOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@ public HttpServerOptions setTcpQuickAck(boolean tcpQuickAck) {
491491
return (HttpServerOptions) super.setTcpQuickAck(tcpQuickAck);
492492
}
493493

494+
@Override
495+
public HttpServerOptions setTcpUserTimeout(int tcpUserTimeout) {
496+
return (HttpServerOptions) super.setTcpUserTimeout(tcpUserTimeout);
497+
}
498+
494499
@Override
495500
public HttpServerOptions addCrlPath(String crlPath) throws NullPointerException {
496501
return (HttpServerOptions) super.addCrlPath(crlPath);

vertx-core/src/main/java/io/vertx/core/impl/transports/EpollTransport.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public void configure(NetServerOptions options, boolean domainSocket, ServerBoot
133133
if (options.isTcpFastOpen()) {
134134
bootstrap.option(ChannelOption.TCP_FASTOPEN, options.isTcpFastOpen() ? pendingFastOpenRequestsThreshold : 0);
135135
}
136+
bootstrap.childOption(EpollChannelOption.TCP_USER_TIMEOUT, options.getTcpUserTimeout());
136137
bootstrap.childOption(EpollChannelOption.TCP_QUICKACK, options.isTcpQuickAck());
137138
bootstrap.childOption(EpollChannelOption.TCP_CORK, options.isTcpCork());
138139
}

vertx-core/src/main/java/io/vertx/core/impl/transports/IoUringTransport.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public void configure(NetServerOptions options, boolean domainSocket, ServerBoot
138138
if (options.isTcpFastOpen()) {
139139
bootstrap.option(IoUringChannelOption.TCP_FASTOPEN, options.isTcpFastOpen() ? pendingFastOpenRequestsThreshold : 0);
140140
}
141+
bootstrap.childOption(IoUringChannelOption.TCP_USER_TIMEOUT, options.getTcpUserTimeout());
141142
bootstrap.childOption(IoUringChannelOption.TCP_QUICKACK, options.isTcpQuickAck());
142143
bootstrap.childOption(IoUringChannelOption.TCP_CORK, options.isTcpCork());
143144
Transport.super.configure(options, false, bootstrap);
@@ -151,6 +152,7 @@ public void configure(ClientOptionsBase options, int connectTimeout, boolean dom
151152
if (options.isTcpFastOpen()) {
152153
bootstrap.option(IoUringChannelOption.TCP_FASTOPEN_CONNECT, options.isTcpFastOpen());
153154
}
155+
bootstrap.option(IoUringChannelOption.TCP_USER_TIMEOUT, options.getTcpUserTimeout());
154156
bootstrap.option(IoUringChannelOption.TCP_QUICKACK, options.isTcpQuickAck());
155157
bootstrap.option(IoUringChannelOption.TCP_CORK, options.isTcpCork());
156158
Transport.super.configure(options, connectTimeout, false, bootstrap);

vertx-core/src/main/java/io/vertx/core/net/NetClientOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ public NetClientOptions setTcpQuickAck(boolean tcpQuickAck) {
239239
return (NetClientOptions) super.setTcpQuickAck(tcpQuickAck);
240240
}
241241

242+
@Override
243+
public NetClientOptions setTcpUserTimeout(int tcpUserTimeout) {
244+
return (NetClientOptions) super.setTcpUserTimeout(tcpUserTimeout);
245+
}
246+
242247
@Override
243248
public NetClientOptions addCrlPath(String crlPath) throws NullPointerException {
244249
return (NetClientOptions) super.addCrlPath(crlPath);

vertx-core/src/main/java/io/vertx/core/net/NetServerOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ public NetServerOptions setTcpQuickAck(boolean tcpQuickAck) {
286286
return (NetServerOptions) super.setTcpQuickAck(tcpQuickAck);
287287
}
288288

289+
@Override
290+
public NetServerOptions setTcpUserTimeout(int tcpUserTimeout) {
291+
return (NetServerOptions) super.setTcpUserTimeout(tcpUserTimeout);
292+
}
293+
289294
@Override
290295
public NetServerOptions addCrlPath(String crlPath) throws NullPointerException {
291296
return (NetServerOptions) super.addCrlPath(crlPath);

vertx-core/src/main/java/io/vertx/core/net/TCPSSLOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,9 @@ public int getTcpUserTimeout() {
697697
* @param tcpUserTimeout the tcp user timeout value
698698
*/
699699
public TCPSSLOptions setTcpUserTimeout(int tcpUserTimeout) {
700+
if (tcpUserTimeout < 0) {
701+
throw new IllegalArgumentException("tcpUserTimeout must be >= 0");
702+
}
700703
this.tcpUserTimeout = tcpUserTimeout;
701704
return this;
702705
}

vertx-core/src/test/java/io/vertx/tests/http/Http1xTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ public void testClientOptions() {
110110
assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive));
111111
assertEquals(!tcpKeepAlive, options.isTcpKeepAlive());
112112

113+
assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout());
114+
int tcpUserTimeout = TestUtils.randomPositiveInt();
115+
assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout));
116+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
117+
assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000));
118+
113119
int soLinger = -1;
114120
assertEquals(soLinger, options.getSoLinger());
115121
rand = TestUtils.randomPositiveInt();
@@ -299,6 +305,12 @@ public void testServerOptions() {
299305
assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive));
300306
assertEquals(!tcpKeepAlive, options.isTcpKeepAlive());
301307

308+
assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout());
309+
int tcpUserTimeout = TestUtils.randomPositiveInt();
310+
assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout));
311+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
312+
assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000));
313+
302314
int soLinger = -1;
303315
assertEquals(soLinger, options.getSoLinger());
304316
rand = TestUtils.randomPositiveInt();
@@ -559,6 +571,7 @@ public void testClientOptionsJson() {
559571
int trafficClass = TestUtils.randomByte() + 128;
560572
boolean tcpNoDelay = rand.nextBoolean();
561573
boolean tcpKeepAlive = rand.nextBoolean();
574+
int tcpUserTimeout = TestUtils.randomPositiveInt();
562575
int soLinger = TestUtils.randomPositiveInt();
563576
int idleTimeout = TestUtils.randomPositiveInt();
564577
boolean ssl = rand.nextBoolean();
@@ -609,6 +622,7 @@ public void testClientOptionsJson() {
609622
.put("trafficClass", trafficClass)
610623
.put("tcpNoDelay", tcpNoDelay)
611624
.put("tcpKeepAlive", tcpKeepAlive)
625+
.put("tcpUserTimeout", tcpUserTimeout)
612626
.put("soLinger", soLinger)
613627
.put("idleTimeout", idleTimeout)
614628
.put("ssl", ssl)
@@ -656,6 +670,7 @@ public void testClientOptionsJson() {
656670
assertEquals(reuseAddress, options.isReuseAddress());
657671
assertEquals(trafficClass, options.getTrafficClass());
658672
assertEquals(tcpKeepAlive, options.isTcpKeepAlive());
673+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
659674
assertEquals(tcpNoDelay, options.isTcpNoDelay());
660675
assertEquals(soLinger, options.getSoLinger());
661676
assertEquals(idleTimeout, options.getIdleTimeout());
@@ -861,6 +876,7 @@ public void testServerOptionsJson() {
861876
int trafficClass = TestUtils.randomByte() + 128;
862877
boolean tcpNoDelay = rand.nextBoolean();
863878
boolean tcpKeepAlive = rand.nextBoolean();
879+
int tcpUserTimeout = TestUtils.randomPositiveInt();
864880
int soLinger = TestUtils.randomPositiveInt();
865881
int idleTimeout = TestUtils.randomPositiveInt();
866882
boolean ssl = rand.nextBoolean();
@@ -904,6 +920,7 @@ public void testServerOptionsJson() {
904920
.put("trafficClass", trafficClass)
905921
.put("tcpNoDelay", tcpNoDelay)
906922
.put("tcpKeepAlive", tcpKeepAlive)
923+
.put("tcpUserTimeout", tcpUserTimeout)
907924
.put("soLinger", soLinger)
908925
.put("idleTimeout", idleTimeout)
909926
.put("ssl", ssl)
@@ -944,6 +961,7 @@ public void testServerOptionsJson() {
944961
assertEquals(reuseAddress, options.isReuseAddress());
945962
assertEquals(trafficClass, options.getTrafficClass());
946963
assertEquals(tcpKeepAlive, options.isTcpKeepAlive());
964+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
947965
assertEquals(tcpNoDelay, options.isTcpNoDelay());
948966
assertEquals(soLinger, options.getSoLinger());
949967
assertEquals(idleTimeout, options.getIdleTimeout());

vertx-core/src/test/java/io/vertx/tests/net/NetTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ public void testClientOptions() {
169169
assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive));
170170
assertEquals(!tcpKeepAlive, options.isTcpKeepAlive());
171171

172+
assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout());
173+
int tcpUserTimeout = TestUtils.randomPositiveInt();
174+
assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout));
175+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
176+
assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000));
177+
172178
int soLinger = -1;
173179
assertEquals(soLinger, options.getSoLinger());
174180
rand = TestUtils.randomPositiveInt();
@@ -278,6 +284,12 @@ public void testServerOptions() {
278284
assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive));
279285
assertEquals(!tcpKeepAlive, options.isTcpKeepAlive());
280286

287+
assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout());
288+
int tcpUserTimeout = TestUtils.randomPositiveInt();
289+
assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout));
290+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
291+
assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000));
292+
281293
int soLinger = -1;
282294
assertEquals(soLinger, options.getSoLinger());
283295
rand = TestUtils.randomPositiveInt();
@@ -368,6 +380,7 @@ public void testCopyClientOptions() {
368380
int trafficClass = TestUtils.randomByte() + 128;
369381
boolean tcpNoDelay = rand.nextBoolean();
370382
boolean tcpKeepAlive = rand.nextBoolean();
383+
int tcpUserTimeout = TestUtils.randomPositiveInt();
371384
int soLinger = TestUtils.randomPositiveInt();
372385
int idleTimeout = TestUtils.randomPositiveInt();
373386
boolean ssl = rand.nextBoolean();
@@ -397,6 +410,7 @@ public void testCopyClientOptions() {
397410
options.setSsl(ssl);
398411
options.setTcpNoDelay(tcpNoDelay);
399412
options.setTcpKeepAlive(tcpKeepAlive);
413+
options.setTcpUserTimeout(tcpUserTimeout);
400414
options.setSoLinger(soLinger);
401415
options.setIdleTimeout(idleTimeout);
402416
options.setKeyCertOptions(keyStoreOptions);
@@ -429,6 +443,7 @@ public void testDefaultClientOptionsJson() {
429443
assertEquals(def.getConnectTimeout(), json.getConnectTimeout());
430444
assertEquals(def.isTcpNoDelay(), json.isTcpNoDelay());
431445
assertEquals(def.isTcpKeepAlive(), json.isTcpKeepAlive());
446+
assertEquals(def.getTcpUserTimeout(), json.getTcpUserTimeout());
432447
assertEquals(def.getSoLinger(), json.getSoLinger());
433448
assertEquals(def.isSsl(), json.isSsl());
434449
assertEquals(def.isUseAlpn(), json.isUseAlpn());
@@ -446,6 +461,7 @@ public void testClientOptionsJson() {
446461
int trafficClass = TestUtils.randomByte() + 128;
447462
boolean tcpNoDelay = rand.nextBoolean();
448463
boolean tcpKeepAlive = rand.nextBoolean();
464+
int tcpUserTimeout = TestUtils.randomPositiveInt();
449465
int soLinger = TestUtils.randomPositiveInt();
450466
int idleTimeout = TestUtils.randomPositiveInt();
451467
boolean ssl = rand.nextBoolean();
@@ -488,6 +504,7 @@ public void testClientOptionsJson() {
488504
.put("trafficClass", trafficClass)
489505
.put("tcpNoDelay", tcpNoDelay)
490506
.put("tcpKeepAlive", tcpKeepAlive)
507+
.put("tcpUserTimeout", tcpUserTimeout)
491508
.put("soLinger", soLinger)
492509
.put("idleTimeout", idleTimeout)
493510
.put("ssl", ssl)
@@ -516,6 +533,7 @@ public void testClientOptionsJson() {
516533
assertEquals(reuseAddress, options.isReuseAddress());
517534
assertEquals(trafficClass, options.getTrafficClass());
518535
assertEquals(tcpKeepAlive, options.isTcpKeepAlive());
536+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
519537
assertEquals(tcpNoDelay, options.isTcpNoDelay());
520538
assertEquals(soLinger, options.getSoLinger());
521539
assertEquals(idleTimeout, options.getIdleTimeout());
@@ -577,6 +595,7 @@ public void testCopyServerOptions() {
577595
int trafficClass = TestUtils.randomByte() + 128;
578596
boolean tcpNoDelay = rand.nextBoolean();
579597
boolean tcpKeepAlive = rand.nextBoolean();
598+
int tcpUserTimeout = TestUtils.randomPositiveInt();
580599
int soLinger = TestUtils.randomPositiveInt();
581600
boolean usePooledBuffers = rand.nextBoolean();
582601
int idleTimeout = TestUtils.randomPositiveInt();
@@ -607,6 +626,7 @@ public void testCopyServerOptions() {
607626
options.setTrafficClass(trafficClass);
608627
options.setTcpNoDelay(tcpNoDelay);
609628
options.setTcpKeepAlive(tcpKeepAlive);
629+
options.setTcpUserTimeout(tcpUserTimeout);
610630
options.setSoLinger(soLinger);
611631
options.setIdleTimeout(idleTimeout);
612632
options.setSsl(ssl);
@@ -646,6 +666,7 @@ public void testDefaultServerOptionsJson() {
646666
assertEquals(def.getHost(), json.getHost());
647667
assertEquals(def.isTcpNoDelay(), json.isTcpNoDelay());
648668
assertEquals(def.isTcpKeepAlive(), json.isTcpKeepAlive());
669+
assertEquals(def.getTcpUserTimeout(), json.getTcpUserTimeout());
649670
assertEquals(def.getSoLinger(), json.getSoLinger());
650671
assertEquals(def.isSsl(), json.isSsl());
651672
assertEquals(def.isUseAlpn(), json.isUseAlpn());
@@ -667,6 +688,7 @@ public void testServerOptionsJson() {
667688
int trafficClass = TestUtils.randomByte() + 128;
668689
boolean tcpNoDelay = rand.nextBoolean();
669690
boolean tcpKeepAlive = rand.nextBoolean();
691+
int tcpUserTimeout = TestUtils.randomPositiveInt();
670692
int soLinger = TestUtils.randomPositiveInt();
671693
boolean usePooledBuffers = rand.nextBoolean();
672694
int idleTimeout = TestUtils.randomPositiveInt();
@@ -701,6 +723,7 @@ public void testServerOptionsJson() {
701723
.put("trafficClass", trafficClass)
702724
.put("tcpNoDelay", tcpNoDelay)
703725
.put("tcpKeepAlive", tcpKeepAlive)
726+
.put("tcpUserTimeout", tcpUserTimeout)
704727
.put("soLinger", soLinger)
705728
.put("usePooledBuffers", usePooledBuffers)
706729
.put("idleTimeout", idleTimeout)
@@ -726,6 +749,7 @@ public void testServerOptionsJson() {
726749
assertEquals(reuseAddress, options.isReuseAddress());
727750
assertEquals(trafficClass, options.getTrafficClass());
728751
assertEquals(tcpKeepAlive, options.isTcpKeepAlive());
752+
assertEquals(tcpUserTimeout, options.getTcpUserTimeout());
729753
assertEquals(tcpNoDelay, options.isTcpNoDelay());
730754
assertEquals(soLinger, options.getSoLinger());
731755
assertEquals(idleTimeout, options.getIdleTimeout());

0 commit comments

Comments
 (0)