mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 21:59:54 +01:00
Allow the transport to specify the maximum segment length.
This commit is contained in:
@@ -8,4 +8,9 @@ public interface SegmentSink {
|
|||||||
|
|
||||||
/** Writes the given segment. */
|
/** Writes the given segment. */
|
||||||
void writeSegment(Segment s) throws IOException;
|
void writeSegment(Segment s) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum length in bytes of the segments this sink accepts.
|
||||||
|
*/
|
||||||
|
int getMaxSegmentLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,4 +11,9 @@ public interface SegmentSource {
|
|||||||
* segment was read, or false if no more segments can be read.
|
* segment was read, or false if no more segments can be read.
|
||||||
*/
|
*/
|
||||||
boolean readSegment(Segment s) throws IOException;
|
boolean readSegment(Segment s) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum length in bytes of the segments this source returns.
|
||||||
|
*/
|
||||||
|
int getMaxSegmentLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
|
|||||||
ConnectionReaderImpl(IncomingReliabilityLayer in, boolean tolerateErrors) {
|
ConnectionReaderImpl(IncomingReliabilityLayer in, boolean tolerateErrors) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.tolerateErrors = tolerateErrors;
|
this.tolerateErrors = tolerateErrors;
|
||||||
frame = new Frame();
|
frame = new Frame(in.getMaxFrameLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package net.sf.briar.transport;
|
|||||||
|
|
||||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
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.MAC_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
|
||||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -19,6 +18,7 @@ import net.sf.briar.api.transport.ConnectionWriter;
|
|||||||
class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
||||||
|
|
||||||
private final OutgoingReliabilityLayer out;
|
private final OutgoingReliabilityLayer out;
|
||||||
|
private final int maxFrameLength;
|
||||||
private final Frame frame;
|
private final Frame frame;
|
||||||
|
|
||||||
private int offset = FRAME_HEADER_LENGTH;
|
private int offset = FRAME_HEADER_LENGTH;
|
||||||
@@ -26,7 +26,8 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
|||||||
|
|
||||||
ConnectionWriterImpl(OutgoingReliabilityLayer out) {
|
ConnectionWriterImpl(OutgoingReliabilityLayer out) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
frame = new Frame();
|
maxFrameLength = out.getMaxFrameLength();
|
||||||
|
frame = new Frame(maxFrameLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
@@ -39,7 +40,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
|||||||
if(offset > FRAME_HEADER_LENGTH)
|
if(offset > FRAME_HEADER_LENGTH)
|
||||||
capacity -= offset + MAC_LENGTH;
|
capacity -= offset + MAC_LENGTH;
|
||||||
// Subtract the overhead from the remaining capacity
|
// Subtract the overhead from the remaining capacity
|
||||||
long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH);
|
long frames = (long) Math.ceil((double) capacity / maxFrameLength);
|
||||||
int overheadPerFrame = FRAME_HEADER_LENGTH + MAC_LENGTH;
|
int overheadPerFrame = FRAME_HEADER_LENGTH + MAC_LENGTH;
|
||||||
return Math.max(0L, capacity - frames * overheadPerFrame);
|
return Math.max(0L, capacity - frames * overheadPerFrame);
|
||||||
}
|
}
|
||||||
@@ -53,7 +54,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
frame.getBuffer()[offset++] = (byte) b;
|
frame.getBuffer()[offset++] = (byte) b;
|
||||||
if(offset + MAC_LENGTH == MAX_FRAME_LENGTH) writeFrame();
|
if(offset + MAC_LENGTH == maxFrameLength) writeFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -64,14 +65,14 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void write(byte[] b, int off, int len) throws IOException {
|
public void write(byte[] b, int off, int len) throws IOException {
|
||||||
byte[] buf = frame.getBuffer();
|
byte[] buf = frame.getBuffer();
|
||||||
int available = MAX_FRAME_LENGTH - offset - MAC_LENGTH;
|
int available = maxFrameLength - offset - MAC_LENGTH;
|
||||||
while(available <= len) {
|
while(available <= len) {
|
||||||
System.arraycopy(b, off, buf, offset, available);
|
System.arraycopy(b, off, buf, offset, available);
|
||||||
offset += available;
|
offset += available;
|
||||||
writeFrame();
|
writeFrame();
|
||||||
off += available;
|
off += available;
|
||||||
len -= available;
|
len -= available;
|
||||||
available = MAX_FRAME_LENGTH - offset - MAC_LENGTH;
|
available = maxFrameLength - offset - MAC_LENGTH;
|
||||||
}
|
}
|
||||||
System.arraycopy(b, off, buf, offset, len);
|
System.arraycopy(b, off, buf, offset, len);
|
||||||
offset += len;
|
offset += len;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package net.sf.briar.transport;
|
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 static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
|
|
||||||
class Frame {
|
class Frame {
|
||||||
|
|
||||||
@@ -13,6 +16,9 @@ class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Frame(int length) {
|
Frame(int length) {
|
||||||
|
if(length < FRAME_HEADER_LENGTH + MAC_LENGTH)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException();
|
||||||
buf = new byte[length];
|
buf = new byte[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,4 +15,7 @@ interface IncomingAuthenticationLayer {
|
|||||||
*/
|
*/
|
||||||
boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
||||||
InvalidDataException;
|
InvalidDataException;
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer returns. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package net.sf.briar.transport;
|
|||||||
|
|
||||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
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.MAC_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@@ -14,13 +13,13 @@ import net.sf.briar.api.crypto.ErasableKey;
|
|||||||
class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer {
|
class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer {
|
||||||
|
|
||||||
private final IncomingErrorCorrectionLayer in;
|
private final IncomingErrorCorrectionLayer in;
|
||||||
|
private final int maxFrameLength;
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
|
|
||||||
IncomingAuthenticationLayerImpl(IncomingErrorCorrectionLayer in, Mac mac,
|
IncomingAuthenticationLayerImpl(IncomingErrorCorrectionLayer in, Mac mac,
|
||||||
ErasableKey macKey) {
|
ErasableKey macKey) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
// Initialise the MAC
|
|
||||||
try {
|
try {
|
||||||
mac.init(macKey);
|
mac.init(macKey);
|
||||||
} catch(InvalidKeyException e) {
|
} catch(InvalidKeyException e) {
|
||||||
@@ -29,6 +28,7 @@ class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer {
|
|||||||
macKey.erase();
|
macKey.erase();
|
||||||
if(mac.getMacLength() != MAC_LENGTH)
|
if(mac.getMacLength() != MAC_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
maxFrameLength = in.getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
public boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
||||||
@@ -39,7 +39,7 @@ class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer {
|
|||||||
int length = f.getLength();
|
int length = f.getLength();
|
||||||
if(length < FRAME_HEADER_LENGTH + MAC_LENGTH)
|
if(length < FRAME_HEADER_LENGTH + MAC_LENGTH)
|
||||||
throw new InvalidDataException();
|
throw new InvalidDataException();
|
||||||
if(length > MAX_FRAME_LENGTH) throw new InvalidDataException();
|
if(length > maxFrameLength) throw new InvalidDataException();
|
||||||
// Check that the payload and padding lengths are correct
|
// Check that the payload and padding lengths are correct
|
||||||
byte[] buf = f.getBuffer();
|
byte[] buf = f.getBuffer();
|
||||||
int payload = HeaderEncoder.getPayloadLength(buf);
|
int payload = HeaderEncoder.getPayloadLength(buf);
|
||||||
@@ -61,4 +61,8 @@ class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,9 @@ interface IncomingEncryptionLayer {
|
|||||||
* may choose whether to retry the read or close the connection.
|
* may choose whether to retry the read or close the connection.
|
||||||
*/
|
*/
|
||||||
boolean readSegment(Segment s) throws IOException, InvalidDataException;
|
boolean readSegment(Segment s) throws IOException, InvalidDataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum length in bytes of the segments this layer returns.
|
||||||
|
*/
|
||||||
|
int getMaxSegmentLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
|||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final Cipher tagCipher, segCipher;
|
private final Cipher tagCipher, segCipher;
|
||||||
private final ErasableKey tagKey, segKey;
|
private final ErasableKey tagKey, segKey;
|
||||||
|
private final boolean tagEverySegment;
|
||||||
private final int blockSize;
|
private final int blockSize;
|
||||||
private final byte[] iv, ciphertext;
|
private final byte[] iv, ciphertext;
|
||||||
private final boolean tagEverySegment;
|
|
||||||
|
|
||||||
private byte[] bufferedTag;
|
private byte[] bufferedTag;
|
||||||
private boolean firstSegment = true;
|
private boolean firstSegment = true;
|
||||||
@@ -128,4 +128,8 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH - TAG_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,4 +15,7 @@ interface IncomingErrorCorrectionLayer {
|
|||||||
*/
|
*/
|
||||||
boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
||||||
InvalidDataException;
|
InvalidDataException;
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer returns. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -14,7 +16,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
|
|
||||||
private final IncomingEncryptionLayer in;
|
private final IncomingEncryptionLayer in;
|
||||||
private final ErasureDecoder decoder;
|
private final ErasureDecoder decoder;
|
||||||
private final int n, k;
|
private final int n, k, maxSegmentLength, maxFrameLength;
|
||||||
private final Map<Long, Integer> discardCounts;
|
private final Map<Long, Integer> discardCounts;
|
||||||
private final Map<Long, Segment[]> segmentSets;
|
private final Map<Long, Segment[]> segmentSets;
|
||||||
private final ArrayList<Segment> freeSegments;
|
private final ArrayList<Segment> freeSegments;
|
||||||
@@ -25,6 +27,8 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
this.decoder = decoder;
|
this.decoder = decoder;
|
||||||
this.n = n;
|
this.n = n;
|
||||||
this.k = k;
|
this.k = k;
|
||||||
|
maxSegmentLength = in.getMaxSegmentLength();
|
||||||
|
maxFrameLength = Math.min(MAX_FRAME_LENGTH, maxSegmentLength * k);
|
||||||
discardCounts = new HashMap<Long, Integer>();
|
discardCounts = new HashMap<Long, Integer>();
|
||||||
segmentSets = new HashMap<Long, Segment[]>();
|
segmentSets = new HashMap<Long, Segment[]>();
|
||||||
freeSegments = new ArrayList<Segment>();
|
freeSegments = new ArrayList<Segment>();
|
||||||
@@ -47,7 +51,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
// Grab a free segment, or allocate one if necessary
|
// Grab a free segment, or allocate one if necessary
|
||||||
Segment s;
|
Segment s;
|
||||||
int free = freeSegments.size();
|
int free = freeSegments.size();
|
||||||
if(free == 0) s = new SegmentImpl();
|
if(free == 0) s = new SegmentImpl(maxSegmentLength);
|
||||||
else s = freeSegments.remove(free - 1);
|
else s = freeSegments.remove(free - 1);
|
||||||
// Read segments until a frame can be decoded
|
// Read segments until a frame can be decoded
|
||||||
while(true) {
|
while(true) {
|
||||||
@@ -74,6 +78,10 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
|
|
||||||
private void countDiscard(long frameNumber) throws FormatException {
|
private void countDiscard(long frameNumber) throws FormatException {
|
||||||
Integer count = discardCounts.get(frameNumber);
|
Integer count = discardCounts.get(frameNumber);
|
||||||
if(count == null) discardCounts.put(frameNumber, 1);
|
if(count == null) discardCounts.put(frameNumber, 1);
|
||||||
|
|||||||
@@ -13,4 +13,7 @@ interface IncomingReliabilityLayer {
|
|||||||
* may choose whether to retry the read or close the connection.
|
* may choose whether to retry the read or close the connection.
|
||||||
*/
|
*/
|
||||||
boolean readFrame(Frame f) throws IOException, InvalidDataException;
|
boolean readFrame(Frame f) throws IOException, InvalidDataException;
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer returns. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
|||||||
private final SegmentSource in;
|
private final SegmentSource in;
|
||||||
private final Cipher tagCipher, segCipher;
|
private final Cipher tagCipher, segCipher;
|
||||||
private final ErasableKey tagKey, segKey;
|
private final ErasableKey tagKey, segKey;
|
||||||
private final int blockSize;
|
|
||||||
private final byte[] iv;
|
|
||||||
private final boolean tagEverySegment;
|
private final boolean tagEverySegment;
|
||||||
|
private final int blockSize, maxSegmentLength;
|
||||||
private final Segment segment;
|
private final Segment segment;
|
||||||
|
private final byte[] iv;
|
||||||
|
|
||||||
private Segment bufferedSegment;
|
private Segment bufferedSegment;
|
||||||
private boolean firstSegment = true;
|
private boolean firstSegment = true;
|
||||||
@@ -42,8 +42,13 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
|||||||
blockSize = segCipher.getBlockSize();
|
blockSize = segCipher.getBlockSize();
|
||||||
if(blockSize < FRAME_HEADER_LENGTH)
|
if(blockSize < FRAME_HEADER_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
int length = in.getMaxSegmentLength();
|
||||||
|
if(length < TAG_LENGTH + FRAME_HEADER_LENGTH + 1 + MAC_LENGTH)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException();
|
||||||
|
maxSegmentLength = length - TAG_LENGTH;
|
||||||
|
segment = new SegmentImpl(length);
|
||||||
iv = IvEncoder.encodeIv(0L, blockSize);
|
iv = IvEncoder.encodeIv(0L, blockSize);
|
||||||
segment = new SegmentImpl();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readSegment(Segment s) throws IOException,
|
public boolean readSegment(Segment s) throws IOException,
|
||||||
@@ -62,9 +67,10 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
|||||||
}
|
}
|
||||||
int offset = expectTag ? TAG_LENGTH : 0;
|
int offset = expectTag ? TAG_LENGTH : 0;
|
||||||
int length = segment.getLength();
|
int length = segment.getLength();
|
||||||
if(length > MAX_SEGMENT_LENGTH) throw new InvalidDataException();
|
|
||||||
if(length < offset + FRAME_HEADER_LENGTH + MAC_LENGTH)
|
if(length < offset + FRAME_HEADER_LENGTH + MAC_LENGTH)
|
||||||
throw new InvalidDataException();
|
throw new InvalidDataException();
|
||||||
|
if(length > offset + maxSegmentLength)
|
||||||
|
throw new InvalidDataException();
|
||||||
byte[] ciphertext = segment.getBuffer();
|
byte[] ciphertext = segment.getBuffer();
|
||||||
// If a tag is expected then decrypt and validate it
|
// If a tag is expected then decrypt and validate it
|
||||||
if(expectTag) {
|
if(expectTag) {
|
||||||
@@ -92,4 +98,8 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return maxSegmentLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ import net.sf.briar.api.transport.Segment;
|
|||||||
class NullIncomingErrorCorrectionLayer implements IncomingErrorCorrectionLayer {
|
class NullIncomingErrorCorrectionLayer implements IncomingErrorCorrectionLayer {
|
||||||
|
|
||||||
private final IncomingEncryptionLayer in;
|
private final IncomingEncryptionLayer in;
|
||||||
|
private final int maxFrameLength;
|
||||||
private final Segment segment;
|
private final Segment segment;
|
||||||
|
|
||||||
NullIncomingErrorCorrectionLayer(IncomingEncryptionLayer in) {
|
NullIncomingErrorCorrectionLayer(IncomingEncryptionLayer in) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
segment = new SegmentImpl();
|
maxFrameLength = in.getMaxSegmentLength();
|
||||||
|
segment = new SegmentImpl(maxFrameLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
public boolean readFrame(Frame f, FrameWindow window) throws IOException,
|
||||||
@@ -28,4 +30,8 @@ class NullIncomingErrorCorrectionLayer implements IncomingErrorCorrectionLayer {
|
|||||||
f.setLength(length);
|
f.setLength(length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import java.io.IOException;
|
|||||||
class NullIncomingReliabilityLayer implements IncomingReliabilityLayer {
|
class NullIncomingReliabilityLayer implements IncomingReliabilityLayer {
|
||||||
|
|
||||||
private final IncomingAuthenticationLayer in;
|
private final IncomingAuthenticationLayer in;
|
||||||
|
private final int maxFrameLength;
|
||||||
private final FrameWindow window;
|
private final FrameWindow window;
|
||||||
|
|
||||||
NullIncomingReliabilityLayer(IncomingAuthenticationLayer in) {
|
NullIncomingReliabilityLayer(IncomingAuthenticationLayer in) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
|
maxFrameLength = in.getMaxFrameLength();
|
||||||
window = new NullFrameWindow();
|
window = new NullFrameWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,4 +20,8 @@ class NullIncomingReliabilityLayer implements IncomingReliabilityLayer {
|
|||||||
if(!window.remove(frameNumber)) throw new IllegalStateException();
|
if(!window.remove(frameNumber)) throw new IllegalStateException();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ import net.sf.briar.api.transport.Segment;
|
|||||||
class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer {
|
class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer {
|
||||||
|
|
||||||
private final OutgoingEncryptionLayer out;
|
private final OutgoingEncryptionLayer out;
|
||||||
|
private final int maxSegmentLength;
|
||||||
private final Segment segment;
|
private final Segment segment;
|
||||||
|
|
||||||
private long segmentNumber = 0L;
|
private long segmentNumber = 0L;
|
||||||
|
|
||||||
public NullOutgoingErrorCorrectionLayer(OutgoingEncryptionLayer out) {
|
public NullOutgoingErrorCorrectionLayer(OutgoingEncryptionLayer out) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
segment = new SegmentImpl();
|
maxSegmentLength = out.getMaxSegmentLength();
|
||||||
|
segment = new SegmentImpl(maxSegmentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeFrame(Frame f) throws IOException {
|
public void writeFrame(Frame f) throws IOException {
|
||||||
@@ -36,4 +38,8 @@ class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return out.getRemainingCapacity();
|
return out.getRemainingCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxSegmentLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import java.io.IOException;
|
|||||||
class NullOutgoingReliabilityLayer implements OutgoingReliabilityLayer {
|
class NullOutgoingReliabilityLayer implements OutgoingReliabilityLayer {
|
||||||
|
|
||||||
private final OutgoingAuthenticationLayer out;
|
private final OutgoingAuthenticationLayer out;
|
||||||
|
private final int maxFrameLength;
|
||||||
|
|
||||||
NullOutgoingReliabilityLayer(OutgoingAuthenticationLayer out) {
|
NullOutgoingReliabilityLayer(OutgoingAuthenticationLayer out) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
|
maxFrameLength = out.getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeFrame(Frame f) throws IOException {
|
public void writeFrame(Frame f) throws IOException {
|
||||||
@@ -21,4 +23,8 @@ class NullOutgoingReliabilityLayer implements OutgoingReliabilityLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return out.getRemainingCapacity();
|
return out.getRemainingCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,4 +12,7 @@ interface OutgoingAuthenticationLayer {
|
|||||||
|
|
||||||
/** Returns the maximum number of bytes that can be written. */
|
/** Returns the maximum number of bytes that can be written. */
|
||||||
long getRemainingCapacity();
|
long getRemainingCapacity();
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer accepts. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer {
|
|||||||
|
|
||||||
private final OutgoingErrorCorrectionLayer out;
|
private final OutgoingErrorCorrectionLayer out;
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
|
private final int maxFrameLength;
|
||||||
|
|
||||||
OutgoingAuthenticationLayerImpl(OutgoingErrorCorrectionLayer out, Mac mac,
|
OutgoingAuthenticationLayerImpl(OutgoingErrorCorrectionLayer out, Mac mac,
|
||||||
ErasableKey macKey) {
|
ErasableKey macKey) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
// Initialise the MAC
|
|
||||||
try {
|
try {
|
||||||
mac.init(macKey);
|
mac.init(macKey);
|
||||||
} catch(InvalidKeyException badKey) {
|
} catch(InvalidKeyException badKey) {
|
||||||
@@ -28,6 +28,7 @@ class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer {
|
|||||||
macKey.erase();
|
macKey.erase();
|
||||||
if(mac.getMacLength() != MAC_LENGTH)
|
if(mac.getMacLength() != MAC_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
maxFrameLength = out.getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeFrame(Frame f) throws IOException {
|
public void writeFrame(Frame f) throws IOException {
|
||||||
@@ -49,4 +50,8 @@ class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return out.getRemainingCapacity();
|
return out.getRemainingCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,9 @@ interface OutgoingEncryptionLayer {
|
|||||||
|
|
||||||
/** Returns the maximum number of bytes that can be written. */
|
/** Returns the maximum number of bytes that can be written. */
|
||||||
long getRemainingCapacity();
|
long getRemainingCapacity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum length in bytes of the segments this layer accepts.
|
||||||
|
*/
|
||||||
|
int getMaxSegmentLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,4 +73,8 @@ class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH - TAG_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,4 +12,7 @@ interface OutgoingErrorCorrectionLayer {
|
|||||||
|
|
||||||
/** Returns the maximum number of bytes that can be written. */
|
/** Returns the maximum number of bytes that can be written. */
|
||||||
long getRemainingCapacity();
|
long getRemainingCapacity();
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer accepts. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import net.sf.briar.api.transport.Segment;
|
import net.sf.briar.api.transport.Segment;
|
||||||
@@ -8,13 +10,15 @@ class OutgoingErrorCorrectionLayerImpl implements OutgoingErrorCorrectionLayer {
|
|||||||
|
|
||||||
private final OutgoingEncryptionLayer out;
|
private final OutgoingEncryptionLayer out;
|
||||||
private final ErasureEncoder encoder;
|
private final ErasureEncoder encoder;
|
||||||
private final int n;
|
private final int n, maxFrameLength;
|
||||||
|
|
||||||
OutgoingErrorCorrectionLayerImpl(OutgoingEncryptionLayer out,
|
OutgoingErrorCorrectionLayerImpl(OutgoingEncryptionLayer out,
|
||||||
ErasureEncoder encoder, int n) {
|
ErasureEncoder encoder, int n, int k) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.encoder = encoder;
|
this.encoder = encoder;
|
||||||
this.n = n;
|
this.n = n;
|
||||||
|
maxFrameLength = Math.min(MAX_FRAME_LENGTH,
|
||||||
|
out.getMaxSegmentLength() * k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeFrame(Frame f) throws IOException {
|
public void writeFrame(Frame f) throws IOException {
|
||||||
@@ -28,4 +32,8 @@ class OutgoingErrorCorrectionLayerImpl implements OutgoingErrorCorrectionLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return out.getRemainingCapacity() / n;
|
return out.getRemainingCapacity() / n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxFrameLength() {
|
||||||
|
return maxFrameLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,4 +12,7 @@ interface OutgoingReliabilityLayer {
|
|||||||
|
|
||||||
/** Returns the maximum number of bytes that can be written. */
|
/** Returns the maximum number of bytes that can be written. */
|
||||||
long getRemainingCapacity();
|
long getRemainingCapacity();
|
||||||
|
|
||||||
|
/** Returns the maximum length in bytes of the frames this layer accepts. */
|
||||||
|
int getMaxFrameLength();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package net.sf.briar.transport;
|
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_SEGMENT_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -18,8 +21,9 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
|||||||
private final Cipher tagCipher, segCipher;
|
private final Cipher tagCipher, segCipher;
|
||||||
private final ErasableKey tagKey, segKey;
|
private final ErasableKey tagKey, segKey;
|
||||||
private final boolean tagEverySegment;
|
private final boolean tagEverySegment;
|
||||||
private final byte[] iv;
|
private final int maxSegmentLength;
|
||||||
private final Segment segment;
|
private final Segment segment;
|
||||||
|
private final byte[] iv;
|
||||||
|
|
||||||
private long capacity;
|
private long capacity;
|
||||||
|
|
||||||
@@ -33,8 +37,13 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
|||||||
this.tagKey = tagKey;
|
this.tagKey = tagKey;
|
||||||
this.segKey = segKey;
|
this.segKey = segKey;
|
||||||
this.tagEverySegment = tagEverySegment;
|
this.tagEverySegment = tagEverySegment;
|
||||||
|
int length = out.getMaxSegmentLength();
|
||||||
|
if(length < TAG_LENGTH + FRAME_HEADER_LENGTH + 1 + MAC_LENGTH)
|
||||||
|
throw new RuntimeException();
|
||||||
|
if(length > MAX_SEGMENT_LENGTH) throw new RuntimeException();
|
||||||
|
maxSegmentLength = length - MAC_LENGTH;
|
||||||
|
segment = new SegmentImpl(length);
|
||||||
iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize());
|
iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize());
|
||||||
segment = new SegmentImpl();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeSegment(Segment s) throws IOException {
|
public void writeSegment(Segment s) throws IOException {
|
||||||
@@ -72,4 +81,8 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return maxSegmentLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.transport;
|
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_SEGMENT_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
import net.sf.briar.api.transport.Segment;
|
import net.sf.briar.api.transport.Segment;
|
||||||
@@ -16,6 +18,9 @@ class SegmentImpl implements Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SegmentImpl(int length) {
|
SegmentImpl(int length) {
|
||||||
|
if(length < FRAME_HEADER_LENGTH + MAC_LENGTH)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException();
|
||||||
buf = new byte[length];
|
buf = new byte[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,5 +160,9 @@ public class IncomingErrorCorrectionLayerImplTest extends BriarTestCase {
|
|||||||
s.setLength(length);
|
s.setLength(length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,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.FRAME_HEADER_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -149,5 +150,9 @@ public class IncomingSegmentedEncryptionLayerTest extends BriarTestCase {
|
|||||||
s.setLength(segment.length);
|
s.setLength(segment.length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package net.sf.briar.transport;
|
|||||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
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.MAC_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -49,4 +51,8 @@ class NullIncomingEncryptionLayer implements IncomingEncryptionLayer {
|
|||||||
s.setSegmentNumber(segmentNumber++);
|
s.setSegmentNumber(segmentNumber++);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH - TAG_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
@@ -34,4 +37,8 @@ class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer {
|
|||||||
public long getRemainingCapacity() {
|
public long getRemainingCapacity() {
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH - TAG_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
@@ -136,5 +137,9 @@ public class OutgoingSegmentedEncryptionLayerTest extends BriarTestCase {
|
|||||||
public void writeSegment(Segment s) throws IOException {
|
public void writeSegment(Segment s) throws IOException {
|
||||||
write(s.getBuffer(), 0, s.getLength());
|
write(s.getBuffer(), 0, s.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxSegmentLength() {
|
||||||
|
return MAX_SEGMENT_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ package net.sf.briar.transport;
|
|||||||
|
|
||||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
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.MAC_LENGTH;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import net.sf.briar.BriarTestCase;
|
import net.sf.briar.BriarTestCase;
|
||||||
import net.sf.briar.api.transport.Segment;
|
import net.sf.briar.api.transport.Segment;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class XorErasureCodeTest extends BriarTestCase {
|
public class XorErasureCodeTest extends BriarTestCase {
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package net.sf.briar.transport;
|
|||||||
import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
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.MAC_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import net.sf.briar.BriarTestCase;
|
import net.sf.briar.BriarTestCase;
|
||||||
import net.sf.briar.api.FormatException;
|
import net.sf.briar.api.FormatException;
|
||||||
import net.sf.briar.api.transport.Segment;
|
import net.sf.briar.api.transport.Segment;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class XorErasureDecoderTest extends BriarTestCase {
|
public class XorErasureDecoderTest extends BriarTestCase {
|
||||||
|
|||||||
@@ -10,30 +10,29 @@ public class XorErasureEncoderTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncoding() {
|
public void testEncoding() {
|
||||||
// Create a 100-byte frame
|
// Create a frame
|
||||||
Frame f = new Frame();
|
Frame f = new Frame();
|
||||||
f.setLength(100);
|
f.setLength(200);
|
||||||
byte[] b = f.getBuffer();
|
byte[] b = f.getBuffer();
|
||||||
for(int i = 0; i < 100; i++) b[i] = (byte) i;
|
for(int i = 0; i < 200; i++) b[i] = (byte) i;
|
||||||
// Encode the frame
|
// Encode the frame
|
||||||
XorErasureEncoder e = new XorErasureEncoder(4);
|
XorErasureEncoder e = new XorErasureEncoder(4);
|
||||||
Segment[] set = e.encodeFrame(f);
|
Segment[] set = e.encodeFrame(f);
|
||||||
// There should be four pieces of 34 bytes each
|
// There should be four pieces of 67 bytes each
|
||||||
assertEquals(4, set.length);
|
assertEquals(4, set.length);
|
||||||
for(int i = 0; i < 4; i++) assertEquals(34, set[i].getLength());
|
for(int i = 0; i < 4; i++) assertEquals(67, set[i].getLength());
|
||||||
// The first three pieces should contain the data, plus two zero bytes
|
// The first three pieces should contain the data plus on padding byte
|
||||||
byte[] b1 = set[0].getBuffer();
|
byte[] b1 = set[0].getBuffer();
|
||||||
for(int i = 0; i < 34; i++) assertEquals(i, b1[i]);
|
for(int i = 0; i < 67; i++) assertEquals((byte) i, b1[i]);
|
||||||
byte[] b2 = set[1].getBuffer();
|
byte[] b2 = set[1].getBuffer();
|
||||||
for(int i = 0; i < 34; i++) assertEquals(i + 34, b2[i]);
|
for(int i = 0; i < 67; i++) assertEquals((byte) (i + 67), b2[i]);
|
||||||
byte[] b3 = set[2].getBuffer();
|
byte[] b3 = set[2].getBuffer();
|
||||||
for(int i = 0; i < 32; i++) assertEquals(i + 68, b3[i]);
|
for(int i = 0; i < 66; i++) assertEquals((byte) (i + 134), b3[i]);
|
||||||
assertEquals(0, b3[32]);
|
assertEquals(0, b3[66]);
|
||||||
assertEquals(0, b3[33]);
|
|
||||||
// The fourth piece should be the XOR of the other three
|
// The fourth piece should be the XOR of the other three
|
||||||
byte[] b4 = set[3].getBuffer();
|
byte[] b4 = set[3].getBuffer();
|
||||||
byte[] expected = new byte[34];
|
byte[] expected = new byte[67];
|
||||||
for(int i = 0; i < 34; i++) {
|
for(int i = 0; i < 67; i++) {
|
||||||
expected[i] = (byte) (b1[i] ^ b2[i] ^ b3[i]);
|
expected[i] = (byte) (b1[i] ^ b2[i] ^ b3[i]);
|
||||||
}
|
}
|
||||||
assertArrayEquals(expected, b4);
|
assertArrayEquals(expected, b4);
|
||||||
|
|||||||
Reference in New Issue
Block a user