mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-22 15:49:53 +01:00
Outgoing error correction layer (untested).
This commit is contained in:
@@ -67,7 +67,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
|
|
||||||
public ConnectionReader createConnectionReader(SegmentSource in,
|
public ConnectionReader createConnectionReader(SegmentSource in,
|
||||||
byte[] secret) {
|
byte[] secret) {
|
||||||
return createConnectionReader(in, secret, new SegmentImpl(), false);
|
return createConnectionReader(in, secret, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionReader createConnectionReader(SegmentSource in,
|
private ConnectionReader createConnectionReader(SegmentSource in,
|
||||||
|
|||||||
9
components/net/sf/briar/transport/ErasureEncoder.java
Normal file
9
components/net/sf/briar/transport/ErasureEncoder.java
Normal 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);
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
// Free any discard counts that are no longer too high for the window
|
// Free any discard counts that are no longer too high for the window
|
||||||
Iterator<Long> it1 = discardCounts.keySet().iterator();
|
Iterator<Long> it1 = discardCounts.keySet().iterator();
|
||||||
while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove();
|
while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove();
|
||||||
// Allocate a segment
|
// FIXME: Unnecessary allocation
|
||||||
Segment s = new SegmentImpl();
|
Segment s = new SegmentImpl();
|
||||||
// Read segments until a frame can be decoded
|
// Read segments until a frame can be decoded
|
||||||
while(true) {
|
while(true) {
|
||||||
@@ -51,9 +51,8 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
|
|||||||
if(set == null) {
|
if(set == null) {
|
||||||
set = new Segment[n];
|
set = new Segment[n];
|
||||||
segmentSets.put(frameNumber, set);
|
segmentSets.put(frameNumber, set);
|
||||||
} else {
|
|
||||||
set[(int) (frameNumber % n)] = s;
|
|
||||||
}
|
}
|
||||||
|
set[(int) (frameNumber % n)] = s;
|
||||||
// Try to decode the frame
|
// Try to decode the frame
|
||||||
if(decoder.decodeFrame(f, set)) return true;
|
if(decoder.decodeFrame(f, set)) return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,24 @@
|
|||||||
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.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.api.transport.Segment;
|
||||||
import net.sf.briar.util.ByteUtils;
|
|
||||||
|
|
||||||
class SegmentImpl implements Segment {
|
class SegmentImpl implements Segment {
|
||||||
|
|
||||||
private final byte[] buf = new byte[MAX_SEGMENT_LENGTH];
|
private final byte[] buf;
|
||||||
|
|
||||||
private int length = -1;
|
private int length = -1;
|
||||||
private long segmentNumber = -1;
|
private long segmentNumber = -1;
|
||||||
|
|
||||||
|
SegmentImpl() {
|
||||||
|
this(MAX_SEGMENT_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentImpl(int length) {
|
||||||
|
buf = new byte[length];
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getBuffer() {
|
public byte[] getBuffer() {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -32,7 +40,7 @@ class SegmentImpl implements Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSegmentNumber(long segmentNumber) {
|
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();
|
throw new IllegalArgumentException();
|
||||||
this.segmentNumber = segmentNumber;
|
this.segmentNumber = segmentNumber;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_FRAME_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
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;
|
||||||
@@ -54,7 +56,13 @@ class XorErasureDecoder implements ErasureDecoder {
|
|||||||
assert missingOffset != -1;
|
assert missingOffset != -1;
|
||||||
System.arraycopy(parity, 0, dest, missingOffset, length);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
components/net/sf/briar/transport/XorErasureEncoder.java
Normal file
30
components/net/sf/briar/transport/XorErasureEncoder.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user