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