Merge branch 'aggressive-polling' into 'master'

Try harder to connect to contacts

* When an outgoing connection is lost, try to reconnect to the contact straight away
* Use periodic polling for Tor, regardless of whether our hidden service descriptor has been published
* Reduce polling intervals for all plugins (this can be reverted if we solve the connectivity issues)

Closes #262, #314. Hopefully helps with #361.

See merge request !177
This commit is contained in:
akwizgran
2016-05-10 14:47:04 +00:00
18 changed files with 230 additions and 127 deletions

View File

@@ -38,7 +38,7 @@ public class AndroidPluginsModule {
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor, DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
androidExecutor, appContext, random, backoffFactory); androidExecutor, appContext, random, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext, DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
locationUtils, reporter, eventBus); locationUtils, reporter, eventBus, backoffFactory);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
backoffFactory, appContext); backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex = final Collection<DuplexPluginFactory> duplex =

View File

@@ -16,8 +16,8 @@ import java.util.concurrent.Executor;
public class DroidtoothPluginFactory implements DuplexPluginFactory { public class DroidtoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -36,14 +36,17 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
} }
@Override
public TransportId getId() { public TransportId getId() {
return DroidtoothPlugin.ID; return DroidtoothPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -15,8 +15,8 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds 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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -30,14 +30,17 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
this.appContext = appContext; this.appContext = appContext;
} }
@Override
public TransportId getId() { public TransportId getId() {
return LanTcpPlugin.ID; return LanTcpPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -23,13 +23,13 @@ import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent; import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.keyagreement.KeyAgreementListener; import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.keyagreement.TransportDescriptor; import org.briarproject.api.keyagreement.TransportDescriptor;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties; import org.briarproject.api.properties.TransportProperties;
import org.briarproject.api.reporting.DevReporter; import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.settings.Settings; import org.briarproject.api.settings.Settings;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.LocationUtils; import org.briarproject.api.system.LocationUtils;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
@@ -79,7 +79,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051; private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051;
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds private static final int COOKIE_TIMEOUT = 3000; // Milliseconds
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
private static final int MIN_DESCRIPTORS_PUBLISHED = 3;
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName()); Logger.getLogger(TorPlugin.class.getName());
@@ -87,10 +86,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
private final Clock clock; private final Backoff backoff;
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, socketTimeout;
private final ConnectionStatus connectionStatus; private final ConnectionStatus connectionStatus;
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
@@ -103,23 +102,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private volatile BroadcastReceiver networkStateReceiver = null; private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext, TorPlugin(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter, Clock clock, LocationUtils locationUtils, DevReporter reporter, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency, DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, int pollingInterval) { int maxIdleTime) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
this.clock = clock; this.backoff = backoff;
this.callback = callback; this.callback = callback;
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;
connectionStatus = new ConnectionStatus(pollingInterval); connectionStatus = new ConnectionStatus();
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");
@@ -228,7 +226,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
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");
connectionStatus.setBootstrapped(); connectionStatus.setBootstrapped();
sendCrashReports(); sendDevReports();
} }
} }
// Register to receive network status events // Register to receive network status events
@@ -359,12 +357,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
} }
private void sendCrashReports() { private void sendDevReports() {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
reporter.sendReports( File reportDir = AndroidUtils.getReportDir(appContext);
AndroidUtils.getReportDir(appContext), SOCKS_PORT); reporter.sendReports(reportDir, SOCKS_PORT);
} }
}); });
} }
@@ -404,6 +402,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
publishHiddenService(localPort); publishHiddenService(localPort);
} }
}); });
backoff.reset();
// Accept incoming hidden service connections from Tor // Accept incoming hidden service connections from Tor
acceptContactConnections(ss); acceptContactConnections(ss);
} }
@@ -470,6 +469,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return; return;
} }
LOG.info("Connection received"); LOG.info("Connection received");
backoff.reset();
TorTransportConnection conn = new TorTransportConnection(this, s); TorTransportConnection conn = new TorTransportConnection(this, s);
callback.incomingConnectionCreated(conn); callback.incomingConnectionCreated(conn);
} }
@@ -517,25 +517,25 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
public int getPollingInterval() { public int getPollingInterval() {
return pollingInterval; return backoff.getPollingInterval();
} }
public void poll(Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!isRunning()) return; if (!isRunning()) return;
if (connectionStatus.shouldPoll(clock.currentTimeMillis())) { backoff.increment();
// TODO: Pass properties to connectAndCallBack() // TODO: Pass properties to connectAndCallBack()
for (ContactId c : callback.getRemoteProperties().keySet()) for (ContactId c : callback.getRemoteProperties().keySet())
if (!connected.contains(c)) connectAndCallBack(c); if (!connected.contains(c)) connectAndCallBack(c);
} else {
LOG.info("Hidden service descriptor published, not polling");
}
} }
private void connectAndCallBack(final ContactId c) { private void connectAndCallBack(final ContactId c) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); DuplexTransportConnection d = createConnection(c);
if (d != null) callback.outgoingConnectionCreated(c, d); if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
}
} }
}); });
} }
@@ -561,7 +561,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return new TorTransportConnection(this, s); return new TorTransportConnection(this, s);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.log(INFO, "Could not connect to " + onion + ": ", e); LOG.info("Could not connect to " + onion + ": " + e.toString());
return null; return null;
} }
} }
@@ -593,6 +593,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (status.equals("BUILT") && if (status.equals("BUILT") &&
connectionStatus.getAndSetCircuitBuilt()) { connectionStatus.getAndSetCircuitBuilt()) {
LOG.info("First circuit built"); LOG.info("First circuit built");
backoff.reset();
if (isRunning()) callback.transportEnabled(); if (isRunning()) callback.transportEnabled();
} }
} }
@@ -614,14 +615,15 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
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%")) {
connectionStatus.setBootstrapped(); connectionStatus.setBootstrapped();
sendCrashReports(); sendDevReports();
backoff.reset();
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"))
connectionStatus.descriptorPublished(clock.currentTimeMillis()); LOG.info("Descriptor uploaded");
} }
private static class WriteObserver extends FileObserver { private static class WriteObserver extends FileObserver {
@@ -707,17 +709,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static class ConnectionStatus { private static class ConnectionStatus {
private final int pollingInterval;
// All of the following are locking: this // All of the following are locking: this
private boolean networkEnabled = false; private boolean networkEnabled = false;
private boolean bootstrapped = false, circuitBuilt = 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() { private synchronized void setBootstrapped() {
bootstrapped = true; bootstrapped = true;
@@ -729,26 +723,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return firstCircuit; return firstCircuit;
} }
private synchronized void descriptorPublished(long now) {
descriptorsPublished++;
if (descriptorsPublished == MIN_DESCRIPTORS_PUBLISHED)
descriptorsPublishedTime = now;
}
private synchronized void enableNetwork(boolean enable) { private synchronized void enableNetwork(boolean enable) {
networkEnabled = enable; networkEnabled = enable;
circuitBuilt = false; circuitBuilt = false;
descriptorsPublished = 0;
descriptorsPublishedTime = Long.MAX_VALUE;
} }
private synchronized boolean isConnected() { private synchronized boolean isConnected() {
return networkEnabled && bootstrapped && circuitBuilt; return networkEnabled && bootstrapped && circuitBuilt;
} }
private synchronized boolean shouldPoll(long now) {
return descriptorsPublished < MIN_DESCRIPTORS_PUBLISHED
|| now - descriptorsPublishedTime < 2 * pollingInterval;
}
} }
} }

View File

@@ -6,13 +6,13 @@ import android.os.Build;
import org.briarproject.android.util.AndroidUtils; import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory; import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.reporting.DevReporter; import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.LocationUtils; import org.briarproject.api.system.LocationUtils;
import org.briarproject.system.SystemClock;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -24,34 +24,39 @@ public class TorPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds 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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final DevReporter reporter; private final DevReporter reporter;
private final EventBus eventBus; private final EventBus eventBus;
private final Clock clock; private final BackoffFactory backoffFactory;
public TorPluginFactory(Executor ioExecutor, Context appContext, public TorPluginFactory(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter, LocationUtils locationUtils, DevReporter reporter,
EventBus eventBus) { EventBus eventBus, BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.reporter = reporter; this.reporter = reporter;
this.eventBus = eventBus; this.eventBus = eventBus;
clock = new SystemClock(); this.backoffFactory = backoffFactory;
} }
@Override
public TransportId getId() { public TransportId getId() {
return TorPlugin.ID; return TorPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
// Check that we have a Tor binary for this architecture // Check that we have a Tor binary for this architecture
@@ -72,10 +77,11 @@ public class TorPluginFactory implements DuplexPluginFactory {
// Use position-independent executable for SDK >= 16 // Use position-independent executable for SDK >= 16
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie"; if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
TorPlugin plugin = Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
new TorPlugin(ioExecutor, appContext, locationUtils, reporter, MAX_POLLING_INTERVAL, BACKOFF_BASE);
clock, callback, architecture, MAX_LATENCY, TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
MAX_IDLE_TIME, POLLING_INTERVAL); reporter, backoff, callback, architecture, MAX_LATENCY,
MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -0,0 +1,30 @@
package org.briarproject.api.event;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
public class ConnectionClosedEvent extends Event {
private final ContactId contactId;
private final TransportId transportId;
private final boolean incoming;
public ConnectionClosedEvent(ContactId contactId, TransportId transportId,
boolean incoming) {
this.contactId = contactId;
this.transportId = transportId;
this.incoming = incoming;
}
public ContactId getContactId() {
return contactId;
}
public TransportId getTransportId() {
return transportId;
}
public boolean isIncoming() {
return incoming;
}
}

View File

@@ -0,0 +1,30 @@
package org.briarproject.api.event;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
public class ConnectionOpenedEvent extends Event {
private final ContactId contactId;
private final TransportId transportId;
private final boolean incoming;
public ConnectionOpenedEvent(ContactId contactId, TransportId transportId,
boolean incoming) {
this.contactId = contactId;
this.transportId = transportId;
this.incoming = incoming;
}
public ContactId getContactId() {
return contactId;
}
public TransportId getTransportId() {
return transportId;
}
public boolean isIncoming() {
return incoming;
}
}

View File

@@ -10,9 +10,9 @@ import java.util.Collection;
*/ */
public interface ConnectionRegistry { public interface ConnectionRegistry {
void registerConnection(ContactId c, TransportId t); void registerConnection(ContactId c, TransportId t, boolean incoming);
void unregisterConnection(ContactId c, TransportId t); void unregisterConnection(ContactId c, TransportId t, boolean incoming);
Collection<ContactId> getConnectedContacts(TransportId t); Collection<ContactId> getConnectedContacts(TransportId t);

View File

@@ -144,7 +144,7 @@ class ConnectionManagerImpl implements ConnectionManager {
return; return;
} }
ContactId contactId = ctx.getContactId(); ContactId contactId = ctx.getContactId();
connectionRegistry.registerConnection(contactId, transportId); connectionRegistry.registerConnection(contactId, transportId, true);
try { try {
// Create and run the incoming session // Create and run the incoming session
createIncomingSession(ctx, reader).run(); createIncomingSession(ctx, reader).run();
@@ -153,7 +153,8 @@ class ConnectionManagerImpl implements ConnectionManager {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId); connectionRegistry.unregisterConnection(contactId, transportId,
true);
} }
} }
@@ -194,7 +195,8 @@ class ConnectionManagerImpl implements ConnectionManager {
disposeWriter(true); disposeWriter(true);
return; return;
} }
connectionRegistry.registerConnection(contactId, transportId); connectionRegistry.registerConnection(contactId, transportId,
false);
try { try {
// Create and run the outgoing session // Create and run the outgoing session
createSimplexOutgoingSession(ctx, writer).run(); createSimplexOutgoingSession(ctx, writer).run();
@@ -203,7 +205,8 @@ class ConnectionManagerImpl implements ConnectionManager {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeWriter(true); disposeWriter(true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId); connectionRegistry.unregisterConnection(contactId, transportId,
false);
} }
} }
@@ -254,7 +257,7 @@ class ConnectionManagerImpl implements ConnectionManager {
return; return;
} }
contactId = ctx.getContactId(); contactId = ctx.getContactId();
connectionRegistry.registerConnection(contactId, transportId); connectionRegistry.registerConnection(contactId, transportId, true);
// Start the outgoing session on another thread // Start the outgoing session on another thread
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
public void run() { public void run() {
@@ -270,7 +273,8 @@ class ConnectionManagerImpl implements ConnectionManager {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId); connectionRegistry.unregisterConnection(contactId, transportId,
true);
} }
} }
@@ -398,7 +402,8 @@ class ConnectionManagerImpl implements ConnectionManager {
disposeReader(true, true); disposeReader(true, true);
return; return;
} }
connectionRegistry.registerConnection(contactId, transportId); connectionRegistry.registerConnection(contactId, transportId,
false);
try { try {
// Create and run the incoming session // Create and run the incoming session
incomingSession = createIncomingSession(ctx, reader); incomingSession = createIncomingSession(ctx, reader);
@@ -408,7 +413,8 @@ class ConnectionManagerImpl implements ConnectionManager {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId); connectionRegistry.unregisterConnection(contactId, transportId,
false);
} }
} }

View File

@@ -2,6 +2,8 @@ package org.briarproject.plugins;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.event.ConnectionClosedEvent;
import org.briarproject.api.event.ConnectionOpenedEvent;
import org.briarproject.api.event.ContactConnectedEvent; import org.briarproject.api.event.ContactConnectedEvent;
import org.briarproject.api.event.ContactDisconnectedEvent; import org.briarproject.api.event.ContactDisconnectedEvent;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
@@ -40,8 +42,12 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
contactCounts = new HashMap<ContactId, Integer>(); contactCounts = new HashMap<ContactId, Integer>();
} }
public void registerConnection(ContactId c, TransportId t) { public void registerConnection(ContactId c, TransportId t,
if (LOG.isLoggable(INFO)) LOG.info("Connection registered: " + t); boolean incoming) {
if (LOG.isLoggable(INFO)) {
if (incoming) LOG.info("Incoming connection registered: " + t);
else LOG.info("Outgoing connection registered: " + t);
}
boolean firstConnection = false; boolean firstConnection = false;
lock.lock(); lock.lock();
try { try {
@@ -63,14 +69,19 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
} finally { } finally {
lock.unlock(); lock.unlock();
} }
eventBus.broadcast(new ConnectionOpenedEvent(c, t, incoming));
if (firstConnection) { if (firstConnection) {
LOG.info("Contact connected"); LOG.info("Contact connected");
eventBus.broadcast(new ContactConnectedEvent(c)); eventBus.broadcast(new ContactConnectedEvent(c));
} }
} }
public void unregisterConnection(ContactId c, TransportId t) { public void unregisterConnection(ContactId c, TransportId t,
if (LOG.isLoggable(INFO)) LOG.info("Connection unregistered: " + t); boolean incoming) {
if (LOG.isLoggable(INFO)) {
if (incoming) LOG.info("Incoming connection unregistered: " + t);
else LOG.info("Outgoing connection unregistered: " + t);
}
boolean lastConnection = false; boolean lastConnection = false;
lock.lock(); lock.lock();
try { try {
@@ -94,6 +105,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
} finally { } finally {
lock.unlock(); lock.unlock();
} }
eventBus.broadcast(new ConnectionClosedEvent(c, t, incoming));
if (lastConnection) { if (lastConnection) {
LOG.info("Contact disconnected"); LOG.info("Contact disconnected");
eventBus.broadcast(new ContactDisconnectedEvent(c)); eventBus.broadcast(new ContactDisconnectedEvent(c));

View File

@@ -3,6 +3,7 @@ package org.briarproject.plugins;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.event.ConnectionClosedEvent;
import org.briarproject.api.event.ContactStatusChangedEvent; import org.briarproject.api.event.ContactStatusChangedEvent;
import org.briarproject.api.event.Event; import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
@@ -141,10 +142,12 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public Plugin getPlugin(TransportId t) { public Plugin getPlugin(TransportId t) {
return plugins.get(t); return plugins.get(t);
} }
@Override
public Collection<DuplexPlugin> getInvitationPlugins() { public Collection<DuplexPlugin> getInvitationPlugins() {
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>();
for (DuplexPlugin d : duplexPlugins) for (DuplexPlugin d : duplexPlugins)
@@ -152,6 +155,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
return Collections.unmodifiableList(supported); return Collections.unmodifiableList(supported);
} }
@Override
public Collection<DuplexPlugin> getKeyAgreementPlugins() { public Collection<DuplexPlugin> getKeyAgreementPlugins() {
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>();
for (DuplexPlugin d : duplexPlugins) for (DuplexPlugin d : duplexPlugins)
@@ -163,7 +167,16 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof ContactStatusChangedEvent) { if (e instanceof ContactStatusChangedEvent) {
ContactStatusChangedEvent c = (ContactStatusChangedEvent) e; ContactStatusChangedEvent c = (ContactStatusChangedEvent) e;
if (c.isActive()) connectToContact(c.getContactId()); if (c.isActive()) {
// Connect to the newly activated contact
connectToContact(c.getContactId());
}
} else if (e instanceof ConnectionClosedEvent) {
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
if (!c.isIncoming()) {
// Connect to the disconnected contact
connectToContact(c.getContactId(), c.getTransportId());
}
} }
} }
@@ -174,8 +187,17 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
if (d.shouldPoll()) connectToContact(c, d); if (d.shouldPoll()) connectToContact(c, d);
} }
private void connectToContact(ContactId c, TransportId t) {
Plugin p = plugins.get(t);
if (p instanceof SimplexPlugin && p.shouldPoll())
connectToContact(c, (SimplexPlugin) p);
else if (p instanceof DuplexPlugin && p.shouldPoll())
connectToContact(c, (DuplexPlugin) p);
}
private void connectToContact(final ContactId c, final SimplexPlugin p) { private void connectToContact(final ContactId c, final SimplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override
public void run() { public void run() {
TransportId t = p.getId(); TransportId t = p.getId();
if (!connectionRegistry.isConnected(c, t)) { if (!connectionRegistry.isConnected(c, t)) {
@@ -189,6 +211,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
private void connectToContact(final ContactId c, final DuplexPlugin p) { private void connectToContact(final ContactId c, final DuplexPlugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override
public void run() { public void run() {
TransportId t = p.getId(); TransportId t = p.getId();
if (!connectionRegistry.isConnected(c, t)) { if (!connectionRegistry.isConnected(c, t)) {
@@ -211,6 +234,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
this.latch = latch; this.latch = latch;
} }
@Override
public void run() { public void run() {
try { try {
TransportId id = factory.getId(); TransportId id = factory.getId();
@@ -230,7 +254,6 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
if (started) { if (started) {
plugins.put(id, plugin); plugins.put(id, plugin);
simplexPlugins.add(plugin); simplexPlugins.add(plugin);
if (plugin.shouldPoll()) poller.addPlugin(plugin);
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
String name = plugin.getClass().getSimpleName(); String name = plugin.getClass().getSimpleName();
LOG.info("Starting " + name + " took " + LOG.info("Starting " + name + " took " +
@@ -263,6 +286,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
this.latch = latch; this.latch = latch;
} }
@Override
public void run() { public void run() {
try { try {
TransportId id = factory.getId(); TransportId id = factory.getId();
@@ -282,7 +306,6 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
if (started) { if (started) {
plugins.put(id, plugin); plugins.put(id, plugin);
duplexPlugins.add(plugin); duplexPlugins.add(plugin);
if (plugin.shouldPoll()) poller.addPlugin(plugin);
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
String name = plugin.getClass().getSimpleName(); String name = plugin.getClass().getSimpleName();
LOG.info("Starting " + name + " took " + LOG.info("Starting " + name + " took " +
@@ -314,6 +337,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
this.latch = latch; this.latch = latch;
} }
@Override
public void run() { public void run() {
try { try {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@@ -339,6 +363,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
this.id = id; this.id = id;
} }
@Override
public Settings getSettings() { public Settings getSettings() {
try { try {
return settingsManager.getSettings(id.getString()); return settingsManager.getSettings(id.getString());
@@ -348,6 +373,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public TransportProperties getLocalProperties() { public TransportProperties getLocalProperties() {
try { try {
TransportProperties p = TransportProperties p =
@@ -359,6 +385,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public Map<ContactId, TransportProperties> getRemoteProperties() { public Map<ContactId, TransportProperties> getRemoteProperties() {
try { try {
return transportPropertyManager.getRemoteProperties(id); return transportPropertyManager.getRemoteProperties(id);
@@ -368,6 +395,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public void mergeSettings(Settings s) { public void mergeSettings(Settings s) {
try { try {
settingsManager.mergeSettings(s, id.getString()); settingsManager.mergeSettings(s, id.getString());
@@ -376,6 +404,7 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public void mergeLocalProperties(TransportProperties p) { public void mergeLocalProperties(TransportProperties p) {
try { try {
transportPropertyManager.mergeLocalProperties(id, p); transportPropertyManager.mergeLocalProperties(id, p);
@@ -384,24 +413,29 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
} }
} }
@Override
public int showChoice(String[] options, String... message) { public int showChoice(String[] options, String... message) {
return uiCallback.showChoice(options, message); return uiCallback.showChoice(options, message);
} }
@Override
public boolean showConfirmationMessage(String... message) { public boolean showConfirmationMessage(String... message) {
return uiCallback.showConfirmationMessage(message); return uiCallback.showConfirmationMessage(message);
} }
@Override
public void showMessage(String... message) { public void showMessage(String... message) {
uiCallback.showMessage(message); uiCallback.showMessage(message);
} }
@Override
public void transportEnabled() { public void transportEnabled() {
eventBus.broadcast(new TransportEnabledEvent(id)); eventBus.broadcast(new TransportEnabledEvent(id));
Plugin p = plugins.get(id); Plugin p = plugins.get(id);
if (p != null) poller.pollNow(p); if (p != null) poller.pollNow(p);
} }
@Override
public void transportDisabled() { public void transportDisabled() {
eventBus.broadcast(new TransportDisabledEvent(id)); eventBus.broadcast(new TransportDisabledEvent(id));
} }
@@ -414,10 +448,12 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
super(id); super(id);
} }
@Override
public void readerCreated(TransportConnectionReader r) { public void readerCreated(TransportConnectionReader r) {
connectionManager.manageIncomingConnection(id, r); connectionManager.manageIncomingConnection(id, r);
} }
@Override
public void writerCreated(ContactId c, TransportConnectionWriter w) { public void writerCreated(ContactId c, TransportConnectionWriter w) {
connectionManager.manageOutgoingConnection(c, id, w); connectionManager.manageOutgoingConnection(c, id, w);
} }
@@ -430,10 +466,12 @@ class PluginManagerImpl implements PluginManager, Service, EventListener {
super(id); super(id);
} }
@Override
public void incomingConnectionCreated(DuplexTransportConnection d) { public void incomingConnectionCreated(DuplexTransportConnection d) {
connectionManager.manageIncomingConnection(id, d); connectionManager.manageIncomingConnection(id, d);
} }
@Override
public void outgoingConnectionCreated(ContactId c, public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) { DuplexTransportConnection d) {
connectionManager.manageOutgoingConnection(c, id, d); connectionManager.manageOutgoingConnection(c, id, d);

View File

@@ -4,9 +4,6 @@ import org.briarproject.api.plugins.Plugin;
interface Poller { interface Poller {
/** Adds the given plugin to the collection of plugins to be polled. */
void addPlugin(Plugin p);
/** Tells the poller to poll the given plugin immediately. */ /** Tells the poller to poll the given plugin immediately. */
void pollNow(Plugin p); void pollNow(Plugin p);

View File

@@ -39,25 +39,17 @@ class PollerImpl implements Poller {
tasks = new ConcurrentHashMap<TransportId, PollTask>(); tasks = new ConcurrentHashMap<TransportId, PollTask>();
} }
@Override
public void stop() { public void stop() {
timer.cancel(); timer.cancel();
} }
public void addPlugin(Plugin p) { @Override
// Randomise first polling interval
if (p.shouldPoll())
schedule(p, randomise(p.getPollingInterval()), false);
}
public void pollNow(Plugin p) { public void pollNow(Plugin p) {
// Randomise next polling interval // Randomise next polling interval
if (p.shouldPoll()) schedule(p, 0, true); if (p.shouldPoll()) schedule(p, 0, true);
} }
private int randomise(int interval) {
return (int) (interval * random.nextDouble());
}
private void schedule(Plugin p, int interval, boolean randomiseNext) { private void schedule(Plugin p, int interval, boolean randomiseNext) {
// Replace any previously scheduled task for this plugin // Replace any previously scheduled task for this plugin
PollTask task = new PollTask(p, randomiseNext); PollTask task = new PollTask(p, randomiseNext);
@@ -68,6 +60,7 @@ class PollerImpl implements Poller {
private void poll(final Plugin p) { private void poll(final Plugin p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override
public void run() { public void run() {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Polling " + p.getClass().getSimpleName()); LOG.info("Polling " + p.getClass().getSimpleName());
@@ -90,7 +83,8 @@ class PollerImpl implements Poller {
public void run() { public void run() {
tasks.remove(plugin.getId()); tasks.remove(plugin.getId());
int interval = plugin.getPollingInterval(); int interval = plugin.getPollingInterval();
if (randomiseNext) interval = randomise(interval); if (randomiseNext)
interval = (int) (interval * random.nextDouble());
schedule(plugin, interval, false); schedule(plugin, interval, false);
poll(plugin); poll(plugin);
} }

View File

@@ -13,8 +13,8 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds 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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -26,14 +26,17 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
} }
@Override
public TransportId getId() { public TransportId getId() {
return LanTcpPlugin.ID; return LanTcpPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -14,8 +14,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds 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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -29,14 +29,17 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
this.shutdownManager = shutdownManager; this.shutdownManager = shutdownManager;
} }
@Override
public TransportId getId() { public TransportId getId() {
return WanTcpPlugin.ID; return WanTcpPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -13,8 +13,8 @@ import java.util.concurrent.Executor;
public class BluetoothPluginFactory implements DuplexPluginFactory { public class BluetoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -28,14 +28,17 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
} }
@Override
public TransportId getId() { public TransportId getId() {
return BluetoothPlugin.ID; return BluetoothPlugin.ID;
} }
@Override
public int getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -3,6 +3,8 @@ package org.briarproject.plugins;
import org.briarproject.BriarTestCase; import org.briarproject.BriarTestCase;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.event.ConnectionClosedEvent;
import org.briarproject.api.event.ConnectionOpenedEvent;
import org.briarproject.api.event.ContactConnectedEvent; import org.briarproject.api.event.ContactConnectedEvent;
import org.briarproject.api.event.ContactDisconnectedEvent; import org.briarproject.api.event.ContactDisconnectedEvent;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
@@ -35,6 +37,10 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
Mockery context = new Mockery(); Mockery context = new Mockery();
final EventBus eventBus = context.mock(EventBus.class); final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
exactly(5).of(eventBus).broadcast(with(any(
ConnectionOpenedEvent.class)));
exactly(2).of(eventBus).broadcast(with(any(
ConnectionClosedEvent.class)));
exactly(3).of(eventBus).broadcast(with(any( exactly(3).of(eventBus).broadcast(with(any(
ContactConnectedEvent.class))); ContactConnectedEvent.class)));
oneOf(eventBus).broadcast(with(any( oneOf(eventBus).broadcast(with(any(
@@ -49,43 +55,46 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId1)); c.getConnectedContacts(transportId1));
// Check that a registered connection shows up - this should // Check that a registered connection shows up - this should
// broadcast a ContactConnectedEvent // broadcast a ConnectionOpenedEvent and a ContactConnectedEvent
c.registerConnection(contactId, transportId); c.registerConnection(contactId, transportId, true);
assertEquals(Collections.singletonList(contactId), assertEquals(Collections.singletonList(contactId),
c.getConnectedContacts(transportId)); c.getConnectedContacts(transportId));
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId1)); c.getConnectedContacts(transportId1));
// Register an identical connection - lookup should be unaffected // Register an identical connection - this should broadcast a
c.registerConnection(contactId, transportId); // ConnectionOpenedEvent and lookup should be unaffected
c.registerConnection(contactId, transportId, true);
assertEquals(Collections.singletonList(contactId), assertEquals(Collections.singletonList(contactId),
c.getConnectedContacts(transportId)); c.getConnectedContacts(transportId));
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId1)); c.getConnectedContacts(transportId1));
// Unregister one of the connections - lookup should be unaffected // Unregister one of the connections - this should broadcast a
c.unregisterConnection(contactId, transportId); // ConnectionClosedEvent and lookup should be unaffected
c.unregisterConnection(contactId, transportId, true);
assertEquals(Collections.singletonList(contactId), assertEquals(Collections.singletonList(contactId),
c.getConnectedContacts(transportId)); c.getConnectedContacts(transportId));
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId1)); c.getConnectedContacts(transportId1));
// Unregister the other connection - lookup should be affected - // Unregister the other connection - this should broadcast a
// this should broadcast a ContactDisconnectedEvent // ConnectionClosedEvent and a ContactDisconnectedEvent
c.unregisterConnection(contactId, transportId); c.unregisterConnection(contactId, transportId, true);
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId)); c.getConnectedContacts(transportId));
assertEquals(Collections.emptyList(), assertEquals(Collections.emptyList(),
c.getConnectedContacts(transportId1)); c.getConnectedContacts(transportId1));
// Try to unregister the connection again - exception should be thrown // Try to unregister the connection again - exception should be thrown
try { try {
c.unregisterConnection(contactId, transportId); c.unregisterConnection(contactId, transportId, true);
fail(); fail();
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
// Expected // Expected
} }
// Register both contacts with one transport, one contact with both - // Register both contacts with one transport, one contact with both -
// this should broadcast two ContactConnectedEvents // this should broadcast three ConnectionOpenedEvents and two
c.registerConnection(contactId, transportId); // ContactConnectedEvents
c.registerConnection(contactId1, transportId); c.registerConnection(contactId, transportId, true);
c.registerConnection(contactId1, transportId1); c.registerConnection(contactId1, transportId, true);
c.registerConnection(contactId1, transportId1, true);
Collection<ContactId> connected = c.getConnectedContacts(transportId); Collection<ContactId> connected = c.getConnectedContacts(transportId);
assertEquals(2, connected.size()); assertEquals(2, connected.size());
assertTrue(connected.contains(contactId)); assertTrue(connected.contains(contactId));

View File

@@ -84,9 +84,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(simplexPlugin)); // Created will(returnValue(simplexPlugin)); // Created
oneOf(simplexPlugin).start(); oneOf(simplexPlugin).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(simplexPlugin).shouldPoll();
will(returnValue(true));
oneOf(poller).addPlugin(simplexPlugin);
// Second simplex plugin // Second simplex plugin
oneOf(simplexFailFactory).getId(); oneOf(simplexFailFactory).getId();
will(returnValue(simplexFailId)); will(returnValue(simplexFailId));
@@ -105,8 +102,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(duplexPlugin)); // Created will(returnValue(duplexPlugin)); // Created
oneOf(duplexPlugin).start(); oneOf(duplexPlugin).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(duplexPlugin).shouldPoll();
will(returnValue(false));
// Second duplex plugin // Second duplex plugin
oneOf(duplexFailFactory).getId(); oneOf(duplexFailFactory).getId();
will(returnValue(duplexFailId)); will(returnValue(duplexFailId));
@@ -193,9 +188,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(simplexPlugin)); // Created will(returnValue(simplexPlugin)); // Created
oneOf(simplexPlugin).start(); oneOf(simplexPlugin).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(simplexPlugin).shouldPoll();
will(returnValue(true)); // Should poll
oneOf(poller).addPlugin(simplexPlugin);
// Second simplex plugin // Second simplex plugin
oneOf(simplexFactory1).getId(); oneOf(simplexFactory1).getId();
will(returnValue(simplexId1)); will(returnValue(simplexId1));
@@ -204,8 +196,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(simplexPlugin1)); // Created will(returnValue(simplexPlugin1)); // Created
oneOf(simplexPlugin1).start(); oneOf(simplexPlugin1).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(simplexPlugin1).shouldPoll();
will(returnValue(false)); // Should not poll
// First duplex plugin // First duplex plugin
oneOf(pluginConfig).getDuplexFactories(); oneOf(pluginConfig).getDuplexFactories();
will(returnValue(Arrays.asList(duplexFactory, duplexFactory1))); will(returnValue(Arrays.asList(duplexFactory, duplexFactory1)));
@@ -216,9 +206,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(duplexPlugin)); // Created will(returnValue(duplexPlugin)); // Created
oneOf(duplexPlugin).start(); oneOf(duplexPlugin).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(duplexPlugin).shouldPoll();
will(returnValue(true)); // Should poll
oneOf(poller).addPlugin(duplexPlugin);
// Second duplex plugin // Second duplex plugin
oneOf(duplexFactory1).getId(); oneOf(duplexFactory1).getId();
will(returnValue(duplexId1)); will(returnValue(duplexId1));
@@ -227,8 +214,6 @@ public class PluginManagerImplTest extends BriarTestCase {
will(returnValue(duplexPlugin1)); // Created will(returnValue(duplexPlugin1)); // Created
oneOf(duplexPlugin1).start(); oneOf(duplexPlugin1).start();
will(returnValue(true)); // Started will(returnValue(true)); // Started
oneOf(duplexPlugin1).shouldPoll();
will(returnValue(false)); // Should not poll
// Start listening for events // Start listening for events
oneOf(eventBus).addListener(with(any(EventListener.class))); oneOf(eventBus).addListener(with(any(EventListener.class)));
// eventOccurred() // eventOccurred()