From e0b86f1232ba8f875c372238dbbf77ed51f141c1 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Thu, 11 Aug 2011 13:22:23 +0100
Subject: [PATCH] Moved ConnectionWindow into the transport module and
 implemented window sliding (untested).

---
 api/net/sf/briar/api/db/ConnectionWindow.java | 12 -----
 .../briar/api/transport/ConnectionWindow.java | 12 +++++
 .../transport/ConnectionWindowFactory.java    |  6 +++
 .../net/sf/briar/db/ConnectionWindowImpl.java | 30 -----------
 components/net/sf/briar/db/Database.java      |  2 +-
 components/net/sf/briar/db/H2Database.java    |  4 +-
 components/net/sf/briar/db/JdbcDatabase.java  | 12 +++--
 .../ConnectionWindowFactoryImpl.java          | 11 ++++
 .../briar/transport/ConnectionWindowImpl.java | 50 +++++++++++++++++++
 .../sf/briar/transport/TransportModule.java   |  4 +-
 test/net/sf/briar/db/H2DatabaseTest.java      | 19 ++++---
 11 files changed, 106 insertions(+), 56 deletions(-)
 delete mode 100644 api/net/sf/briar/api/db/ConnectionWindow.java
 create mode 100644 api/net/sf/briar/api/transport/ConnectionWindow.java
 create mode 100644 api/net/sf/briar/api/transport/ConnectionWindowFactory.java
 delete mode 100644 components/net/sf/briar/db/ConnectionWindowImpl.java
 create mode 100644 components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java
 create mode 100644 components/net/sf/briar/transport/ConnectionWindowImpl.java

diff --git a/api/net/sf/briar/api/db/ConnectionWindow.java b/api/net/sf/briar/api/db/ConnectionWindow.java
deleted file mode 100644
index 53ed0ed23e..0000000000
--- a/api/net/sf/briar/api/db/ConnectionWindow.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package net.sf.briar.api.db;
-
-public interface ConnectionWindow {
-
-	long getCentre();
-
-	void setCentre(long centre);
-
-	int getBitmap();
-
-	void setBitmap(int bitmap);
-}
diff --git a/api/net/sf/briar/api/transport/ConnectionWindow.java b/api/net/sf/briar/api/transport/ConnectionWindow.java
new file mode 100644
index 0000000000..f04b6c4a16
--- /dev/null
+++ b/api/net/sf/briar/api/transport/ConnectionWindow.java
@@ -0,0 +1,12 @@
+package net.sf.briar.api.transport;
+
+public interface ConnectionWindow {
+
+	long getCentre();
+
+	int getBitmap();
+
+	boolean isSeen(long connectionNumber);
+
+	void setSeen(long connectionNumber);
+}
diff --git a/api/net/sf/briar/api/transport/ConnectionWindowFactory.java b/api/net/sf/briar/api/transport/ConnectionWindowFactory.java
new file mode 100644
index 0000000000..40ad981528
--- /dev/null
+++ b/api/net/sf/briar/api/transport/ConnectionWindowFactory.java
@@ -0,0 +1,6 @@
+package net.sf.briar.api.transport;
+
+public interface ConnectionWindowFactory {
+
+	ConnectionWindow createConnectionWindow(long centre, int bitmap);
+}
diff --git a/components/net/sf/briar/db/ConnectionWindowImpl.java b/components/net/sf/briar/db/ConnectionWindowImpl.java
deleted file mode 100644
index 6010a0fc36..0000000000
--- a/components/net/sf/briar/db/ConnectionWindowImpl.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package net.sf.briar.db;
-
-import net.sf.briar.api.db.ConnectionWindow;
-
-class ConnectionWindowImpl implements ConnectionWindow {
-
-	private long centre;
-	private int bitmap;
-
-	ConnectionWindowImpl(long centre, int bitmap) {
-		this.centre = centre;
-		this.bitmap = bitmap;
-	}
-
-	public long getCentre() {
-		return centre;
-	}
-
-	public void setCentre(long centre) {
-		this.centre = centre;
-	}
-
-	public int getBitmap() {
-		return bitmap;
-	}
-
-	public void setBitmap(int bitmap) {
-		this.bitmap = bitmap;
-	}
-}
diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index 39042ef7ea..425438081a 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -5,7 +5,6 @@ import java.util.Map;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
-import net.sf.briar.api.db.ConnectionWindow;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
 import net.sf.briar.api.protocol.AuthorId;
@@ -14,6 +13,7 @@ import net.sf.briar.api.protocol.Group;
 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.transport.ConnectionWindow;
 
 /**
  * A low-level interface to the database (DatabaseComponent provides a
diff --git a/components/net/sf/briar/db/H2Database.java b/components/net/sf/briar/db/H2Database.java
index 3092556462..6a1548f753 100644
--- a/components/net/sf/briar/db/H2Database.java
+++ b/components/net/sf/briar/db/H2Database.java
@@ -14,6 +14,7 @@ import net.sf.briar.api.crypto.Password;
 import net.sf.briar.api.db.DatabasePassword;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.protocol.GroupFactory;
+import net.sf.briar.api.transport.ConnectionWindowFactory;
 
 import org.apache.commons.io.FileSystemUtils;
 
@@ -32,8 +33,9 @@ class H2Database extends JdbcDatabase {
 
 	@Inject
 	H2Database(File dir, @DatabasePassword Password password, long maxSize,
+			ConnectionWindowFactory connectionWindowFactory,
 			GroupFactory groupFactory) {
-		super(groupFactory, "BINARY(32)", "BINARY");
+		super(connectionWindowFactory, groupFactory, "BINARY(32)", "BINARY");
 		home = new File(dir, "db");
 		this.password = password;
 		url = "jdbc:h2:split:" + home.getPath()
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 39bdf88b03..5002ca4fd1 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -20,7 +20,6 @@ import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
-import net.sf.briar.api.db.ConnectionWindow;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
@@ -31,6 +30,8 @@ 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.transport.ConnectionWindow;
+import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.util.FileUtils;
 
 /**
@@ -200,6 +201,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 
 	// Different database libraries use different names for certain types
 	private final String hashType, binaryType;
+	private final ConnectionWindowFactory connectionWindowFactory;
 	private final GroupFactory groupFactory;
 	private final LinkedList<Connection> connections =
 		new LinkedList<Connection>(); // Locking: self
@@ -209,8 +211,9 @@ abstract class JdbcDatabase implements Database<Connection> {
 
 	protected abstract Connection createConnection() throws SQLException;
 
-	JdbcDatabase(GroupFactory groupFactory, String hashType,
-			String binaryType) {
+	JdbcDatabase(ConnectionWindowFactory connectionWindowFactory,
+			GroupFactory groupFactory, String hashType, String binaryType) {
+		this.connectionWindowFactory = connectionWindowFactory;
 		this.groupFactory = groupFactory;
 		this.hashType = hashType;
 		this.binaryType = binaryType;
@@ -750,7 +753,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 			}
 			rs.close();
 			ps.close();
-			return new ConnectionWindowImpl(centre, bitmap);
+			return connectionWindowFactory.createConnectionWindow(centre,
+					bitmap);
 		} catch(SQLException e) {
 			tryToClose(rs);
 			tryToClose(ps);
diff --git a/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java
new file mode 100644
index 0000000000..ff5b3f2fdc
--- /dev/null
+++ b/components/net/sf/briar/transport/ConnectionWindowFactoryImpl.java
@@ -0,0 +1,11 @@
+package net.sf.briar.transport;
+
+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);
+	}
+}
diff --git a/components/net/sf/briar/transport/ConnectionWindowImpl.java b/components/net/sf/briar/transport/ConnectionWindowImpl.java
new file mode 100644
index 0000000000..25910776f7
--- /dev/null
+++ b/components/net/sf/briar/transport/ConnectionWindowImpl.java
@@ -0,0 +1,50 @@
+package net.sf.briar.transport;
+
+import net.sf.briar.api.transport.ConnectionWindow;
+
+class ConnectionWindowImpl implements ConnectionWindow {
+
+	private static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
+
+	private long centre;
+	private int bitmap;
+
+	ConnectionWindowImpl(long centre, int bitmap) {
+		this.centre = centre;
+		this.bitmap = bitmap;
+	}
+
+	public long getCentre() {
+		return centre;
+	}
+
+	public int getBitmap() {
+		return bitmap;
+	}
+
+	public boolean isSeen(long connectionNumber) {
+		int offset = getOffset(connectionNumber);
+		int mask = 0x80000000 >>> offset;
+		return (bitmap & mask) != 0;
+	}
+
+	public void setSeen(long connectionNumber) {
+		int offset = getOffset(connectionNumber);
+		int mask = 0x80000000 >>> offset;
+		bitmap |= mask;
+		// If the new connection number is above the centre, slide the window
+		if(connectionNumber >= centre) {
+			centre = connectionNumber + 1;
+			bitmap <<= offset - 16 + 1;
+		}
+	}
+
+	private int getOffset(long connectionNumber) {
+		if(connectionNumber < 0L) throw new IllegalArgumentException();
+		if(connectionNumber > MAX_32_BIT_UNSIGNED)
+			throw new IllegalArgumentException();
+		int offset = (int) (connectionNumber - centre) + 16;
+		if(offset < 0 || offset > 31) throw new IllegalArgumentException();
+		return offset;
+	}
+}
diff --git a/components/net/sf/briar/transport/TransportModule.java b/components/net/sf/briar/transport/TransportModule.java
index 8a138334df..a2a6807cb2 100644
--- a/components/net/sf/briar/transport/TransportModule.java
+++ b/components/net/sf/briar/transport/TransportModule.java
@@ -1,5 +1,6 @@
 package net.sf.briar.transport;
 
+import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.api.transport.PacketWriter;
 
 import com.google.inject.AbstractModule;
@@ -8,6 +9,7 @@ public class TransportModule extends AbstractModule {
 
 	@Override
 	protected void configure() {
-		bind(PacketWriter.class).to(PacketWriterImpl.class);
+		bind(ConnectionWindowFactory.class).to(
+				ConnectionWindowFactoryImpl.class);
 	}
 }
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index 95021acd29..87497ed4ca 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -17,7 +17,6 @@ import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
 import net.sf.briar.api.crypto.Password;
-import net.sf.briar.api.db.ConnectionWindow;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
 import net.sf.briar.api.protocol.AuthorId;
@@ -27,9 +26,12 @@ 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.transport.ConnectionWindow;
+import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.protocol.ProtocolModule;
 import net.sf.briar.serial.SerialModule;
+import net.sf.briar.transport.TransportModule;
 
 import org.apache.commons.io.FileSystemUtils;
 import org.junit.After;
@@ -49,6 +51,7 @@ public class H2DatabaseTest extends TestCase {
 	private final String passwordString = "foo bar";
 	private final Password password = new TestPassword();
 	private final Random random = new Random();
+	private final ConnectionWindowFactory connectionWindowFactory;
 	private final GroupFactory groupFactory;
 
 	private final AuthorId authorId;
@@ -67,7 +70,9 @@ public class H2DatabaseTest extends TestCase {
 	public H2DatabaseTest() throws Exception {
 		super();
 		Injector i = Guice.createInjector(new CryptoModule(),
-				new ProtocolModule(), new SerialModule());
+				new ProtocolModule(), new SerialModule(),
+				new TransportModule());
+		connectionWindowFactory = i.getInstance(ConnectionWindowFactory.class);
 		groupFactory = i.getInstance(GroupFactory.class);
 		authorId = new AuthorId(TestUtils.getRandomId());
 		batchId = new BatchId(TestUtils.getRandomId());
@@ -1248,15 +1253,15 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(0, w.getBitmap());
 
 		// Update the connection window and store it
-		w.setCentre(1);
-		w.setBitmap(0x00008000);
+		w.setSeen(5L);
 		db.setConnectionWindow(txn, contactId, 123, w);
 
 		// Check that the connection window was stored
 		w = db.getConnectionWindow(txn, contactId, 123);
 		assertNotNull(w);
-		assertEquals(1L, w.getCentre());
-		assertEquals(0x00008000, w.getBitmap());
+		assertEquals(6L, w.getCentre());
+		assertTrue(w.isSeen(5L));
+		assertEquals(0x00010000, w.getBitmap());
 
 		db.commitTransaction(txn);
 		db.close();
@@ -1280,7 +1285,7 @@ public class H2DatabaseTest extends TestCase {
 
 	private Database<Connection> open(boolean resume) throws DbException {
 		Database<Connection> db = new H2Database(testDir, password, MAX_SIZE,
-				groupFactory);
+				connectionWindowFactory, groupFactory);
 		db.open(resume);
 		return db;
 	}
-- 
GitLab