mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Application layer keepalives to detect dead TCP connections.
DuplexOutgoingSession flushes its output stream if it's idle for a transport-defined interval, causing an empty frame to be sent. The TCP and Tor plugins use a socket timeout equal to twice the idle interval to detect dead connections. See bugs #27, #46 and #60.
This commit is contained in:
@@ -17,8 +17,9 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
static final TransportId ID = new TransportId("lan");
|
||||
|
||||
LanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency,
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency, maxIdleTime,
|
||||
pollingInterval);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final int MAX_FRAME_LENGTH = 1024;
|
||||
private static final long MAX_LATENCY = 60 * 1000; // 1 minute
|
||||
private static final long MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
|
||||
|
||||
private final Executor ioExecutor;
|
||||
@@ -25,6 +26,6 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||
return new LanTcpPlugin(ioExecutor, callback, MAX_FRAME_LENGTH,
|
||||
MAX_LATENCY, POLLING_INTERVAL);
|
||||
MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
|
||||
protected final Executor ioExecutor;
|
||||
protected final DuplexPluginCallback callback;
|
||||
protected final int maxFrameLength;
|
||||
protected final long maxLatency, pollingInterval;
|
||||
protected final int maxFrameLength, socketTimeout;
|
||||
protected final long maxLatency, maxIdleTime, pollingInterval;
|
||||
|
||||
protected volatile boolean running = false;
|
||||
protected volatile ServerSocket socket = null;
|
||||
@@ -53,12 +53,17 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
protected abstract boolean isConnectable(InetSocketAddress remote);
|
||||
|
||||
protected TcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long pollingInterval) {
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.callback = callback;
|
||||
this.maxFrameLength = maxFrameLength;
|
||||
this.maxLatency = maxLatency;
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
this.pollingInterval = pollingInterval;
|
||||
if(2 * maxIdleTime > Integer.MAX_VALUE)
|
||||
socketTimeout = Integer.MAX_VALUE;
|
||||
else socketTimeout = (int) (2 * maxIdleTime);
|
||||
}
|
||||
|
||||
public int getMaxFrameLength() {
|
||||
@@ -69,6 +74,10 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
running = true;
|
||||
bind();
|
||||
@@ -136,6 +145,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
Socket s;
|
||||
try {
|
||||
s = socket.accept();
|
||||
s.setSoTimeout(socketTimeout);
|
||||
} catch(IOException e) {
|
||||
// This is expected when the socket is closed
|
||||
if(LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||
@@ -195,6 +205,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
try {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
|
||||
s.connect(remote);
|
||||
s.setSoTimeout(socketTimeout);
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
|
||||
return new TcpTransportConnection(this, s);
|
||||
} catch(IOException e) {
|
||||
|
||||
@@ -21,9 +21,9 @@ class WanTcpPlugin extends TcpPlugin {
|
||||
private volatile MappingResult mappingResult;
|
||||
|
||||
WanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long pollingInterval,
|
||||
PortMapper portMapper) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency,
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval, PortMapper portMapper) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency, maxIdleTime,
|
||||
pollingInterval);
|
||||
this.portMapper = portMapper;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final int MAX_FRAME_LENGTH = 1024;
|
||||
private static final long MAX_LATENCY = 60 * 1000; // 1 minute
|
||||
private static final long MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final long POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
private final Executor ioExecutor;
|
||||
@@ -29,7 +30,7 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||
return new WanTcpPlugin(ioExecutor, callback, MAX_FRAME_LENGTH,
|
||||
MAX_LATENCY, POLLING_INTERVAL,
|
||||
MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL,
|
||||
new PortMapperImpl(shutdownManager));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user