diff --git a/docs/src/reference/docbook/ip.xml b/docs/src/reference/docbook/ip.xml
index 6891402580..848ff17fd0 100644
--- a/docs/src/reference/docbook/ip.xml
+++ b/docs/src/reference/docbook/ip.xml
@@ -725,12 +725,7 @@
factory.
- It is not currently possible to set this to an infinite value
- (0); the maximum value can be set using a SpEL expression as
- follows.
-
- so-timeout="#{T(java.lang.Integer).MAX_VALUE}"
-
+ Setting the attribute to 0 will enable an infinite timeout.
@@ -867,7 +862,9 @@
Y
Defaults to 0 (infinity), except when the connection
- factory is used by collaborating adapters, where it
+ factory is used by collaborating adapters, and for
+ server connection factories with single-use="true".
+ In those cases, it
defaults to the default reply timeout (10 seconds).
See the section about collaborating adapters above
and java.net.Socket. setSoTimeout().
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
index c1d3d14ac1..7b4252fe8b 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
@@ -74,8 +74,13 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection
connection.registerListener(listener);
}
if (listener != null || this.isSingleUse()) {
- if (this.getSoTimeout() <= 0) {
+ if (this.getSoTimeout() < 0) {
try {
+ /* Default so-timeout, when we have a collaborating inbound adapter,
+ * may go to infinity in a future release; currently it's 10 seconds.
+ * While it makes sense in a request/reply scenario, it doesn't
+ * really for completely asynchronous communication between peers.
+ */
socket.setSoTimeout(DEFAULT_REPLY_TIMEOUT);
} catch (SocketException e) {
logger.error("Error setting default reply timeout", e);
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
index 181e6477ac..27e1280e98 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
@@ -67,7 +67,7 @@ public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
private volatile TcpSender sender;
- private volatile int soTimeout;
+ private volatile int soTimeout = -1;
private volatile int soSendBufferSize;
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
index 8bb5e3726d..d981334c33 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
@@ -84,11 +84,12 @@ public abstract class AbstractServerConnectionFactory extends AbstractConnection
connection.setSerializer(this.getSerializer());
connection.setSingleUse(this.isSingleUse());
/*
- * If we have a collaborating outbound channel adapter and we are configured
+ * If we are configured
* for single use; need to enforce a timeout on the socket so we will close
- * it some period after the response was sent (timeout on the next read).
+ * if the client connects, but sends nothing. (Protect against DoS).
+ * Behavior can be overridden by explicitly setting the timeout to zero.
*/
- if (this.isSingleUse() && this.getSoTimeout() <= 0 && listener != null) {
+ if (this.isSingleUse() && this.getSoTimeout() < 0) {
try {
socket.setSoTimeout(DEFAULT_REPLY_TIMEOUT);
} catch (SocketException e) {
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioClientConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioClientConnectionFactory.java
index 4bb7e0fa6a..1763387e7b 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioClientConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioClientConnectionFactory.java
@@ -122,7 +122,8 @@ public class TcpNioClientConnectionFactory extends
this.selector = Selector.open();
while (this.isActive()) {
SocketChannel newChannel;
- int selectionCount = selector.select(this.getSoTimeout());
+ int soTimeout = this.getSoTimeout();
+ int selectionCount = selector.select(soTimeout < 0 ? 0 : soTimeout);
while ((newChannel = newChannels.poll()) != null) {
newChannel.register(this.selector, SelectionKey.OP_READ, connections.get(newChannel));
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioServerConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioServerConnectionFactory.java
index 24c549bc60..806a07df5c 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioServerConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNioServerConnectionFactory.java
@@ -113,7 +113,8 @@ public class TcpNioServerConnectionFactory extends AbstractServerConnectionFacto
private void doSelect(ServerSocketChannel server, final Selector selector)
throws IOException, ClosedChannelException, SocketException {
while (this.isActive()) {
- int selectionCount = selector.select(this.getSoTimeout());
+ int soTimeout = this.getSoTimeout();
+ int selectionCount = selector.select(soTimeout < 0 ? 0 : soTimeout);
this.processNioSelections(selectionCount, selector, server, this.connections);
}
}