mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Refactored connection status variables into inner class.
This commit is contained in:
@@ -50,8 +50,6 @@ import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipInputStream;
|
||||
@@ -60,15 +58,13 @@ import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||
import static android.net.ConnectivityManager.EXTRA_NO_CONNECTIVITY;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
EventListener {
|
||||
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
static final TransportId ID = new TransportId("tor");
|
||||
|
||||
@@ -93,18 +89,12 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
private final DuplexPluginCallback callback;
|
||||
private final String architecture;
|
||||
private final int maxLatency, maxIdleTime, pollingInterval, socketTimeout;
|
||||
private final ConnectionStatus connectionStatus;
|
||||
private final File torDirectory, torFile, geoIpFile, configFile, doneFile;
|
||||
private final File cookieFile, hostnameFile;
|
||||
private final AtomicBoolean circuitBuilt;
|
||||
private final AtomicInteger descriptorsPublished;
|
||||
private final PowerManager.WakeLock wakeLock;
|
||||
|
||||
private volatile boolean running = false, networkEnabled = false;
|
||||
private volatile boolean bootstrapped = false;
|
||||
private volatile boolean connectedToWifi = false;
|
||||
private volatile boolean online = false;
|
||||
private volatile long descriptorsPublishedTime = Long.MAX_VALUE;
|
||||
|
||||
private volatile boolean running = false;
|
||||
private volatile ServerSocket socket = null;
|
||||
private volatile Socket controlSocket = null;
|
||||
private volatile TorControlConnection controlConnection = null;
|
||||
@@ -127,6 +117,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
if (maxIdleTime > Integer.MAX_VALUE / 2)
|
||||
socketTimeout = Integer.MAX_VALUE;
|
||||
else socketTimeout = maxIdleTime * 2;
|
||||
connectionStatus = new ConnectionStatus(pollingInterval);
|
||||
torDirectory = appContext.getDir("tor", MODE_PRIVATE);
|
||||
torFile = new File(torDirectory, "tor");
|
||||
geoIpFile = new File(torDirectory, "geoip");
|
||||
@@ -134,8 +125,6 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
doneFile = new File(torDirectory, "done");
|
||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||
hostnameFile = new File(torDirectory, "hs/hostname");
|
||||
circuitBuilt = new AtomicBoolean(false);
|
||||
descriptorsPublished = new AtomicInteger(0);
|
||||
Object o = appContext.getSystemService(POWER_SERVICE);
|
||||
PowerManager pm = (PowerManager) o;
|
||||
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin");
|
||||
@@ -237,7 +226,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
String phase = controlConnection.getInfo("status/bootstrap-phase");
|
||||
if (phase != null && phase.contains("PROGRESS=100")) {
|
||||
LOG.info("Tor has already bootstrapped");
|
||||
bootstrapped = true;
|
||||
connectionStatus.setBootstrapped();
|
||||
sendCrashReports();
|
||||
}
|
||||
}
|
||||
@@ -495,13 +484,8 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
|
||||
private void enableNetwork(boolean enable) throws IOException {
|
||||
if (!running) return;
|
||||
if (networkEnabled == enable) return;
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable);
|
||||
if (enable) wakeLock.acquire();
|
||||
circuitBuilt.set(false);
|
||||
descriptorsPublished.set(0);
|
||||
descriptorsPublishedTime = Long.MAX_VALUE;
|
||||
networkEnabled = enable;
|
||||
connectionStatus.enableNetwork(enable);
|
||||
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
||||
if (!enable) {
|
||||
callback.transportDisabled();
|
||||
@@ -532,7 +516,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running && networkEnabled && bootstrapped && circuitBuilt.get();
|
||||
return running && connectionStatus.isConnected();
|
||||
}
|
||||
|
||||
public boolean shouldPoll() {
|
||||
@@ -545,16 +529,13 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
if (!isRunning()) return;
|
||||
if (descriptorsPublished.get() >= MIN_DESCRIPTORS_PUBLISHED) {
|
||||
long now = clock.currentTimeMillis();
|
||||
if (now - descriptorsPublishedTime >= 2 * pollingInterval) {
|
||||
LOG.info("Hidden service descriptor published, not polling");
|
||||
return;
|
||||
}
|
||||
if (connectionStatus.shouldPoll(clock.currentTimeMillis())) {
|
||||
// TODO: Pass properties to connectAndCallBack()
|
||||
for (ContactId c : callback.getRemoteProperties().keySet())
|
||||
if (!connected.contains(c)) connectAndCallBack(c);
|
||||
} else {
|
||||
LOG.info("Hidden service descriptor published, not polling");
|
||||
}
|
||||
// TODO: Pass properties to connectAndCallBack()
|
||||
for (ContactId c : callback.getRemoteProperties().keySet())
|
||||
if (!connected.contains(c)) connectAndCallBack(c);
|
||||
}
|
||||
|
||||
private void connectAndCallBack(final ContactId c) {
|
||||
@@ -616,7 +597,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
}
|
||||
|
||||
public void circuitStatus(String status, String id, String path) {
|
||||
if (status.equals("BUILT") && !circuitBuilt.getAndSet(true)) {
|
||||
if (status.equals("BUILT") && connectionStatus.setCircuitBuilt()) {
|
||||
LOG.info("First circuit built");
|
||||
if (isRunning()) callback.transportEnabled();
|
||||
}
|
||||
@@ -638,20 +619,15 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
public void message(String severity, String msg) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
||||
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
|
||||
bootstrapped = true;
|
||||
connectionStatus.setBootstrapped();
|
||||
sendCrashReports();
|
||||
if (isRunning()) callback.transportEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
public void unrecognized(String type, String msg) {
|
||||
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED")) {
|
||||
int descriptors = descriptorsPublished.incrementAndGet();
|
||||
if (descriptors == MIN_DESCRIPTORS_PUBLISHED) {
|
||||
LOG.info("Hidden service descriptor published");
|
||||
descriptorsPublishedTime = clock.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED"))
|
||||
connectionStatus.descriptorPublished(clock.currentTimeMillis());
|
||||
}
|
||||
|
||||
private static class WriteObserver extends FileObserver {
|
||||
@@ -673,7 +649,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof SettingsUpdatedEvent) {
|
||||
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
|
||||
// Wifi setting may have been updated
|
||||
LOG.info("Tor settings updated");
|
||||
updateConnectionStatus();
|
||||
}
|
||||
}
|
||||
@@ -684,17 +660,23 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
|
||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||
ConnectivityManager cm = (ConnectivityManager) o;
|
||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||
boolean online = net != null && net.isConnected();
|
||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
||||
String country = locationUtils.getCurrentCountry();
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Online: " + online);
|
||||
if ("".equals(country)) LOG.info("Country code unknown");
|
||||
else LOG.info("Country code: " + country);
|
||||
}
|
||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
||||
country);
|
||||
Settings s = callback.getSettings();
|
||||
boolean useMobileData = s.getBoolean("torOverMobile", true);
|
||||
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||
if ("".equals(country)) LOG.info("Country code unknown");
|
||||
else LOG.info("Country code: " + country);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!online) {
|
||||
LOG.info("Disabling network, device is offline");
|
||||
@@ -702,10 +684,11 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
} else if (blocked) {
|
||||
LOG.info("Disabling network, country is blocked");
|
||||
enableNetwork(false);
|
||||
} else if (!useMobileData & !connectedToWifi) {
|
||||
} else if (!wifi && !useMobileData) {
|
||||
LOG.info("Disabling network due to data setting");
|
||||
enableNetwork(false);
|
||||
} else {
|
||||
LOG.info("Enabling network");
|
||||
enableNetwork(true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -723,16 +706,55 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
if (!running) return;
|
||||
if (CONNECTIVITY_ACTION.equals(i.getAction())) {
|
||||
LOG.info("Detected connectivity change");
|
||||
online = !i.getBooleanExtra(EXTRA_NO_CONNECTIVITY, false);
|
||||
// Some devices fail to set EXTRA_NO_CONNECTIVITY, double check
|
||||
Object o = ctx.getSystemService(CONNECTIVITY_SERVICE);
|
||||
ConnectivityManager cm = (ConnectivityManager) o;
|
||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||
if (net == null || !net.isConnected()) online = false;
|
||||
connectedToWifi = (net != null && net.getType() == TYPE_WIFI
|
||||
&& net.isConnected());
|
||||
updateConnectionStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConnectionStatus {
|
||||
|
||||
private final int pollingInterval;
|
||||
|
||||
// All of the following are locking: this
|
||||
private boolean networkEnabled = false;
|
||||
private boolean bootstrapped = false, circuitBuilt = false;
|
||||
private int descriptorsPublished = 0;
|
||||
private long descriptorsPublishedTime = Long.MAX_VALUE;
|
||||
|
||||
private ConnectionStatus(int pollingInterval) {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
|
||||
private synchronized void setBootstrapped() {
|
||||
bootstrapped = true;
|
||||
}
|
||||
|
||||
private synchronized boolean setCircuitBuilt() {
|
||||
boolean firstCircuit = !circuitBuilt;
|
||||
circuitBuilt = true;
|
||||
return firstCircuit;
|
||||
}
|
||||
|
||||
private synchronized void descriptorPublished(long now) {
|
||||
descriptorsPublished++;
|
||||
if (descriptorsPublished == MIN_DESCRIPTORS_PUBLISHED)
|
||||
descriptorsPublishedTime = now;
|
||||
}
|
||||
|
||||
private synchronized void enableNetwork(boolean enable) {
|
||||
networkEnabled = enable;
|
||||
circuitBuilt = false;
|
||||
descriptorsPublished = 0;
|
||||
descriptorsPublishedTime = Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
private synchronized boolean isConnected() {
|
||||
return networkEnabled && bootstrapped && circuitBuilt;
|
||||
}
|
||||
|
||||
private synchronized boolean shouldPoll(long now) {
|
||||
return descriptorsPublished < MIN_DESCRIPTORS_PUBLISHED
|
||||
|| now - descriptorsPublishedTime < 2 * pollingInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user