From 066285b86a24b6164366bca7ebd3076accffd093 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 12 Feb 2016 14:13:50 +0000 Subject: [PATCH 1/2] New polling logic for Tor. #250 Poll for outgoing connections each time the network is enabled, then disable polling once our hidden service descriptor has been published. --- .../briarproject/plugins/tor/TorPlugin.java | 20 +++++++++++++++++-- .../briarproject/plugins/tcp/TcpPlugin.java | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index b0cc91746..4831a0f7c 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -44,6 +44,7 @@ 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; @@ -63,7 +64,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, static final TransportId ID = new TransportId("tor"); private static final String[] EVENTS = { - "CIRC", "ORCONN", "NOTICE", "WARN", "ERR" + "CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR" }; private static final String OWNER = "__OwningControllerProcess"; private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051; @@ -71,6 +72,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, private static final int HOSTNAME_TIMEOUT = 30 * 1000; // Milliseconds private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}\\.onion"); + private static final int DESCRIPTOR_THRESHOLD = 3; private static final Logger LOG = Logger.getLogger(TorPlugin.class.getName()); @@ -83,6 +85,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, private final File torDirectory, torFile, geoIpFile, configFile, doneFile; private final File cookieFile, hostnameFile; private final AtomicBoolean circuitBuilt; + private final AtomicInteger descriptorsPublished; private volatile boolean running = false, networkEnabled = false; private volatile boolean bootstrapped = false; @@ -117,6 +120,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); hostnameFile = new File(torDirectory, "hs/hostname"); circuitBuilt = new AtomicBoolean(false); + descriptorsPublished = new AtomicInteger(0); } public TransportId getId() { @@ -462,6 +466,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, if (LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable); if (!enable) { circuitBuilt.set(false); + descriptorsPublished.set(0); callback.transportDisabled(); } networkEnabled = enable; @@ -503,6 +508,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, public void poll(Collection connected) { if (!isRunning()) return; + if (descriptorsPublished.get() >= DESCRIPTOR_THRESHOLD) { + LOG.info("Hidden service descriptor published, not polling"); + return; + } + // TODO: Pass properties to connectAndCallBack() for (ContactId c : callback.getRemoteProperties().keySet()) if (!connected.contains(c)) connectAndCallBack(c); } @@ -576,7 +586,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, } } - public void unrecognized(String type, String msg) {} + public void unrecognized(String type, String msg) { + if (type.equals("HS_DESC") && msg.startsWith("UPLOADED")) { + int descriptors = descriptorsPublished.incrementAndGet(); + if (descriptors == DESCRIPTOR_THRESHOLD) + LOG.info("Hidden service descriptor published"); + } + } private static class WriteObserver extends FileObserver { diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java index 03263bd77..64f91c4d1 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java @@ -176,6 +176,7 @@ abstract class TcpPlugin implements DuplexPlugin { public void poll(Collection connected) { if (!isRunning()) return; backoff.increment(); + // TODO: Pass properties to connectAndCallBack() for (ContactId c : callback.getRemoteProperties().keySet()) if (!connected.contains(c)) connectAndCallBack(c); } From d8079b1841aa7fdac9a61e4d7c4827f88574ff43 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 25 Feb 2016 10:01:07 +0000 Subject: [PATCH 2/2] Fixed race condition in descriptor publication. If two contacts publish their descriptors simultaneously, they may both stop polling without retrieving each other's descriptors. Continue polling for 2 intervals after publishing the descriptor. --- .../briarproject/plugins/tor/TorPlugin.java | 26 +++++++++++++------ .../plugins/tor/TorPluginFactory.java | 8 ++++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index 4831a0f7c..d98c21343 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -24,6 +24,7 @@ import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.properties.TransportProperties; import org.briarproject.api.settings.Settings; +import org.briarproject.api.system.Clock; import org.briarproject.api.system.LocationUtils; import org.briarproject.util.StringUtils; @@ -72,13 +73,14 @@ class TorPlugin implements DuplexPlugin, EventHandler, private static final int HOSTNAME_TIMEOUT = 30 * 1000; // Milliseconds private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}\\.onion"); - private static final int DESCRIPTOR_THRESHOLD = 3; + private static final int MIN_DESCRIPTORS_PUBLISHED = 3; private static final Logger LOG = Logger.getLogger(TorPlugin.class.getName()); private final Executor ioExecutor; private final Context appContext; private final LocationUtils locationUtils; + private final Clock clock; private final DuplexPluginCallback callback; private final String architecture; private final int maxLatency, maxIdleTime, pollingInterval, socketTimeout; @@ -91,6 +93,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, 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 Socket controlSocket = null; @@ -98,12 +101,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, private volatile BroadcastReceiver networkStateReceiver = null; TorPlugin(Executor ioExecutor, Context appContext, - LocationUtils locationUtils, DuplexPluginCallback callback, - String architecture, int maxLatency, int maxIdleTime, - int pollingInterval) { + LocationUtils locationUtils, Clock clock, + DuplexPluginCallback callback, String architecture, int maxLatency, + int maxIdleTime, int pollingInterval) { this.ioExecutor = ioExecutor; this.appContext = appContext; this.locationUtils = locationUtils; + this.clock = clock; this.callback = callback; this.architecture = architecture; this.maxLatency = maxLatency; @@ -467,6 +471,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, if (!enable) { circuitBuilt.set(false); descriptorsPublished.set(0); + descriptorsPublishedTime = Long.MAX_VALUE; callback.transportDisabled(); } networkEnabled = enable; @@ -508,9 +513,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, public void poll(Collection connected) { if (!isRunning()) return; - if (descriptorsPublished.get() >= DESCRIPTOR_THRESHOLD) { - LOG.info("Hidden service descriptor published, not polling"); - 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; + } } // TODO: Pass properties to connectAndCallBack() for (ContactId c : callback.getRemoteProperties().keySet()) @@ -589,8 +597,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, public void unrecognized(String type, String msg) { if (type.equals("HS_DESC") && msg.startsWith("UPLOADED")) { int descriptors = descriptorsPublished.incrementAndGet(); - if (descriptors == DESCRIPTOR_THRESHOLD) + if (descriptors == MIN_DESCRIPTORS_PUBLISHED) { LOG.info("Hidden service descriptor published"); + descriptorsPublishedTime = clock.currentTimeMillis(); + } } } diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java b/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java index 8561e4cdf..3c6a74986 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java @@ -9,7 +9,9 @@ import org.briarproject.api.event.EventBus; import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginFactory; +import org.briarproject.api.system.Clock; import org.briarproject.api.system.LocationUtils; +import org.briarproject.system.SystemClock; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -21,12 +23,13 @@ public class TorPluginFactory implements DuplexPluginFactory { private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds - private static final int POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes + private static final int POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private final Executor ioExecutor; private final Context appContext; private final LocationUtils locationUtils; private final EventBus eventBus; + private final Clock clock; public TorPluginFactory(Executor ioExecutor, Context appContext, LocationUtils locationUtils, EventBus eventBus) { @@ -34,6 +37,7 @@ public class TorPluginFactory implements DuplexPluginFactory { this.appContext = appContext; this.locationUtils = locationUtils; this.eventBus = eventBus; + clock = new SystemClock(); } public TransportId getId() { @@ -61,7 +65,7 @@ public class TorPluginFactory implements DuplexPluginFactory { if (Build.VERSION.SDK_INT >= 16) architecture += "-pie"; TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils, - callback, architecture, MAX_LATENCY, MAX_IDLE_TIME, + clock, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL); eventBus.addListener(plugin); return plugin;