Keep the connection windows in memory.

This commit is contained in:
akwizgran
2011-11-16 17:57:56 +00:00
parent f10512d787
commit 01dd658200
4 changed files with 38 additions and 28 deletions

View File

@@ -6,7 +6,7 @@ public interface ConnectionWindow {
boolean isSeen(long connection); boolean isSeen(long connection);
void setSeen(long connection); byte[] setSeen(long connection);
Map<Long, byte[]> getUnseen(); Map<Long, byte[]> getUnseen();
} }

View File

@@ -46,7 +46,7 @@ DatabaseListener {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final DatabaseComponent db; private final DatabaseComponent db;
private final Cipher ivCipher; private final Cipher ivCipher;
private final Map<Bytes, ConnectionContext> expected; private final Map<Bytes, Context> expected;
private final Collection<TransportId> localTransportIds; private final Collection<TransportId> localTransportIds;
private boolean initialised = false; private boolean initialised = false;
@@ -56,7 +56,7 @@ DatabaseListener {
this.crypto = crypto; this.crypto = crypto;
this.db = db; this.db = db;
ivCipher = crypto.getIvCipher(); ivCipher = crypto.getIvCipher();
expected = new HashMap<Bytes, ConnectionContext>(); expected = new HashMap<Bytes, Context>();
localTransportIds = new ArrayList<TransportId>(); localTransportIds = new ArrayList<TransportId>();
db.addListener(this); db.addListener(this);
} }
@@ -93,7 +93,7 @@ DatabaseListener {
ErasableKey ivKey = crypto.deriveIvKey(secret, true); ErasableKey ivKey = crypto.deriveIvKey(secret, true);
Bytes iv = new Bytes(encryptIv(i, unseen, ivKey)); Bytes iv = new Bytes(encryptIv(i, unseen, ivKey));
ivKey.erase(); ivKey.erase();
expected.put(iv, new ConnectionContextImpl(c, i, unseen, secret)); expected.put(iv, new Context(c, i, unseen, w));
} }
} }
@@ -117,28 +117,25 @@ DatabaseListener {
if(encryptedIv.length != IV_LENGTH) if(encryptedIv.length != IV_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if(!initialised) initialise(); if(!initialised) initialise();
ConnectionContext ctx = expected.remove(new Bytes(encryptedIv)); Context ctx = expected.remove(new Bytes(encryptedIv));
if(ctx == null) return null; // The IV was not expected if(ctx == null) return null; // The IV was not expected
// Get the secret and update the connection window
byte[] secret = ctx.window.setSeen(ctx.connection);
try { try {
ContactId c = ctx.getContactId(); db.setConnectionWindow(ctx.contactId, ctx.index, ctx.window);
TransportIndex i = ctx.getTransportIndex();
// Update the connection window
ConnectionWindow w = db.getConnectionWindow(c, i);
w.setSeen(ctx.getConnectionNumber());
db.setConnectionWindow(c, i, w);
// Update the set of expected IVs
Iterator<ConnectionContext> it = expected.values().iterator();
while(it.hasNext()) {
ConnectionContext ctx1 = it.next();
ContactId c1 = ctx1.getContactId();
TransportIndex i1 = ctx1.getTransportIndex();
if(c1.equals(c) && i1.equals(i)) it.remove();
}
calculateIvs(c, i, w);
} catch(NoSuchContactException e) { } catch(NoSuchContactException e) {
// The contact was removed - clean up when we get the event // The contact was removed - clean up when we get the event
} }
return ctx; // Update the set of expected IVs
Iterator<Context> it = expected.values().iterator();
while(it.hasNext()) {
Context ctx1 = it.next();
if(ctx1.contactId.equals(ctx.contactId)
&& ctx1.index.equals(ctx.index)) it.remove();
}
calculateIvs(ctx.contactId, ctx.index, ctx.window);
return new ConnectionContextImpl(ctx.contactId, ctx.index,
ctx.connection, secret);
} }
public void eventOccurred(DatabaseEvent e) { public void eventOccurred(DatabaseEvent e) {
@@ -175,9 +172,8 @@ DatabaseListener {
} }
private synchronized void removeIvs(ContactId c) { private synchronized void removeIvs(ContactId c) {
if(!initialised) return; Iterator<Context> it = expected.values().iterator();
Iterator<ConnectionContext> it = expected.values().iterator(); while(it.hasNext()) if(it.next().contactId.equals(c)) it.remove();
while(it.hasNext()) if(it.next().getContactId().equals(c)) it.remove();
} }
private synchronized void calculateIvs(TransportId t) throws DbException { private synchronized void calculateIvs(TransportId t) throws DbException {
@@ -193,4 +189,20 @@ DatabaseListener {
} }
} }
} }
private static class Context {
private final ContactId contactId;
private final TransportIndex index;
private final long connection;
private final ConnectionWindow window;
private Context(ContactId contactId, TransportIndex index,
long connection, ConnectionWindow window) {
this.contactId = contactId;
this.index = index;
this.connection = connection;
this.window = window;
}
}
} }

View File

@@ -54,7 +54,7 @@ class ConnectionWindowImpl implements ConnectionWindow {
return !unseen.containsKey(connection); return !unseen.containsKey(connection);
} }
public void setSeen(long connection) { public byte[] setSeen(long connection) {
long bottom = getBottom(centre); long bottom = getBottom(centre);
long top = getTop(centre); long top = getTop(centre);
if(connection < bottom || connection > top) if(connection < bottom || connection > top)
@@ -78,7 +78,7 @@ class ConnectionWindowImpl implements ConnectionWindow {
} }
byte[] seen = unseen.remove(connection); byte[] seen = unseen.remove(connection);
assert seen != null; assert seen != null;
ByteUtils.erase(seen); return seen;
} }
// Returns the lowest value contained in a window with the given centre // Returns the lowest value contained in a window with the given centre

View File

@@ -106,8 +106,6 @@ public class ConnectionRecogniserImplTest extends TestCase {
oneOf(db).getConnectionWindow(contactId, remoteIndex); oneOf(db).getConnectionWindow(contactId, remoteIndex);
will(returnValue(connectionWindow)); will(returnValue(connectionWindow));
// Update the window // Update the window
oneOf(db).getConnectionWindow(contactId, remoteIndex);
will(returnValue(connectionWindow));
oneOf(db).setConnectionWindow(contactId, remoteIndex, oneOf(db).setConnectionWindow(contactId, remoteIndex,
connectionWindow); connectionWindow);
}}); }});