From a104548f7c380cb68a0efba8f8f8beb8d884cb6b Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Tue, 28 Aug 2012 14:22:29 +0100 Subject: [PATCH] Allow for the maximum overhead when calculating capacity. --- .../briar/api/protocol/ProtocolConstants.java | 9 +++-- .../briar/transport/ConnectionWriterImpl.java | 13 ++----- .../net/sf/briar/transport/FrameWriter.java | 4 +-- .../transport/OutgoingEncryptionLayer.java | 35 ++++++++++++------- .../briar/transport/ConnectionWriterTest.java | 12 +++---- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/api/net/sf/briar/api/protocol/ProtocolConstants.java b/api/net/sf/briar/api/protocol/ProtocolConstants.java index ba87ec12cf..aa54918a36 100644 --- a/api/net/sf/briar/api/protocol/ProtocolConstants.java +++ b/api/net/sf/briar/api/protocol/ProtocolConstants.java @@ -1,19 +1,18 @@ 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; diff --git a/components/net/sf/briar/transport/ConnectionWriterImpl.java b/components/net/sf/briar/transport/ConnectionWriterImpl.java index 39ee053790..4932cff5c7 100644 --- a/components/net/sf/briar/transport/ConnectionWriterImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterImpl.java @@ -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++; } diff --git a/components/net/sf/briar/transport/FrameWriter.java b/components/net/sf/briar/transport/FrameWriter.java index c3167b411d..947e8bf1b7 100644 --- a/components/net/sf/briar/transport/FrameWriter.java +++ b/components/net/sf/briar/transport/FrameWriter.java @@ -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; diff --git a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java b/components/net/sf/briar/transport/OutgoingEncryptionLayer.java index c9080a6c5e..9d6a67260c 100644 --- a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java +++ b/components/net/sf/briar/transport/OutgoingEncryptionLayer.java @@ -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 diff --git a/test/net/sf/briar/transport/ConnectionWriterTest.java b/test/net/sf/briar/transport/ConnectionWriterTest.java index 9b7ebc082d..6c416658ec 100644 --- a/test/net/sf/briar/transport/ConnectionWriterTest.java +++ b/test/net/sf/briar/transport/ConnectionWriterTest.java @@ -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); } } -- GitLab