diff --git a/api/net/sf/briar/api/protocol/ProtocolConstants.java b/api/net/sf/briar/api/protocol/ProtocolConstants.java index 7e23d247a0474010ab9a5aaba6c860f2a48168e1..ba3f5fb6581a4c8ce6cbea121b4e296903f11419 100644 --- a/api/net/sf/briar/api/protocol/ProtocolConstants.java +++ b/api/net/sf/briar/api/protocol/ProtocolConstants.java @@ -48,4 +48,7 @@ public interface ProtocolConstants { /** The length of a message's random salt in bytes. */ static final int SALT_LENGTH = 8; + + /** The size of the connection reordering window. */ + static final int CONNECTION_WINDOW_SIZE = 32; } diff --git a/api/net/sf/briar/api/transport/ConnectionWindow.java b/api/net/sf/briar/api/transport/ConnectionWindow.java index a7e8eb98b2cb5bb29b6d08a980a6301b5aed8cf4..35fc872f15cee0f8cbe16902e841167a0fe0f63f 100644 --- a/api/net/sf/briar/api/transport/ConnectionWindow.java +++ b/api/net/sf/briar/api/transport/ConnectionWindow.java @@ -4,13 +4,9 @@ import java.util.Collection; public interface ConnectionWindow { - long getCentre(); - - int getBitmap(); - boolean isSeen(long connection); void setSeen(long connection); - Collection<Long> getUnseenConnectionNumbers(); + Collection<Long> getUnseen(); } diff --git a/api/net/sf/briar/api/transport/ConnectionWindowFactory.java b/api/net/sf/briar/api/transport/ConnectionWindowFactory.java index 40ad981528f39cf2815ac34f570ebc14f83c0ebe..33ef8e7a6aa9650d5356accd7242ffa85505d53e 100644 --- a/api/net/sf/briar/api/transport/ConnectionWindowFactory.java +++ b/api/net/sf/briar/api/transport/ConnectionWindowFactory.java @@ -1,6 +1,10 @@ package net.sf.briar.api.transport; +import java.util.Collection; + public interface ConnectionWindowFactory { - ConnectionWindow createConnectionWindow(long centre, int bitmap); + ConnectionWindow createConnectionWindow(); + + ConnectionWindow createConnectionWindow(Collection<Long> unseen); } diff --git a/api/net/sf/briar/api/transport/StreamConnectionFactory.java b/api/net/sf/briar/api/transport/StreamConnectionFactory.java index 621a072518b594e40a79e0653e84c4efcded2aef..3287453e7e984861a7c812e6a9ba910ac3a4eb04 100644 --- a/api/net/sf/briar/api/transport/StreamConnectionFactory.java +++ b/api/net/sf/briar/api/transport/StreamConnectionFactory.java @@ -5,7 +5,7 @@ import net.sf.briar.api.protocol.TransportIndex; public interface StreamConnectionFactory { - void createIncomingConnection(TransportIndex i, ContactId c, + void createIncomingConnection(TransportIndex i, ContactId c, StreamTransportConnection s, byte[] encryptedIv); void createOutgoingConnection(TransportIndex i, ContactId c, diff --git a/components/net/sf/briar/crypto/CryptoModule.java b/components/net/sf/briar/crypto/CryptoModule.java index 221c0bb1307aef949f8fbe206b6ac2d842a7d21a..31dbc46ac7ddf6045240e8f23f61a469de42b767 100644 --- a/components/net/sf/briar/crypto/CryptoModule.java +++ b/components/net/sf/briar/crypto/CryptoModule.java @@ -18,6 +18,5 @@ public class CryptoModule extends AbstractModule { // FIXME: Use a real key bind(SecretKey.class).annotatedWith(SecretStorageKey.class).toInstance( new SecretKeySpec(new byte[32], "AES")); - } } diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java index 39eb9889af59403a7dee2bec971e57215acfa546..60a7b3a80d94037dc665b9d289691890727b1d54 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -28,7 +28,7 @@ import net.sf.briar.api.transport.ConnectionWindow; * obtained by calling startTransaction(). Every transaction must be * terminated by calling either abortTransaction() or commitTransaction(), * even if an exception is thrown. - * + * <p> * Locking is provided by the DatabaseComponent implementation. To prevent * deadlock, locks must be acquired in the following order: * <ul> diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java index e9947db4bf565b0a0fd938401bd60924363778de..fe2172b9651eabb4ba13092477957a558c23927b 100644 --- a/components/net/sf/briar/db/DatabaseComponentImpl.java +++ b/components/net/sf/briar/db/DatabaseComponentImpl.java @@ -1597,7 +1597,7 @@ DatabaseCleaner.Callback { } /** - * Removes the given message (and all associated state) from the database. + * Removes the given message (and all associated state) from the database. * <p> * Locking: contact read, message write, messageStatus write. */ diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java index 58b905b61c13114b4df2f98191fa45a3969d4d10..0ec9015392e60610466fa0607021f38ea183a1b4 100644 --- a/components/net/sf/briar/db/JdbcDatabase.java +++ b/components/net/sf/briar/db/JdbcDatabase.java @@ -214,17 +214,24 @@ abstract class JdbcDatabase implements Database<Connection> { + " FOREIGN KEY (contactId) REFERENCES contacts (contactId)" + " ON DELETE CASCADE)"; - private static final String CREATE_CONNECTION_WINDOWS = - "CREATE TABLE connectionWindows" + private static final String CREATE_CONNECTIONS = + "CREATE TABLE connections" + " (contactId INT NOT NULL," + " index INT NOT NULL," - + " centre BIGINT NOT NULL," - + " bitmap INT NOT NULL," + " outgoing BIGINT NOT NULL," + " PRIMARY KEY (contactId, index)," + " FOREIGN KEY (contactId) REFERENCES contacts (contactId)" + " ON DELETE CASCADE)"; + private static final String CREATE_CONNECTION_WINDOWS = + "CREATE TABLE connectionWindows" + + " (contactId INT NOT NULL," + + " index INT NOT NULL," + + " unseen BIGINT NOT NULL," + + " PRIMARY KEY (contactId, index, unseen)," + + " FOREIGN KEY (contactId) REFERENCES contacts (contactId)" + + " ON DELETE CASCADE)"; + private static final String CREATE_SUBSCRIPTION_TIMESTAMPS = "CREATE TABLE subscriptionTimestamps" + " (contactId INT NOT NULL," @@ -342,6 +349,7 @@ abstract class JdbcDatabase implements Database<Connection> { s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_PROPS)); s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORTS)); s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_PROPS)); + s.executeUpdate(insertTypeNames(CREATE_CONNECTIONS)); s.executeUpdate(insertTypeNames(CREATE_CONNECTION_WINDOWS)); s.executeUpdate(insertTypeNames(CREATE_SUBSCRIPTION_TIMESTAMPS)); s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_TIMESTAMPS)); @@ -895,19 +903,19 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT outgoing FROM connectionWindows" + String sql = "SELECT outgoing FROM connections" + " WHERE contactId = ? AND index = ?"; ps = txn.prepareStatement(sql); ps.setInt(1, c.getInt()); ps.setInt(2, i.getInt()); rs = ps.executeQuery(); if(rs.next()) { - // A connection window row exists - update it + // A connection row exists - update it long outgoing = rs.getLong(1); if(rs.next()) throw new DbStateException(); rs.close(); ps.close(); - sql = "UPDATE connectionWindows SET outgoing = ?" + sql = "UPDATE connections SET outgoing = ?" + " WHERE contactId = ? AND index = ?"; ps = txn.prepareStatement(sql); ps.setLong(1, outgoing + 1); @@ -918,12 +926,11 @@ abstract class JdbcDatabase implements Database<Connection> { ps.close(); return outgoing; } else { - // No connection window row exists - create one + // No connection row exists - create one rs.close(); ps.close(); - sql = "INSERT INTO connectionWindows" - + " (contactId, index, centre, bitmap, outgoing)" - + " VALUES(?, ?, ZERO(), ZERO(), ZERO())"; + sql = "INSERT INTO connections (contactId, index, outgoing)" + + " VALUES(?, ?, ZERO())"; ps = txn.prepareStatement(sql); ps.setInt(1, c.getInt()); ps.setInt(2, i.getInt()); @@ -944,23 +951,19 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT centre, bitmap FROM connectionWindows" + String sql = "SELECT unseen FROM connectionWindows" + " WHERE contactId = ? AND index = ?"; ps = txn.prepareStatement(sql); ps.setInt(1, c.getInt()); ps.setInt(2, i.getInt()); rs = ps.executeQuery(); - long centre = 0L; - int bitmap = 0; - if(rs.next()) { - centre = rs.getLong(1); - bitmap = rs.getInt(2); - if(rs.next()) throw new DbStateException(); - } + Collection<Long> unseen = new ArrayList<Long>(); + while(rs.next()) unseen.add(rs.getLong(1)); rs.close(); ps.close(); - return connectionWindowFactory.createConnectionWindow(centre, - bitmap); + if(unseen.isEmpty()) + return connectionWindowFactory.createConnectionWindow(); + else return connectionWindowFactory.createConnectionWindow(unseen); } catch(SQLException e) { tryToClose(rs); tryToClose(ps); @@ -2154,46 +2157,34 @@ abstract class JdbcDatabase implements Database<Connection> { public void setConnectionWindow(Connection txn, ContactId c, TransportIndex i, ConnectionWindow w) throws DbException { PreparedStatement ps = null; - ResultSet rs = null; try { - String sql = "SELECT NULL FROM connectionWindows" + // Delete any existing connection window + String sql = "DELETE FROM connectionWindows" + " WHERE contactId = ? AND index = ?"; ps = txn.prepareStatement(sql); ps.setInt(1, c.getInt()); ps.setInt(2, i.getInt()); - rs = ps.executeQuery(); - boolean found = rs.next(); - if(rs.next()) throw new DbStateException(); - rs.close(); + ps.executeUpdate(); ps.close(); - if(found) { - // A connection window row exists - update it - sql = "UPDATE connectionWindows SET centre = ?, bitmap = ?" - + " WHERE contactId = ? AND index = ?"; - ps = txn.prepareStatement(sql); - ps.setLong(1, w.getCentre()); - ps.setInt(2, w.getBitmap()); - ps.setInt(3, c.getInt()); - ps.setInt(4, i.getInt()); - int affected = ps.executeUpdate(); - if(affected != 1) throw new DbStateException(); - ps.close(); - } else { - // No connection window row exists - create one - sql = "INSERT INTO connectionWindows" - + " (contactId, index, centre, bitmap, outgoing)" - + " VALUES(?, ?, ?, ?, ZERO())"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - ps.setInt(2, i.getInt()); - ps.setLong(3, w.getCentre()); - ps.setInt(4, w.getBitmap()); - int affected = ps.executeUpdate(); - if(affected != 1) throw new DbStateException(); - ps.close(); + // Store the new connection window + sql = "INSERT INTO connectionWindows (contactId, index, unseen)" + + " VALUES(?, ?, ?)"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setInt(2, i.getInt()); + Collection<Long> unseen = w.getUnseen(); + for(long l : unseen) { + ps.setLong(3, l); + ps.addBatch(); } + int[] affectedBatch = ps.executeBatch(); + if(affectedBatch.length != unseen.size()) + throw new DbStateException(); + for(int j = 0; j < affectedBatch.length; j++) { + if(affectedBatch[j] != 1) throw new DbStateException(); + } + ps.close(); } catch(SQLException e) { - tryToClose(rs); tryToClose(ps); throw new DbException(e); } diff --git a/components/net/sf/briar/serial/ReaderImpl.java b/components/net/sf/briar/serial/ReaderImpl.java index 0795d27a4e7db5cc20fb1f2df777a21ed0a273f2..90d5529b7359655277bd300bc503caf18069de06 100644 --- a/components/net/sf/briar/serial/ReaderImpl.java +++ b/components/net/sf/briar/serial/ReaderImpl.java @@ -104,7 +104,7 @@ class ReaderImpl implements Reader { objectReaders.length); objectReaders = newObjectReaders; } - objectReaders[id] = o; + objectReaders[id] = o; } public void removeObjectReader(int id) { diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java index 56f728f619ac631f7e37ca188dbad29034431c0e..b82bbec12a7f4f5a1d161e8252db6ca00fa2089f 100644 --- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java +++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java @@ -88,7 +88,7 @@ DatabaseListener { private synchronized void calculateIvs(ContactId c, TransportId t, TransportIndex i, SecretKey ivKey, ConnectionWindow w) throws DbException { - for(Long unseen : w.getUnseenConnectionNumbers()) { + for(Long unseen : w.getUnseen()) { Bytes iv = new Bytes(encryptIv(i, unseen, ivKey)); expected.put(iv, new ConnectionContextImpl(c, t, i, unseen)); } diff --git a/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java index ff5b3f2fdc9f507eceacb763b84b84b4aac8780a..69a80afd2b27c6e4f68b39c6fad4f9b9c4e10dfe 100644 --- a/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java @@ -1,11 +1,17 @@ package net.sf.briar.transport; +import java.util.Collection; + import net.sf.briar.api.transport.ConnectionWindow; import net.sf.briar.api.transport.ConnectionWindowFactory; class ConnectionWindowFactoryImpl implements ConnectionWindowFactory { - public ConnectionWindow createConnectionWindow(long centre, int bitmap) { - return new ConnectionWindowImpl(centre, bitmap); + public ConnectionWindow createConnectionWindow() { + return new ConnectionWindowImpl(); + } + + public ConnectionWindow createConnectionWindow(Collection<Long> unseen) { + return new ConnectionWindowImpl(unseen); } } diff --git a/components/net/sf/briar/transport/ConnectionWindowImpl.java b/components/net/sf/briar/transport/ConnectionWindowImpl.java index f0485cb1acafd2cdc0581c315f6f276d509fff00..3be375edbf8959319355b6a245616208ebdc63cf 100644 --- a/components/net/sf/briar/transport/ConnectionWindowImpl.java +++ b/components/net/sf/briar/transport/ConnectionWindowImpl.java @@ -1,69 +1,74 @@ package net.sf.briar.transport; -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; +import static net.sf.briar.api.protocol.ProtocolConstants.CONNECTION_WINDOW_SIZE; -import java.util.ArrayList; import java.util.Collection; +import java.util.Set; +import java.util.TreeSet; import net.sf.briar.api.transport.ConnectionWindow; +import net.sf.briar.util.ByteUtils; class ConnectionWindowImpl implements ConnectionWindow { - private long centre; - private int bitmap; + private final Set<Long> unseen; - ConnectionWindowImpl(long centre, int bitmap) { - this.centre = centre; - this.bitmap = bitmap; - } + private long centre; - public long getCentre() { - return centre; + ConnectionWindowImpl() { + unseen = new TreeSet<Long>(); + for(long l = 0; l < CONNECTION_WINDOW_SIZE / 2; l++) unseen.add(l); + centre = 0; } - public int getBitmap() { - return bitmap; + ConnectionWindowImpl(Collection<Long> unseen) { + long min = Long.MAX_VALUE, max = Long.MIN_VALUE; + for(long l : unseen) { + if(l < 0 || l > ByteUtils.MAX_32_BIT_UNSIGNED) + throw new IllegalArgumentException(); + if(l < min) min = l; + if(l > max) max = l; + } + if(max - min > CONNECTION_WINDOW_SIZE) + throw new IllegalArgumentException(); + this.unseen = new TreeSet<Long>(unseen); + centre = max - CONNECTION_WINDOW_SIZE / 2 + 1; + for(long l = centre; l <= max; l++) { + if(!this.unseen.contains(l)) throw new IllegalArgumentException(); + } } public boolean isSeen(long connection) { - int offset = getOffset(connection); - int mask = 0x80000000 >>> offset; - return (bitmap & mask) != 0; - } - - private int getOffset(long connection) { - if(connection < 0L) throw new IllegalArgumentException(); - if(connection > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - int offset = (int) (connection - centre) + 16; - if(offset < 0 || offset > 31) throw new IllegalArgumentException(); - return offset; + return !unseen.contains(connection); } public void setSeen(long connection) { - int offset = getOffset(connection); - int mask = 0x80000000 >>> offset; - if((bitmap & mask) != 0) throw new IllegalArgumentException(); - bitmap |= mask; - // If the new connection number is above the centre, slide the window + long bottom = getBottom(centre); + long top = getTop(centre); + if(connection < bottom || connection > top) + throw new IllegalArgumentException(); + if(!unseen.remove(connection)) throw new IllegalArgumentException(); if(connection >= centre) { centre = connection + 1; - bitmap <<= offset - 16 + 1; + long newBottom = getBottom(centre); + long newTop = getTop(centre); + for(long l = bottom; l < newBottom; l++) unseen.remove(l); + for(long l = top + 1; l <= newTop; l++) unseen.add(l); } } - public Collection<Long> getUnseenConnectionNumbers() { - Collection<Long> unseen = new ArrayList<Long>(); - for(int i = 0; i < 32; i++) { - int mask = 0x80000000 >>> i; - if((bitmap & mask) == 0) { - long c = centre - 16 + i; - if(c >= 0L && c <= MAX_32_BIT_UNSIGNED) unseen.add(c); - } - } - // The centre of the window should be an unseen value unless the - // maximum possible value has been seen - assert unseen.contains(centre) || centre == MAX_32_BIT_UNSIGNED + 1; + // Returns the lowest value contained in a window with the given centre + private long getBottom(long centre) { + return Math.max(0, centre - CONNECTION_WINDOW_SIZE / 2); + } + + // Returns the highest value contained in a window with the given centre + private long getTop(long centre) { + return Math.min(ByteUtils.MAX_32_BIT_UNSIGNED, + centre + CONNECTION_WINDOW_SIZE / 2 - 1); + } + + public Collection<Long> getUnseen() { return unseen; } } diff --git a/test/net/sf/briar/db/BasicH2Test.java b/test/net/sf/briar/db/BasicH2Test.java index 843b0519612e465356cf914967eaba187cca162f..f9ddbc93e5f034089ed7be8dc427e01a63bf4752 100644 --- a/test/net/sf/briar/db/BasicH2Test.java +++ b/test/net/sf/briar/db/BasicH2Test.java @@ -60,7 +60,7 @@ public class BasicH2Test extends TestCase { // Check that the name can be retrieved using the unique ID assertEquals("foo", getName(uniqueId)); } - + private void addRow(byte[] uniqueId, String name) throws SQLException { String sql = "INSERT INTO foo (uniqueId, name) VALUES (?, ?)"; PreparedStatement ps = null; diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java index 0d54f31d76c50bd26d406fe17d9d8f915612cf08..9d9471f21b99543d36606a04c5b5509a3f8e0fdf 100644 --- a/test/net/sf/briar/db/H2DatabaseTest.java +++ b/test/net/sf/briar/db/H2DatabaseTest.java @@ -33,6 +33,7 @@ import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.ProtocolConstants; import net.sf.briar.api.protocol.Transport; import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportIndex; @@ -1446,8 +1447,8 @@ public class H2DatabaseTest extends TestCase { remoteIndex); // The connection window should exist and be in the initial state assertNotNull(w); - assertEquals(0L, w.getCentre()); - assertEquals(0, w.getBitmap()); + long top = ProtocolConstants.CONNECTION_WINDOW_SIZE / 2 - 1; + for(long l = 0; l <= top; l++) assertFalse(w.isSeen(l)); db.commitTransaction(txn); db.close(); @@ -1465,17 +1466,21 @@ public class H2DatabaseTest extends TestCase { remoteIndex); // The connection window should exist and be in the initial state assertNotNull(w); - assertEquals(0L, w.getCentre()); - assertEquals(0, w.getBitmap()); + Collection<Long> unseen = w.getUnseen(); + long top = ProtocolConstants.CONNECTION_WINDOW_SIZE / 2 - 1; + assertEquals(top + 1, unseen.size()); + for(long l = 0; l <= top; l++) { + assertFalse(w.isSeen(l)); + assertTrue(unseen.contains(l)); + } // Update the connection window and store it - w.setSeen(5L); + w.setSeen(5); db.setConnectionWindow(txn, contactId, remoteIndex, w); // Check that the connection window was stored w = db.getConnectionWindow(txn, contactId, remoteIndex); assertNotNull(w); - assertEquals(6L, w.getCentre()); - assertTrue(w.isSeen(5L)); - assertEquals(0x00010000, w.getBitmap()); + top += 5; + for(long l = 0; l <= top; l++) assertEquals(l == 5, w.isSeen(l)); db.commitTransaction(txn); db.close(); diff --git a/test/net/sf/briar/protocol/ConsumersTest.java b/test/net/sf/briar/protocol/ConsumersTest.java index 9605c1c403daaabe83b84eb6f67383ee1ef0158b..4c09535a779c9562d1ef0fd55e74c4e16adb726e 100644 --- a/test/net/sf/briar/protocol/ConsumersTest.java +++ b/test/net/sf/briar/protocol/ConsumersTest.java @@ -28,7 +28,7 @@ public class ConsumersTest extends TestCase { Injector i = Guice.createInjector(new CryptoModule()); crypto = i.getInstance(CryptoComponent.class); } - + @Test public void testDigestingConsumer() throws Exception { MessageDigest messageDigest = crypto.getMessageDigest(); diff --git a/test/net/sf/briar/serial/WriterImplTest.java b/test/net/sf/briar/serial/WriterImplTest.java index 7fe9b285072144c97dad2a30b367d690715b2404..72b2eace7bff74edc88eeff5b7021903535dff74 100644 --- a/test/net/sf/briar/serial/WriterImplTest.java +++ b/test/net/sf/briar/serial/WriterImplTest.java @@ -101,7 +101,7 @@ public class WriterImplTest extends TestCase { @Test public void testWriteFloat32() throws IOException { // http://babbage.cs.qc.edu/IEEE-754/Decimal.html - // 1 bit for sign, 8 for exponent, 23 for significand + // 1 bit for sign, 8 for exponent, 23 for significand w.writeFloat32(0F); // 0 0 0 -> 0x00000000 w.writeFloat32(1F); // 0 127 1 -> 0x3F800000 w.writeFloat32(2F); // 0 128 1 -> 0x40000000 @@ -118,7 +118,7 @@ public class WriterImplTest extends TestCase { @Test public void testWriteFloat64() throws IOException { - // 1 bit for sign, 11 for exponent, 52 for significand + // 1 bit for sign, 11 for exponent, 52 for significand w.writeFloat64(0.0); // 0 0 0 -> 0x0000000000000000 w.writeFloat64(1.0); // 0 1023 1 -> 0x3FF0000000000000 w.writeFloat64(2.0); // 0 1024 1 -> 0x4000000000000000 diff --git a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java index 20361bac56f93cdf7492eb290efcf760a4fcb82c..369ad8c5e0c84daa4b93af3df3af0aceed66d0ac 100644 --- a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java +++ b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java @@ -84,7 +84,7 @@ public class ConnectionDecrypterImplTest extends TestCase { out.write(ciphertextMac); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); // Use a ConnectionDecrypter to decrypt the ciphertext - ConnectionDecrypter d = new ConnectionDecrypterImpl(in, + ConnectionDecrypter d = new ConnectionDecrypterImpl(in, IvEncoder.encodeIv(initiator, transportIndex, connection), frameCipher, frameKey); // First frame diff --git a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java index 2400c2dceb4f4d3977317b0446463371e8d40ede..e01d7e2518cebdbe41016a8bb4803cf31a4a076a 100644 --- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java +++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java @@ -49,7 +49,7 @@ public class ConnectionRecogniserImplTest extends TestCase { Transport transport = new Transport(transportId, localIndex, Collections.singletonMap("foo", "bar")); transports = Collections.singletonList(transport); - connectionWindow = new ConnectionWindowImpl(0L, 0); + connectionWindow = new ConnectionWindowImpl(); } @Test @@ -120,8 +120,7 @@ public class ConnectionRecogniserImplTest extends TestCase { // Second time - the IV should no longer be expected assertNull(c.acceptConnection(encryptedIv)); // The window should have advanced - assertEquals(4L, connectionWindow.getCentre()); - Collection<Long> unseen = connectionWindow.getUnseenConnectionNumbers(); + Collection<Long> unseen = connectionWindow.getUnseen(); assertEquals(19, unseen.size()); for(int i = 0; i < 19; i++) { if(i == 3) continue; diff --git a/test/net/sf/briar/transport/ConnectionWindowImplTest.java b/test/net/sf/briar/transport/ConnectionWindowImplTest.java index 54595b2342b66152afdae866daf4ab3071096baf..d39855f911276ca79500d9a09c23bd77c78ad050 100644 --- a/test/net/sf/briar/transport/ConnectionWindowImplTest.java +++ b/test/net/sf/briar/transport/ConnectionWindowImplTest.java @@ -1,18 +1,18 @@ package net.sf.briar.transport; +import java.util.ArrayList; import java.util.Collection; import junit.framework.TestCase; +import net.sf.briar.util.ByteUtils; import org.junit.Test; public class ConnectionWindowImplTest extends TestCase { - private static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1 - @Test public void testWindowSliding() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); for(int i = 0; i < 100; i++) { assertFalse(w.isSeen(i)); w.setSeen(i); @@ -22,7 +22,7 @@ public class ConnectionWindowImplTest extends TestCase { @Test public void testWindowJumping() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); for(int i = 0; i < 100; i += 13) { assertFalse(w.isSeen(i)); w.setSeen(i); @@ -32,7 +32,7 @@ public class ConnectionWindowImplTest extends TestCase { @Test public void testWindowUpperLimit() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); // Centre is 0, highest value in window is 15 w.setSeen(15); // Centre is 16, highest value in window is 31 @@ -42,18 +42,22 @@ public class ConnectionWindowImplTest extends TestCase { w.setSeen(48); fail(); } catch(IllegalArgumentException expected) {} - w = new ConnectionWindowImpl(MAX_32_BIT_UNSIGNED - 1, 0); - // Values greater than 2^31 - 1 should never be allowed - w.setSeen(MAX_32_BIT_UNSIGNED); + // Values greater than 2^32 - 1 should never be allowed + Collection<Long> unseen = new ArrayList<Long>(); + for(int i = 0; i < 32; i++) { + unseen.add(ByteUtils.MAX_32_BIT_UNSIGNED - i); + } + w = new ConnectionWindowImpl(unseen); + w.setSeen(ByteUtils.MAX_32_BIT_UNSIGNED); try { - w.setSeen(MAX_32_BIT_UNSIGNED + 1); + w.setSeen(ByteUtils.MAX_32_BIT_UNSIGNED + 1); fail(); } catch(IllegalArgumentException expected) {} } @Test public void testWindowLowerLimit() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); // Centre is 0, negative values should never be allowed try { w.setSeen(-1); @@ -83,7 +87,7 @@ public class ConnectionWindowImplTest extends TestCase { @Test public void testCannotSetSeenTwice() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); w.setSeen(15); try { w.setSeen(15); @@ -93,9 +97,9 @@ public class ConnectionWindowImplTest extends TestCase { @Test public void testGetUnseenConnectionNumbers() { - ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0); + ConnectionWindowImpl w = new ConnectionWindowImpl(); // Centre is 0; window should cover 0 to 15, inclusive, with none seen - Collection<Long> unseen = w.getUnseenConnectionNumbers(); + Collection<Long> unseen = w.getUnseen(); assertEquals(16, unseen.size()); for(int i = 0; i < 16; i++) { assertTrue(unseen.contains(Long.valueOf(i))); @@ -104,7 +108,7 @@ public class ConnectionWindowImplTest extends TestCase { w.setSeen(3); w.setSeen(4); // Centre is 5; window should cover 0 to 20, inclusive, with two seen - unseen = w.getUnseenConnectionNumbers(); + unseen = w.getUnseen(); assertEquals(19, unseen.size()); for(int i = 0; i < 21; i++) { if(i == 3 || i == 4) { @@ -117,7 +121,7 @@ public class ConnectionWindowImplTest extends TestCase { } w.setSeen(19); // Centre is 20; window should cover 4 to 35, inclusive, with two seen - unseen = w.getUnseenConnectionNumbers(); + unseen = w.getUnseen(); assertEquals(30, unseen.size()); for(int i = 4; i < 36; i++) { if(i == 4 || i == 19) {