mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Poll Tor plugin infrequently once our HS is reachable.
This commit is contained in:
@@ -43,11 +43,12 @@ class AndroidTorPlugin extends TorPlugin {
|
|||||||
BatteryManager batteryManager,
|
BatteryManager batteryManager,
|
||||||
TorRendezvousCrypto torRendezvousCrypto,
|
TorRendezvousCrypto torRendezvousCrypto,
|
||||||
PluginCallback callback, String architecture, int maxLatency,
|
PluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime, int pollingInterval) {
|
int maxIdleTime, int initialPollingInterval,
|
||||||
|
int stablePollingInterval) {
|
||||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||||
torRendezvousCrypto, callback, architecture, maxLatency,
|
torRendezvousCrypto, callback, architecture, maxLatency,
|
||||||
maxIdleTime, pollingInterval,
|
maxIdleTime, initialPollingInterval, stablePollingInterval,
|
||||||
appContext.getDir("tor", MODE_PRIVATE));
|
appContext.getDir("tor", MODE_PRIVATE));
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
PowerManager pm = (PowerManager)
|
PowerManager pm = (PowerManager)
|
||||||
|
|||||||
@@ -25,17 +25,31 @@ import javax.net.SocketFactory;
|
|||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(AndroidTorPluginFactory.class.getName());
|
getLogger(AndroidTorPluginFactory.class.getName());
|
||||||
|
|
||||||
private static final int MAX_LATENCY = (int) SECONDS.toMillis(30);
|
private static final int MAX_LATENCY = (int) SECONDS.toMillis(30);
|
||||||
private static final int MAX_IDLE_TIME = (int) SECONDS.toMillis(30);
|
private static final int MAX_IDLE_TIME = (int) SECONDS.toMillis(30);
|
||||||
private static final int POLLING_INTERVAL = (int) MINUTES.toMillis(1);
|
|
||||||
|
/**
|
||||||
|
* How often to poll before our hidden service becomes reachable.
|
||||||
|
*/
|
||||||
|
private static final int INITIAL_POLLING_INTERVAL =
|
||||||
|
(int) MINUTES.toMillis(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How often to poll when our hidden service is reachable. Our contacts
|
||||||
|
* will poll when they come online, so our polling is just a fallback in
|
||||||
|
* case of repeated connection failures.
|
||||||
|
*/
|
||||||
|
private static final int STABLE_POLLING_INTERVAL =
|
||||||
|
(int) MINUTES.toMillis(15);
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
@@ -111,7 +125,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
|||||||
appContext, networkManager, locationUtils, torSocketFactory,
|
appContext, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||||
torRendezvousCrypto, callback, architecture, MAX_LATENCY,
|
torRendezvousCrypto, callback, architecture, MAX_LATENCY,
|
||||||
MAX_IDLE_TIME, POLLING_INTERVAL);
|
MAX_IDLE_TIME, INITIAL_POLLING_INTERVAL,
|
||||||
|
STABLE_POLLING_INTERVAL);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,15 +110,46 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
private static final Logger LOG = getLogger(TorPlugin.class.getName());
|
private static final Logger LOG = getLogger(TorPlugin.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller events we want to receive.
|
||||||
|
*/
|
||||||
private static final String[] EVENTS = {
|
private static final String[] EVENTS = {
|
||||||
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command-line argument to set our process as Tor's owning controller
|
||||||
|
* so Tor exits when our process dies.
|
||||||
|
*/
|
||||||
private static final String OWNER = "__OwningControllerProcess";
|
private static final String OWNER = "__OwningControllerProcess";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long to wait for the authentication cookie file to be created.
|
||||||
|
*/
|
||||||
private static final int COOKIE_TIMEOUT_MS = 3000;
|
private static final int COOKIE_TIMEOUT_MS = 3000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How often to check whether the authentication cookie file has been
|
||||||
|
* created.
|
||||||
|
*/
|
||||||
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex for matching v2 hidden service names.
|
||||||
|
*/
|
||||||
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
|
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex for matching v3 hidden service names.
|
||||||
|
*/
|
||||||
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many copies of our descriptor must be uploaded before we consider
|
||||||
|
* our hidden service to be reachable and switch to less frequent polling.
|
||||||
|
*/
|
||||||
|
private static final int MIN_DESCRIPTORS_UPLOADED = 5;
|
||||||
|
|
||||||
private final Executor ioExecutor, connectionStatusExecutor;
|
private final Executor ioExecutor, connectionStatusExecutor;
|
||||||
private final NetworkManager networkManager;
|
private final NetworkManager networkManager;
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
@@ -130,7 +161,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private final String architecture;
|
private final String architecture;
|
||||||
private final CircumventionProvider circumventionProvider;
|
private final CircumventionProvider circumventionProvider;
|
||||||
private final ResourceProvider resourceProvider;
|
private final ResourceProvider resourceProvider;
|
||||||
private final int maxLatency, maxIdleTime, pollingInterval, socketTimeout;
|
private final int maxLatency, maxIdleTime, socketTimeout;
|
||||||
|
private final int initialPollingInterval, stablePollingInterval;
|
||||||
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
|
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
|
||||||
private final File doneFile, cookieFile;
|
private final File doneFile, cookieFile;
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
@@ -152,7 +184,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
BatteryManager batteryManager,
|
BatteryManager batteryManager,
|
||||||
TorRendezvousCrypto torRendezvousCrypto,
|
TorRendezvousCrypto torRendezvousCrypto,
|
||||||
PluginCallback callback, String architecture, int maxLatency,
|
PluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime, int pollingInterval, File torDirectory) {
|
int maxIdleTime, int initialPollingInterval,
|
||||||
|
int stablePollingInterval, File torDirectory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.networkManager = networkManager;
|
this.networkManager = networkManager;
|
||||||
this.locationUtils = locationUtils;
|
this.locationUtils = locationUtils;
|
||||||
@@ -166,10 +199,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
this.architecture = architecture;
|
this.architecture = architecture;
|
||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
this.maxIdleTime = maxIdleTime;
|
this.maxIdleTime = maxIdleTime;
|
||||||
this.pollingInterval = pollingInterval;
|
|
||||||
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;
|
||||||
|
this.initialPollingInterval = initialPollingInterval;
|
||||||
|
this.stablePollingInterval = stablePollingInterval;
|
||||||
this.torDirectory = torDirectory;
|
this.torDirectory = torDirectory;
|
||||||
torFile = new File(torDirectory, "tor");
|
torFile = new File(torDirectory, "tor");
|
||||||
geoIpFile = new File(torDirectory, "geoip");
|
geoIpFile = new File(torDirectory, "geoip");
|
||||||
@@ -604,7 +638,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
return pollingInterval;
|
if (state.isDescriptorPublished()) {
|
||||||
|
LOG.info("Using stable polling interval");
|
||||||
|
return stablePollingInterval;
|
||||||
|
} else {
|
||||||
|
LOG.info("Using initial polling interval");
|
||||||
|
return initialPollingInterval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -788,13 +828,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
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")) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
String[] words = msg.split(" ");
|
||||||
String[] words = msg.split(" ");
|
if (words.length > 1 && ONION_V3.matcher(words[1]).matches()) {
|
||||||
if (words.length > 1 && ONION_V3.matcher(words[1]).matches()) {
|
LOG.info("V3 descriptor uploaded");
|
||||||
LOG.info("V3 descriptor uploaded");
|
state.descriptorUploaded();
|
||||||
} else {
|
} else {
|
||||||
LOG.info("V2 descriptor uploaded");
|
LOG.info("V2 descriptor uploaded");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -953,6 +992,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private final Set<String> orConnections = new HashSet<>();
|
private final Set<String> orConnections = new HashSet<>();
|
||||||
|
|
||||||
|
@GuardedBy("this")
|
||||||
|
private int descriptorsUploaded = 0;
|
||||||
|
|
||||||
synchronized void setStarted() {
|
synchronized void setStarted() {
|
||||||
started = true;
|
started = true;
|
||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
@@ -986,7 +1028,10 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
synchronized void enableNetwork(boolean enable) {
|
synchronized void enableNetwork(boolean enable) {
|
||||||
networkInitialised = true;
|
networkInitialised = true;
|
||||||
networkEnabled = enable;
|
networkEnabled = enable;
|
||||||
if (!enable) circuitBuilt = false;
|
if (!enable) {
|
||||||
|
circuitBuilt = false;
|
||||||
|
descriptorsUploaded = 0;
|
||||||
|
}
|
||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,6 +1048,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
orConnections.remove(orName);
|
orConnections.remove(orName);
|
||||||
|
if (orConnections.isEmpty()) descriptorsUploaded = 0;
|
||||||
}
|
}
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info(orConnections.size() + " OR connections");
|
LOG.info(orConnections.size() + " OR connections");
|
||||||
@@ -1010,6 +1056,19 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't affect getState()
|
||||||
|
synchronized void descriptorUploaded() {
|
||||||
|
if (networkEnabled && !orConnections.isEmpty()) {
|
||||||
|
descriptorsUploaded++;
|
||||||
|
} else {
|
||||||
|
LOG.warning("Descriptor was uploaded with no OR connection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized boolean isDescriptorPublished() {
|
||||||
|
return descriptorsUploaded >= MIN_DESCRIPTORS_UPLOADED;
|
||||||
|
}
|
||||||
|
|
||||||
// Doesn't affect getState()
|
// Doesn't affect getState()
|
||||||
synchronized boolean setServerSocket(ServerSocket ss) {
|
synchronized boolean setServerSocket(ServerSocket ss) {
|
||||||
if (stopped || serverSocket != null) return false;
|
if (stopped || serverSocket != null) return false;
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ abstract class JavaTorPlugin extends TorPlugin {
|
|||||||
BatteryManager batteryManager,
|
BatteryManager batteryManager,
|
||||||
TorRendezvousCrypto torRendezvousCrypto,
|
TorRendezvousCrypto torRendezvousCrypto,
|
||||||
PluginCallback callback, String architecture, int maxLatency,
|
PluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime, int pollingInterval, File torDirectory) {
|
int maxIdleTime, int initialPollingInterval,
|
||||||
|
int stablePollingInterval, File torDirectory) {
|
||||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||||
torRendezvousCrypto, callback, architecture, maxLatency,
|
torRendezvousCrypto, callback, architecture, maxLatency,
|
||||||
maxIdleTime, pollingInterval, torDirectory);
|
maxIdleTime, initialPollingInterval, stablePollingInterval,
|
||||||
|
torDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ class UnixTorPlugin extends JavaTorPlugin {
|
|||||||
BatteryManager batteryManager,
|
BatteryManager batteryManager,
|
||||||
TorRendezvousCrypto torRendezvousCrypto,
|
TorRendezvousCrypto torRendezvousCrypto,
|
||||||
PluginCallback callback, String architecture, int maxLatency,
|
PluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime, int pollingInterval, File torDirectory) {
|
int maxIdleTime, int initialPollingInterval,
|
||||||
|
int stablePollingInterval, File torDirectory) {
|
||||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||||
torRendezvousCrypto, callback, architecture, maxLatency,
|
torRendezvousCrypto, callback, architecture,
|
||||||
maxIdleTime, pollingInterval, torDirectory);
|
maxLatency, maxIdleTime, initialPollingInterval,
|
||||||
|
stablePollingInterval, torDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -34,7 +34,20 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
|
|||||||
|
|
||||||
private static final int MAX_LATENCY = (int) SECONDS.toMillis(30);
|
private static final int MAX_LATENCY = (int) SECONDS.toMillis(30);
|
||||||
private static final int MAX_IDLE_TIME = (int) SECONDS.toMillis(30);
|
private static final int MAX_IDLE_TIME = (int) SECONDS.toMillis(30);
|
||||||
private static final int POLLING_INTERVAL = (int) MINUTES.toMillis(1);
|
|
||||||
|
/**
|
||||||
|
* How often to poll before our hidden service becomes reachable.
|
||||||
|
*/
|
||||||
|
private static final int INITIAL_POLLING_INTERVAL =
|
||||||
|
(int) MINUTES.toMillis(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How often to poll when our hidden service is reachable. Our contacts
|
||||||
|
* will poll when they come online, so our polling is just a fallback in
|
||||||
|
* case of repeated connection failures.
|
||||||
|
*/
|
||||||
|
private static final int STABLE_POLLING_INTERVAL =
|
||||||
|
(int) MINUTES.toMillis(15);
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final NetworkManager networkManager;
|
private final NetworkManager networkManager;
|
||||||
@@ -95,7 +108,8 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
|
|||||||
locationUtils, torSocketFactory, clock, resourceProvider,
|
locationUtils, torSocketFactory, clock, resourceProvider,
|
||||||
circumventionProvider, batteryManager, torRendezvousCrypto,
|
circumventionProvider, batteryManager, torRendezvousCrypto,
|
||||||
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME,
|
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME,
|
||||||
POLLING_INTERVAL, torDirectory);
|
INITIAL_POLLING_INTERVAL, STABLE_POLLING_INTERVAL,
|
||||||
|
torDirectory);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user