diff --git a/briar-core/src/org/briarproject/plugins/PluginsModule.java b/briar-core/src/org/briarproject/plugins/PluginsModule.java index 764708512cee7fffef5325222a19450590f617e4..2610b3a932ffa2ee5bd879c7342e84e200ee234c 100644 --- a/briar-core/src/org/briarproject/plugins/PluginsModule.java +++ b/briar-core/src/org/briarproject/plugins/PluginsModule.java @@ -7,12 +7,10 @@ import org.briarproject.api.plugins.BackoffFactory; import org.briarproject.api.plugins.ConnectionManager; import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.PluginManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.transport.KeyManager; -import org.briarproject.api.transport.StreamReaderFactory; -import org.briarproject.api.transport.StreamWriterFactory; +import java.security.SecureRandom; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import javax.inject.Singleton; @@ -37,32 +35,34 @@ public class PluginsModule { @Provides @Singleton - Poller providePoller(EventBus eventBus, PollerImpl poller) { + Poller providePoller(@IoExecutor Executor ioExecutor, + ScheduledExecutorService scheduler, + ConnectionManager connectionManager, + ConnectionRegistry connectionRegistry, PluginManager pluginManager, + SecureRandom random, EventBus eventBus) { + Poller poller = new Poller(ioExecutor, scheduler, connectionManager, + connectionRegistry, pluginManager, random); eventBus.addListener(poller); return poller; } @Provides + @Singleton ConnectionManager provideConnectionManager( - @IoExecutor Executor ioExecutor, KeyManager keyManager, - StreamReaderFactory streamReaderFactory, - StreamWriterFactory streamWriterFactory, - SyncSessionFactory syncSessionFactory, - ConnectionRegistry connectionRegistry) { - return new ConnectionManagerImpl(ioExecutor, keyManager, - streamReaderFactory, streamWriterFactory, syncSessionFactory, - connectionRegistry); + ConnectionManagerImpl connectionManager) { + return connectionManager; } @Provides @Singleton - ConnectionRegistry provideConnectionRegistry(EventBus eventBus) { - return new ConnectionRegistryImpl(eventBus); + ConnectionRegistry provideConnectionRegistry( + ConnectionRegistryImpl connectionRegistry) { + return connectionRegistry; } @Provides @Singleton - PluginManager getPluginManager(LifecycleManager lifecycleManager, + PluginManager providePluginManager(LifecycleManager lifecycleManager, PluginManagerImpl pluginManager) { lifecycleManager.registerService(pluginManager); return pluginManager; diff --git a/briar-core/src/org/briarproject/plugins/Poller.java b/briar-core/src/org/briarproject/plugins/Poller.java index c344935ffc16181a5c456a40fcb91e458078ecb1..557e7ad09702ee70fdbc3351a85d85dd0ac55e78 100644 --- a/briar-core/src/org/briarproject/plugins/Poller.java +++ b/briar-core/src/org/briarproject/plugins/Poller.java @@ -1,6 +1,173 @@ package org.briarproject.plugins; -interface Poller { +import org.briarproject.api.TransportId; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.event.ConnectionClosedEvent; +import org.briarproject.api.event.ContactStatusChangedEvent; +import org.briarproject.api.event.Event; +import org.briarproject.api.event.EventListener; +import org.briarproject.api.event.TransportEnabledEvent; +import org.briarproject.api.lifecycle.IoExecutor; +import org.briarproject.api.plugins.ConnectionManager; +import org.briarproject.api.plugins.ConnectionRegistry; +import org.briarproject.api.plugins.Plugin; +import org.briarproject.api.plugins.PluginManager; +import org.briarproject.api.plugins.TransportConnectionWriter; +import org.briarproject.api.plugins.duplex.DuplexPlugin; +import org.briarproject.api.plugins.duplex.DuplexTransportConnection; +import org.briarproject.api.plugins.simplex.SimplexPlugin; - // TODO: Remove this interface +import java.security.SecureRandom; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.logging.Level.INFO; + +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 SecureRandom random; + private final Map<TransportId, PollTask> tasks; + + @Inject + Poller(@IoExecutor Executor ioExecutor, ScheduledExecutorService scheduler, + ConnectionManager connectionManager, + ConnectionRegistry connectionRegistry, PluginManager pluginManager, + SecureRandom random) { + this.ioExecutor = ioExecutor; + this.connectionManager = connectionManager; + this.connectionRegistry = connectionRegistry; + this.pluginManager = pluginManager; + this.random = random; + this.scheduler = scheduler; + tasks = new ConcurrentHashMap<TransportId, PollTask>(); + } + + @Override + public void eventOccurred(Event e) { + if (e instanceof ContactStatusChangedEvent) { + ContactStatusChangedEvent c = (ContactStatusChangedEvent) e; + if (c.isActive()) { + // Connect to the newly activated contact + connectToContact(c.getContactId()); + } + } else if (e instanceof ConnectionClosedEvent) { + ConnectionClosedEvent c = (ConnectionClosedEvent) e; + if (!c.isIncoming()) { + // Connect to the disconnected contact + connectToContact(c.getContactId(), c.getTransportId()); + } + } else if (e instanceof TransportEnabledEvent) { + TransportEnabledEvent t = (TransportEnabledEvent) e; + pollNow(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(final ContactId c, final SimplexPlugin p) { + ioExecutor.execute(new Runnable() { + @Override + public void run() { + TransportId t = p.getId(); + if (!connectionRegistry.isConnected(c, t)) { + TransportConnectionWriter w = p.createWriter(c); + if (w != null) + connectionManager.manageOutgoingConnection(c, t, w); + } + } + }); + } + + private void connectToContact(final ContactId c, final DuplexPlugin p) { + ioExecutor.execute(new Runnable() { + @Override + public void run() { + TransportId t = p.getId(); + if (!connectionRegistry.isConnected(c, t)) { + DuplexTransportConnection d = p.createConnection(c); + if (d != null) + connectionManager.manageOutgoingConnection(c, t, d); + } + } + }); + } + + private void pollNow(TransportId t) { + Plugin p = pluginManager.getPlugin(t); + // Randomise next polling interval + if (p.shouldPoll()) schedule(p, 0, true); + } + + private void schedule(Plugin p, int interval, boolean randomiseNext) { + // Replace any previously scheduled task for this plugin + PollTask task = new PollTask(p, randomiseNext); + PollTask replaced = tasks.put(p.getId(), task); + if (replaced != null) replaced.cancel(); + scheduler.schedule(task, interval, MILLISECONDS); + } + + private void poll(final Plugin p) { + ioExecutor.execute(new Runnable() { + @Override + public void run() { + if (LOG.isLoggable(INFO)) + LOG.info("Polling " + p.getClass().getSimpleName()); + p.poll(connectionRegistry.getConnectedContacts(p.getId())); + } + }); + } + + private class PollTask implements Runnable { + + private final Plugin plugin; + private final boolean randomiseNext; + + private volatile boolean cancelled = false; + + private PollTask(Plugin plugin, boolean randomiseNext) { + this.plugin = plugin; + this.randomiseNext = randomiseNext; + } + + private void cancel() { + cancelled = true; + } + + @Override + public void run() { + if (cancelled) return; + tasks.remove(plugin.getId()); + int interval = plugin.getPollingInterval(); + if (randomiseNext) + interval = (int) (interval * random.nextDouble()); + schedule(plugin, interval, false); + poll(plugin); + } + } } diff --git a/briar-core/src/org/briarproject/plugins/PollerImpl.java b/briar-core/src/org/briarproject/plugins/PollerImpl.java deleted file mode 100644 index 32f54129d2fc4fe5c241889dc83fcf85a2bbda07..0000000000000000000000000000000000000000 --- a/briar-core/src/org/briarproject/plugins/PollerImpl.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.briarproject.plugins; - -import org.briarproject.api.TransportId; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.event.ConnectionClosedEvent; -import org.briarproject.api.event.ContactStatusChangedEvent; -import org.briarproject.api.event.Event; -import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.TransportEnabledEvent; -import org.briarproject.api.lifecycle.IoExecutor; -import org.briarproject.api.plugins.ConnectionManager; -import org.briarproject.api.plugins.ConnectionRegistry; -import org.briarproject.api.plugins.Plugin; -import org.briarproject.api.plugins.PluginManager; -import org.briarproject.api.plugins.TransportConnectionWriter; -import org.briarproject.api.plugins.duplex.DuplexPlugin; -import org.briarproject.api.plugins.duplex.DuplexTransportConnection; -import org.briarproject.api.plugins.simplex.SimplexPlugin; - -import java.security.SecureRandom; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; -import java.util.logging.Logger; - -import javax.inject.Inject; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.logging.Level.INFO; - -class PollerImpl implements Poller, EventListener { - - private static final Logger LOG = - Logger.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 SecureRandom random; - private final Map<TransportId, PollTask> tasks; - - @Inject - PollerImpl(@IoExecutor Executor ioExecutor, - ScheduledExecutorService scheduler, - ConnectionManager connectionManager, - ConnectionRegistry connectionRegistry, PluginManager pluginManager, - SecureRandom random) { - this.ioExecutor = ioExecutor; - this.connectionManager = connectionManager; - this.connectionRegistry = connectionRegistry; - this.pluginManager = pluginManager; - this.random = random; - this.scheduler = scheduler; - tasks = new ConcurrentHashMap<TransportId, PollTask>(); - } - - - @Override - public void eventOccurred(Event e) { - if (e instanceof ContactStatusChangedEvent) { - ContactStatusChangedEvent c = (ContactStatusChangedEvent) e; - if (c.isActive()) { - // Connect to the newly activated contact - connectToContact(c.getContactId()); - } - } else if (e instanceof ConnectionClosedEvent) { - ConnectionClosedEvent c = (ConnectionClosedEvent) e; - if (!c.isIncoming()) { - // Connect to the disconnected contact - connectToContact(c.getContactId(), c.getTransportId()); - } - } else if (e instanceof TransportEnabledEvent) { - TransportEnabledEvent t = (TransportEnabledEvent) e; - Plugin p = pluginManager.getPlugin(t.getTransportId()); - if (p.shouldPoll()) pollNow(p); - } - } - - 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(final ContactId c, final SimplexPlugin p) { - ioExecutor.execute(new Runnable() { - @Override - public void run() { - TransportId t = p.getId(); - if (!connectionRegistry.isConnected(c, t)) { - TransportConnectionWriter w = p.createWriter(c); - if (w != null) - connectionManager.manageOutgoingConnection(c, t, w); - } - } - }); - } - - private void connectToContact(final ContactId c, final DuplexPlugin p) { - ioExecutor.execute(new Runnable() { - @Override - public void run() { - TransportId t = p.getId(); - if (!connectionRegistry.isConnected(c, t)) { - DuplexTransportConnection d = p.createConnection(c); - if (d != null) - connectionManager.manageOutgoingConnection(c, t, d); - } - } - }); - } - - private void pollNow(Plugin p) { - // Randomise next polling interval - schedule(p, 0, true); - } - - private void schedule(Plugin p, int interval, boolean randomiseNext) { - // Replace any previously scheduled task for this plugin - PollTask task = new PollTask(p, randomiseNext); - PollTask replaced = tasks.put(p.getId(), task); - if (replaced != null) replaced.cancel(); - scheduler.schedule(task, interval, MILLISECONDS); - } - - private void poll(final Plugin p) { - ioExecutor.execute(new Runnable() { - @Override - public void run() { - if (LOG.isLoggable(INFO)) - LOG.info("Polling " + p.getClass().getSimpleName()); - p.poll(connectionRegistry.getConnectedContacts(p.getId())); - } - }); - } - - private class PollTask implements Runnable { - - private final Plugin plugin; - private final boolean randomiseNext; - - private volatile boolean cancelled = false; - - private PollTask(Plugin plugin, boolean randomiseNext) { - this.plugin = plugin; - this.randomiseNext = randomiseNext; - } - - private void cancel() { - cancelled = true; - } - - @Override - public void run() { - if (cancelled) return; - tasks.remove(plugin.getId()); - int interval = plugin.getPollingInterval(); - if (randomiseNext) - interval = (int) (interval * random.nextDouble()); - schedule(plugin, interval, false); - poll(plugin); - } - } -} diff --git a/briar-tests/src/org/briarproject/plugins/PollerImplTest.java b/briar-tests/src/org/briarproject/plugins/PollerTest.java similarity index 96% rename from briar-tests/src/org/briarproject/plugins/PollerImplTest.java rename to briar-tests/src/org/briarproject/plugins/PollerTest.java index 0093d85de5ad4cdaadb5ec80731255608fea9382..69af841d5048a1448e43ddda61c1ca64bd06af62 100644 --- a/briar-tests/src/org/briarproject/plugins/PollerImplTest.java +++ b/briar-tests/src/org/briarproject/plugins/PollerTest.java @@ -30,7 +30,7 @@ import java.util.concurrent.ScheduledExecutorService; import static java.util.concurrent.TimeUnit.MILLISECONDS; -public class PollerImplTest extends BriarTestCase { +public class PollerTest extends BriarTestCase { private final ContactId contactId = new ContactId(234); @@ -111,7 +111,7 @@ public class PollerImplTest extends BriarTestCase { will(returnValue(false)); }}); - PollerImpl p = new PollerImpl(ioExecutor, scheduler, connectionManager, + Poller p = new Poller(ioExecutor, scheduler, connectionManager, connectionRegistry, pluginManager, random); p.eventOccurred(new ContactStatusChangedEvent(contactId, true)); @@ -158,7 +158,7 @@ public class PollerImplTest extends BriarTestCase { transportId, duplexConnection); }}); - PollerImpl p = new PollerImpl(ioExecutor, scheduler, connectionManager, + Poller p = new Poller(ioExecutor, scheduler, connectionManager, connectionRegistry, pluginManager, random); p.eventOccurred(new ConnectionClosedEvent(contactId, transportId, @@ -212,7 +212,7 @@ public class PollerImplTest extends BriarTestCase { oneOf(plugin).poll(connected); }}); - PollerImpl p = new PollerImpl(ioExecutor, scheduler, connectionManager, + Poller p = new Poller(ioExecutor, scheduler, connectionManager, connectionRegistry, pluginManager, random); p.eventOccurred(new TransportEnabledEvent(transportId));