From d8079b1841aa7fdac9a61e4d7c4827f88574ff43 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 25 Feb 2016 10:01:07 +0000
Subject: [PATCH] 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 4831a0f7ca..d98c213436 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<ContactId> 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 8561e4cdff..3c6a749867 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;
-- 
GitLab