Merge branch '1232-poller-refactoring' into 'master'

Pass a connection handler to plugins when polling

See merge request briar/briar!1101
This commit is contained in:
Torsten Grote
2019-05-21 13:33:53 +00:00
41 changed files with 710 additions and 660 deletions

View File

@@ -12,8 +12,8 @@ import android.content.IntentFilter;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
@@ -51,6 +51,7 @@ import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@@ -58,7 +59,7 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final Logger LOG =
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
getLogger(AndroidBluetoothPlugin.class.getName());
private static final int MAX_DISCOVERY_MS = 10_000;
@@ -75,7 +76,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Clock clock,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
Backoff backoff, PluginCallback callback, int maxLatency) {
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
maxLatency);
this.androidExecutor = androidExecutor;

View File

@@ -6,9 +6,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
@@ -61,7 +61,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl();
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import java.io.IOException;
import java.net.InetAddress;
@@ -32,17 +32,18 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private static final Logger LOG =
getLogger(AndroidLanTcpPlugin.class.getName());
private static final byte[] WIFI_AP_ADDRESS_BYTES =
{(byte) 192, (byte) 168, 43, 1};
private static final InetAddress WIFI_AP_ADDRESS;
private static final Logger LOG =
Logger.getLogger(AndroidLanTcpPlugin.class.getName());
static {
try {
WIFI_AP_ADDRESS = InetAddress.getByAddress(WIFI_AP_ADDRESS_BYTES);
@@ -60,7 +61,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private volatile SocketFactory socketFactory;
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
Backoff backoff, DuplexPluginCallback callback, int maxLatency,
Backoff backoff, PluginCallback callback, int maxLatency,
int maxIdleTime) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
// Don't execute more than one connection status check at a time

View File

@@ -6,9 +6,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.util.concurrent.Executor;
@@ -51,7 +51,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,

View File

@@ -11,7 +11,7 @@ import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
@@ -41,7 +41,7 @@ class AndroidTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,

View File

@@ -9,10 +9,10 @@ import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
@@ -84,7 +84,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
// Check that we have a Tor binary for this architecture
String architecture = null;

View File

@@ -0,0 +1,28 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
/**
* An interface for handling connections created by transport plugins.
*/
@NotNullByDefault
public interface ConnectionHandler {
/**
* Handles a connection created by a {@link DuplexPlugin}.
*/
void handleConnection(DuplexTransportConnection c);
/**
* Handles a reader created by a {@link SimplexPlugin}.
*/
void handleReader(TransportConnectionReader r);
/**
* Handles a writer created by a {@link SimplexPlugin}.
*/
void handleWriter(TransportConnectionWriter w);
}

View File

@@ -1,10 +1,10 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.util.Map;
import java.util.Collection;
@NotNullByDefault
public interface Plugin {
@@ -51,8 +51,9 @@ public interface Plugin {
int getPollingInterval();
/**
* Attempts to establish connections to the given contacts, passing any
* created connections to the callback.
* Attempts to create connections using the given transport properties,
* passing any created connections to the corresponding handlers.
*/
void poll(Map<ContactId, TransportProperties> contacts);
void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties);
}

View File

@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.settings.Settings;
* the application.
*/
@NotNullByDefault
public interface PluginCallback {
public interface PluginCallback extends ConnectionHandler {
/**
* Returns the plugin's settings

View File

@@ -1,17 +0,0 @@
package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
/**
* An interface through which a duplex plugin interacts with the rest of the
* application.
*/
@NotNullByDefault
public interface DuplexPluginCallback extends PluginCallback {
void incomingConnectionCreated(DuplexTransportConnection d);
void outgoingConnectionCreated(ContactId c, DuplexTransportConnection d);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
@@ -25,5 +26,5 @@ public interface DuplexPluginFactory {
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
DuplexPlugin createPlugin(DuplexPluginCallback callback);
DuplexPlugin createPlugin(PluginCallback callback);
}

View File

@@ -1,19 +0,0 @@
package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
/**
* An interface through which a simplex plugin interacts with the rest of the
* application.
*/
@NotNullByDefault
public interface SimplexPluginCallback extends PluginCallback {
void readerCreated(TransportConnectionReader r);
void writerCreated(ContactId c, TransportConnectionWriter w);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
@@ -25,5 +26,5 @@ public interface SimplexPluginFactory {
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
SimplexPlugin createPlugin(SimplexPluginCallback callback);
SimplexPlugin createPlugin(PluginCallback callback);
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
@@ -8,7 +7,6 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginConfig;
@@ -18,22 +16,17 @@ import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.Scheduler;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -42,7 +35,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
@@ -52,6 +44,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -61,18 +54,14 @@ import static org.briarproject.bramble.util.LogUtils.now;
class PluginManagerImpl implements PluginManager, Service {
private static final Logger LOG =
Logger.getLogger(PluginManagerImpl.class.getName());
getLogger(PluginManagerImpl.class.getName());
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final EventBus eventBus;
private final PluginConfig pluginConfig;
private final ConnectionManager connectionManager;
private final ConnectionRegistry connectionRegistry;
private final SettingsManager settingsManager;
private final TransportPropertyManager transportPropertyManager;
private final SecureRandom random;
private final Clock clock;
private final Map<TransportId, Plugin> plugins;
private final List<SimplexPlugin> simplexPlugins;
private final List<DuplexPlugin> duplexPlugins;
@@ -80,46 +69,30 @@ class PluginManagerImpl implements PluginManager, Service {
private final AtomicBoolean used = new AtomicBoolean(false);
@Inject
PluginManagerImpl(@IoExecutor Executor ioExecutor,
@Scheduler ScheduledExecutorService scheduler, EventBus eventBus,
PluginManagerImpl(@IoExecutor Executor ioExecutor, EventBus eventBus,
PluginConfig pluginConfig, ConnectionManager connectionManager,
ConnectionRegistry connectionRegistry,
SettingsManager settingsManager,
TransportPropertyManager transportPropertyManager,
SecureRandom random, Clock clock) {
TransportPropertyManager transportPropertyManager) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.eventBus = eventBus;
this.pluginConfig = pluginConfig;
this.connectionManager = connectionManager;
this.connectionRegistry = connectionRegistry;
this.settingsManager = settingsManager;
this.transportPropertyManager = transportPropertyManager;
this.random = random;
this.clock = clock;
plugins = new ConcurrentHashMap<>();
simplexPlugins = new CopyOnWriteArrayList<>();
duplexPlugins = new CopyOnWriteArrayList<>();
startLatches = new ConcurrentHashMap<>();
}
@Override
public void startService() {
if (used.getAndSet(true)) throw new IllegalStateException();
// Instantiate the poller
if (pluginConfig.shouldPoll()) {
LOG.info("Starting poller");
Poller poller = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, this, transportPropertyManager, random,
clock);
eventBus.addListener(poller);
}
// Instantiate the simplex plugins and start them asynchronously
LOG.info("Starting simplex plugins");
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories()) {
TransportId t = f.getId();
SimplexPlugin s = f.createPlugin(new SimplexCallback(t));
SimplexPlugin s = f.createPlugin(new Callback(t));
if (s == null) {
if (LOG.isLoggable(WARNING))
LOG.warning("Could not create plugin for " + t);
@@ -135,7 +108,7 @@ class PluginManagerImpl implements PluginManager, Service {
LOG.info("Starting duplex plugins");
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories()) {
TransportId t = f.getId();
DuplexPlugin d = f.createPlugin(new DuplexCallback(t));
DuplexPlugin d = f.createPlugin(new Callback(t));
if (d == null) {
if (LOG.isLoggable(WARNING))
LOG.warning("Could not create plugin for " + t);
@@ -266,12 +239,11 @@ class PluginManagerImpl implements PluginManager, Service {
}
}
@NotNullByDefault
private abstract class PluginCallbackImpl implements PluginCallback {
private class Callback implements PluginCallback {
protected final TransportId id;
private final TransportId id;
PluginCallbackImpl(TransportId id) {
private Callback(TransportId id) {
this.id = id;
}
@@ -322,44 +294,21 @@ class PluginManagerImpl implements PluginManager, Service {
public void transportDisabled() {
eventBus.broadcast(new TransportDisabledEvent(id));
}
}
@NotNullByDefault
private class SimplexCallback extends PluginCallbackImpl
implements SimplexPluginCallback {
private SimplexCallback(TransportId id) {
super(id);
}
@Override
public void readerCreated(TransportConnectionReader r) {
connectionManager.manageIncomingConnection(id, r);
}
@Override
public void writerCreated(ContactId c, TransportConnectionWriter w) {
connectionManager.manageOutgoingConnection(c, id, w);
}
}
@NotNullByDefault
private class DuplexCallback extends PluginCallbackImpl
implements DuplexPluginCallback {
private DuplexCallback(TransportId id) {
super(id);
}
@Override
public void incomingConnectionCreated(DuplexTransportConnection d) {
public void handleConnection(DuplexTransportConnection d) {
connectionManager.manageIncomingConnection(id, d);
}
@Override
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {
connectionManager.manageOutgoingConnection(c, id, d);
public void handleReader(TransportConnectionReader r) {
connectionManager.manageIncomingConnection(id, r);
}
@Override
public void handleWriter(TransportConnectionWriter w) {
// TODO: Support simplex plugins that write to incoming connections
throw new UnsupportedOperationException();
}
}
}

View File

@@ -1,9 +1,11 @@
package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.PluginManager;
import javax.inject.Inject;
@@ -18,6 +20,8 @@ public class PluginModule {
public static class EagerSingletons {
@Inject
PluginManager pluginManager;
@Inject
Poller poller;
}
@Provides
@@ -46,4 +50,12 @@ public class PluginModule {
lifecycleManager.registerService(pluginManager);
return pluginManager;
}
@Provides
@Singleton
Poller providePoller(PluginConfig config, EventBus eventBus,
PollerImpl poller) {
if (config.shouldPoll()) eventBus.addListener(poller);
return poller;
}
}

View File

@@ -1,259 +1,7 @@
package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.Scheduler;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class Poller implements EventListener {
private static final Logger LOG = Logger.getLogger(Poller.class.getName());
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final ConnectionManager connectionManager;
private final ConnectionRegistry connectionRegistry;
private final PluginManager pluginManager;
private final TransportPropertyManager transportPropertyManager;
private final SecureRandom random;
private final Clock clock;
private final Lock lock;
private final Map<TransportId, ScheduledPollTask> tasks; // Locking: lock
Poller(@IoExecutor Executor ioExecutor,
@Scheduler ScheduledExecutorService scheduler,
ConnectionManager connectionManager,
ConnectionRegistry connectionRegistry, PluginManager pluginManager,
TransportPropertyManager transportPropertyManager,
SecureRandom random, Clock clock) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.connectionManager = connectionManager;
this.connectionRegistry = connectionRegistry;
this.pluginManager = pluginManager;
this.transportPropertyManager = transportPropertyManager;
this.random = random;
this.clock = clock;
lock = new ReentrantLock();
tasks = new HashMap<>();
}
@Override
public void eventOccurred(Event e) {
if (e instanceof ContactAddedEvent) {
ContactAddedEvent c = (ContactAddedEvent) e;
// Connect to the newly activated contact
connectToContact(c.getContactId());
} else if (e instanceof ConnectionClosedEvent) {
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
if (!c.isIncoming()) {
// Connect to the disconnected contact
connectToContact(c.getContactId(), c.getTransportId());
}
} else if (e instanceof ConnectionOpenedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
} else if (e instanceof TransportEnabledEvent) {
TransportEnabledEvent t = (TransportEnabledEvent) e;
// Poll the newly enabled transport
pollNow(t.getTransportId());
} else if (e instanceof TransportDisabledEvent) {
TransportDisabledEvent t = (TransportDisabledEvent) e;
// Cancel polling for the disabled transport
cancel(t.getTransportId());
}
}
private void connectToContact(ContactId c) {
for (SimplexPlugin s : pluginManager.getSimplexPlugins())
if (s.shouldPoll()) connectToContact(c, s);
for (DuplexPlugin d : pluginManager.getDuplexPlugins())
if (d.shouldPoll()) connectToContact(c, d);
}
private void connectToContact(ContactId c, TransportId t) {
Plugin p = pluginManager.getPlugin(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(ContactId c, SimplexPlugin p) {
ioExecutor.execute(() -> {
TransportId t = p.getId();
if (connectionRegistry.isConnected(c, t)) return;
try {
TransportProperties props =
transportPropertyManager.getRemoteProperties(c, t);
TransportConnectionWriter w = p.createWriter(props);
if (w != null)
connectionManager.manageOutgoingConnection(c, t, w);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
private void connectToContact(ContactId c, DuplexPlugin p) {
ioExecutor.execute(() -> {
TransportId t = p.getId();
if (connectionRegistry.isConnected(c, t)) return;
try {
TransportProperties props =
transportPropertyManager.getRemoteProperties(c, t);
DuplexTransportConnection d = p.createConnection(props);
if (d != null)
connectionManager.manageOutgoingConnection(c, t, d);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
private void reschedule(TransportId t) {
Plugin p = pluginManager.getPlugin(t);
if (p != null && p.shouldPoll())
schedule(p, p.getPollingInterval(), false);
}
private void pollNow(TransportId t) {
Plugin p = pluginManager.getPlugin(t);
// Randomise next polling interval
if (p != null && p.shouldPoll()) schedule(p, 0, true);
}
private void schedule(Plugin p, int delay, boolean randomiseNext) {
// Replace any later scheduled task for this plugin
long due = clock.currentTimeMillis() + delay;
TransportId t = p.getId();
lock.lock();
try {
ScheduledPollTask scheduled = tasks.get(t);
if (scheduled == null || due < scheduled.task.due) {
// If a later task exists, cancel it. If it's already started
// it will abort safely when it finds it's been replaced
if (scheduled != null) scheduled.future.cancel(false);
PollTask task = new PollTask(p, due, randomiseNext);
Future future = scheduler.schedule(
() -> ioExecutor.execute(task), delay, MILLISECONDS);
tasks.put(t, new ScheduledPollTask(task, future));
}
} finally {
lock.unlock();
}
}
private void cancel(TransportId t) {
lock.lock();
try {
ScheduledPollTask scheduled = tasks.remove(t);
if (scheduled != null) scheduled.future.cancel(false);
} finally {
lock.unlock();
}
}
@IoExecutor
private void poll(Plugin p) {
TransportId t = p.getId();
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
try {
Map<ContactId, TransportProperties> remote =
transportPropertyManager.getRemoteProperties(t);
Collection<ContactId> connected =
connectionRegistry.getConnectedContacts(t);
remote = new HashMap<>(remote);
remote.keySet().removeAll(connected);
if (!remote.isEmpty()) p.poll(remote);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
private class ScheduledPollTask {
private final PollTask task;
private final Future future;
private ScheduledPollTask(PollTask task, Future future) {
this.task = task;
this.future = future;
}
}
private class PollTask implements Runnable {
private final Plugin plugin;
private final long due;
private final boolean randomiseNext;
private PollTask(Plugin plugin, long due, boolean randomiseNext) {
this.plugin = plugin;
this.due = due;
this.randomiseNext = randomiseNext;
}
@Override
@IoExecutor
public void run() {
lock.lock();
try {
TransportId t = plugin.getId();
ScheduledPollTask scheduled = tasks.get(t);
if (scheduled != null && scheduled.task != this)
return; // Replaced by another task
tasks.remove(t);
} finally {
lock.unlock();
}
int delay = plugin.getPollingInterval();
if (randomiseNext) delay = (int) (delay * random.nextDouble());
schedule(plugin, delay, false);
poll(plugin);
}
}
/**
* Empty interface used for injecting the poller.
*/
interface Poller {
}

View File

@@ -0,0 +1,303 @@
package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.Scheduler;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class PollerImpl implements Poller, EventListener {
private static final Logger LOG = getLogger(PollerImpl.class.getName());
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final ConnectionManager connectionManager;
private final ConnectionRegistry connectionRegistry;
private final PluginManager pluginManager;
private final TransportPropertyManager transportPropertyManager;
private final SecureRandom random;
private final Clock clock;
private final Lock lock;
@GuardedBy("lock")
private final Map<TransportId, ScheduledPollTask> tasks;
@Inject
PollerImpl(@IoExecutor Executor ioExecutor,
@Scheduler ScheduledExecutorService scheduler,
ConnectionManager connectionManager,
ConnectionRegistry connectionRegistry, PluginManager pluginManager,
TransportPropertyManager transportPropertyManager,
SecureRandom random, Clock clock) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.connectionManager = connectionManager;
this.connectionRegistry = connectionRegistry;
this.pluginManager = pluginManager;
this.transportPropertyManager = transportPropertyManager;
this.random = random;
this.clock = clock;
lock = new ReentrantLock();
tasks = new HashMap<>();
}
@Override
public void eventOccurred(Event e) {
if (e instanceof ContactAddedEvent) {
ContactAddedEvent c = (ContactAddedEvent) e;
// Connect to the newly added contact
connectToContact(c.getContactId());
} else if (e instanceof ConnectionClosedEvent) {
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
if (!c.isIncoming()) {
// Connect to the disconnected contact
connectToContact(c.getContactId(), c.getTransportId());
}
} else if (e instanceof ConnectionOpenedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
// Reschedule polling, the polling interval may have decreased
reschedule(c.getTransportId());
} else if (e instanceof TransportEnabledEvent) {
TransportEnabledEvent t = (TransportEnabledEvent) e;
// Poll the newly enabled transport
pollNow(t.getTransportId());
} else if (e instanceof TransportDisabledEvent) {
TransportDisabledEvent t = (TransportDisabledEvent) e;
// Cancel polling for the disabled transport
cancel(t.getTransportId());
}
}
private void connectToContact(ContactId c) {
for (SimplexPlugin s : pluginManager.getSimplexPlugins())
if (s.shouldPoll()) connectToContact(c, s);
for (DuplexPlugin d : pluginManager.getDuplexPlugins())
if (d.shouldPoll()) connectToContact(c, d);
}
private void connectToContact(ContactId c, TransportId t) {
Plugin p = pluginManager.getPlugin(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(ContactId c, SimplexPlugin p) {
ioExecutor.execute(() -> {
TransportId t = p.getId();
if (connectionRegistry.isConnected(c, t)) return;
try {
TransportProperties props =
transportPropertyManager.getRemoteProperties(c, t);
TransportConnectionWriter w = p.createWriter(props);
if (w != null)
connectionManager.manageOutgoingConnection(c, t, w);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
private void connectToContact(ContactId c, DuplexPlugin p) {
ioExecutor.execute(() -> {
TransportId t = p.getId();
if (connectionRegistry.isConnected(c, t)) return;
try {
TransportProperties props =
transportPropertyManager.getRemoteProperties(c, t);
DuplexTransportConnection d = p.createConnection(props);
if (d != null)
connectionManager.manageOutgoingConnection(c, t, d);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
private void reschedule(TransportId t) {
Plugin p = pluginManager.getPlugin(t);
if (p != null && p.shouldPoll())
schedule(p, p.getPollingInterval(), false);
}
private void pollNow(TransportId t) {
Plugin p = pluginManager.getPlugin(t);
// Randomise next polling interval
if (p != null && p.shouldPoll()) schedule(p, 0, true);
}
private void schedule(Plugin p, int delay, boolean randomiseNext) {
// Replace any later scheduled task for this plugin
long due = clock.currentTimeMillis() + delay;
TransportId t = p.getId();
lock.lock();
try {
ScheduledPollTask scheduled = tasks.get(t);
if (scheduled == null || due < scheduled.task.due) {
// If a later task exists, cancel it. If it's already started
// it will abort safely when it finds it's been replaced
if (scheduled != null) scheduled.future.cancel(false);
PollTask task = new PollTask(p, due, randomiseNext);
Future future = scheduler.schedule(() ->
ioExecutor.execute(task), delay, MILLISECONDS);
tasks.put(t, new ScheduledPollTask(task, future));
}
} finally {
lock.unlock();
}
}
private void cancel(TransportId t) {
lock.lock();
try {
ScheduledPollTask scheduled = tasks.remove(t);
if (scheduled != null) scheduled.future.cancel(false);
} finally {
lock.unlock();
}
}
@IoExecutor
private void poll(Plugin p) {
TransportId t = p.getId();
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
try {
Map<ContactId, TransportProperties> remote =
transportPropertyManager.getRemoteProperties(t);
Collection<ContactId> connected =
connectionRegistry.getConnectedContacts(t);
Collection<Pair<TransportProperties, ConnectionHandler>>
properties = new ArrayList<>();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c))
properties.add(new Pair<>(e.getValue(), new Handler(c, t)));
}
if (!properties.isEmpty()) p.poll(properties);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
private class ScheduledPollTask {
private final PollTask task;
private final Future future;
private ScheduledPollTask(PollTask task, Future future) {
this.task = task;
this.future = future;
}
}
private class PollTask implements Runnable {
private final Plugin plugin;
private final long due;
private final boolean randomiseNext;
private PollTask(Plugin plugin, long due, boolean randomiseNext) {
this.plugin = plugin;
this.due = due;
this.randomiseNext = randomiseNext;
}
@Override
@IoExecutor
public void run() {
lock.lock();
try {
TransportId t = plugin.getId();
ScheduledPollTask scheduled = tasks.get(t);
if (scheduled != null && scheduled.task != this)
return; // Replaced by another task
tasks.remove(t);
} finally {
lock.unlock();
}
int delay = plugin.getPollingInterval();
if (randomiseNext) delay = (int) (delay * random.nextDouble());
schedule(plugin, delay, false);
poll(plugin);
}
}
private class Handler implements ConnectionHandler {
private final ContactId contactId;
private final TransportId transportId;
private Handler(ContactId contactId, TransportId transportId) {
this.contactId = contactId;
this.transportId = transportId;
}
@Override
public void handleConnection(DuplexTransportConnection c) {
connectionManager.manageOutgoingConnection(contactId,
transportId, c);
}
@Override
public void handleReader(TransportConnectionReader r) {
// TODO: Support simplex plugins that read from outgoing connections
throw new UnsupportedOperationException();
}
@Override
public void handleWriter(TransportConnectionWriter w) {
connectionManager.manageOutgoingConnection(contactId,
transportId, w);
}
}
}

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.plugin.bluetooth;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
@@ -12,10 +12,11 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStoppedListen
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
@@ -26,8 +27,7 @@ import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,6 +37,7 @@ import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
@@ -54,14 +55,14 @@ import static org.briarproject.bramble.util.StringUtils.macToString;
abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
private static final Logger LOG =
Logger.getLogger(BluetoothPlugin.class.getName());
getLogger(BluetoothPlugin.class.getName());
final BluetoothConnectionLimiter connectionLimiter;
private final Executor ioExecutor;
private final SecureRandom secureRandom;
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final PluginCallback callback;
private final int maxLatency;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -103,7 +104,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, SecureRandom secureRandom,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
Backoff backoff, PluginCallback callback, int maxLatency) {
this.connectionLimiter = connectionLimiter;
this.ioExecutor = ioExecutor;
this.secureRandom = secureRandom;
@@ -226,7 +227,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
}
backoff.reset();
if (connectionLimiter.contactConnectionOpened(conn))
callback.incomingConnectionCreated(conn);
callback.handleConnection(conn);
if (!running) return;
}
}
@@ -255,29 +256,32 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
}
@Override
public void poll(Map<ContactId, TransportProperties> contacts) {
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) {
if (!isRunning() || !shouldAllowContactConnections()) return;
backoff.increment();
// Try to connect to known devices in parallel
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
String address = e.getValue().get(PROP_ADDRESS);
if (isNullOrEmpty(address)) continue;
String uuid = e.getValue().get(PROP_UUID);
if (isNullOrEmpty(uuid)) continue;
ContactId c = e.getKey();
ioExecutor.execute(() -> {
if (!isRunning() || !shouldAllowContactConnections()) return;
if (!connectionLimiter.canOpenContactConnection()) return;
DuplexTransportConnection conn = connect(address, uuid);
if (conn != null) {
backoff.reset();
if (connectionLimiter.contactConnectionOpened(conn))
callback.outgoingConnectionCreated(c, conn);
}
});
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond());
}
}
private void connect(TransportProperties p, ConnectionHandler h) {
String address = p.get(PROP_ADDRESS);
if (isNullOrEmpty(address)) return;
String uuid = p.get(PROP_UUID);
if (isNullOrEmpty(uuid)) return;
ioExecutor.execute(() -> {
if (!isRunning() || !shouldAllowContactConnections()) return;
if (!connectionLimiter.canOpenContactConnection()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
if (connectionLimiter.contactConnectionOpened(d))
h.handleConnection(d);
}
});
}
@Nullable
private DuplexTransportConnection connect(String address, String uuid) {
// Validate the address

View File

@@ -1,10 +1,10 @@
package org.briarproject.bramble.plugin.file;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.File;
@@ -14,6 +14,7 @@ import java.io.IOException;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@@ -22,9 +23,9 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
abstract class FilePlugin implements SimplexPlugin {
private static final Logger LOG =
Logger.getLogger(FilePlugin.class.getName());
getLogger(FilePlugin.class.getName());
protected final SimplexPluginCallback callback;
protected final PluginCallback callback;
protected final int maxLatency;
protected abstract void writerFinished(File f, boolean exception);
@@ -32,7 +33,7 @@ abstract class FilePlugin implements SimplexPlugin {
protected abstract void readerFinished(File f, boolean exception,
boolean recognised);
FilePlugin(SimplexPluginCallback callback, int maxLatency) {
FilePlugin(PluginCallback callback, int maxLatency) {
this.callback = callback;
this.maxLatency = maxLatency;
}

View File

@@ -6,13 +6,12 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
import java.net.Inet4Address;
@@ -23,26 +22,30 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import static java.util.Collections.addAll;
import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
import static org.briarproject.bramble.util.StringUtils.join;
@NotNullByDefault
class LanTcpPlugin extends TcpPlugin {
private static final Logger LOG =
Logger.getLogger(LanTcpPlugin.class.getName());
private static final Logger LOG = getLogger(LanTcpPlugin.class.getName());
private static final LanAddressComparator ADDRESS_COMPARATOR =
new LanAddressComparator();
@@ -50,8 +53,8 @@ class LanTcpPlugin extends TcpPlugin {
private static final int MAX_ADDRESSES = 4;
private static final String SEPARATOR = ",";
LanTcpPlugin(Executor ioExecutor, Backoff backoff,
DuplexPluginCallback callback, int maxLatency, int maxIdleTime) {
LanTcpPlugin(Executor ioExecutor, Backoff backoff, PluginCallback callback,
int maxLatency, int maxIdleTime) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
}
@@ -77,12 +80,12 @@ class LanTcpPlugin extends TcpPlugin {
locals.add(new InetSocketAddress(local, 0));
}
}
Collections.sort(locals, ADDRESS_COMPARATOR);
sort(locals, ADDRESS_COMPARATOR);
return locals;
}
private List<InetSocketAddress> parseSocketAddresses(String ipPorts) {
if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList();
if (isNullOrEmpty(ipPorts)) return emptyList();
String[] split = ipPorts.split(SEPARATOR);
List<InetSocketAddress> addresses = new ArrayList<>();
for (String ipPort : split) {
@@ -98,24 +101,24 @@ class LanTcpPlugin extends TcpPlugin {
// Get the list of recently used addresses
String setting = callback.getSettings().get(PREF_LAN_IP_PORTS);
List<String> recent = new ArrayList<>();
if (!StringUtils.isNullOrEmpty(setting))
Collections.addAll(recent, setting.split(SEPARATOR));
if (!isNullOrEmpty(setting))
addAll(recent, setting.split(SEPARATOR));
// Is the address already in the list?
if (recent.remove(ipPort)) {
// Move the address to the start of the list
recent.add(0, ipPort);
setting = StringUtils.join(recent, SEPARATOR);
setting = join(recent, SEPARATOR);
} else {
// Add the address to the start of the list
recent.add(0, ipPort);
// Drop the least recently used address if the list is full
if (recent.size() > MAX_ADDRESSES)
recent = recent.subList(0, MAX_ADDRESSES);
setting = StringUtils.join(recent, SEPARATOR);
setting = join(recent, SEPARATOR);
// Update the list of addresses shared with contacts
List<String> shared = new ArrayList<>(recent);
Collections.sort(shared);
String property = StringUtils.join(shared, SEPARATOR);
sort(shared);
String property = join(shared, SEPARATOR);
TransportProperties properties = new TransportProperties();
properties.put(PROP_IP_PORTS, property);
callback.mergeLocalProperties(properties);

View File

@@ -3,9 +3,9 @@ package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.util.concurrent.Executor;
@@ -44,7 +44,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
return new LanTcpPlugin(ioExecutor, backoff, callback, MAX_LATENCY,

View File

@@ -1,18 +1,18 @@
package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
import java.net.InetAddress;
@@ -27,8 +27,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
@@ -41,21 +39,23 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.list;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
abstract class TcpPlugin implements DuplexPlugin {
private static final Logger LOG = getLogger(TcpPlugin.class.getName());
private static final Pattern DOTTED_QUAD =
Pattern.compile("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$");
private static final Logger LOG =
Logger.getLogger(TcpPlugin.class.getName());
protected final Executor ioExecutor, bindExecutor;
protected final Backoff backoff;
protected final DuplexPluginCallback callback;
protected final PluginCallback callback;
protected final int maxLatency, maxIdleTime, socketTimeout;
protected final AtomicBoolean used = new AtomicBoolean(false);
@@ -86,8 +86,8 @@ abstract class TcpPlugin implements DuplexPlugin {
*/
protected abstract boolean isConnectable(InetSocketAddress remote);
TcpPlugin(Executor ioExecutor, Backoff backoff,
DuplexPluginCallback callback, int maxLatency, int maxIdleTime) {
TcpPlugin(Executor ioExecutor, Backoff backoff, PluginCallback callback,
int maxLatency, int maxIdleTime) {
this.ioExecutor = ioExecutor;
this.backoff = backoff;
this.callback = callback;
@@ -180,8 +180,7 @@ abstract class TcpPlugin implements DuplexPlugin {
LOG.info("Connection from " +
scrubSocketAddress(s.getRemoteSocketAddress()));
backoff.reset();
TcpTransportConnection conn = new TcpTransportConnection(this, s);
callback.incomingConnectionCreated(conn);
callback.handleConnection(new TcpTransportConnection(this, s));
}
}
@@ -207,20 +206,21 @@ abstract class TcpPlugin implements DuplexPlugin {
}
@Override
public void poll(Map<ContactId, TransportProperties> contacts) {
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) {
if (!isRunning()) return;
backoff.increment();
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
connectAndCallBack(e.getKey(), e.getValue());
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond());
}
}
private void connectAndCallBack(ContactId c, TransportProperties p) {
private void connect(TransportProperties p, ConnectionHandler h) {
ioExecutor.execute(() -> {
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
h.handleConnection(d);
}
});
}
@@ -263,7 +263,7 @@ abstract class TcpPlugin implements DuplexPlugin {
@Nullable
InetSocketAddress parseSocketAddress(String ipPort) {
if (StringUtils.isNullOrEmpty(ipPort)) return null;
if (isNullOrEmpty(ipPort)) return null;
String[] split = ipPort.split(":");
if (split.length != 2) return null;
String addr = split[0], port = split[1];

View File

@@ -3,18 +3,19 @@ package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.plugin.WanTcpConstants.ID;
@MethodsNotNullByDefault
@@ -28,7 +29,7 @@ class WanTcpPlugin extends TcpPlugin {
private volatile MappingResult mappingResult;
WanTcpPlugin(Executor ioExecutor, Backoff backoff, PortMapper portMapper,
DuplexPluginCallback callback, int maxLatency, int maxIdleTime) {
PluginCallback callback, int maxLatency, int maxIdleTime) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
this.portMapper = portMapper;
}
@@ -80,8 +81,8 @@ class WanTcpPlugin extends TcpPlugin {
protected List<InetSocketAddress> getRemoteSocketAddresses(
TransportProperties p) {
InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT));
if (parsed == null) return Collections.emptyList();
return Collections.singletonList(parsed);
if (parsed == null) return emptyList();
return singletonList(parsed);
}
@Override

View File

@@ -4,9 +4,9 @@ import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.util.concurrent.Executor;
@@ -47,7 +47,7 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
return new WanTcpPlugin(ioExecutor, backoff,

View File

@@ -4,9 +4,9 @@ import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
@@ -17,11 +17,12 @@ import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
@@ -47,7 +48,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -60,6 +60,7 @@ import javax.net.SocketFactory;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
@@ -81,8 +82,7 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@ParametersNotNullByDefault
abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName());
private static final Logger LOG = getLogger(TorPlugin.class.getName());
private static final String[] EVENTS = {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
@@ -100,7 +100,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Clock clock;
private final BatteryManager batteryManager;
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final PluginCallback callback;
private final String architecture;
private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
@@ -126,7 +126,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor;
this.networkManager = networkManager;
@@ -458,8 +458,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
LOG.info("Connection received");
backoff.reset();
TorTransportConnection conn = new TorTransportConnection(this, s);
callback.incomingConnectionCreated(conn);
callback.handleConnection(new TorTransportConnection(this, s));
}
}
@@ -521,20 +520,21 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public void poll(Map<ContactId, TransportProperties> contacts) {
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) {
if (!isRunning()) return;
backoff.increment();
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
connectAndCallBack(e.getKey(), e.getValue());
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond());
}
}
private void connectAndCallBack(ContactId c, TransportProperties p) {
private void connect(TransportProperties p, ConnectionHandler h) {
ioExecutor.execute(() -> {
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
h.handleConnection(d);
}
});
}

View File

@@ -2,30 +2,25 @@ package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.Test;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static org.briarproject.bramble.test.TestUtils.getTransportId;
@@ -37,16 +32,10 @@ public class PluginManagerImplTest extends BrambleTestCase {
setThreadingPolicy(new Synchroniser());
}};
Executor ioExecutor = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class);
SecureRandom random = new SecureRandom();
Clock clock = context.mock(Clock.class);
EventBus eventBus = context.mock(EventBus.class);
PluginConfig pluginConfig = context.mock(PluginConfig.class);
ConnectionManager connectionManager =
context.mock(ConnectionManager.class);
ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class);
SettingsManager settingsManager =
context.mock(SettingsManager.class);
TransportPropertyManager transportPropertyManager =
@@ -88,15 +77,14 @@ public class PluginManagerImplTest extends BrambleTestCase {
simplexFailFactory)));
oneOf(simplexFactory).getId();
will(returnValue(simplexId));
oneOf(simplexFactory).createPlugin(with(any(
SimplexPluginCallback.class)));
oneOf(simplexFactory).createPlugin(with(any(PluginCallback.class)));
will(returnValue(simplexPlugin)); // Created
oneOf(simplexPlugin).start();
// Second simplex plugin
oneOf(simplexFailFactory).getId();
will(returnValue(simplexFailId));
oneOf(simplexFailFactory).createPlugin(with(any(
SimplexPluginCallback.class)));
PluginCallback.class)));
will(returnValue(simplexFailPlugin)); // Created
oneOf(simplexFailPlugin).start();
will(throwException(new PluginException()));
@@ -105,15 +93,14 @@ public class PluginManagerImplTest extends BrambleTestCase {
will(returnValue(Arrays.asList(duplexFactory, duplexFailFactory)));
oneOf(duplexFactory).getId();
will(returnValue(duplexId));
oneOf(duplexFactory).createPlugin(with(any(
DuplexPluginCallback.class)));
oneOf(duplexFactory).createPlugin(with(any(PluginCallback.class)));
will(returnValue(duplexPlugin)); // Created
oneOf(duplexPlugin).start();
// Second duplex plugin
oneOf(duplexFailFactory).getId();
will(returnValue(duplexFailId));
oneOf(duplexFailFactory).createPlugin(with(any(
DuplexPluginCallback.class)));
PluginCallback.class)));
will(returnValue(null)); // Failed to create a plugin
// stop()
// Stop the plugins
@@ -122,9 +109,9 @@ public class PluginManagerImplTest extends BrambleTestCase {
oneOf(duplexPlugin).stop();
}});
PluginManagerImpl p = new PluginManagerImpl(ioExecutor, scheduler,
eventBus, pluginConfig, connectionManager, connectionRegistry,
settingsManager, transportPropertyManager, random, clock);
PluginManagerImpl p = new PluginManagerImpl(ioExecutor, eventBus,
pluginConfig, connectionManager, settingsManager,
transportPropertyManager);
// Two plugins should be started and stopped
p.startService();

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.plugin.Plugin;
@@ -23,6 +24,7 @@ import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.RunAction;
import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before;
import org.junit.Test;
import java.security.SecureRandom;
@@ -36,10 +38,12 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.test.CollectionMatcher.collectionOf;
import static org.briarproject.bramble.test.PairMatcher.pairOf;
import static org.briarproject.bramble.test.TestUtils.getContactId;
import static org.briarproject.bramble.test.TestUtils.getTransportId;
public class PollerTest extends BrambleMockTestCase {
public class PollerImplTest extends BrambleMockTestCase {
private final ScheduledExecutorService scheduler =
context.mock(ScheduledExecutorService.class);
@@ -62,11 +66,20 @@ public class PollerTest extends BrambleMockTestCase {
private final int pollingInterval = 60 * 1000;
private final long now = System.currentTimeMillis();
public PollerTest() {
private PollerImpl poller;
public PollerImplTest() {
context.setImposteriser(ClassImposteriser.INSTANCE);
random = context.mock(SecureRandom.class);
}
@Before
public void setUp() {
poller = new PollerImpl(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
}
@Test
public void testConnectOnContactAdded() throws Exception {
// Two simplex plugins: one supports polling, the other doesn't
@@ -140,11 +153,7 @@ public class PollerTest extends BrambleMockTestCase {
will(returnValue(false));
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new ContactAddedEvent(contactId));
poller.eventOccurred(new ContactAddedEvent(contactId));
}
@Test
@@ -194,11 +203,7 @@ public class PollerTest extends BrambleMockTestCase {
transportId, duplexConnection);
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new ConnectionClosedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionClosedEvent(contactId, transportId,
false));
}
@@ -225,11 +230,7 @@ public class PollerTest extends BrambleMockTestCase {
will(returnValue(future));
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
}
@@ -269,13 +270,9 @@ public class PollerTest extends BrambleMockTestCase {
will(returnValue(now + 1));
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
p.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
}
@@ -318,13 +315,9 @@ public class PollerTest extends BrambleMockTestCase {
with((long) pollingInterval - 2), with(MILLISECONDS));
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
p.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
}
@@ -364,14 +357,11 @@ public class PollerTest extends BrambleMockTestCase {
oneOf(connectionRegistry).getConnectedContacts(transportId);
will(returnValue(emptyList()));
// Poll the plugin
oneOf(plugin).poll(singletonMap(contactId, properties));
oneOf(plugin).poll(with(collectionOf(
pairOf(equal(properties), any(ConnectionHandler.class)))));
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new TransportEnabledEvent(transportId));
poller.eventOccurred(new TransportEnabledEvent(transportId));
}
@Test
@@ -412,11 +402,7 @@ public class PollerTest extends BrambleMockTestCase {
// All contacts are connected, so don't poll the plugin
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new TransportEnabledEvent(transportId));
poller.eventOccurred(new TransportEnabledEvent(transportId));
}
@Test
@@ -442,11 +428,7 @@ public class PollerTest extends BrambleMockTestCase {
oneOf(future).cancel(false);
}});
Poller p = new Poller(ioExecutor, scheduler, connectionManager,
connectionRegistry, pluginManager, transportPropertyManager,
random, clock);
p.eventOccurred(new TransportEnabledEvent(transportId));
p.eventOccurred(new TransportDisabledEvent(transportId));
poller.eventOccurred(new TransportEnabledEvent(transportId));
poller.eventOccurred(new TransportDisabledEvent(transportId));
}
}

View File

@@ -1,12 +1,13 @@
package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
@@ -21,13 +22,14 @@ import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.net.NetworkInterface.getNetworkInterfaces;
import static java.util.Collections.list;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
@@ -39,10 +41,13 @@ import static org.junit.Assert.assertTrue;
public class LanTcpPluginTest extends BrambleTestCase {
private final Backoff backoff = new TestBackoff();
private final ExecutorService ioExecutor = newCachedThreadPool();
@Test
public void testAddressesAreOnSameLan() {
LanTcpPlugin plugin = new LanTcpPlugin(null, null, null, 0, 0);
Callback callback = new Callback();
LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
0, 0);
// Local and remote in 10.0.0.0/8 should return true
assertTrue(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0),
makeAddress(10, 255, 255, 255)));
@@ -93,8 +98,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
return;
}
Callback callback = new Callback();
Executor executor = Executors.newCachedThreadPool();
DuplexPlugin plugin = new LanTcpPlugin(executor, backoff, callback,
DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
0, 0);
plugin.start();
// The plugin should have bound a socket and stored the port number
@@ -129,8 +133,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
return;
}
Callback callback = new Callback();
Executor executor = Executors.newCachedThreadPool();
DuplexPlugin plugin = new LanTcpPlugin(executor, backoff, callback,
DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
0, 0);
plugin.start();
// The plugin should have bound a socket and stored the port number
@@ -179,8 +182,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
return;
}
Callback callback = new Callback();
Executor executor = Executors.newCachedThreadPool();
DuplexPlugin plugin = new LanTcpPlugin(executor, backoff, callback,
DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
0, 0);
plugin.start();
assertTrue(callback.propertiesLatch.await(5, SECONDS));
@@ -228,8 +230,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
return;
}
Callback callback = new Callback();
Executor executor = Executors.newCachedThreadPool();
DuplexPlugin plugin = new LanTcpPlugin(executor, backoff, callback,
DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback,
0, 0);
plugin.start();
// The plugin should have bound a socket and stored the port number
@@ -327,9 +328,8 @@ public class LanTcpPluginTest extends BrambleTestCase {
}
private boolean systemHasLocalIpv4Address() throws Exception {
for (NetworkInterface i : Collections.list(
NetworkInterface.getNetworkInterfaces())) {
for (InetAddress a : Collections.list(i.getInetAddresses())) {
for (NetworkInterface i : list(getNetworkInterfaces())) {
for (InetAddress a : list(i.getInetAddresses())) {
if (a instanceof Inet4Address)
return a.isLinkLocalAddress() || a.isSiteLocalAddress();
}
@@ -338,7 +338,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
}
@NotNullByDefault
private static class Callback implements DuplexPluginCallback {
private static class Callback implements PluginCallback {
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
@@ -364,16 +364,6 @@ public class LanTcpPluginTest extends BrambleTestCase {
propertiesLatch.countDown();
}
@Override
public void incomingConnectionCreated(DuplexTransportConnection d) {
connectionsLatch.countDown();
}
@Override
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {
}
@Override
public void transportEnabled() {
}
@@ -381,6 +371,19 @@ public class LanTcpPluginTest extends BrambleTestCase {
@Override
public void transportDisabled() {
}
@Override
public void handleConnection(DuplexTransportConnection d) {
connectionsLatch.countDown();
}
@Override
public void handleReader(TransportConnectionReader r) {
}
@Override
public void handleWriter(TransportConnectionWriter w) {
}
}
private static class TestBackoff implements Backoff {

View File

@@ -0,0 +1,39 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import java.util.Collection;
import javax.annotation.Nullable;
@NotNullByDefault
public class CollectionMatcher<T> extends BaseMatcher<Collection<T>> {
private final Matcher<T> elementMatcher;
public CollectionMatcher(Matcher<T> elementMatcher) {
this.elementMatcher = elementMatcher;
}
@Override
public boolean matches(@Nullable Object item) {
if (!(item instanceof Collection)) return false;
Collection collection = (Collection) item;
for (Object element : collection) {
if (!elementMatcher.matches(element)) return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText("matches a collection");
}
public static <T> CollectionMatcher<T> collectionOf(Matcher<T> t) {
return new CollectionMatcher<>(t);
}
}

View File

@@ -0,0 +1,38 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import javax.annotation.Nullable;
@NotNullByDefault
public class PairMatcher<A, B> extends BaseMatcher<Pair<A, B>> {
private final Matcher<A> firstMatcher;
private final Matcher<B> secondMatcher;
public PairMatcher(Matcher<A> firstMatcher, Matcher<B> secondMatcher) {
this.firstMatcher = firstMatcher;
this.secondMatcher = secondMatcher;
}
@Override
public boolean matches(@Nullable Object item) {
if (!(item instanceof Pair)) return false;
Pair pair = (Pair) item;
return firstMatcher.matches(pair.getFirst()) &&
secondMatcher.matches(pair.getSecond());
}
@Override
public void describeTo(Description description) {
description.appendText("matches a pair");
}
public static <A, B> PairMatcher<A, B> pairOf(Matcher<A> a, Matcher<B> b) {
return new PairMatcher<>(a, b);
}
}

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import java.util.Collection;
@@ -40,7 +40,7 @@ public class TestPluginConfigModule {
@Override
@Nullable
public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
public SimplexPlugin createPlugin(PluginCallback callback) {
return null;
}
};

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.plugin.bluetooth;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import java.io.IOException;
@@ -19,6 +19,7 @@ import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isValidMac;
@@ -27,14 +28,14 @@ import static org.briarproject.bramble.util.StringUtils.isValidMac;
class JavaBluetoothPlugin extends BluetoothPlugin<StreamConnectionNotifier> {
private static final Logger LOG =
Logger.getLogger(JavaBluetoothPlugin.class.getName());
getLogger(JavaBluetoothPlugin.class.getName());
// Non-null if the plugin started successfully
private volatile LocalDevice localDevice = null;
JavaBluetoothPlugin(BluetoothConnectionLimiter connectionManager,
Executor ioExecutor, SecureRandom secureRandom,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
Backoff backoff, PluginCallback callback, int maxLatency) {
super(connectionManager, ioExecutor, secureRandom, backoff, callback,
maxLatency);
}

View File

@@ -4,9 +4,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.security.SecureRandom;
@@ -50,7 +50,7 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl();
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,

View File

@@ -1,29 +1,31 @@
package org.briarproject.bramble.plugin.modem;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -33,11 +35,11 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
new TransportId("org.briarproject.bramble.modem");
private static final Logger LOG =
Logger.getLogger(ModemPlugin.class.getName());
getLogger(ModemPlugin.class.getName());
private final ModemFactory modemFactory;
private final SerialPortList serialPortList;
private final DuplexPluginCallback callback;
private final PluginCallback callback;
private final int maxLatency;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -45,7 +47,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private volatile Modem modem = null;
ModemPlugin(ModemFactory modemFactory, SerialPortList serialPortList,
DuplexPluginCallback callback, int maxLatency) {
PluginCallback callback, int maxLatency) {
this.modemFactory = modemFactory;
this.serialPortList = serialPortList;
this.callback = callback;
@@ -116,7 +118,8 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
@Override
public void poll(Map<ContactId, TransportProperties> contacts) {
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) {
throw new UnsupportedOperationException();
}
@@ -144,13 +147,13 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
if (!running) return null;
// Get the ISO 3166 code for the caller's country
String fromIso = callback.getLocalProperties().get("iso3166");
if (StringUtils.isNullOrEmpty(fromIso)) return null;
if (isNullOrEmpty(fromIso)) return null;
// Get the ISO 3166 code for the callee's country
String toIso = p.get("iso3166");
if (StringUtils.isNullOrEmpty(toIso)) return null;
if (isNullOrEmpty(toIso)) return null;
// Get the callee's phone number
String number = p.get("number");
if (StringUtils.isNullOrEmpty(number)) return null;
if (isNullOrEmpty(number)) return null;
// Convert the number into direct dialling form
number = CountryCodes.translate(number, fromIso, toIso);
if (number == null) return null;
@@ -184,7 +187,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
@Override
public void incomingCallConnected() {
LOG.info("Incoming call connected");
callback.incomingConnectionCreated(new ModemTransportConnection());
callback.handleConnection(new ModemTransportConnection());
}
private class ModemTransportConnection

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.plugin.modem;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.reliability.ReliabilityLayerFactory;
import org.briarproject.bramble.util.StringUtils;
@@ -38,7 +38,7 @@ public class ModemPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
// This plugin is not enabled by default
String enabled = callback.getSettings().get("enabled");
if (StringUtils.isNullOrEmpty(enabled)) return null;

View File

@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
@@ -25,7 +25,7 @@ abstract class JavaTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,

View File

@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
@@ -25,7 +25,7 @@ class UnixTorPlugin extends JavaTorPlugin {
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
@@ -40,7 +40,7 @@ class UnixTorPlugin extends JavaTorPlugin {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
int getpid();
}

View File

@@ -6,10 +6,10 @@ import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
@@ -80,7 +80,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
}
@Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(PluginCallback callback) {
// Check that we have a Tor binary for this architecture
String architecture = null;
if (isLinux()) {

View File

@@ -1,10 +1,10 @@
package org.briarproject.bramble.plugin.modem;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
@@ -12,23 +12,29 @@ import java.io.IOException;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class ModemPluginTest extends BrambleTestCase {
public class ModemPluginTest extends BrambleMockTestCase {
private static final String ISO_1336 = "GB";
private static final String NUMBER = "0123456789";
private final ModemFactory modemFactory = context.mock(ModemFactory.class);
private final SerialPortList serialPortList =
context.mock(SerialPortList.class);
private final PluginCallback callback = context.mock(PluginCallback.class);
private final Modem modem = context.mock(Modem.class);
private ModemPlugin plugin;
@Before
public void setUp() {
plugin = new ModemPlugin(modemFactory, serialPortList, callback, 0);
}
@Test
public void testModemCreation() throws Exception {
Mockery context = new Mockery();
ModemFactory modemFactory = context.mock(ModemFactory.class);
SerialPortList serialPortList =
context.mock(SerialPortList.class);
ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, null, 0);
Modem modem = context.mock(Modem.class);
context.checking(new Expectations() {{
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo", "bar", "baz" }));
will(returnValue(new String[] {"foo", "bar", "baz"}));
// First call to createModem() returns false
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
@@ -45,30 +51,22 @@ public class ModemPluginTest extends BrambleTestCase {
oneOf(modem).start();
will(returnValue(true));
}});
plugin.start();
context.assertIsSatisfied();
}
@Test
public void testCreateConnection() throws Exception {
Mockery context = new Mockery();
ModemFactory modemFactory = context.mock(ModemFactory.class);
SerialPortList serialPortList =
context.mock(SerialPortList.class);
DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0);
Modem modem = context.mock(Modem.class);
TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
will(returnValue(new String[] {"foo"}));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
@@ -79,32 +77,24 @@ public class ModemPluginTest extends BrambleTestCase {
oneOf(modem).dial(NUMBER);
will(returnValue(true));
}});
plugin.start();
// A connection should be returned
assertNotNull(plugin.createConnection(remote));
context.assertIsSatisfied();
}
@Test
public void testCreateConnectionWhenDialReturnsFalse() throws Exception {
Mockery context = new Mockery();
ModemFactory modemFactory = context.mock(ModemFactory.class);
SerialPortList serialPortList =
context.mock(SerialPortList.class);
DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0);
Modem modem = context.mock(Modem.class);
TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
will(returnValue(new String[] {"foo"}));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
@@ -115,32 +105,24 @@ public class ModemPluginTest extends BrambleTestCase {
oneOf(modem).dial(NUMBER);
will(returnValue(false));
}});
plugin.start();
// No connection should be returned
assertNull(plugin.createConnection(remote));
context.assertIsSatisfied();
}
@Test
public void testCreateConnectionWhenDialThrowsException() throws Exception {
Mockery context = new Mockery();
ModemFactory modemFactory = context.mock(ModemFactory.class);
SerialPortList serialPortList =
context.mock(SerialPortList.class);
DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
ModemPlugin plugin = new ModemPlugin(modemFactory,
serialPortList, callback, 0);
Modem modem = context.mock(Modem.class);
TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
will(returnValue(new String[] {"foo"}));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
@@ -152,15 +134,15 @@ public class ModemPluginTest extends BrambleTestCase {
will(throwException(new IOException()));
// resetModem()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
will(returnValue(new String[] {"foo"}));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
}});
plugin.start();
// No connection should be returned
assertNull(plugin.createConnection(remote));
context.assertIsSatisfied();
}
}

View File

@@ -127,7 +127,7 @@ public class BridgeTest extends BrambleTestCase {
@Test
public void testBridges() throws Exception {
DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack());
factory.createPlugin(new TestPluginCallback());
assertNotNull(duplexPlugin);
UnixTorPlugin plugin = (UnixTorPlugin) duplexPlugin;

View File

@@ -1,25 +1,15 @@
package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
@NotNullByDefault
public class TorPluginCallBack implements DuplexPluginCallback {
@Override
public void incomingConnectionCreated(DuplexTransportConnection d) {
}
@Override
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {
}
public class TestPluginCallback implements PluginCallback {
@Override
public Settings getSettings() {
@@ -33,22 +23,29 @@ public class TorPluginCallBack implements DuplexPluginCallback {
@Override
public void mergeSettings(Settings s) {
}
@Override
public void mergeLocalProperties(TransportProperties p) {
}
@Override
public void transportEnabled() {
}
@Override
public void transportDisabled() {
}
@Override
public void handleConnection(DuplexTransportConnection c) {
}
@Override
public void handleReader(TransportConnectionReader r) {
}
@Override
public void handleWriter(TransportConnectionWriter w) {
}
}