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:
@@ -107,6 +107,11 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
// Bluetooth detects dead connections so we don't need keepalives
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
public boolean start() throws IOException {
|
||||
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
|
||||
// with a message queue, so submit it to the AndroidExecutor
|
||||
@@ -361,6 +366,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
|
||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
int state = intent.getIntExtra(EXTRA_STATE, 0);
|
||||
if(state == STATE_ON) {
|
||||
|
||||
@@ -27,8 +27,8 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
||||
|
||||
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
|
||||
DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
|
||||
long pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency,
|
||||
long maxIdleTime, long pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency, maxIdleTime,
|
||||
pollingInterval);
|
||||
this.appContext = appContext;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public class AndroidLanTcpPluginFactory 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;
|
||||
@@ -29,6 +30,6 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||
return new AndroidLanTcpPlugin(ioExecutor, appContext, callback,
|
||||
MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
|
||||
MAX_FRAME_LENGTH, MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
private final Context appContext;
|
||||
private final LocationUtils locationUtils;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final int maxFrameLength;
|
||||
private final long maxLatency, pollingInterval;
|
||||
private final int maxFrameLength, socketTimeout;
|
||||
private final long maxLatency, maxIdleTime, pollingInterval;
|
||||
private final File torDirectory, torFile, geoIpFile, configFile, doneFile;
|
||||
private final File cookieFile, hostnameFile;
|
||||
private final AtomicBoolean circuitBuilt;
|
||||
@@ -90,14 +90,19 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
|
||||
TorPlugin(Executor ioExecutor, Context appContext,
|
||||
LocationUtils locationUtils, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long pollingInterval) {
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.appContext = appContext;
|
||||
this.locationUtils = locationUtils;
|
||||
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);
|
||||
torDirectory = appContext.getDir("tor", MODE_PRIVATE);
|
||||
torFile = new File(torDirectory, "tor");
|
||||
geoIpFile = new File(torDirectory, "geoip");
|
||||
@@ -120,6 +125,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
public boolean start() throws IOException {
|
||||
// Try to connect to an existing Tor process if there is one
|
||||
boolean startProcess = false;
|
||||
@@ -446,6 +455,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
Socket s;
|
||||
try {
|
||||
s = ss.accept();
|
||||
s.setSoTimeout(socketTimeout);
|
||||
} catch(IOException e) {
|
||||
// This is expected when the socket is closed
|
||||
if(LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||
@@ -529,6 +539,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
|
||||
proxy.resolveAddrLocally(false);
|
||||
Socket s = new SocksSocket(proxy, onion, 80);
|
||||
s.setSoTimeout(socketTimeout);
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Connected to " + onion);
|
||||
return new TorTransportConnection(this, s);
|
||||
} catch(IOException e) {
|
||||
|
||||
@@ -19,6 +19,7 @@ public class TorPluginFactory 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 = 3 * 60 * 1000; // 3 minutes
|
||||
|
||||
private final Executor ioExecutor;
|
||||
@@ -43,6 +44,6 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
||||
return null;
|
||||
}
|
||||
return new TorPlugin(ioExecutor,appContext, locationUtils, callback,
|
||||
MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
|
||||
MAX_FRAME_LENGTH, MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user