mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Expose the encryption and authentication overhead without breaking
encapsulation. This should allow callers to calculate maximum packet sizes without knowing the details of the transport protocol.
This commit is contained in:
@@ -11,4 +11,11 @@ interface ConnectionEncrypter {
|
||||
|
||||
/** Encrypts and writes the MAC for the current frame. */
|
||||
void writeMac(byte[] mac) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the number of encrypted bytes that can be written without
|
||||
* writing more than the given number of bytes, including encryption
|
||||
* overhead.
|
||||
*/
|
||||
long getCapacity(long capacity);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,11 @@ implements ConnectionEncrypter {
|
||||
betweenFrames = true;
|
||||
}
|
||||
|
||||
public long getCapacity(long capacity) {
|
||||
if(capacity < 0L) throw new IllegalArgumentException();
|
||||
return ivWritten ? capacity : Math.max(0L, capacity - IV_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if(!ivWritten) writeIv();
|
||||
|
||||
@@ -20,13 +20,13 @@ import net.sf.briar.util.ByteUtils;
|
||||
class ConnectionWriterImpl extends FilterOutputStream
|
||||
implements ConnectionWriter {
|
||||
|
||||
private final ConnectionEncrypter encrypter;
|
||||
private final Mac mac;
|
||||
private final int maxPayloadLength;
|
||||
private final ByteArrayOutputStream buf;
|
||||
private final byte[] header;
|
||||
protected final ConnectionEncrypter encrypter;
|
||||
protected final Mac mac;
|
||||
protected final int maxPayloadLength;
|
||||
protected final ByteArrayOutputStream buf;
|
||||
protected final byte[] header;
|
||||
|
||||
private long frame = 0L;
|
||||
protected long frame = 0L;
|
||||
|
||||
ConnectionWriterImpl(ConnectionEncrypter encrypter, Mac mac) {
|
||||
super(encrypter.getOutputStream());
|
||||
@@ -41,6 +41,18 @@ implements ConnectionWriter {
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getCapacity(long capacity) {
|
||||
if(capacity < 0L) throw new IllegalArgumentException();
|
||||
// Subtract the encryption overhead
|
||||
capacity = encrypter.getCapacity(capacity);
|
||||
// If there's any data buffered, subtract it and its auth overhead
|
||||
int overheadPerFrame = header.length + mac.getMacLength();
|
||||
if(buf.size() > 0) capacity -= buf.size() + overheadPerFrame;
|
||||
// Subtract the auth overhead from the remaining capacity
|
||||
long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH);
|
||||
return Math.max(0L, capacity - frames * overheadPerFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if(buf.size() > 0) writeFrame();
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
|
||||
import net.sf.briar.api.transport.ConnectionWriter;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
/**
|
||||
@@ -19,33 +14,18 @@ import net.sf.briar.util.ByteUtils;
|
||||
* padding inserted if necessary. Calls to the writer's write() methods will
|
||||
* block until there is space to buffer the data.
|
||||
*/
|
||||
class PaddedConnectionWriter extends FilterOutputStream
|
||||
implements ConnectionWriter {
|
||||
class PaddedConnectionWriter extends ConnectionWriterImpl {
|
||||
|
||||
private final ConnectionEncrypter encrypter;
|
||||
private final Mac mac;
|
||||
private final int maxPayloadLength;
|
||||
private final ByteArrayOutputStream buf;
|
||||
private final byte[] header, padding;
|
||||
private final byte[] padding;
|
||||
|
||||
private long frame = 0L;
|
||||
private boolean closed = false;
|
||||
private IOException exception = null;
|
||||
|
||||
PaddedConnectionWriter(ConnectionEncrypter encrypter, Mac mac) {
|
||||
super(encrypter.getOutputStream());
|
||||
this.encrypter = encrypter;
|
||||
this.mac = mac;
|
||||
maxPayloadLength = MAX_FRAME_LENGTH - 4 - mac.getMacLength();
|
||||
buf = new ByteArrayOutputStream(maxPayloadLength);
|
||||
header = new byte[4];
|
||||
super(encrypter, mac);
|
||||
padding = new byte[maxPayloadLength];
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
if(exception != null) throw exception;
|
||||
|
||||
Reference in New Issue
Block a user