Store each connection window slot as a database row.

This is less memory-efficient but necessary for the coming forward
secrecy changes.
This commit is contained in:
akwizgran
2011-11-15 13:08:20 +00:00
parent cf49a28c95
commit df054b1743
19 changed files with 152 additions and 140 deletions

View File

@@ -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));
}

View File

@@ -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);
}
}

View File

@@ -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 final Set<Long> unseen;
private long centre;
private int bitmap;
ConnectionWindowImpl(long centre, int bitmap) {
this.centre = centre;
this.bitmap = bitmap;
ConnectionWindowImpl() {
unseen = new TreeSet<Long>();
for(long l = 0; l < CONNECTION_WINDOW_SIZE / 2; l++) unseen.add(l);
centre = 0;
}
public long getCentre() {
return centre;
}
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;
}
}