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