diff --git a/components/net/sf/briar/transport/ConnectionWindow.java b/components/net/sf/briar/transport/ConnectionWindow.java index 3a2ced3163842b2e123b7e540046c71779f2148c..3f0a6861116da4ab7d0315b9eec6d955261bcc42 100644 --- a/components/net/sf/briar/transport/ConnectionWindow.java +++ b/components/net/sf/briar/transport/ConnectionWindow.java @@ -22,20 +22,22 @@ class ConnectionWindow { } ConnectionWindow(long centre, byte[] bitmap) { - if(centre < 0 || centre > MAX_32_BIT_UNSIGNED) + if(centre < 0 || centre > MAX_32_BIT_UNSIGNED + 1) throw new IllegalArgumentException(); if(bitmap.length != CONNECTION_WINDOW_SIZE / 8) throw new IllegalArgumentException(); + this.centre = centre; unseen = new HashSet<Long>(); - long bottom = getBottom(centre); - long top = getTop(centre); - for(long l = bottom; l < top; l++) { - int offset = (int) (l - bottom); - int bytes = offset / 8; - int bits = offset % 8; - if((bitmap[bytes] & (128 >> bits)) == 0) unseen.add(l); + long bitmapBottom = centre - CONNECTION_WINDOW_SIZE / 2; + for(int bytes = 0; bytes < bitmap.length; bytes++) { + for(int bits = 0; bits < 8; bits++) { + long connection = bitmapBottom + bytes * 8 + bits; + if(connection >= 0 && connection <= MAX_32_BIT_UNSIGNED) { + if((bitmap[bytes] & (128 >> bits)) == 0) + unseen.add(connection); + } + } } - this.centre = centre; } boolean isSeen(long connection) { @@ -70,7 +72,16 @@ class ConnectionWindow { byte[] getBitmap() { byte[] bitmap = new byte[CONNECTION_WINDOW_SIZE / 8]; - // FIXME + long bitmapBottom = centre - CONNECTION_WINDOW_SIZE / 2; + for(int bytes = 0; bytes < bitmap.length; bytes++) { + for(int bits = 0; bits < 8; bits++) { + long connection = bitmapBottom + bytes * 8 + bits; + if(connection >= 0 && connection <= MAX_32_BIT_UNSIGNED) { + if(!unseen.contains(connection)) + bitmap[bytes] |= 128 >> bits; + } + } + } return bitmap; } diff --git a/test/net/sf/briar/transport/ConnectionWindowTest.java b/test/net/sf/briar/transport/ConnectionWindowTest.java index 74de234cf9be49ab509c26121d90c9767848ba01..808f6a8107b68d84b29bf13becb49fc399cf6895 100644 --- a/test/net/sf/briar/transport/ConnectionWindowTest.java +++ b/test/net/sf/briar/transport/ConnectionWindowTest.java @@ -1,5 +1,9 @@ package net.sf.briar.transport; +import static net.sf.briar.api.transport.TransportConstants.CONNECTION_WINDOW_SIZE; +import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; +import static org.junit.Assert.assertArrayEquals; + import java.util.Collection; import net.sf.briar.BriarTestCase; @@ -40,6 +44,29 @@ public class ConnectionWindowTest extends BriarTestCase { w.setSeen(48); fail(); } catch(IllegalArgumentException expected) {} + // Centre is max - 1, highest value in window is max + byte[] bitmap = new byte[CONNECTION_WINDOW_SIZE / 8]; + w = new ConnectionWindow(MAX_32_BIT_UNSIGNED - 1, bitmap); + assertFalse(w.isSeen(MAX_32_BIT_UNSIGNED - 1)); + assertFalse(w.isSeen(MAX_32_BIT_UNSIGNED)); + // Values greater than max should never be allowed + try { + w.setSeen(MAX_32_BIT_UNSIGNED + 1); + fail(); + } catch(IllegalArgumentException expected) {} + w.setSeen(MAX_32_BIT_UNSIGNED); + assertTrue(w.isSeen(MAX_32_BIT_UNSIGNED)); + // Centre should have moved to max + 1 + assertEquals(MAX_32_BIT_UNSIGNED + 1, w.getCentre()); + // The bit corresponding to max should be set + byte[] expectedBitmap = new byte[CONNECTION_WINDOW_SIZE / 8]; + expectedBitmap[expectedBitmap.length / 2 - 1] = 1; // 00000001 + assertArrayEquals(expectedBitmap, w.getBitmap()); + // Values greater than max should never be allowed even if centre > max + try { + w.setSeen(MAX_32_BIT_UNSIGNED + 1); + fail(); + } catch(IllegalArgumentException expected) {} } @Test @@ -70,6 +97,13 @@ public class ConnectionWindowTest extends BriarTestCase { w.setSeen(9); fail(); } catch(IllegalArgumentException expected) {} + // Centre should still be 26 + assertEquals(26, w.getCentre()); + // The bits corresponding to 10, 15, 16 and 25 should be set + byte[] expectedBitmap = new byte[CONNECTION_WINDOW_SIZE / 8]; + expectedBitmap[0] = (byte) 134; // 10000110 + expectedBitmap[1] = 1; // 00000001 + assertArrayEquals(expectedBitmap, w.getBitmap()); } @Test