From 879003f7bb699a38b75dc9b2edd230d31b01e638 Mon Sep 17 00:00:00 2001 From: Shashank Bairy R Date: Fri, 6 Feb 2026 19:58:13 +0530 Subject: [PATCH 1/2] tcp user timeout changes --- src/main/java/examples/CoreExamples.java | 3 ++- .../io/vertx/core/http/HttpServerOptions.java | 5 +++++ .../io/vertx/core/net/NetClientOptions.java | 5 +++++ .../io/vertx/core/net/NetServerOptions.java | 5 +++++ .../java/io/vertx/core/net/TCPSSLOptions.java | 3 +++ .../java/io/vertx/core/http/Http1xTest.java | 18 ++++++++++++++++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/java/examples/CoreExamples.java b/src/main/java/examples/CoreExamples.java index ba863cfe9e4..0b177c50ed6 100644 --- a/src/main/java/examples/CoreExamples.java +++ b/src/main/java/examples/CoreExamples.java @@ -412,13 +412,14 @@ public void configureNative() { System.out.println("Running with native: " + usingNative); } - public void configureLinuxOptions(Vertx vertx, boolean fastOpen, boolean cork, boolean quickAck, boolean reusePort) { + public void configureLinuxOptions(Vertx vertx, boolean fastOpen, boolean cork, boolean quickAck, boolean reusePort, int tcpUserTimeout) { // Available on Linux vertx.createHttpServer(new HttpServerOptions() .setTcpFastOpen(fastOpen) .setTcpCork(cork) .setTcpQuickAck(quickAck) .setReusePort(reusePort) + .setTcpUserTimeout(tcpUserTimeout) ); } diff --git a/src/main/java/io/vertx/core/http/HttpServerOptions.java b/src/main/java/io/vertx/core/http/HttpServerOptions.java index 345c804f862..447767ca7a0 100755 --- a/src/main/java/io/vertx/core/http/HttpServerOptions.java +++ b/src/main/java/io/vertx/core/http/HttpServerOptions.java @@ -509,6 +509,11 @@ public HttpServerOptions setTcpQuickAck(boolean tcpQuickAck) { return (HttpServerOptions) super.setTcpQuickAck(tcpQuickAck); } + @Override + public HttpServerOptions setTcpUserTimeout(int tcpUserTimeout) { + return (HttpServerOptions) super.setTcpUserTimeout(tcpUserTimeout); + } + @Override public HttpServerOptions addCrlPath(String crlPath) throws NullPointerException { return (HttpServerOptions) super.addCrlPath(crlPath); diff --git a/src/main/java/io/vertx/core/net/NetClientOptions.java b/src/main/java/io/vertx/core/net/NetClientOptions.java index 5c9fcd56120..79f4bef00da 100755 --- a/src/main/java/io/vertx/core/net/NetClientOptions.java +++ b/src/main/java/io/vertx/core/net/NetClientOptions.java @@ -289,6 +289,11 @@ public NetClientOptions setTcpQuickAck(boolean tcpQuickAck) { return (NetClientOptions) super.setTcpQuickAck(tcpQuickAck); } + @Override + public NetClientOptions setTcpUserTimeout(int tcpUserTimeout) { + return (NetClientOptions) super.setTcpUserTimeout(tcpUserTimeout); + } + @Deprecated @Override public ClientOptionsBase setOpenSslEngineOptions(OpenSSLEngineOptions sslEngineOptions) { diff --git a/src/main/java/io/vertx/core/net/NetServerOptions.java b/src/main/java/io/vertx/core/net/NetServerOptions.java index 125b079d4a6..0c9352d4c6a 100755 --- a/src/main/java/io/vertx/core/net/NetServerOptions.java +++ b/src/main/java/io/vertx/core/net/NetServerOptions.java @@ -332,6 +332,11 @@ public NetServerOptions setTcpQuickAck(boolean tcpQuickAck) { return (NetServerOptions) super.setTcpQuickAck(tcpQuickAck); } + @Override + public NetServerOptions setTcpUserTimeout(int tcpUserTimeout) { + return (NetServerOptions) super.setTcpUserTimeout(tcpUserTimeout); + } + @Override public NetServerOptions addCrlPath(String crlPath) throws NullPointerException { return (NetServerOptions) super.addCrlPath(crlPath); diff --git a/src/main/java/io/vertx/core/net/TCPSSLOptions.java b/src/main/java/io/vertx/core/net/TCPSSLOptions.java index 3b2f6e569df..a697da66476 100755 --- a/src/main/java/io/vertx/core/net/TCPSSLOptions.java +++ b/src/main/java/io/vertx/core/net/TCPSSLOptions.java @@ -870,6 +870,9 @@ public int getTcpUserTimeout() { * @param tcpUserTimeout the tcp user timeout value */ public TCPSSLOptions setTcpUserTimeout(int tcpUserTimeout) { + if (tcpUserTimeout < 0) { + throw new IllegalArgumentException("tcpUserTimeout must be >= 0"); + } this.tcpUserTimeout = tcpUserTimeout; return this; } diff --git a/src/test/java/io/vertx/core/http/Http1xTest.java b/src/test/java/io/vertx/core/http/Http1xTest.java index f324ff5b778..8ccda582293 100644 --- a/src/test/java/io/vertx/core/http/Http1xTest.java +++ b/src/test/java/io/vertx/core/http/Http1xTest.java @@ -108,6 +108,12 @@ public void testClientOptions() { assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive)); assertEquals(!tcpKeepAlive, options.isTcpKeepAlive()); + assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout()); + int tcpUserTimeout = TestUtils.randomPositiveInt(); + assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout)); + assertEquals(tcpUserTimeout, options.getTcpUserTimeout()); + assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000)); + int soLinger = -1; assertEquals(soLinger, options.getSoLinger()); rand = TestUtils.randomPositiveInt(); @@ -317,6 +323,12 @@ public void testServerOptions() { assertEquals(options, options.setTcpKeepAlive(!tcpKeepAlive)); assertEquals(!tcpKeepAlive, options.isTcpKeepAlive()); + assertEquals(TCPSSLOptions.DEFAULT_TCP_USER_TIMEOUT, options.getTcpUserTimeout()); + int tcpUserTimeout = TestUtils.randomPositiveInt(); + assertEquals(options, options.setTcpUserTimeout(tcpUserTimeout)); + assertEquals(tcpUserTimeout, options.getTcpUserTimeout()); + assertIllegalArgumentException(() -> options.setTcpUserTimeout(-1000)); + int soLinger = -1; assertEquals(soLinger, options.getSoLinger()); rand = TestUtils.randomPositiveInt(); @@ -584,6 +596,7 @@ public void testClientOptionsJson() { int trafficClass = TestUtils.randomByte() + 128; boolean tcpNoDelay = rand.nextBoolean(); boolean tcpKeepAlive = rand.nextBoolean(); + int tcpUserTimeout = TestUtils.randomPositiveInt(); int soLinger = TestUtils.randomPositiveInt(); int idleTimeout = TestUtils.randomPositiveInt(); boolean ssl = rand.nextBoolean(); @@ -634,6 +647,7 @@ public void testClientOptionsJson() { .put("trafficClass", trafficClass) .put("tcpNoDelay", tcpNoDelay) .put("tcpKeepAlive", tcpKeepAlive) + .put("tcpUserTimeout", tcpUserTimeout) .put("soLinger", soLinger) .put("idleTimeout", idleTimeout) .put("ssl", ssl) @@ -681,6 +695,7 @@ public void testClientOptionsJson() { assertEquals(reuseAddress, options.isReuseAddress()); assertEquals(trafficClass, options.getTrafficClass()); assertEquals(tcpKeepAlive, options.isTcpKeepAlive()); + assertEquals(tcpUserTimeout, options.getTcpUserTimeout()); assertEquals(tcpNoDelay, options.isTcpNoDelay()); assertEquals(soLinger, options.getSoLinger()); assertEquals(idleTimeout, options.getIdleTimeout()); @@ -888,6 +903,7 @@ public void testServerOptionsJson() { int trafficClass = TestUtils.randomByte() + 128; boolean tcpNoDelay = rand.nextBoolean(); boolean tcpKeepAlive = rand.nextBoolean(); + int tcpUserTimeout = TestUtils.randomPositiveInt(); int soLinger = TestUtils.randomPositiveInt(); int idleTimeout = TestUtils.randomPositiveInt(); boolean ssl = rand.nextBoolean(); @@ -931,6 +947,7 @@ public void testServerOptionsJson() { .put("trafficClass", trafficClass) .put("tcpNoDelay", tcpNoDelay) .put("tcpKeepAlive", tcpKeepAlive) + .put("tcpUserTimeout", tcpUserTimeout) .put("soLinger", soLinger) .put("idleTimeout", idleTimeout) .put("ssl", ssl) @@ -971,6 +988,7 @@ public void testServerOptionsJson() { assertEquals(reuseAddress, options.isReuseAddress()); assertEquals(trafficClass, options.getTrafficClass()); assertEquals(tcpKeepAlive, options.isTcpKeepAlive()); + assertEquals(tcpUserTimeout, options.getTcpUserTimeout()); assertEquals(tcpNoDelay, options.isTcpNoDelay()); assertEquals(soLinger, options.getSoLinger()); assertEquals(idleTimeout, options.getIdleTimeout()); From 7fbcafbdb857745669565950e8953a5b5bedab05 Mon Sep 17 00:00:00 2001 From: Shashank Bairy R Date: Fri, 6 Feb 2026 20:03:27 +0530 Subject: [PATCH 2/2] set tcp user timeout in epoll transport --- src/main/java/io/vertx/core/impl/transports/EpollTransport.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/vertx/core/impl/transports/EpollTransport.java b/src/main/java/io/vertx/core/impl/transports/EpollTransport.java index c03c9c2f68e..8d32e24d264 100644 --- a/src/main/java/io/vertx/core/impl/transports/EpollTransport.java +++ b/src/main/java/io/vertx/core/impl/transports/EpollTransport.java @@ -143,6 +143,7 @@ public void configure(NetServerOptions options, boolean domainSocket, ServerBoot if (options.isTcpFastOpen()) { bootstrap.option(EpollChannelOption.TCP_FASTOPEN, options.isTcpFastOpen() ? pendingFastOpenRequestsThreshold : 0); } + bootstrap.childOption(EpollChannelOption.TCP_USER_TIMEOUT, options.getTcpUserTimeout()); bootstrap.childOption(EpollChannelOption.TCP_QUICKACK, options.isTcpQuickAck()); bootstrap.childOption(EpollChannelOption.TCP_CORK, options.isTcpCork());