Outgoing error correction layer (untested).

This commit is contained in:
akwizgran
2012-01-20 16:07:07 +00:00
parent e46ef15afb
commit f10af33b6f
7 changed files with 93 additions and 8 deletions

View File

@@ -67,7 +67,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
public ConnectionReader createConnectionReader(SegmentSource in,
byte[] secret) {
return createConnectionReader(in, secret, new SegmentImpl(), false);
return createConnectionReader(in, secret, null, false);
}
private ConnectionReader createConnectionReader(SegmentSource in,

View File

@@ -0,0 +1,9 @@
package net.sf.briar.transport;
import net.sf.briar.api.transport.Segment;
interface ErasureEncoder {
/** Encodes the given frame as a set of segments. */
Segment[] encodeFrame(Frame f);
}

View File

@@ -34,7 +34,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
// Free any discard counts that are no longer too high for the window
Iterator<Long> it1 = discardCounts.keySet().iterator();
while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove();
// Allocate a segment
// FIXME: Unnecessary allocation
Segment s = new SegmentImpl();
// Read segments until a frame can be decoded
while(true) {
@@ -51,9 +51,8 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
if(set == null) {
set = new Segment[n];
segmentSets.put(frameNumber, set);
} else {
set[(int) (frameNumber % n)] = s;
}
set[(int) (frameNumber % n)] = s;
// Try to decode the frame
if(decoder.decodeFrame(f, set)) return true;
}

View File

@@ -0,0 +1,31 @@
package net.sf.briar.transport;
import java.io.IOException;
import net.sf.briar.api.transport.Segment;
class OutgoingErrorCorrectionLayerImpl implements OutgoingErrorCorrectionLayer {
private final OutgoingEncryptionLayer out;
private final ErasureEncoder encoder;
private final int n;
OutgoingErrorCorrectionLayerImpl(OutgoingEncryptionLayer out,
ErasureEncoder encoder, int n) {
this.out = out;
this.encoder = encoder;
this.n = n;
}
public void writeFrame(Frame f) throws IOException {
for(Segment s : encoder.encodeFrame(f)) out.writeSegment(s);
}
public void flush() throws IOException {
out.flush();
}
public long getRemainingCapacity() {
return out.getRemainingCapacity() / n;
}
}

View File

@@ -1,16 +1,24 @@
package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import net.sf.briar.api.transport.Segment;
import net.sf.briar.util.ByteUtils;
class SegmentImpl implements Segment {
private final byte[] buf = new byte[MAX_SEGMENT_LENGTH];
private final byte[] buf;
private int length = -1;
private long segmentNumber = -1;
SegmentImpl() {
this(MAX_SEGMENT_LENGTH);
}
SegmentImpl(int length) {
buf = new byte[length];
}
public byte[] getBuffer() {
return buf;
}
@@ -32,7 +40,7 @@ class SegmentImpl implements Segment {
}
public void setSegmentNumber(long segmentNumber) {
if(segmentNumber < 0 || segmentNumber > ByteUtils.MAX_32_BIT_UNSIGNED)
if(segmentNumber < 0 || segmentNumber > MAX_32_BIT_UNSIGNED)
throw new IllegalArgumentException();
this.segmentNumber = segmentNumber;
}

View File

@@ -1,5 +1,7 @@
package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.transport.Segment;
@@ -54,7 +56,13 @@ class XorErasureDecoder implements ErasureDecoder {
assert missingOffset != -1;
System.arraycopy(parity, 0, dest, missingOffset, length);
}
f.setLength(offset);
assert offset == length * (n - 1);
// The frame length may not be an exact multiple of the segment length
int payload = HeaderEncoder.getPayloadLength(dest);
int padding = HeaderEncoder.getPaddingLength(dest);
int frameLength = FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH;
if(frameLength > MAX_FRAME_LENGTH) throw new FormatException();
f.setLength(frameLength);
return true;
}
}

View File

@@ -0,0 +1,30 @@
package net.sf.briar.transport;
import net.sf.briar.api.transport.Segment;
/** An erasure encoder than uses k data segments and one parity segment. */
class XorErasureEncoder implements ErasureEncoder {
private final int n;
XorErasureEncoder(int n) {
this.n = n;
}
public Segment[] encodeFrame(Frame f) {
Segment[] set = new Segment[n];
int length = (int) Math.ceil((float) f.getLength() / (n - 1));
for(int i = 0; i < n; i++) {
set[i] = new SegmentImpl(length);
set[i].setLength(length);
}
byte[] src = f.getBuffer(), parity = set[n - 1].getBuffer();
int offset = 0;
for(int i = 0; i < n - 1; i++) {
System.arraycopy(src, 0, set[i].getBuffer(), offset, length);
for(int j = 0; j < length; j++) parity[j] ^= src[j];
offset += length;
}
return set;
}
}