diff --git a/api/net/sf/briar/api/ContactTransport.java b/api/net/sf/briar/api/db/ContactTransport.java similarity index 54% rename from api/net/sf/briar/api/ContactTransport.java rename to api/net/sf/briar/api/db/ContactTransport.java index c1d25893fe099fee92d4c48cc56ac054f2663831..90fd11f33e34b7e80dcaa048edc2fe6b74940549 100644 --- a/api/net/sf/briar/api/ContactTransport.java +++ b/api/net/sf/briar/api/db/ContactTransport.java @@ -1,23 +1,33 @@ -package net.sf.briar.api; +package net.sf.briar.api.db; +import net.sf.briar.api.ContactId; import net.sf.briar.api.protocol.TransportId; -public class ContactTransport extends TemporarySecret { +public class ContactTransport { + private final ContactId contactId; + private final TransportId transportId; private final long epoch, clockDiff, latency; private final boolean alice; public ContactTransport(ContactId contactId, TransportId transportId, - long epoch, long clockDiff, long latency, boolean alice, - long period, byte[] secret, long outgoing, long centre, - byte[] bitmap) { - super(contactId, transportId, period, secret, outgoing, centre, bitmap); + long epoch, long clockDiff, long latency, boolean alice) { + this.contactId = contactId; + this.transportId = transportId; this.epoch = epoch; this.clockDiff = clockDiff; this.latency = latency; this.alice = alice; } + public ContactId getContactId() { + return contactId; + } + + public TransportId getTransportId() { + return transportId; + } + public long getEpoch() { return epoch; } diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java index 2581773ec36f927669361162861dc741d0673ce0..b5af41229dc560d4a458f4364d492cd55549bc4a 100644 --- a/api/net/sf/briar/api/db/DatabaseComponent.java +++ b/api/net/sf/briar/api/db/DatabaseComponent.java @@ -5,9 +5,7 @@ import java.util.Collection; import java.util.Map; import net.sf.briar.api.ContactId; -import net.sf.briar.api.ContactTransport; import net.sf.briar.api.Rating; -import net.sf.briar.api.TemporarySecret; import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.db.event.DatabaseListener; diff --git a/api/net/sf/briar/api/TemporarySecret.java b/api/net/sf/briar/api/db/TemporarySecret.java similarity index 78% rename from api/net/sf/briar/api/TemporarySecret.java rename to api/net/sf/briar/api/db/TemporarySecret.java index 2ea4f26ccf38a5c0f6cb1ffacb9279fc66e839d3..08455e32520580e9e6c09afa02016829fb714499 100644 --- a/api/net/sf/briar/api/TemporarySecret.java +++ b/api/net/sf/briar/api/db/TemporarySecret.java @@ -1,13 +1,14 @@ -package net.sf.briar.api; +package net.sf.briar.api.db; +import net.sf.briar.api.ContactId; import net.sf.briar.api.protocol.TransportId; public class TemporarySecret { - protected final ContactId contactId; - protected final TransportId transportId; - protected final long period, outgoing, centre; - protected final byte[] secret, bitmap; + private final ContactId contactId; + private final TransportId transportId; + private final long period, outgoing, centre; + private final byte[] secret, bitmap; public TemporarySecret(ContactId contactId, TransportId transportId, long period, byte[] secret, long outgoing, long centre, diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java index 75a6bd15eb291db251bf4182ce945075c2abde0a..a554c58175a24fed7fd644ccada8c982baae587b 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -5,14 +5,14 @@ import java.util.Collection; import java.util.Map; import net.sf.briar.api.ContactId; -import net.sf.briar.api.ContactTransport; import net.sf.briar.api.Rating; -import net.sf.briar.api.TemporarySecret; import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportProperties; +import net.sf.briar.api.db.ContactTransport; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.MessageHeader; import net.sf.briar.api.db.Status; +import net.sf.briar.api.db.TemporarySecret; import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Group; @@ -91,8 +91,7 @@ interface Database<T> { * <p> * Locking: contact read, window write. */ - void addContactTransport(T txn, ContactTransport ct) - throws DbException; + void addContactTransport(T txn, ContactTransport ct) throws DbException; /** * Returns false if the given message is already in the database. Otherwise @@ -366,6 +365,13 @@ interface Database<T> { Map<ContactId, TransportProperties> getRemoteProperties(T txn, TransportId t) throws DbException; + /** + * Returns all temporary secrets. + * <p> + * Locking: contact read, window read. + */ + Collection<TemporarySecret> getSecrets(T txn) throws DbException; + /** * Returns the sendability score of the given group message. * <p> diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java index 5828b36a7daf4d0382f9bf31518117f0ebb8441b..3f319a2afb7369bc7bb4501eb1d7487ee288d74f 100644 --- a/components/net/sf/briar/db/DatabaseComponentImpl.java +++ b/components/net/sf/briar/db/DatabaseComponentImpl.java @@ -22,18 +22,18 @@ import java.util.logging.Level; import java.util.logging.Logger; import net.sf.briar.api.ContactId; -import net.sf.briar.api.ContactTransport; import net.sf.briar.api.Rating; -import net.sf.briar.api.TemporarySecret; import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.clock.Clock; +import net.sf.briar.api.db.ContactTransport; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.MessageHeader; import net.sf.briar.api.db.NoSuchContactException; import net.sf.briar.api.db.NoSuchContactTransportException; import net.sf.briar.api.db.Status; +import net.sf.briar.api.db.TemporarySecret; import net.sf.briar.api.db.event.BatchReceivedEvent; import net.sf.briar.api.db.event.ContactAddedEvent; import net.sf.briar.api.db.event.ContactRemovedEvent; diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java index fde56a67e6053464df5168e61a5bd5ecbc4bc48b..ccea9401ae16dedd4779260a1d6d2aba2d6f27ec 100644 --- a/components/net/sf/briar/db/JdbcDatabase.java +++ b/components/net/sf/briar/db/JdbcDatabase.java @@ -24,15 +24,15 @@ import java.util.logging.Level; import java.util.logging.Logger; import net.sf.briar.api.ContactId; -import net.sf.briar.api.ContactTransport; import net.sf.briar.api.Rating; -import net.sf.briar.api.TemporarySecret; import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.clock.Clock; +import net.sf.briar.api.db.ContactTransport; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.MessageHeader; import net.sf.briar.api.db.Status; +import net.sf.briar.api.db.TemporarySecret; import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Group; @@ -559,21 +559,6 @@ abstract class JdbcDatabase implements Database<Connection> { int affected = ps.executeUpdate(); if(affected != 1) throw new DbStateException(); ps.close(); - sql = "INSERT INTO secrets" - + " (contactId, transportId, period, secret, outgoing," - + " centre, bitmap)" - + " VALUES (?, ?, ?, ?, ?, ?, ?)"; - ps = txn.prepareStatement(sql); - ps.setInt(1, ct.getContactId().getInt()); - ps.setBytes(2, ct.getTransportId().getBytes()); - ps.setLong(3, ct.getPeriod()); - ps.setBytes(4, ct.getSecret()); - ps.setLong(5, ct.getOutgoingConnectionCounter()); - ps.setLong(6, ct.getWindowCentre()); - ps.setBytes(7, ct.getWindowBitmap()); - affected = ps.executeUpdate(); - if(affected != 1) throw new DbStateException(); - ps.close(); } catch(SQLException e) { tryToClose(ps); throw new DbException(e); @@ -1094,32 +1079,21 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT c.contactId, c.transportId, epoch," - + " clockDiff, latency, alice, period, secret," - + " outgoing, centre, bitmap" - + " FROM contactTransports AS c" - + " JOIN secrets AS s" - + " ON c.contactId = s.contactId" - + " AND c.transportId = s.transportId"; + String sql = "SELECT contactId, transportId, epoch, clockDiff," + + " latency, alice" + + " FROM contactTransports"; ps = txn.prepareStatement(sql); rs = ps.executeQuery(); List<ContactTransport> cts = new ArrayList<ContactTransport>(); while(rs.next()) { - ContactId contactId = new ContactId(rs.getInt(1)); - TransportId transportId = new TransportId(rs.getBytes(2)); + ContactId c = new ContactId(rs.getInt(1)); + TransportId t = new TransportId(rs.getBytes(2)); long epoch = rs.getLong(3); long clockDiff = rs.getLong(4); long latency = rs.getLong(5); boolean alice = rs.getBoolean(6); - long period = rs.getLong(7); - byte[] secret = rs.getBytes(8); - long outgoing = rs.getLong(9); - long centre = rs.getLong(10); - byte[] bitmap = rs.getBytes(11); - ContactTransport ct = new ContactTransport(contactId, - transportId, epoch, clockDiff, latency, alice, period, - secret, outgoing, centre, bitmap); - cts.add(ct); + cts.add(new ContactTransport(c, t, epoch, clockDiff, latency, + alice)); } return Collections.unmodifiableList(cts); } catch(SQLException e) { @@ -1577,6 +1551,38 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public Collection<TemporarySecret> getSecrets(Connection txn) + throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT contactId, transportId, period, secret," + + " outgoing, centre, bitmap" + + " FROM secrets"; + ps = txn.prepareStatement(sql); + rs = ps.executeQuery(); + List<TemporarySecret> secrets = new ArrayList<TemporarySecret>(); + while(rs.next()) { + ContactId c = new ContactId(rs.getInt(1)); + TransportId t = new TransportId(rs.getBytes(2)); + long period = rs.getLong(3); + byte[] secret = rs.getBytes(4); + long outgoing = rs.getLong(5); + long centre = rs.getLong(6); + byte[] bitmap = rs.getBytes(7); + secrets.add(new TemporarySecret(c, t, period, secret, outgoing, + centre, bitmap)); + } + rs.close(); + ps.close(); + return Collections.unmodifiableList(secrets); + } catch(SQLException e) { + tryToClose(rs); + tryToClose(ps); + throw new DbException(e); + } + } + public int getSendability(Connection txn, MessageId m) throws DbException { PreparedStatement ps = null; ResultSet rs = null; diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java index e03a3389dd80959c95e2ec23c688e8ffe38cc26f..8b8f7eba92391b2ef996fbd4dc7862b3fa3bfb9f 100644 --- a/test/net/sf/briar/ProtocolIntegrationTest.java +++ b/test/net/sf/briar/ProtocolIntegrationTest.java @@ -153,21 +153,14 @@ public class ProtocolIntegrationTest extends BriarTestCase { Ack a = packetFactory.createAck(Collections.singletonList(ack)); writer.writeAck(a); - Collection<byte[]> batch = Arrays.asList(new byte[][] { - message.getSerialised(), - message1.getSerialised(), - message2.getSerialised(), - message3.getSerialised() - }); + Collection<byte[]> batch = Arrays.asList(message.getSerialised(), + message1.getSerialised(), message2.getSerialised(), + message3.getSerialised()); RawBatch b = packetFactory.createBatch(batch); writer.writeBatch(b); - Collection<MessageId> offer = Arrays.asList(new MessageId[] { - message.getId(), - message1.getId(), - message2.getId(), - message3.getId() - }); + Collection<MessageId> offer = Arrays.asList(message.getId(), + message1.getId(), message2.getId(), message3.getId()); Offer o = packetFactory.createOffer(offer); writer.writeOffer(o); diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java index 3918650be8e6fd957612e5cb18b31366995394c6..7e88bd2e628e5a256be12f0e9b1802c113e13366 100644 --- a/test/net/sf/briar/db/DatabaseComponentTest.java +++ b/test/net/sf/briar/db/DatabaseComponentTest.java @@ -639,10 +639,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase { public void testGenerateBatch() throws Exception { final MessageId messageId1 = new MessageId(TestUtils.getRandomId()); final byte[] raw1 = new byte[size]; - final Collection<MessageId> sendable = - Arrays.asList(new MessageId[] {messageId, messageId1}); - final Collection<byte[]> messages = - Arrays.asList(new byte[][] {raw, raw1}); + final Collection<MessageId> sendable = Arrays.asList(messageId, + messageId1); + final Collection<byte[]> messages = Arrays.asList(raw, raw1); Mockery context = new Mockery(); @SuppressWarnings("unchecked") final Database<Object> database = context.mock(Database.class); @@ -689,7 +688,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { requested.add(messageId); requested.add(messageId1); requested.add(messageId2); - final Collection<byte[]> msgs = Arrays.asList(new byte[][] {raw1}); + final Collection<byte[]> msgs = Arrays.asList(raw1); Mockery context = new Mockery(); @SuppressWarnings("unchecked") final Database<Object> database = context.mock(Database.class); @@ -1477,8 +1476,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { @Test public void testVisibilityChangedCallsListeners() throws Exception { final ContactId contactId1 = new ContactId(123); - final Collection<ContactId> both = - Arrays.asList(new ContactId[] {contactId, contactId1}); + final Collection<ContactId> both = Arrays.asList(contactId, contactId1); Mockery context = new Mockery(); @SuppressWarnings("unchecked") final Database<Object> database = context.mock(Database.class); @@ -1510,8 +1508,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { @Test public void testVisibilityUnchangedDoesNotCallListeners() throws Exception { final ContactId contactId1 = new ContactId(234); - final Collection<ContactId> both = - Arrays.asList(new ContactId[] {contactId, contactId1}); + final Collection<ContactId> both = Arrays.asList(contactId, contactId1); Mockery context = new Mockery(); @SuppressWarnings("unchecked") final Database<Object> database = context.mock(Database.class); diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java index 8e98aed0babf420f9352c1d2db4f59b769bf4952..35caa4ec45c41de7ca238c89c6f886514890750b 100644 --- a/test/net/sf/briar/db/H2DatabaseTest.java +++ b/test/net/sf/briar/db/H2DatabaseTest.java @@ -25,6 +25,7 @@ import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.clock.SystemClock; import net.sf.briar.api.crypto.Password; +import net.sf.briar.api.db.ContactTransport; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.MessageHeader; import net.sf.briar.api.db.Status; @@ -1720,6 +1721,59 @@ public class H2DatabaseTest extends BriarTestCase { // FIXME: Test new methods + @Test + public void testContactTransports() throws Exception { + // Create some contact transports + TransportId transportId1 = new TransportId(TestUtils.getRandomId()); + ContactTransport ct1 = new ContactTransport(contactId, transportId, + 123L, 2345L, 34567L, true); + ContactTransport ct2 = new ContactTransport(contactId, transportId1, + 12345L, 2345L, 345L, false); + + Database<Connection> db = open(false); + Connection txn = db.startTransaction(); + + // Initially there should be no contact transports in the database + assertEquals(Collections.emptyList(), db.getContactTransports(txn)); + + // Add a contact and the contact transports + assertEquals(contactId, db.addContact(txn)); + db.addContactTransport(txn, ct1); + db.addContactTransport(txn, ct2); + + // Retrieve the contact transports + Collection<ContactTransport> cts = db.getContactTransports(txn); + assertEquals(2, cts.size()); + boolean foundFirst = false, foundSecond = false; + for(ContactTransport ct : cts) { + assertEquals(contactId, ct.getContactId()); + if(ct.getTransportId().equals(transportId)) { + assertEquals(123L, ct.getEpoch()); + assertEquals(2345L, ct.getClockDifference()); + assertEquals(34567L, ct.getLatency()); + assertTrue(ct.getAlice()); + foundFirst = true; + } else if(ct.getTransportId().equals(transportId1)) { + assertEquals(12345L, ct.getEpoch()); + assertEquals(2345L, ct.getClockDifference()); + assertEquals(345L, ct.getLatency()); + assertFalse(ct.getAlice()); + foundSecond = true; + } else { + fail(); + } + } + assertTrue(foundFirst); + assertTrue(foundSecond); + + // Removing the contact should remove the contact transports + db.removeContact(txn, contactId); + assertEquals(Collections.emptyList(), db.getContactTransports(txn)); + + db.commitTransaction(txn); + db.close(); + } + @Test public void testExceptionHandling() throws Exception { Database<Connection> db = open(false); diff --git a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java index 6d9230bffd335de93e923787667a5a127f0accab..caf2ecca145a7f91ef37048938eb18cfec70c49a 100644 --- a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java +++ b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java @@ -30,7 +30,7 @@ public class PollingRemovableDriveMonitorTest extends BriarTestCase { public Collection<File> findRemovableDrives() throws IOException { if(firstCall.getAndSet(false)) return Collections.emptyList(); - else return Arrays.asList(new File[] {file1, file2}); + else return Arrays.asList(file1, file2); } }; // Create a callback that waits for two files diff --git a/test/net/sf/briar/protocol/UnverifiedBatchImplTest.java b/test/net/sf/briar/protocol/UnverifiedBatchImplTest.java index dcf6f38a85cb820580fc27fbdd7fe8585fb007a3..126f8a983aa3894f385a1f694ce90d8afb90cda1 100644 --- a/test/net/sf/briar/protocol/UnverifiedBatchImplTest.java +++ b/test/net/sf/briar/protocol/UnverifiedBatchImplTest.java @@ -66,9 +66,9 @@ public class UnverifiedBatchImplTest extends BriarTestCase { // Verify the batch Mockery context = new Mockery(); final UnverifiedMessage message = - context.mock(UnverifiedMessage.class, "message"); + context.mock(UnverifiedMessage.class, "message"); final UnverifiedMessage message1 = - context.mock(UnverifiedMessage.class, "message1"); + context.mock(UnverifiedMessage.class, "message1"); context.checking(new Expectations() {{ // First message oneOf(message).getRaw(); @@ -105,8 +105,8 @@ public class UnverifiedBatchImplTest extends BriarTestCase { oneOf(message1).getBodyLength(); will(returnValue(1000)); }}); - Collection<UnverifiedMessage> messages = - Arrays.asList(new UnverifiedMessage[] {message, message1}); + Collection<UnverifiedMessage> messages = Arrays.asList(message, + message1); UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages); Batch verifiedBatch = batch.verify(); // Check that the batch and message IDs match @@ -137,11 +137,11 @@ public class UnverifiedBatchImplTest extends BriarTestCase { // Verify the batch Mockery context = new Mockery(); final UnverifiedMessage message = - context.mock(UnverifiedMessage.class, "message"); + context.mock(UnverifiedMessage.class, "message"); final Author author = context.mock(Author.class); final Group group = context.mock(Group.class); final UnverifiedMessage message1 = - context.mock(UnverifiedMessage.class, "message1"); + context.mock(UnverifiedMessage.class, "message1"); context.checking(new Expectations() {{ // First message oneOf(message).getRaw(); @@ -194,8 +194,8 @@ public class UnverifiedBatchImplTest extends BriarTestCase { oneOf(message1).getBodyLength(); will(returnValue(1000)); }}); - Collection<UnverifiedMessage> messages = - Arrays.asList(new UnverifiedMessage[] {message, message1}); + Collection<UnverifiedMessage> messages = Arrays.asList(message, + message1); UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages); batch.verify(); context.assertIsSatisfied(); @@ -215,10 +215,10 @@ public class UnverifiedBatchImplTest extends BriarTestCase { // Verify the batch Mockery context = new Mockery(); final UnverifiedMessage message = - context.mock(UnverifiedMessage.class, "message"); + context.mock(UnverifiedMessage.class, "message"); final Author author = context.mock(Author.class); final UnverifiedMessage message1 = - context.mock(UnverifiedMessage.class, "message1"); + context.mock(UnverifiedMessage.class, "message1"); context.checking(new Expectations() {{ // First message - verification will fail at the author's signature oneOf(message).getRaw(); @@ -232,8 +232,8 @@ public class UnverifiedBatchImplTest extends BriarTestCase { oneOf(message).getAuthorSignature(); will(returnValue(authorSignature)); }}); - Collection<UnverifiedMessage> messages = - Arrays.asList(new UnverifiedMessage[] {message, message1}); + Collection<UnverifiedMessage> messages = Arrays.asList(message, + message1); UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages); try { batch.verify(); diff --git a/test/net/sf/briar/transport/ConnectionRegistryImplTest.java b/test/net/sf/briar/transport/ConnectionRegistryImplTest.java index ef9fc87b98bb247031cb44678c8b428e97f6a1b4..af5e853acc9181ed6c771eab4481c3e356c6307f 100644 --- a/test/net/sf/briar/transport/ConnectionRegistryImplTest.java +++ b/test/net/sf/briar/transport/ConnectionRegistryImplTest.java @@ -65,7 +65,7 @@ public class ConnectionRegistryImplTest extends BriarTestCase { c.registerConnection(contactId, transportId); c.registerConnection(contactId1, transportId); c.registerConnection(contactId1, transportId1); - assertEquals(Arrays.asList(new ContactId[] {contactId, contactId1}), + assertEquals(Arrays.asList(contactId, contactId1), c.getConnectedContacts(transportId)); assertEquals(Collections.singletonList(contactId1), c.getConnectedContacts(transportId1));