diff --git a/api/net/sf/briar/api/transport/ConnectionRecogniser.java b/api/net/sf/briar/api/transport/ConnectionRecogniser.java index 01bd760beda392edcb94f4076ddf5005aa95ff1f..dc12799b3c239f40da49624245c68a4c7099bc0c 100644 --- a/api/net/sf/briar/api/transport/ConnectionRecogniser.java +++ b/api/net/sf/briar/api/transport/ConnectionRecogniser.java @@ -10,9 +10,18 @@ import net.sf.briar.api.protocol.TransportId; public interface ConnectionRecogniser { /** - * Returns the connection's context if the connection should be accepted, - * or null if the connection should be rejected. + * Asynchronously calls one of the callback's connectionAccepted(), + * connectionRejected() or handleException() methods. */ - ConnectionContext acceptConnection(TransportId t, byte[] encryptedIv) - throws DbException; + void acceptConnection(TransportId t, byte[] encryptedIv, + Callback c); + + interface Callback { + + void connectionAccepted(ConnectionContext ctx); + + void connectionRejected(); + + void handleException(DbException e); + } } diff --git a/components/net/sf/briar/plugins/PluginManagerImpl.java b/components/net/sf/briar/plugins/PluginManagerImpl.java index f7d28c45004a8da44c54e1a9b881b55b337bbbf5..3f6de4a0ff98e5b243ea884c0ebe8736bd6afd93 100644 --- a/components/net/sf/briar/plugins/PluginManagerImpl.java +++ b/components/net/sf/briar/plugins/PluginManagerImpl.java @@ -8,7 +8,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.logging.Level; import java.util.logging.Logger; @@ -51,24 +50,22 @@ class PluginManagerImpl implements PluginManager { "net.sf.briar.plugins.socket.SimpleSocketPluginFactory" }; - private static final int THREAD_POOL_SIZE = 5; - private final DatabaseComponent db; + private final Executor executor; private final Poller poller; private final ConnectionDispatcher dispatcher; private final UiCallback uiCallback; - private final Executor executor; private final List<BatchPlugin> batchPlugins; private final List<StreamPlugin> streamPlugins; @Inject - PluginManagerImpl(DatabaseComponent db, Poller poller, + PluginManagerImpl(DatabaseComponent db, Executor executor, Poller poller, ConnectionDispatcher dispatcher, UiCallback uiCallback) { this.db = db; + this.executor = executor; this.poller = poller; this.dispatcher = dispatcher; this.uiCallback = uiCallback; - executor = new ScheduledThreadPoolExecutor(THREAD_POOL_SIZE); batchPlugins = new ArrayList<BatchPlugin>(); streamPlugins = new ArrayList<StreamPlugin>(); } diff --git a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java index e93a44fe6b0a7a091cc92ee73190400b8258e6d3..adbb5ad45d85091287a93198c26eca1fae1f29da 100644 --- a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java +++ b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java @@ -15,6 +15,7 @@ import net.sf.briar.api.transport.BatchTransportWriter; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionDispatcher; import net.sf.briar.api.transport.ConnectionRecogniser; +import net.sf.briar.api.transport.ConnectionRecogniser.Callback; import net.sf.briar.api.transport.StreamConnectionFactory; import net.sf.briar.api.transport.StreamTransportConnection; import net.sf.briar.api.transport.TransportConstants; @@ -39,9 +40,9 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher { this.streamConnFactory = streamConnFactory; } - public void dispatchReader(TransportId t, BatchTransportReader r) { + public void dispatchReader(TransportId t, final BatchTransportReader r) { // Read the encrypted IV - byte[] encryptedIv; + final byte[] encryptedIv; try { encryptedIv = readIv(r.getInputStream()); } catch(IOException e) { @@ -49,20 +50,22 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher { r.dispose(false); return; } - // Get the connection context, or null if the IV wasn't expected - ConnectionContext ctx; - try { - ctx = recogniser.acceptConnection(t, encryptedIv); - } catch(DbException e) { - if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); - r.dispose(false); - return; - } - if(ctx == null) { - r.dispose(false); - return; - } - batchConnFactory.createIncomingConnection(ctx, r, encryptedIv); + // Get the connection context asynchronously + recogniser.acceptConnection(t, encryptedIv, new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + batchConnFactory.createIncomingConnection(ctx, r, encryptedIv); + } + + public void connectionRejected() { + r.dispose(false); + } + + public void handleException(DbException e) { + if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); + r.dispose(false); + } + }); } private byte[] readIv(InputStream in) throws IOException { @@ -82,9 +85,9 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher { } public void dispatchIncomingConnection(TransportId t, - StreamTransportConnection s) { + final StreamTransportConnection s) { // Read the encrypted IV - byte[] encryptedIv; + final byte[] encryptedIv; try { encryptedIv = readIv(s.getInputStream()); } catch(IOException e) { @@ -92,20 +95,22 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher { s.dispose(false); return; } - // Get the connection context, or null if the IV wasn't expected - ConnectionContext ctx; - try { - ctx = recogniser.acceptConnection(t, encryptedIv); - } catch(DbException e) { - if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); - s.dispose(false); - return; - } - if(ctx == null) { - s.dispose(false); - return; - } - streamConnFactory.createIncomingConnection(ctx, s, encryptedIv); + // Get the connection context asynchronously + recogniser.acceptConnection(t, encryptedIv, new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + streamConnFactory.createIncomingConnection(ctx, s, encryptedIv); + } + + public void connectionRejected() { + s.dispose(false); + } + + public void handleException(DbException e) { + if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); + s.dispose(false); + } + }); } public void dispatchOutgoingConnection(ContactId c, TransportIndex i, diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java index 4fac2b3544c543b8b99ee7feac07930c46e1fc1c..44825a42558d090f101132bead3366f1b94306a8 100644 --- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java +++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; @@ -31,7 +32,6 @@ import net.sf.briar.api.db.event.TransportAddedEvent; import net.sf.briar.api.protocol.Transport; import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportIndex; -import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionRecogniser; import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.util.ByteUtils; @@ -46,6 +46,7 @@ DatabaseListener { private final CryptoComponent crypto; private final DatabaseComponent db; + private final Executor executor; private final Cipher ivCipher; private final Map<Bytes, Context> expected; private final Collection<TransportId> localTransportIds; @@ -53,9 +54,11 @@ DatabaseListener { private boolean initialised = false; @Inject - ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db) { + ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db, + Executor executor) { this.crypto = crypto; this.db = db; + this.executor = executor; ivCipher = crypto.getIvCipher(); expected = new HashMap<Bytes, Context>(); localTransportIds = new ArrayList<TransportId>(); @@ -63,6 +66,12 @@ DatabaseListener { } private synchronized void initialise() throws DbException { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + eraseSecrets(); + } + }); for(Transport t : db.getLocalTransports()) { localTransportIds.add(t.getId()); } @@ -73,12 +82,6 @@ DatabaseListener { // The contact was removed - clean up in eventOccurred() } } - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - eraseSecrets(); - } - }); initialised = true; } @@ -125,36 +128,53 @@ DatabaseListener { } } - public synchronized ConnectionContext acceptConnection(TransportId t, - byte[] encryptedIv) throws DbException { - if(encryptedIv.length != IV_LENGTH) - throw new IllegalArgumentException(); - if(!initialised) initialise(); - Bytes b = new Bytes(encryptedIv); - Context ctx = expected.get(b); - // If the IV was not expected by this transport, reject the connection - if(ctx == null || !ctx.transportId.equals(t)) return null; - expected.remove(b); - ContactId c = ctx.contactId; - TransportIndex i = ctx.transportIndex; - long connection = ctx.connection; - ConnectionWindow w = ctx.window; - // Get the secret and update the connection window - byte[] secret = w.setSeen(connection); + public void acceptConnection(final TransportId t, final byte[] encryptedIv, + final Callback callback) { + executor.execute(new Runnable() { + public void run() { + acceptConnectionSync(t, encryptedIv, callback); + } + }); + } + + private synchronized void acceptConnectionSync(TransportId t, + byte[] encryptedIv, Callback callback) { try { - db.setConnectionWindow(c, i, w); - } catch(NoSuchContactException e) { - // The contact was removed - clean up when we get the event - } - // Update the set of expected IVs - Iterator<Context> it = expected.values().iterator(); - while(it.hasNext()) { - Context ctx1 = it.next(); - if(ctx1.contactId.equals(c) && ctx1.transportIndex.equals(i)) - it.remove(); + if(encryptedIv.length != IV_LENGTH) + throw new IllegalArgumentException(); + if(!initialised) initialise(); + Bytes b = new Bytes(encryptedIv); + Context ctx = expected.get(b); + if(ctx == null || !ctx.transportId.equals(t)) { + callback.connectionRejected(); + return; + } + // The IV was expected + expected.remove(b); + ContactId c = ctx.contactId; + TransportIndex i = ctx.transportIndex; + long connection = ctx.connection; + ConnectionWindow w = ctx.window; + // Get the secret and update the connection window + byte[] secret = w.setSeen(connection); + try { + db.setConnectionWindow(c, i, w); + } catch(NoSuchContactException e) { + // The contact was removed - clean up in eventOccurred() + } + // Update the set of expected IVs + Iterator<Context> it = expected.values().iterator(); + while(it.hasNext()) { + Context ctx1 = it.next(); + if(ctx1.contactId.equals(c) && ctx1.transportIndex.equals(i)) + it.remove(); + } + calculateIvs(c, t, i, w); + callback.connectionAccepted(new ConnectionContextImpl(c, i, + connection, secret)); + } catch(DbException e) { + callback.handleException(e); } - calculateIvs(c, t, i, w); - return new ConnectionContextImpl(c, i, connection, secret); } public void eventOccurred(DatabaseEvent e) { diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java index add29b25683a9a9751afa885bc42dda28ac6e3f8..c2d875726c6fc402f9fad08d019de8006ae1bc0a 100644 --- a/test/net/sf/briar/ProtocolIntegrationTest.java +++ b/test/net/sf/briar/ProtocolIntegrationTest.java @@ -14,6 +14,8 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledThreadPoolExecutor; import junit.framework.TestCase; import net.sf.briar.api.ContactId; @@ -62,8 +64,10 @@ import net.sf.briar.transport.stream.TransportStreamModule; import org.bouncycastle.util.Arrays; import org.junit.Test; +import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Module; public class ProtocolIntegrationTest extends TestCase { @@ -90,7 +94,14 @@ public class ProtocolIntegrationTest extends TestCase { public ProtocolIntegrationTest() throws Exception { super(); - Injector i = Guice.createInjector(new CryptoModule(), + Module testModule = new AbstractModule() { + @Override + public void configure() { + bind(Executor.class).toInstance( + new ScheduledThreadPoolExecutor(5)); + } + }; + Injector i = Guice.createInjector(testModule, new CryptoModule(), new DatabaseModule(), new ProtocolModule(), new ProtocolWritersModule(), new SerialModule(), new TestDatabaseModule(), new TransportBatchModule(), diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java index 60ff32646b7680c0b7b0988b1d564963441e4330..dcb4062ea55d3c953b676fcad1394eab5585c5fd 100644 --- a/test/net/sf/briar/db/H2DatabaseTest.java +++ b/test/net/sf/briar/db/H2DatabaseTest.java @@ -13,6 +13,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Random; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -54,8 +56,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Module; public class H2DatabaseTest extends TestCase { @@ -93,7 +97,14 @@ public class H2DatabaseTest extends TestCase { public H2DatabaseTest() throws Exception { super(); - Injector i = Guice.createInjector(new CryptoModule(), + Module testModule = new AbstractModule() { + @Override + public void configure() { + bind(Executor.class).toInstance( + new ScheduledThreadPoolExecutor(5)); + } + }; + Injector i = Guice.createInjector(testModule, new CryptoModule(), new DatabaseModule(), new ProtocolModule(), new ProtocolWritersModule(), new SerialModule(), new TransportBatchModule(), new TransportModule(), diff --git a/test/net/sf/briar/plugins/PluginManagerImplTest.java b/test/net/sf/briar/plugins/PluginManagerImplTest.java index a9f89b050dc5e3fef122bd57cf98911c30a8b8e8..0a1b4693ff88dd152693fcdc11a458c67541c17d 100644 --- a/test/net/sf/briar/plugins/PluginManagerImplTest.java +++ b/test/net/sf/briar/plugins/PluginManagerImplTest.java @@ -1,5 +1,6 @@ package net.sf.briar.plugins; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; @@ -36,9 +37,10 @@ public class PluginManagerImplTest extends TestCase { allowing(db).setLocalProperties(with(any(TransportId.class)), with(any(TransportProperties.class))); }}); + Executor executor = new ImmediateExecutor(); Poller poller = new PollerImpl(); - PluginManagerImpl p = new PluginManagerImpl(db, poller, dispatcher, - uiCallback); + PluginManagerImpl p = new PluginManagerImpl(db, executor, poller, + dispatcher, uiCallback); // The Bluetooth plugin will not start without a Bluetooth device, so // we expect two plugins to be started assertEquals(2, p.startPlugins()); diff --git a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java index 87eacbd7f95f3454f27d04674b41fbc227e58643..560fda09bd30529e2d45adf71cb8d1ea66931dbb 100644 --- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java +++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Random; +import java.util.concurrent.Executor; import javax.crypto.Cipher; @@ -15,12 +16,16 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.api.db.DatabaseComponent; +import net.sf.briar.api.db.DbException; import net.sf.briar.api.protocol.Transport; import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportIndex; import net.sf.briar.api.transport.ConnectionContext; +import net.sf.briar.api.transport.ConnectionRecogniser; +import net.sf.briar.api.transport.ConnectionRecogniser.Callback; import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.crypto.CryptoModule; +import net.sf.briar.plugins.ImmediateExecutor; import org.jmock.Expectations; import org.jmock.Mockery; @@ -72,9 +77,22 @@ public class ConnectionRecogniserImplTest extends TestCase { oneOf(db).getConnectionWindow(contactId, remoteIndex); will(returnValue(connectionWindow)); }}); - final ConnectionRecogniserImpl c = - new ConnectionRecogniserImpl(crypto, db); - assertNull(c.acceptConnection(transportId, new byte[IV_LENGTH])); + Executor e = new ImmediateExecutor(); + ConnectionRecogniser c = new ConnectionRecogniserImpl(crypto, db, e); + c.acceptConnection(transportId, new byte[IV_LENGTH], new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + fail(); + } + + public void connectionRejected() { + // Expected + } + + public void handleException(DbException e) { + fail(); + } + }); context.assertIsSatisfied(); } @@ -109,19 +127,57 @@ public class ConnectionRecogniserImplTest extends TestCase { oneOf(db).setConnectionWindow(contactId, remoteIndex, connectionWindow); }}); - final ConnectionRecogniserImpl c = - new ConnectionRecogniserImpl(crypto, db); + Executor e = new ImmediateExecutor(); + ConnectionRecogniser c = new ConnectionRecogniserImpl(crypto, db, e); // The IV should not be expected by the wrong transport TransportId wrong = new TransportId(TestUtils.getRandomId()); - assertNull(c.acceptConnection(wrong, encryptedIv)); + c.acceptConnection(wrong, encryptedIv, new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + fail(); + } + + public void connectionRejected() { + // Expected + } + + public void handleException(DbException e) { + fail(); + } + }); // The IV should be expected by the right transport - ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv); - assertNotNull(ctx); - assertEquals(contactId, ctx.getContactId()); - assertEquals(remoteIndex, ctx.getTransportIndex()); - assertEquals(3L, ctx.getConnectionNumber()); + c.acceptConnection(transportId, encryptedIv, new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + assertNotNull(ctx); + assertEquals(contactId, ctx.getContactId()); + assertEquals(remoteIndex, ctx.getTransportIndex()); + assertEquals(3L, ctx.getConnectionNumber()); + } + + public void connectionRejected() { + fail(); + } + + public void handleException(DbException e) { + fail(); + } + }); // The IV should no longer be expected - assertNull(c.acceptConnection(transportId, encryptedIv)); + c.acceptConnection(transportId, encryptedIv, new Callback() { + + public void connectionAccepted(ConnectionContext ctx) { + fail(); + } + + public void connectionRejected() { + // Expected + } + + public void handleException(DbException e) { + fail(); + } + }); // The window should have advanced Map<Long, byte[]> unseen = connectionWindow.getUnseen(); assertEquals(19, unseen.size()); diff --git a/test/net/sf/briar/transport/ConnectionWriterTest.java b/test/net/sf/briar/transport/ConnectionWriterTest.java index 9e7290316a3a036505777dfc0d2e41ec517ecef7..416943b3d001c3b6c434e07c8f38782569c79f3e 100644 --- a/test/net/sf/briar/transport/ConnectionWriterTest.java +++ b/test/net/sf/briar/transport/ConnectionWriterTest.java @@ -5,6 +5,8 @@ import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGT import java.io.ByteArrayOutputStream; import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledThreadPoolExecutor; import junit.framework.TestCase; import net.sf.briar.TestDatabaseModule; @@ -24,8 +26,10 @@ import net.sf.briar.transport.stream.TransportStreamModule; import org.junit.Test; +import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Module; public class ConnectionWriterTest extends TestCase { @@ -38,7 +42,14 @@ public class ConnectionWriterTest extends TestCase { public ConnectionWriterTest() throws Exception { super(); - Injector i = Guice.createInjector(new CryptoModule(), + Module testModule = new AbstractModule() { + @Override + public void configure() { + bind(Executor.class).toInstance( + new ScheduledThreadPoolExecutor(5)); + } + }; + Injector i = Guice.createInjector(testModule, new CryptoModule(), new DatabaseModule(), new ProtocolModule(), new ProtocolWritersModule(), new SerialModule(), new TestDatabaseModule(), new TransportBatchModule(), diff --git a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java index 0eab9d978f592a1e0916c1a15472cbab8217f1a2..14bf846af9e4b7a3f2dce4c24580f3b7d2356c7b 100644 --- a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java +++ b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java @@ -10,12 +10,16 @@ import java.io.OutputStream; import java.util.Collection; import java.util.Collections; import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledThreadPoolExecutor; import junit.framework.TestCase; import net.sf.briar.TestDatabaseModule; import net.sf.briar.TestUtils; import net.sf.briar.api.ContactId; import net.sf.briar.api.db.DatabaseComponent; +import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.event.DatabaseEvent; import net.sf.briar.api.db.event.DatabaseListener; import net.sf.briar.api.db.event.MessagesAddedEvent; @@ -32,6 +36,7 @@ import net.sf.briar.api.transport.BatchTransportWriter; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.ConnectionReaderFactory; import net.sf.briar.api.transport.ConnectionRecogniser; +import net.sf.briar.api.transport.ConnectionRecogniser.Callback; import net.sf.briar.api.transport.ConnectionWriterFactory; import net.sf.briar.crypto.CryptoModule; import net.sf.briar.db.DatabaseModule; @@ -45,8 +50,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Module; public class BatchConnectionReadWriteTest extends TestCase { @@ -75,17 +82,31 @@ public class BatchConnectionReadWriteTest extends TestCase { public void setUp() { testDir.mkdirs(); // Create Alice's injector - alice = Guice.createInjector(new CryptoModule(), new DatabaseModule(), - new ProtocolModule(), new ProtocolWritersModule(), - new SerialModule(), new TestDatabaseModule(aliceDir), - new TransportBatchModule(), new TransportModule(), - new TransportStreamModule()); + Module aliceTestModule = new AbstractModule() { + @Override + public void configure() { + bind(Executor.class).toInstance( + new ScheduledThreadPoolExecutor(5)); + } + }; + alice = Guice.createInjector(aliceTestModule, new CryptoModule(), + new DatabaseModule(), new ProtocolModule(), + new ProtocolWritersModule(), new SerialModule(), + new TestDatabaseModule(aliceDir), new TransportBatchModule(), + new TransportModule(), new TransportStreamModule()); // Create Bob's injector - bob = Guice.createInjector(new CryptoModule(), new DatabaseModule(), - new ProtocolModule(), new ProtocolWritersModule(), - new SerialModule(), new TestDatabaseModule(bobDir), - new TransportBatchModule(), new TransportModule(), - new TransportStreamModule()); + Module bobTestModule = new AbstractModule() { + @Override + public void configure() { + bind(Executor.class).toInstance( + new ScheduledThreadPoolExecutor(5)); + } + }; + bob = Guice.createInjector(bobTestModule, new CryptoModule(), + new DatabaseModule(), new ProtocolModule(), + new ProtocolWritersModule(), new SerialModule(), + new TestDatabaseModule(bobDir), new TransportBatchModule(), + new TransportModule(), new TransportStreamModule()); } @Test @@ -159,7 +180,10 @@ public class BatchConnectionReadWriteTest extends TestCase { byte[] encryptedIv = new byte[IV_LENGTH]; int read = in.read(encryptedIv); assertEquals(encryptedIv.length, read); - ConnectionContext ctx = rec.acceptConnection(transportId, encryptedIv); + TestCallback callback = new TestCallback(); + rec.acceptConnection(transportId, encryptedIv, callback); + callback.latch.await(); + ConnectionContext ctx = callback.ctx; assertNotNull(ctx); assertEquals(contactId, ctx.getContactId()); assertEquals(transportIndex, ctx.getTransportIndex()); @@ -234,4 +258,25 @@ public class BatchConnectionReadWriteTest extends TestCase { assertTrue(success); } } + + private static class TestCallback implements Callback { + + private final CountDownLatch latch = new CountDownLatch(1); + private ConnectionContext ctx = null; + + public void connectionAccepted(ConnectionContext ctx) { + this.ctx = ctx; + latch.countDown(); + } + + public void connectionRejected() { + fail(); + latch.countDown(); + } + + public void handleException(DbException e) { + fail(); + latch.countDown(); + } + } }