Skip to content
Snippets Groups Projects
Commit a104548f authored by akwizgran's avatar akwizgran
Browse files

Allow for the maximum overhead when calculating capacity.

parent 521ed076
No related branches found
No related tags found
No related merge requests found
package net.sf.briar.api.protocol;
import net.sf.briar.api.transport.TransportConstants;
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
public interface ProtocolConstants {
/**
* The maximum length of a serialised packet in bytes. To allow for future
* changes in the protocol, this is smaller than the minimum connection
* length minus the encryption and authentication overhead.
* length minus the maximum encryption and authentication overhead.
*/
static final int MAX_PACKET_LENGTH =
TransportConstants.MIN_CONNECTION_LENGTH - 1024;
static final int MAX_PACKET_LENGTH = MIN_CONNECTION_LENGTH / 2;
/** The maximum number of transports a node may support. */
static final int MAX_TRANSPORTS = 50;
static final int MAX_TRANSPORTS = 25;
/** The maximum number of properties per transport. */
static final int MAX_PROPERTIES_PER_TRANSPORT = 100;
......
......@@ -35,11 +35,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
}
public long getRemainingCapacity() {
long capacity = out.getRemainingCapacity();
int maxPayloadLength = frameLength - HEADER_LENGTH - MAC_LENGTH;
long frames = (long) Math.ceil((double) capacity / maxPayloadLength);
long overhead = (frames + 1) * (HEADER_LENGTH + MAC_LENGTH);
return capacity - overhead - length;
return out.getRemainingCapacity();
}
@Override
......@@ -83,12 +79,9 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
length += len;
}
private void writeFrame(boolean lastFrame) throws IOException {
private void writeFrame(boolean finalFrame) throws IOException {
if(frameNumber > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
int capacity = (int) Math.min(frameLength, out.getRemainingCapacity());
int paddingLength = capacity - HEADER_LENGTH - length - MAC_LENGTH;
if(paddingLength < 0) throw new IllegalStateException();
out.writeFrame(frame, length, lastFrame ? 0 : paddingLength, lastFrame);
out.writeFrame(frame, length, finalFrame);
length = 0;
frameNumber++;
}
......
......@@ -5,8 +5,8 @@ import java.io.IOException;
interface FrameWriter {
/** Writes the given frame. */
void writeFrame(byte[] frame, int payloadLength, int paddingLength,
boolean lastFrame) throws IOException;
void writeFrame(byte[] frame, int payloadLength, boolean finalFrame)
throws IOException;
/** Flushes the stack. */
void flush() throws IOException;
......
......@@ -6,6 +6,7 @@ import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import java.io.IOException;
import java.io.OutputStream;
......@@ -33,7 +34,7 @@ class OutgoingEncryptionLayer implements FrameWriter {
AuthenticatedCipher frameCipher, ErasableKey tagKey,
ErasableKey frameKey, int frameLength) {
this.out = out;
this.capacity = capacity - TAG_LENGTH;
this.capacity = capacity;
this.tagCipher = tagCipher;
this.frameCipher = frameCipher;
this.tagKey = tagKey;
......@@ -64,17 +65,11 @@ class OutgoingEncryptionLayer implements FrameWriter {
writeTag = false;
}
public void writeFrame(byte[] frame, int payloadLength, int paddingLength,
boolean lastFrame) throws IOException {
int plaintextLength = HEADER_LENGTH + payloadLength + paddingLength;
int ciphertextLength = plaintextLength + MAC_LENGTH;
if(ciphertextLength > frameLength)
throw new IllegalArgumentException();
if(!lastFrame && ciphertextLength < frameLength)
throw new IllegalArgumentException();
public void writeFrame(byte[] frame, int payloadLength, boolean finalFrame)
throws IOException {
// If the initiator's side of the connection is closed without writing
// any payload or padding, don't write a tag or an empty frame
if(writeTag && lastFrame && payloadLength + paddingLength == 0) return;
// any data, don't write anything to the underlying transport
if(writeTag && finalFrame && payloadLength == 0) return;
// Write the tag if required
if(writeTag) {
TagEncoder.encodeTag(ciphertext, tagCipher, tagKey);
......@@ -85,10 +80,20 @@ class OutgoingEncryptionLayer implements FrameWriter {
tagKey.erase();
throw e;
}
capacity -= TAG_LENGTH;
writeTag = false;
}
// Encode the header
FrameEncoder.encodeHeader(frame, lastFrame, payloadLength);
FrameEncoder.encodeHeader(frame, finalFrame, payloadLength);
// Don't pad the final frame
int plaintextLength, ciphertextLength;
if(finalFrame) {
plaintextLength = HEADER_LENGTH + payloadLength;
ciphertextLength = plaintextLength + MAC_LENGTH;
} else {
plaintextLength = frameLength - MAC_LENGTH;
ciphertextLength = frameLength;
}
// If there's any padding it must all be zeroes
for(int i = HEADER_LENGTH + payloadLength; i < plaintextLength; i++)
frame[i] = 0;
......@@ -120,6 +125,10 @@ class OutgoingEncryptionLayer implements FrameWriter {
}
public long getRemainingCapacity() {
return capacity;
long capacityExcludingTag = writeTag ? capacity - TAG_LENGTH : capacity;
long frames = capacityExcludingTag / frameLength;
long frameNumbers = MAX_32_BIT_UNSIGNED - frameNumber + 1;
int maxPayloadLength = frameLength - HEADER_LENGTH - MAC_LENGTH;
return maxPayloadLength * Math.min(frames, frameNumbers);
}
}
\ No newline at end of file
......@@ -48,14 +48,14 @@ public class ConnectionWriterTest extends BriarTestCase {
MIN_CONNECTION_LENGTH, secret, true);
// Check that the connection writer thinks there's room for a packet
long capacity = w.getRemainingCapacity();
assertTrue(capacity >= MAX_PACKET_LENGTH);
assertTrue(capacity <= MIN_CONNECTION_LENGTH);
assertTrue(capacity > MAX_PACKET_LENGTH);
assertTrue(capacity < MIN_CONNECTION_LENGTH);
// Check that there really is room for a packet
byte[] payload = new byte[MAX_PACKET_LENGTH];
w.getOutputStream().write(payload);
w.getOutputStream().close();
long used = out.size();
assertTrue(used >= MAX_PACKET_LENGTH);
assertTrue(used > MAX_PACKET_LENGTH);
assertTrue(used <= MIN_CONNECTION_LENGTH);
}
......@@ -67,14 +67,14 @@ public class ConnectionWriterTest extends BriarTestCase {
MIN_CONNECTION_LENGTH, secret, false);
// Check that the connection writer thinks there's room for a packet
long capacity = w.getRemainingCapacity();
assertTrue(capacity >= MAX_PACKET_LENGTH);
assertTrue(capacity <= MIN_CONNECTION_LENGTH);
assertTrue(capacity > MAX_PACKET_LENGTH);
assertTrue(capacity < MIN_CONNECTION_LENGTH);
// Check that there really is room for a packet
byte[] payload = new byte[MAX_PACKET_LENGTH];
w.getOutputStream().write(payload);
w.getOutputStream().close();
long used = out.size();
assertTrue(used >= MAX_PACKET_LENGTH);
assertTrue(used > MAX_PACKET_LENGTH);
assertTrue(used <= MIN_CONNECTION_LENGTH);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment