From 03bd5e604846944cc4cccb6a5dc143410e41a3f9 Mon Sep 17 00:00:00 2001 From: Mitch Gaffigan Date: Sat, 17 Oct 2026 15:54:48 -0500 Subject: [PATCH] Configure idle keepalive timers to traverse nat Signed-off-by: Mitch Gaffigan --- .../connect/connectors/tcp/SocketUtil.java | 21 +++++++++++++++++++ .../connect/connectors/tcp/TcpDispatcher.java | 6 ++++-- .../connect/connectors/tcp/TcpReceiver.java | 4 +++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/mirth/connect/connectors/tcp/SocketUtil.java b/server/src/main/java/com/mirth/connect/connectors/tcp/SocketUtil.java index a9830e4d7f..ae5f6301a2 100644 --- a/server/src/main/java/com/mirth/connect/connectors/tcp/SocketUtil.java +++ b/server/src/main/java/com/mirth/connect/connectors/tcp/SocketUtil.java @@ -13,14 +13,21 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketException; import java.net.UnknownHostException; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.mirth.connect.util.TcpUtil; +import jdk.net.ExtendedSocketOptions; + public class SocketUtil { + private static final Logger logger = LogManager.getLogger(SocketUtil.class); + public static Socket createSocket(TcpConfiguration configuration) throws UnknownHostException, IOException { return createSocket(configuration, null); } @@ -67,6 +74,20 @@ public static void connectSocket(Socket socket, String host, int port, int timeo socket.connect(new InetSocketAddress(InetAddress.getByName(TcpUtil.getFixedHost(host)), port), timeout); } + /** Set TCP keepalive options on a socket */ + public static void setKeepAlive(Socket socket) throws SocketException { + socket.setKeepAlive(true); + + try { + int keepAliveIdle = Integer.parseInt(System.getProperty("mirth.tcp.keepalive.idle", "120").trim()); + if (keepAliveIdle > 0) { + socket.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, keepAliveIdle); + } + } catch (Exception e) { + logger.warn("Failed to set TCP keepalive options on socket.", e); + } + } + public static void closeSocket(Socket socket) throws IOException { if (socket != null) { /* diff --git a/server/src/main/java/com/mirth/connect/connectors/tcp/TcpDispatcher.java b/server/src/main/java/com/mirth/connect/connectors/tcp/TcpDispatcher.java index 16dd25a411..067b0aca7e 100644 --- a/server/src/main/java/com/mirth/connect/connectors/tcp/TcpDispatcher.java +++ b/server/src/main/java/com/mirth/connect/connectors/tcp/TcpDispatcher.java @@ -376,7 +376,9 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage m socket.setReceiveBufferSize(bufferSize); socket.setSendBufferSize(bufferSize); socket.setSoTimeout(responseTimeout); - socket.setKeepAlive(tcpDispatcherProperties.isKeepConnectionOpen()); + if (tcpDispatcherProperties.isKeepConnectionOpen()) { + SocketUtil.setKeepAlive(socket); + } eventController.dispatchEvent(new ConnectorCountEvent(getChannelId(), getMetaDataId(), getDestinationName(), ConnectionStatusEventType.CONNECTED, SocketUtil.getLocalAddress(socket) + " -> " + SocketUtil.getInetAddress(socket), true)); } @@ -810,7 +812,7 @@ private void initSocket(Socket socket) throws SocketException { socket.setReceiveBufferSize(bufferSize); socket.setSendBufferSize(bufferSize); socket.setSoTimeout(responseTimeout); - socket.setKeepAlive(true); + SocketUtil.setKeepAlive(socket); socket.setReuseAddress(true); socket.setTcpNoDelay(true); } diff --git a/server/src/main/java/com/mirth/connect/connectors/tcp/TcpReceiver.java b/server/src/main/java/com/mirth/connect/connectors/tcp/TcpReceiver.java index 66f48433db..57a46c5222 100644 --- a/server/src/main/java/com/mirth/connect/connectors/tcp/TcpReceiver.java +++ b/server/src/main/java/com/mirth/connect/connectors/tcp/TcpReceiver.java @@ -1067,7 +1067,9 @@ private void initSocket(Socket socket) throws SocketException { socket.setReceiveBufferSize(bufferSize); socket.setSendBufferSize(bufferSize); socket.setSoTimeout(timeout); - socket.setKeepAlive(connectorProperties.isKeepConnectionOpen()); + if (connectorProperties.isKeepConnectionOpen()) { + SocketUtil.setKeepAlive(socket); + } socket.setReuseAddress(true); socket.setTcpNoDelay(true); }