diff --git a/briar-android/.classpath b/briar-android/.classpath
index 33324c41541a6f5f4c0711211e7fcf3eddad4c8b..591a99a8cc90c035e10471ad340eef194dc5553b 100644
--- a/briar-android/.classpath
+++ b/briar-android/.classpath
@@ -7,5 +7,6 @@
 	<classpathentry combineaccessrules="false" kind="src" path="/briar-core"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/briar-api"/>
 	<classpathentry kind="lib" path="/briar-api/libs/guice-3.0-no_aop.jar"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
 	<classpathentry kind="output" path="bin/classes"/>
 </classpath>
diff --git a/briar-api/src/net/sf/briar/api/plugins/Plugin.java b/briar-api/src/net/sf/briar/api/plugins/Plugin.java
index a332eb63dca5f465163d13675409bbeb3035b1ea..123dfd0ad16e7524678261db66177c13c7804115 100644
--- a/briar-api/src/net/sf/briar/api/plugins/Plugin.java
+++ b/briar-api/src/net/sf/briar/api/plugins/Plugin.java
@@ -14,6 +14,9 @@ public interface Plugin {
 	/** Returns a label for looking up the plugin's translated name. */
 	String getName();
 
+	/** Returns the transport's maximum frame length in bytes. */
+	int getMaxFrameLength();
+
 	/** Returns the transport's maximum latency in milliseconds. */
 	long getMaxLatency();
 
diff --git a/briar-api/src/net/sf/briar/api/plugins/duplex/DuplexTransportConnection.java b/briar-api/src/net/sf/briar/api/plugins/duplex/DuplexTransportConnection.java
index 06e0f148bfcf4bccf3502e2a7904eab41d2a4545..5d115795389c1fe06996224fdc11ef9d4b5bf2fa 100644
--- a/briar-api/src/net/sf/briar/api/plugins/duplex/DuplexTransportConnection.java
+++ b/briar-api/src/net/sf/briar/api/plugins/duplex/DuplexTransportConnection.java
@@ -11,6 +11,9 @@ import java.io.OutputStream;
  */
 public interface DuplexTransportConnection {
 
+	/** Returns the maximum frame length of the transport in bytes. */
+	int getMaxFrameLength();
+
 	/** Returns the maximum latency of the transport in milliseconds. */
 	long getMaxLatency();
 
diff --git a/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java b/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
index ffda7ef0d50df74efe0ad739e62d7f4a2fdb2400..00850b12e50421f14adf80e98e446d83d9d9c84b 100644
--- a/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
+++ b/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
@@ -9,6 +9,9 @@ import java.io.InputStream;
  */
 public interface SimplexTransportReader {
 
+	/** Returns the maximum frame length of the transport in bytes. */
+	int getMaxFrameLength();
+
 	/** Returns an input stream for reading from the transport. */
 	InputStream getInputStream() throws IOException;
 
diff --git a/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java b/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
index facb4769c32d75bf80538d32ac14716a6e71a7d7..f21aaf032b2bbe719714c6ca1bc8ce32f9e89ec1 100644
--- a/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
+++ b/briar-api/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
@@ -12,6 +12,9 @@ public interface SimplexTransportWriter {
 	/** Returns the capacity of the transport in bytes. */
 	long getCapacity();
 
+	/** Returns the maximum frame length of the transport in bytes. */
+	int getMaxFrameLength();
+
 	/** Returns the maximum latency of the transport in milliseconds. */
 	long getMaxLatency();
 
diff --git a/briar-api/src/net/sf/briar/api/transport/ConnectionReaderFactory.java b/briar-api/src/net/sf/briar/api/transport/ConnectionReaderFactory.java
index 518578c39cdea2b40b81991528ec7e2217d7a5f0..b070b3c63c50c96f39488a2490cad91b1370842b 100644
--- a/briar-api/src/net/sf/briar/api/transport/ConnectionReaderFactory.java
+++ b/briar-api/src/net/sf/briar/api/transport/ConnectionReaderFactory.java
@@ -5,10 +5,10 @@ import java.io.InputStream;
 public interface ConnectionReaderFactory {
 
 	/** Creates a connection reader for one side of a connection. */
-	ConnectionReader createConnectionReader(InputStream in,
+	ConnectionReader createConnectionReader(InputStream in, int maxFrameLength,
 			ConnectionContext ctx, boolean incoming, boolean initiator);
 
 	/** Creates a connection reader for one side of an invitation connection. */
 	ConnectionReader createInvitationConnectionReader(InputStream in,
-			byte[] secret, boolean alice);
+			int maxFrameLength, byte[] secret, boolean alice);
 }
diff --git a/briar-api/src/net/sf/briar/api/transport/ConnectionWriterFactory.java b/briar-api/src/net/sf/briar/api/transport/ConnectionWriterFactory.java
index 4bff478a34c9c07c58d5d15880ebc3d388d267f1..00d4126030d702334a3a5c64df292dbca2a9965a 100644
--- a/briar-api/src/net/sf/briar/api/transport/ConnectionWriterFactory.java
+++ b/briar-api/src/net/sf/briar/api/transport/ConnectionWriterFactory.java
@@ -5,10 +5,11 @@ import java.io.OutputStream;
 public interface ConnectionWriterFactory {
 
 	/** Creates a connection writer for one side of a connection. */
-	ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
-			ConnectionContext ctx, boolean incoming, boolean initiator);
+	ConnectionWriter createConnectionWriter(OutputStream out,
+			int maxFrameLength, long capacity, ConnectionContext ctx,
+			boolean incoming, boolean initiator);
 
 	/** Creates a connection writer for one side of an invitation connection. */
 	ConnectionWriter createInvitationConnectionWriter(OutputStream out,
-			byte[] secret, boolean alice);
+			int maxFrameLength, byte[] secret, boolean alice);
 }
diff --git a/briar-core/src/net/sf/briar/invitation/AliceConnector.java b/briar-core/src/net/sf/briar/invitation/AliceConnector.java
index 6337959617ce595c273f8c6820903f9f55583c08..b4e1b0cdf4ceb08c331148efe270c0e458cef6e6 100644
--- a/briar-core/src/net/sf/briar/invitation/AliceConnector.java
+++ b/briar-core/src/net/sf/briar/invitation/AliceConnector.java
@@ -135,13 +135,14 @@ class AliceConnector extends Connector {
 		// Confirmation succeeded - upgrade to a secure connection
 		if(LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
+		int maxFrameLength = conn.getMaxFrameLength();
 		ConnectionReader connectionReader =
 				connectionReaderFactory.createInvitationConnectionReader(in,
-						secret, false);
+						maxFrameLength, secret, false);
 		r = readerFactory.createReader(connectionReader.getInputStream());
 		ConnectionWriter connectionWriter =
 				connectionWriterFactory.createInvitationConnectionWriter(out,
-						secret, true);
+						maxFrameLength, secret, true);
 		w = writerFactory.createWriter(connectionWriter.getOutputStream());
 		// Derive the invitation nonces
 		byte[][] nonces = crypto.deriveInvitationNonces(secret);
diff --git a/briar-core/src/net/sf/briar/invitation/BobConnector.java b/briar-core/src/net/sf/briar/invitation/BobConnector.java
index 3f03a65b618b135b6abc34df248cb03615d50124..20bb1b71ee6d039c187f0b27538de5dde0344fc4 100644
--- a/briar-core/src/net/sf/briar/invitation/BobConnector.java
+++ b/briar-core/src/net/sf/briar/invitation/BobConnector.java
@@ -135,13 +135,14 @@ class BobConnector extends Connector {
 		// Confirmation succeeded - upgrade to a secure connection
 		if(LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
+		int maxFrameLength = conn.getMaxFrameLength();
 		ConnectionReader connectionReader =
 				connectionReaderFactory.createInvitationConnectionReader(in,
-						secret, true);
+						maxFrameLength, secret, true);
 		r = readerFactory.createReader(connectionReader.getInputStream());
 		ConnectionWriter connectionWriter =
 				connectionWriterFactory.createInvitationConnectionWriter(out,
-						secret, false);
+						maxFrameLength, secret, false);
 		w = writerFactory.createWriter(connectionWriter.getOutputStream());
 		// Derive the nonces
 		byte[][] nonces = crypto.deriveInvitationNonces(secret);
diff --git a/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java
index 1ec9ad384fa8665bf9ca2bc6f259b44923ceec5f..03619f6bf7f7910dd0fba7a979943fd4b753756a 100644
--- a/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java
+++ b/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java
@@ -1,6 +1,8 @@
 package net.sf.briar.messaging.duplex;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.db.DatabaseComponent;
@@ -32,13 +34,17 @@ class IncomingDuplexConnection extends DuplexConnection {
 
 	@Override
 	protected ConnectionReader createConnectionReader() throws IOException {
-		return connReaderFactory.createConnectionReader(
-				transport.getInputStream(), ctx, true, true);
+		InputStream in = transport.getInputStream();
+		int maxFrameLength = transport.getMaxFrameLength();
+		return connReaderFactory.createConnectionReader(in, maxFrameLength,
+				ctx, true, true);
 	}
 
 	@Override
 	protected ConnectionWriter createConnectionWriter() throws IOException {
-		return connWriterFactory.createConnectionWriter(
-				transport.getOutputStream(), Long.MAX_VALUE, ctx, true, false);
+		OutputStream out = transport.getOutputStream();
+		int maxFrameLength = transport.getMaxFrameLength();
+		return connWriterFactory.createConnectionWriter(out, maxFrameLength,
+				Long.MAX_VALUE, ctx, true, false);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java
index f1767773ceaaea6758acfe33c95e8dd71951344e..9a3a86cfd9df0ae2593d412a8ac32b63e2f25729 100644
--- a/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java
+++ b/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java
@@ -1,6 +1,8 @@
 package net.sf.briar.messaging.duplex;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.db.DatabaseComponent;
@@ -32,13 +34,17 @@ class OutgoingDuplexConnection extends DuplexConnection {
 
 	@Override
 	protected ConnectionReader createConnectionReader() throws IOException {
-		return connReaderFactory.createConnectionReader(
-				transport.getInputStream(), ctx, false, false);
+		InputStream in = transport.getInputStream();
+		int maxFrameLength = transport.getMaxFrameLength();
+		return connReaderFactory.createConnectionReader(in, maxFrameLength,
+				ctx, false, false);
 	}
 
 	@Override
 	protected ConnectionWriter createConnectionWriter() throws IOException {
-		return connWriterFactory.createConnectionWriter(
-				transport.getOutputStream(), Long.MAX_VALUE, ctx, false, true);
+		OutputStream out = transport.getOutputStream();
+		int maxFrameLength = transport.getMaxFrameLength();
+		return connWriterFactory.createConnectionWriter(out, maxFrameLength,
+				Long.MAX_VALUE, ctx, false, true);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java b/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java
index 8f829064c9c82ace60a5909426d598b28633c3fa..64b52dd54c162b1fd80b3f87bc23fec2e24a18a0 100644
--- a/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java
+++ b/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java
@@ -70,9 +70,11 @@ class IncomingSimplexConnection {
 	void read() {
 		connRegistry.registerConnection(contactId, transportId);
 		try {
-			ConnectionReader conn = connReaderFactory.createConnectionReader(
-					transport.getInputStream(), ctx, true, true);
-			InputStream in = conn.getInputStream();
+			InputStream in = transport.getInputStream();
+			int maxFrameLength = transport.getMaxFrameLength();
+			ConnectionReader conn = connReaderFactory.createConnectionReader(in,
+					maxFrameLength, ctx, true, true);
+			in = conn.getInputStream();
 			PacketReader reader = packetReaderFactory.createPacketReader(in);
 			// Read packets until EOF
 			while(!reader.eof()) {
diff --git a/briar-core/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnection.java b/briar-core/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnection.java
index 4d30ba973221447208c028fe0181375c2c22838e..8b259c844f1454216a88001ec7224300935bc623 100644
--- a/briar-core/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnection.java
+++ b/briar-core/src/net/sf/briar/messaging/simplex/OutgoingSimplexConnection.java
@@ -63,10 +63,12 @@ class OutgoingSimplexConnection {
 	void write() {
 		connRegistry.registerConnection(contactId, transportId);
 		try {
+			OutputStream out = transport.getOutputStream();
+			long capacity = transport.getCapacity();
+			int maxFrameLength = transport.getMaxFrameLength();
 			ConnectionWriter conn = connWriterFactory.createConnectionWriter(
-					transport.getOutputStream(), transport.getCapacity(), ctx,
-					false, true);
-			OutputStream out = conn.getOutputStream();
+					out, maxFrameLength, capacity, ctx, false, true);
+			out = conn.getOutputStream();
 			if(conn.getRemainingCapacity() < MAX_PACKET_LENGTH)
 				throw new EOFException();
 			PacketWriter writer = packetWriterFactory.createPacketWriter(out,
@@ -79,7 +81,7 @@ class OutgoingSimplexConnection {
 			if(hasSpace) hasSpace = writeRetentionAck(conn, writer);
 			if(hasSpace) hasSpace = writeRetentionUpdate(conn, writer);
 			// Write acks until you can't write acks no more
-			long capacity = conn.getRemainingCapacity();
+			capacity = conn.getRemainingCapacity();
 			int maxMessages = writer.getMaxMessagesForAck(capacity);
 			Ack a = db.generateAck(contactId, maxMessages);
 			while(a != null) {
diff --git a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
index c07cc1b364b9d4d0ddb011d3654b0471fe8819bf..1581db927252a9670f6a3d97bb58eda189b01331 100644
--- a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
@@ -49,6 +49,7 @@ class BluetoothPlugin implements DuplexPlugin {
 	private final Clock clock;
 	private final SecureRandom secureRandom;
 	private final DuplexPluginCallback callback;
+	private final int maxFrameLength;
 	private final long maxLatency, pollingInterval;
 	private final Semaphore discoverySemaphore = new Semaphore(1);
 
@@ -58,11 +59,12 @@ class BluetoothPlugin implements DuplexPlugin {
 
 	BluetoothPlugin(Executor pluginExecutor, Clock clock,
 			SecureRandom secureRandom, DuplexPluginCallback callback,
-			long maxLatency, long pollingInterval) {
+			int maxFrameLength, long maxLatency, long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
 		this.clock = clock;
 		this.secureRandom = secureRandom;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 		this.pollingInterval = pollingInterval;
 	}
@@ -75,6 +77,10 @@ class BluetoothPlugin implements DuplexPlugin {
 		return "BLUETOOTH_PLUGIN_NAME";
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
@@ -159,7 +165,7 @@ class BluetoothPlugin implements DuplexPlugin {
 				return;
 			}
 			BluetoothTransportConnection conn =
-					new BluetoothTransportConnection(s, maxLatency);
+					new BluetoothTransportConnection(this, s);
 			callback.incomingConnectionCreated(conn);
 			if(!running) return;
 		}
@@ -205,7 +211,7 @@ class BluetoothPlugin implements DuplexPlugin {
 	private DuplexTransportConnection connect(String url) {
 		try {
 			StreamConnection s = (StreamConnection) Connector.open(url);
-			return new BluetoothTransportConnection(s, maxLatency);
+			return new BluetoothTransportConnection(this, s);
 		} catch(IOException e) {
 			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			return null;
@@ -303,7 +309,7 @@ class BluetoothPlugin implements DuplexPlugin {
 		// Try to accept a connection
 		try {
 			StreamConnection s = scn.acceptAndOpen();
-			return new BluetoothTransportConnection(s, maxLatency);
+			return new BluetoothTransportConnection(this, s);
 		} catch(IOException e) {
 			// This is expected when the socket is closed
 			if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
diff --git a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
index 48611f8fd10ccd07c42324add599dd0d25010cdd..88ede376efa1abdbb56e8c08b9e6448aad3428f0 100644
--- a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java
@@ -12,6 +12,7 @@ import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
 
 public class BluetoothPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
 
@@ -32,6 +33,6 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
 		return new BluetoothPlugin(pluginExecutor, clock, secureRandom,
-				callback, MAX_LATENCY, POLLING_INTERVAL);
+				callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothTransportConnection.java b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothTransportConnection.java
index 5d5fda3b95da2d5faa31014ce869bc571b135635..7d1a17ab3306b8047e4d64b7563093c9f6764c88 100644
--- a/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothTransportConnection.java
+++ b/briar-core/src/net/sf/briar/plugins/bluetooth/BluetoothTransportConnection.java
@@ -6,20 +6,25 @@ import java.io.OutputStream;
 
 import javax.microedition.io.StreamConnection;
 
+import net.sf.briar.api.plugins.Plugin;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
 
 class BluetoothTransportConnection implements DuplexTransportConnection {
 
+	private final Plugin plugin;
 	private final StreamConnection stream;
-	private final long maxLatency;
 
-	BluetoothTransportConnection(StreamConnection stream, long maxLatency) {
+	BluetoothTransportConnection(Plugin plugin, StreamConnection stream) {
+		this.plugin = plugin;
 		this.stream = stream;
-		this.maxLatency = maxLatency;
+	}
+
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
 	}
 
 	public long getMaxLatency() {
-		return maxLatency;
+		return plugin.getMaxLatency();
 	}
 
 	public InputStream getInputStream() throws IOException {
diff --git a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
index d978fa74b5ae4a0bd0067fa0153281135a755a33..042d672924b7787fae9e3e9b079ca1fed87b673f 100644
--- a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
@@ -62,6 +62,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 	private final Context appContext;
 	private final SecureRandom secureRandom;
 	private final DuplexPluginCallback callback;
+	private final int maxFrameLength;
 	private final long maxLatency, pollingInterval;
 
 	private volatile boolean running = false;
@@ -72,13 +73,14 @@ class DroidtoothPlugin implements DuplexPlugin {
 
 	DroidtoothPlugin(Executor pluginExecutor, AndroidExecutor androidExecutor,
 			Context appContext, SecureRandom secureRandom,
-			DuplexPluginCallback callback, long maxLatency,
+			DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
 			long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
 		this.androidExecutor = androidExecutor;
 		this.appContext = appContext;
 		this.secureRandom = secureRandom;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 		this.pollingInterval = pollingInterval;
 	}
@@ -92,6 +94,10 @@ class DroidtoothPlugin implements DuplexPlugin {
 		return "BLUETOOTH_PLUGIN_NAME";
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
@@ -207,7 +213,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 				return;
 			}
 			DroidtoothTransportConnection conn =
-					new DroidtoothTransportConnection(s, maxLatency);
+					new DroidtoothTransportConnection(this, s);
 			callback.incomingConnectionCreated(conn);
 			if(!running) return;
 		}
@@ -296,7 +302,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 			if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + address);
 			s.connect();
 			if(LOG.isLoggable(INFO)) LOG.info("Connected to " + address);
-			return new DroidtoothTransportConnection(s, maxLatency);
+			return new DroidtoothTransportConnection(this, s);
 		} catch(IOException e) {
 			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			tryToClose(s);
@@ -375,7 +381,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 				String address = s.getRemoteDevice().getAddress();
 				LOG.info("Incoming connection from " + address);
 			}
-			return new DroidtoothTransportConnection(s, maxLatency);
+			return new DroidtoothTransportConnection(this, s);
 		} catch(SocketTimeoutException e) {
 			if(LOG.isLoggable(INFO)) LOG.info("Invitation timed out");
 			return null;
diff --git a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
index bb884bdd5a4665bf6e75bba408395ad5ab7e0dcc..ee6566ed217a834db18a3a179ec456f4c7c9e1d2 100644
--- a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java
@@ -12,6 +12,7 @@ import android.content.Context;
 
 public class DroidtoothPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
 
@@ -35,6 +36,7 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
 		return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext,
-				secureRandom, callback, MAX_LATENCY, POLLING_INTERVAL);
+				secureRandom, callback, MAX_FRAME_LENGTH, MAX_LATENCY,
+				POLLING_INTERVAL);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothTransportConnection.java b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothTransportConnection.java
index 2a3238033b6394548570f74d0519035e7651ec5d..f1cce80c180855fd247679cdc94144a08c905702 100644
--- a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothTransportConnection.java
+++ b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothTransportConnection.java
@@ -4,21 +4,26 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import net.sf.briar.api.plugins.Plugin;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
 import android.bluetooth.BluetoothSocket;
 
 class DroidtoothTransportConnection implements DuplexTransportConnection {
 
+	private final Plugin plugin;
 	private final BluetoothSocket socket;
-	private final long maxLatency;
 
-	DroidtoothTransportConnection(BluetoothSocket socket, long maxLatency) {
+	DroidtoothTransportConnection(Plugin plugin, BluetoothSocket socket) {
+		this.plugin = plugin;
 		this.socket = socket;
-		this.maxLatency = maxLatency;
+	}
+
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
 	}
 
 	public long getMaxLatency() {
-		return maxLatency;
+		return plugin.getMaxLatency();
 	}
 
 	public InputStream getInputStream() throws IOException {
diff --git a/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java b/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
index 8adc969260ac0c8c61307880b4dd4a0533a74d41..2064c377b399f2c41517d6288c2772111ca94ae4 100644
--- a/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/file/FilePlugin.java
@@ -27,6 +27,7 @@ public abstract class FilePlugin implements SimplexPlugin {
 
 	protected final Executor pluginExecutor;
 	protected final SimplexPluginCallback callback;
+	protected final int maxFrameLength;
 	protected final long maxLatency;
 
 	protected volatile boolean running = false;
@@ -37,12 +38,22 @@ public abstract class FilePlugin implements SimplexPlugin {
 	protected abstract void readerFinished(File f);
 
 	protected FilePlugin(Executor pluginExecutor,
-			SimplexPluginCallback callback, long maxLatency) {
+			SimplexPluginCallback callback, int maxFrameLength,
+			long maxLatency) {
 		this.pluginExecutor = pluginExecutor;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
+	public long getMaxLatency() {
+		return maxLatency;
+	}
+
 	public SimplexTransportReader createReader(ContactId c) {
 		return null;
 	}
@@ -73,7 +84,7 @@ public abstract class FilePlugin implements SimplexPlugin {
 			long capacity = getCapacity(dir.getPath());
 			if(capacity < MIN_CONNECTION_LENGTH) return null;
 			OutputStream out = new FileOutputStream(f);
-			return new FileTransportWriter(f, out, capacity, maxLatency, this);
+			return new FileTransportWriter(f, out, capacity, this);
 		} catch(IOException e) {
 			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			f.delete();
diff --git a/briar-core/src/net/sf/briar/plugins/file/FileTransportReader.java b/briar-core/src/net/sf/briar/plugins/file/FileTransportReader.java
index e2c7648c95fd897d688587322c3c43fd536b4388..77d48699f5407ac87f3283ebd09d36db9d71ce77 100644
--- a/briar-core/src/net/sf/briar/plugins/file/FileTransportReader.java
+++ b/briar-core/src/net/sf/briar/plugins/file/FileTransportReader.java
@@ -12,7 +12,7 @@ import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
 class FileTransportReader implements SimplexTransportReader {
 
 	private static final Logger LOG =
-		Logger.getLogger(FileTransportReader.class.getName());
+			Logger.getLogger(FileTransportReader.class.getName());
 
 	private final File file;
 	private final InputStream in;
@@ -24,6 +24,10 @@ class FileTransportReader implements SimplexTransportReader {
 		this.plugin = plugin;
 	}
 
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
+	}
+
 	public InputStream getInputStream() {
 		return in;
 	}
diff --git a/briar-core/src/net/sf/briar/plugins/file/FileTransportWriter.java b/briar-core/src/net/sf/briar/plugins/file/FileTransportWriter.java
index e86b2f81457900db3eadf2be7793cc5467ac7dee..921d748ad423e6ccb31f3b8d7d6bdf2901ba4e97 100644
--- a/briar-core/src/net/sf/briar/plugins/file/FileTransportWriter.java
+++ b/briar-core/src/net/sf/briar/plugins/file/FileTransportWriter.java
@@ -12,19 +12,18 @@ import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
 class FileTransportWriter implements SimplexTransportWriter {
 
 	private static final Logger LOG =
-		Logger.getLogger(FileTransportWriter.class.getName());
+			Logger.getLogger(FileTransportWriter.class.getName());
 
 	private final File file;
 	private final OutputStream out;
-	private final long capacity, maxLatency;
+	private final long capacity;
 	private final FilePlugin plugin;
 
 	FileTransportWriter(File file, OutputStream out, long capacity,
-			long maxLatency, FilePlugin plugin) {
+			FilePlugin plugin) {
 		this.file = file;
 		this.out = out;
 		this.capacity = capacity;
-		this.maxLatency = maxLatency;
 		this.plugin = plugin;
 	}
 
@@ -32,8 +31,12 @@ class FileTransportWriter implements SimplexTransportWriter {
 		return capacity;
 	}
 
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
+	}
+
 	public long getMaxLatency() {
-		return maxLatency;
+		return plugin.getMaxLatency();
 	}
 
 	public OutputStream getOutputStream() {
diff --git a/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java b/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
index f406993c1a18a7063c58ea936cdfc33bbbeceb75..1cc9936eeacba758eda307c35f06fb47beb4983e 100644
--- a/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java
@@ -33,8 +33,9 @@ implements RemovableDriveMonitor.Callback {
 
 	RemovableDrivePlugin(Executor pluginExecutor,
 			SimplexPluginCallback callback, RemovableDriveFinder finder,
-			RemovableDriveMonitor monitor, long maxLatency) {
-		super(pluginExecutor, callback, maxLatency);
+			RemovableDriveMonitor monitor, int maxFrameLength,
+			long maxLatency) {
+		super(pluginExecutor, callback, maxFrameLength, maxLatency);
 		this.finder = finder;
 		this.monitor = monitor;
 	}
@@ -47,10 +48,6 @@ implements RemovableDriveMonitor.Callback {
 		return "REMOVABLE_DRIVE_PLUGIN_NAME";
 	}
 
-	public long getMaxLatency() {
-		return maxLatency;
-	}
-
 	public boolean start() throws IOException {
 		running = true;
 		monitor.start(this);
diff --git a/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java b/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
index 0823a13d310dc2147f2b49411c68a3da547008ee..1ed88d03b6b792750942f3cb8d78a2d289bff370 100644
--- a/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java
@@ -1,5 +1,7 @@
 package net.sf.briar.plugins.file;
 
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.TransportId;
@@ -46,6 +48,6 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
 			return null;
 		}
 		return new RemovableDrivePlugin(pluginExecutor, callback, finder,
-				monitor, MAX_LATENCY);
+				monitor, MAX_FRAME_LENGTH, MAX_LATENCY);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java b/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java
index 5cf653eed4e9f8f780b7d2bc322c8ba31f56c4ac..893205225cfac755b6e94929a7c1ee6c83a5247c 100644
--- a/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java
@@ -40,6 +40,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
 	private final ModemFactory modemFactory;
 	private final SerialPortList serialPortList;
 	private final DuplexPluginCallback callback;
+	private final int maxFrameLength;
 	private final long maxLatency, pollingInterval;
 	private final boolean shuffle; // Used to disable shuffling for testing
 
@@ -48,11 +49,13 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
 
 	ModemPlugin(Executor pluginExecutor, ModemFactory modemFactory,
 			SerialPortList serialPortList, DuplexPluginCallback callback,
-			long maxLatency, long pollingInterval, boolean shuffle) {
+			int maxFrameLength, long maxLatency, long pollingInterval,
+			boolean shuffle) {
 		this.pluginExecutor = pluginExecutor;
 		this.modemFactory = modemFactory;
 		this.serialPortList = serialPortList;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 		this.pollingInterval = pollingInterval;
 		this.shuffle = shuffle;
@@ -66,6 +69,10 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
 		return "MODEM_PLUGIN_NAME";
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
@@ -232,6 +239,10 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
 
 		private final CountDownLatch finished = new CountDownLatch(1);
 
+		public int getMaxFrameLength() {
+			return maxFrameLength;
+		}
+
 		public long getMaxLatency() {
 			return maxLatency;
 		}
diff --git a/briar-core/src/net/sf/briar/plugins/modem/ModemPluginFactory.java b/briar-core/src/net/sf/briar/plugins/modem/ModemPluginFactory.java
index c09e67d6f239012197527081ba800c85a7afb41d..f9270db5616cdee57eb4e2306909b53b5dc587e6 100644
--- a/briar-core/src/net/sf/briar/plugins/modem/ModemPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/modem/ModemPluginFactory.java
@@ -11,6 +11,7 @@ import net.sf.briar.util.StringUtils;
 
 public class ModemPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour
 
@@ -34,6 +35,7 @@ public class ModemPluginFactory implements DuplexPluginFactory {
 		String enabled = callback.getConfig().get("enabled");
 		if(StringUtils.isNullOrEmpty(enabled)) return null;
 		return new ModemPlugin(pluginExecutor, modemFactory, serialPortList,
-				callback, MAX_LATENCY, POLLING_INTERVAL, true);
+				callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL,
+				true);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
index 818472cbd7567f462cb3a54584756d64dd394e0c..067984e1dfe4459c6b71e0f003ac7f2c7a7f8df4 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
@@ -17,9 +17,10 @@ class DroidLanTcpPlugin extends LanTcpPlugin {
 	private final Context appContext;
 
 	DroidLanTcpPlugin(Executor pluginExecutor, Context appContext, Clock clock,
-			DuplexPluginCallback callback, long maxLatency,
+			DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
 			long pollingInterval) {
-		super(pluginExecutor, clock, callback, maxLatency, pollingInterval);
+		super(pluginExecutor, clock, callback, maxFrameLength, maxLatency,
+				pollingInterval);
 		this.appContext = appContext;
 	}
 
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
index 44d4881658423ef1146d74afb3bc1f31f2889885..32ca3261a7b0ac32b6e3824cec22eb0cc46c4d70 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
@@ -12,6 +12,7 @@ import android.content.Context;
 
 public class DroidLanTcpPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
 
@@ -32,6 +33,6 @@ public class DroidLanTcpPluginFactory implements DuplexPluginFactory {
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
 		return new DroidLanTcpPlugin(pluginExecutor, appContext, clock,
-				callback, MAX_LATENCY, POLLING_INTERVAL);
+				callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
index b81250fd13673c0bcedbefa341fd44a82d6b1aad..b5fdc5e6b5392fbd6e35228536ddd8ced605fddb 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
@@ -47,9 +47,10 @@ class LanTcpPlugin extends TcpPlugin {
 	private final Clock clock;
 
 	LanTcpPlugin(Executor pluginExecutor, Clock clock,
-			DuplexPluginCallback callback, long maxLatency,
+			DuplexPluginCallback callback, int maxFrameLength, long maxLatency,
 			long pollingInterval) {
-		super(pluginExecutor, callback, maxLatency, pollingInterval);
+		super(pluginExecutor, callback, maxFrameLength, maxLatency,
+				pollingInterval);
 		this.clock = clock;
 	}
 
@@ -160,7 +161,7 @@ class LanTcpPlugin extends TcpPlugin {
 							// Connect back on the advertised TCP port
 							Socket s = new Socket(packet.getAddress(), port);
 							if(LOG.isLoggable(INFO)) LOG.info("Connected back");
-							return new TcpTransportConnection(s, maxLatency);
+							return new TcpTransportConnection(this, s);
 						} catch(IOException e) {
 							if(LOG.isLoggable(WARNING))
 								LOG.log(WARNING, e.toString(), e);
@@ -294,7 +295,7 @@ class LanTcpPlugin extends TcpPlugin {
 					Socket s = ss.accept();
 					if(LOG.isLoggable(INFO))
 						LOG.info("Received a TCP connection");
-					return new TcpTransportConnection(s, maxLatency);
+					return new TcpTransportConnection(this, s);
 				} catch(SocketTimeoutException e) {
 					now = clock.currentTimeMillis();
 					if(now < end) {
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
index 73e0b216851e423f3de323955a736a54c94ed83b..d3339b3b3f3809dea623f94531b053989f81bca1 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java
@@ -11,6 +11,7 @@ import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
 
 public class LanTcpPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
 
@@ -27,7 +28,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
 	}
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
-		return new LanTcpPlugin(pluginExecutor, clock, callback, MAX_LATENCY,
-				POLLING_INTERVAL);
+		return new LanTcpPlugin(pluginExecutor, clock, callback,
+				MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/TcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/TcpPlugin.java
index 5f8fb8195f7195ad78e023c0f0b1cf7ef0b11d51..49eb023e2f58712d2278a82f15da271896e01277 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/TcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/TcpPlugin.java
@@ -30,6 +30,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 
 	protected final Executor pluginExecutor;
 	protected final DuplexPluginCallback callback;
+	protected final int maxFrameLength;
 	protected final long maxLatency, pollingInterval;
 
 	protected volatile boolean running = false;
@@ -42,13 +43,18 @@ abstract class TcpPlugin implements DuplexPlugin {
 	protected abstract List<SocketAddress> getLocalSocketAddresses();
 
 	protected TcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback,
-			long maxLatency, long pollingInterval) {
+			int maxFrameLength, long maxLatency, long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 		this.pollingInterval = pollingInterval;
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
@@ -128,8 +134,8 @@ abstract class TcpPlugin implements DuplexPlugin {
 			}
 			if(LOG.isLoggable(INFO))
 				LOG.info("Connection from " + s.getRemoteSocketAddress());
-			callback.incomingConnectionCreated(new TcpTransportConnection(s,
-					maxLatency));
+			TcpTransportConnection conn = new TcpTransportConnection(this, s);
+			callback.incomingConnectionCreated(conn);
 			if(!running) return;
 		}
 	}
@@ -175,7 +181,7 @@ abstract class TcpPlugin implements DuplexPlugin {
 			if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + addr);
 			s.connect(addr);
 			if(LOG.isLoggable(INFO)) LOG.info("Connected to " + addr);
-			return new TcpTransportConnection(s, maxLatency);
+			return new TcpTransportConnection(this, s);
 		} catch(IOException e) {
 			if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
 			return null;
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/TcpTransportConnection.java b/briar-core/src/net/sf/briar/plugins/tcp/TcpTransportConnection.java
index ee27cf22a6750de813057dcea3b954d1e853301d..9cc129b503fc03b2786b853d3762e6698da37dde 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/TcpTransportConnection.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/TcpTransportConnection.java
@@ -5,20 +5,25 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 
+import net.sf.briar.api.plugins.Plugin;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
 
 class TcpTransportConnection implements DuplexTransportConnection {
 
+	private final Plugin plugin;
 	private final Socket socket;
-	private final long maxLatency;
 
-	TcpTransportConnection(Socket socket, long maxLatency) {
+	TcpTransportConnection(Plugin plugin, Socket socket) {
+		this.plugin = plugin;
 		this.socket = socket;
-		this.maxLatency = maxLatency;
+	}
+
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
 	}
 
 	public long getMaxLatency() {
-		return maxLatency;
+		return plugin.getMaxLatency();
 	}
 
 	public InputStream getInputStream() throws IOException {
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java
index 962d52ccc52b6c44310327a5663d75c0b0267623..770f2f7a5682350812c22ec3520451d46818bbce 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java
@@ -38,8 +38,10 @@ class WanTcpPlugin extends TcpPlugin {
 	private volatile MappingResult mappingResult;
 
 	WanTcpPlugin(Executor pluginExecutor, DuplexPluginCallback callback,
-			long maxLatency, long pollingInterval, PortMapper portMapper) {
-		super(pluginExecutor, callback, maxLatency, pollingInterval);
+			int maxFrameLength, long maxLatency, long pollingInterval,
+			PortMapper portMapper) {
+		super(pluginExecutor, callback, maxFrameLength, maxLatency,
+				pollingInterval);
 		this.portMapper = portMapper;
 	}
 
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java
index 23bf0dc0ae854c9ddd5dcd8415406606e4a8ffc8..7540f20971e5b7be8b3a3f526db9b54570e10d6b 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java
@@ -10,6 +10,7 @@ import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
 
 public class WanTcpPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
 
@@ -27,7 +28,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
 	}
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
-		return new WanTcpPlugin(pluginExecutor, callback, MAX_LATENCY,
-				POLLING_INTERVAL, new PortMapperImpl(shutdownManager));
+		return new WanTcpPlugin(pluginExecutor, callback, MAX_FRAME_LENGTH,
+				MAX_LATENCY, POLLING_INTERVAL,
+				new PortMapperImpl(shutdownManager));
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java b/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java
index 14e63cf70ba9322c451e3e6c2e6868f9faccefbe..2b1eacee345ad85d48b206f335b01e4197be734d 100644
--- a/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java
@@ -65,6 +65,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 	private final Context appContext;
 	private final ShutdownManager shutdownManager;
 	private final DuplexPluginCallback callback;
+	private final int maxFrameLength;
 	private final long maxLatency, pollingInterval;
 	private final File torDirectory, torFile, geoIpFile, configFile, doneFile;
 	private final File cookieFile, pidFile, hostnameFile;
@@ -78,11 +79,12 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 
 	TorPlugin(Executor pluginExecutor, Context appContext,
 			ShutdownManager shutdownManager, DuplexPluginCallback callback,
-			long maxLatency, long pollingInterval) {
+			int maxFrameLength, long maxLatency, long pollingInterval) {
 		this.pluginExecutor = pluginExecutor;
 		this.appContext = appContext;
 		this.shutdownManager = shutdownManager;
 		this.callback = callback;
+		this.maxFrameLength = maxFrameLength;
 		this.maxLatency = maxLatency;
 		this.pollingInterval = pollingInterval;
 		torDirectory = appContext.getDir("tor", MODE_PRIVATE);
@@ -103,6 +105,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 		return "TOR_PLUGIN_NAME";
 	}
 
+	public int getMaxFrameLength() {
+		return maxFrameLength;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
@@ -426,8 +432,8 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 				return;
 			}
 			if(LOG.isLoggable(INFO)) LOG.info("Connection received");
-			callback.incomingConnectionCreated(new TorTransportConnection(s,
-					maxLatency));
+			TorTransportConnection conn = new TorTransportConnection(this, s);
+			callback.incomingConnectionCreated(conn);
 			if(!running) return;
 		}
 	}
@@ -496,7 +502,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
 			proxy.resolveAddrLocally(false);
 			Socket s = new SocksSocket(proxy, onion, 80);
 			if(LOG.isLoggable(INFO)) LOG.info("Connected to " + onion);
-			return new TorTransportConnection(s, maxLatency);
+			return new TorTransportConnection(this, s);
 		} catch(IOException e) {
 			if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
 			return null;
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java
index 59ca7c45254d29174a8638ae5bce21ed65b94763..494edc0e11e42c9dea91c45d0505e1ae583e7f59 100644
--- a/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java
+++ b/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java
@@ -11,6 +11,7 @@ import android.content.Context;
 
 public class TorPluginFactory implements DuplexPluginFactory {
 
+	private static final int MAX_FRAME_LENGTH = 1024;
 	private static final long MAX_LATENCY = 60 * 1000; // 1 minute
 	private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
 
@@ -31,6 +32,6 @@ public class TorPluginFactory implements DuplexPluginFactory {
 
 	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
 		return new TorPlugin(pluginExecutor,appContext, shutdownManager,
-				callback, MAX_LATENCY, POLLING_INTERVAL);
+				callback, MAX_FRAME_LENGTH, MAX_LATENCY, POLLING_INTERVAL);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java b/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java
index 9e897aacb220db328861303e5a83b534f8dac7ed..2965b36afbe92fcc4989559644145aff9496b661 100644
--- a/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java
+++ b/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java
@@ -5,20 +5,25 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 
+import net.sf.briar.api.plugins.Plugin;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
 
 class TorTransportConnection implements DuplexTransportConnection {
 
+	private final Plugin plugin;
 	private final Socket socket;
-	private final long maxLatency;
 
-	TorTransportConnection(Socket socket, long maxLatency) {
+	TorTransportConnection(Plugin plugin, Socket socket) {
+		this.plugin = plugin;
 		this.socket = socket;
-		this.maxLatency = maxLatency;
+	}
+
+	public int getMaxFrameLength() {
+		return plugin.getMaxFrameLength();
 	}
 
 	public long getMaxLatency() {
-		return maxLatency;
+		return plugin.getMaxLatency();
 	}
 
 	public InputStream getInputStream() throws IOException {
diff --git a/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
index 1af211a5326f9073dc3322d0819e64c90f7058ec..ae4aefb064068e3027a800cc8ba9b4484d404514 100644
--- a/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
+++ b/briar-core/src/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
@@ -1,7 +1,5 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
-
 import java.io.InputStream;
 
 import net.sf.briar.api.crypto.CryptoComponent;
@@ -22,7 +20,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 	}
 
 	public ConnectionReader createConnectionReader(InputStream in,
-			ConnectionContext ctx, boolean incoming, boolean initiator) {
+			int maxFrameLength, ConnectionContext ctx, boolean incoming,
+			boolean initiator) {
 		byte[] secret = ctx.getSecret();
 		long connection = ctx.getConnectionNumber();
 		boolean weAreAlice = ctx.getAlice();
@@ -30,15 +29,15 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 		ErasableKey frameKey = crypto.deriveFrameKey(secret, connection,
 				initiatorIsAlice, initiator);
 		FrameReader encryption = new IncomingEncryptionLayer(in,
-				crypto.getFrameCipher(), frameKey, MAX_FRAME_LENGTH);
-		return new ConnectionReaderImpl(encryption, MAX_FRAME_LENGTH);
+				crypto.getFrameCipher(), frameKey, maxFrameLength);
+		return new ConnectionReaderImpl(encryption, maxFrameLength);
 	}
 
 	public ConnectionReader createInvitationConnectionReader(InputStream in,
-			byte[] secret, boolean alice) {
+			int maxFrameLength, byte[] secret, boolean alice) {
 		ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
 		FrameReader encryption = new IncomingEncryptionLayer(in,
-				crypto.getFrameCipher(), frameKey, MAX_FRAME_LENGTH);
-		return new ConnectionReaderImpl(encryption, MAX_FRAME_LENGTH);
+				crypto.getFrameCipher(), frameKey, maxFrameLength);
+		return new ConnectionReaderImpl(encryption, maxFrameLength);
 	}
 }
diff --git a/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
index daf99021e3c871d4080e909dd23db720b2f183ef..dbfe989cf045b01b8e1683db5e26fa4c742ce310 100644
--- a/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
+++ b/briar-core/src/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
@@ -1,6 +1,5 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
 import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 
 import java.io.OutputStream;
@@ -25,8 +24,8 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 	}
 
 	public ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, ConnectionContext ctx, boolean incoming,
-			boolean initiator) {
+			int maxFrameLength, long capacity, ConnectionContext ctx,
+			boolean incoming, boolean initiator) {
 		byte[] secret = ctx.getSecret();
 		long connection = ctx.getConnectionNumber();
 		boolean weAreAlice = ctx.getAlice();
@@ -41,20 +40,20 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 			crypto.encodeTag(tag, tagCipher, tagKey, connection);
 			tagKey.erase();
 			encryption = new OutgoingEncryptionLayer(out, capacity,
-					crypto.getFrameCipher(), frameKey, MAX_FRAME_LENGTH, tag);
+					crypto.getFrameCipher(), frameKey, maxFrameLength, tag);
 		} else {
 			encryption = new OutgoingEncryptionLayer(out, capacity,
-					crypto.getFrameCipher(), frameKey, MAX_FRAME_LENGTH);
+					crypto.getFrameCipher(), frameKey, maxFrameLength);
 		}
-		return new ConnectionWriterImpl(encryption, MAX_FRAME_LENGTH);
+		return new ConnectionWriterImpl(encryption, maxFrameLength);
 	}
 
 	public ConnectionWriter createInvitationConnectionWriter(OutputStream out,
-			byte[] secret, boolean alice) {
+			int maxFrameLength, byte[] secret, boolean alice) {
 		ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
 		FrameWriter encryption = new OutgoingEncryptionLayer(out,
 				Long.MAX_VALUE, crypto.getFrameCipher(), frameKey,
-				MAX_FRAME_LENGTH);
-		return new ConnectionWriterImpl(encryption, MAX_FRAME_LENGTH);
+				maxFrameLength);
+		return new ConnectionWriterImpl(encryption, maxFrameLength);
 	}
 }
\ No newline at end of file
diff --git a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java
index 9b9c177eded603caa8e03f04a212c31fe87e084e..4557cc17cb55061c26ca9ecb9451daf602740f1c 100644
--- a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java
+++ b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java
@@ -62,8 +62,9 @@ class TransportConnectionRecogniser {
 		db.setConnectionWindow(t.contactId, transportId, t.period,
 				t.window.getCentre(), t.window.getBitmap());
 		// Clone the secret - the key manager will erase the original
-		return new ConnectionContext(t.contactId, transportId,
-				t.secret.clone(), t.connection, t.alice);
+		byte[] secret = t.secret.clone();
+		return new ConnectionContext(t.contactId, transportId, secret,
+				t.connection, t.alice);
 	}
 
 	synchronized void addSecret(TemporarySecret s) {
diff --git a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
index 2eaed4147438cb14bce23edc772d30ab120e74bf..e535ff331ed89ab38ac321c3f1a322989a0497f7 100644
--- a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
+++ b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java
@@ -1,5 +1,6 @@
 package net.sf.briar;
 
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
 import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
@@ -135,7 +136,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 		ConnectionContext ctx = new ConnectionContext(contactId, transportId,
 				secret.clone(), 0, true);
 		ConnectionWriter conn = connectionWriterFactory.createConnectionWriter(
-				out, Long.MAX_VALUE, ctx, false, true);
+				out, MAX_FRAME_LENGTH, Long.MAX_VALUE, ctx, false, true);
 		OutputStream out1 = conn.getOutputStream();
 		PacketWriter writer = packetWriterFactory.createPacketWriter(out1,
 				false);
@@ -174,7 +175,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 		ConnectionContext ctx = new ConnectionContext(contactId, transportId,
 				secret.clone(), 0, false);
 		ConnectionReader conn = connectionReaderFactory.createConnectionReader(
-				in, ctx, true, true);
+				in, MAX_FRAME_LENGTH, ctx, true, true);
 		InputStream in1 = conn.getInputStream();
 		PacketReader reader = packetReaderFactory.createPacketReader(in1);
 
diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportReader.java b/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportReader.java
index dafa494f076c73316dadcab6016b1b206e55bde9..b8f075c1202e725cfaee4ddefd3239318cc6193b 100644
--- a/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportReader.java
+++ b/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportReader.java
@@ -1,5 +1,7 @@
 package net.sf.briar.messaging.simplex;
 
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+
 import java.io.InputStream;
 
 import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
@@ -14,6 +16,10 @@ class TestSimplexTransportReader implements SimplexTransportReader {
 		this.in = in;
 	}
 
+	public int getMaxFrameLength() {
+		return MAX_FRAME_LENGTH;
+	}
+
 	public InputStream getInputStream() {
 		return in;
 	}
diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportWriter.java b/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportWriter.java
index e2fc34ed269d01e185206bd23698112c63ba0448..691a4bd211c30f88bedfa4d1cd2c53fcef069b68 100644
--- a/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportWriter.java
+++ b/briar-tests/src/net/sf/briar/messaging/simplex/TestSimplexTransportWriter.java
@@ -1,5 +1,7 @@
 package net.sf.briar.messaging.simplex;
 
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 
@@ -25,6 +27,10 @@ class TestSimplexTransportWriter implements SimplexTransportWriter {
 		return capacity;
 	}
 
+	public int getMaxFrameLength() {
+		return MAX_FRAME_LENGTH;
+	}
+
 	public long getMaxLatency() {
 		return maxLatency;
 	}
diff --git a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
index d137c2481f20ee7fc26ef8cd1a666ff19623d257..18be16bfd1ae5a3d953d402fa2d6eeefe9463239 100644
--- a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
@@ -28,7 +28,7 @@ public class BluetoothClientTest extends DuplexClientTest {
 		callback = new ClientCallback(new TransportConfig(),
 				new TransportProperties(), remote);
 		plugin = new BluetoothPlugin(executor, new SystemClock(),
-				new SecureRandom(), callback, 0, 0);
+				new SecureRandom(), callback, 0, 0, 0);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
index d60d2dda904f22e79c17b8ffd2f32fddb13295db..08ade2b39e3f75b0cba19c09b6334be7ae70f6e5 100644
--- a/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
@@ -23,7 +23,7 @@ public class BluetoothServerTest extends DuplexServerTest {
 		callback = new ServerCallback(new TransportConfig(), local,
 				Collections.singletonMap(contactId, new TransportProperties()));
 		plugin = new BluetoothPlugin(executor, new SystemClock(),
-				new SecureRandom(), callback, 0, 0);
+				new SecureRandom(), callback, 0, 0, 0);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java b/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
index 27d8220c4f05b06e7d2b1bd9c818876f2a9fd221..6a83e1dae11f9c1568961e48c7d60de2abd088ac 100644
--- a/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
@@ -1,5 +1,6 @@
 package net.sf.briar.plugins.file;
 
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
 import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
 
 import java.io.File;
@@ -41,11 +42,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -54,7 +55,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		assertNull(plugin.createWriter(contactId));
@@ -73,11 +74,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -89,7 +90,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		assertNull(plugin.createWriter(contactId));
@@ -110,11 +111,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -126,7 +127,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		assertNull(plugin.createWriter(contactId));
@@ -149,11 +150,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -165,7 +166,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		assertNull(plugin.createWriter(contactId));
@@ -188,11 +189,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -204,7 +205,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		assertNotNull(plugin.createWriter(contactId));
@@ -230,11 +231,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -247,7 +248,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		SimplexTransportWriter writer = plugin.createWriter(contactId);
@@ -275,18 +276,18 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		plugin.driveInserted(testDir);
@@ -299,14 +300,14 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		Mockery context = new Mockery();
 		final Executor executor = context.mock(Executor.class);
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
-				callback, finder, monitor, 0);
+				callback, finder, monitor, MAX_FRAME_LENGTH, 0);
 
 		assertFalse(plugin.isPossibleConnectionFilename("abcdefg.dat"));
 		assertFalse(plugin.isPossibleConnectionFilename("abcdefghi.dat"));
@@ -322,11 +323,11 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 	public void testReaderIsCreated() throws Exception {
 		Mockery context = new Mockery();
 		final SimplexPluginCallback callback =
-			context.mock(SimplexPluginCallback.class);
+				context.mock(SimplexPluginCallback.class);
 		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
+				context.mock(RemovableDriveFinder.class);
 		final RemovableDriveMonitor monitor =
-			context.mock(RemovableDriveMonitor.class);
+				context.mock(RemovableDriveMonitor.class);
 
 		context.checking(new Expectations() {{
 			oneOf(monitor).start(with(any(Callback.class)));
@@ -334,7 +335,8 @@ public class RemovableDrivePluginTest extends BriarTestCase {
 		}});
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(
-				new ImmediateExecutor(), callback, finder, monitor, 0);
+				new ImmediateExecutor(), callback, finder, monitor,
+				MAX_FRAME_LENGTH, 0);
 		plugin.start();
 
 		File f = new File(testDir, "abcdefgh.dat");
diff --git a/briar-tests/src/net/sf/briar/plugins/modem/ModemPluginTest.java b/briar-tests/src/net/sf/briar/plugins/modem/ModemPluginTest.java
index 7707760015f6fdd8dfde6fcac5f0d602b6ec50e7..fadaa044a6574b20e710e315157c2ec264746580 100644
--- a/briar-tests/src/net/sf/briar/plugins/modem/ModemPluginTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/modem/ModemPluginTest.java
@@ -37,7 +37,7 @@ public class ModemPluginTest extends BriarTestCase {
 		final SerialPortList serialPortList =
 				context.mock(SerialPortList.class);
 		final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
-				serialPortList, null, 0, 0, true);
+				serialPortList, null, 0, 0, 0, true);
 		final Modem modem = context.mock(Modem.class);
 		context.checking(new Expectations() {{
 			oneOf(serialPortList).getPortNames();
@@ -71,7 +71,7 @@ public class ModemPluginTest extends BriarTestCase {
 		final DuplexPluginCallback callback =
 				context.mock(DuplexPluginCallback.class);
 		final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
-				serialPortList, callback, 0, 0, true);
+				serialPortList, callback, 0, 0, 0, true);
 		final Modem modem = context.mock(Modem.class);
 		final TransportProperties local = new TransportProperties();
 		local.put("iso3166", ISO_1336);
@@ -112,7 +112,7 @@ public class ModemPluginTest extends BriarTestCase {
 		final DuplexPluginCallback callback =
 				context.mock(DuplexPluginCallback.class);
 		final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
-				serialPortList, callback, 0, 0, true);
+				serialPortList, callback, 0, 0, 0, true);
 		final Modem modem = context.mock(Modem.class);
 		final TransportProperties local = new TransportProperties();
 		local.put("iso3166", ISO_1336);
@@ -153,7 +153,7 @@ public class ModemPluginTest extends BriarTestCase {
 		final DuplexPluginCallback callback =
 				context.mock(DuplexPluginCallback.class);
 		final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
-				serialPortList, callback, 0, 0, true);
+				serialPortList, callback, 0, 0, 0, true);
 		final Modem modem = context.mock(Modem.class);
 		final TransportProperties local = new TransportProperties();
 		local.put("iso3166", ISO_1336);
@@ -204,7 +204,7 @@ public class ModemPluginTest extends BriarTestCase {
 				context.mock(DuplexPluginCallback.class);
 		// Disable shuffling for this test, it confuses jMock
 		final ModemPlugin plugin = new ModemPlugin(pluginExecutor, modemFactory,
-				serialPortList, callback, 0, 0, false);
+				serialPortList, callback, 0, 0, 0, false);
 		final Modem modem = context.mock(Modem.class);
 		final TransportProperties local = new TransportProperties();
 		local.put("iso3166", ISO_1336);
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
index c3ba14c384286ad0af4d474f06b4ca2ff27ae245..9472213b13462f2ca9116889c4458e1a15c0547c 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpClientTest.java
@@ -9,6 +9,7 @@ import java.util.concurrent.Executors;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
+import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.plugins.DuplexClientTest;
 
@@ -27,7 +28,8 @@ public class LanTcpClientTest extends DuplexClientTest {
 		// Create the plugin
 		callback = new ClientCallback(new TransportConfig(),
 				new TransportProperties(), remote);
-		plugin = new LanTcpPlugin(executor, new SystemClock(), callback, 0, 0);
+		Clock clock = new SystemClock();
+		plugin = new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
index 61d563c34dcbbf4fd196f1d63591c72f92e0f42c..a335a908d69da74f1aa705024cfe35f3771bb485 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpPluginTest.java
@@ -36,7 +36,8 @@ public class LanTcpPluginTest extends BriarTestCase {
 		callback.local.put("port", "0");
 		Executor executor = Executors.newCachedThreadPool();
 		Clock clock = new SystemClock();
-		DuplexPlugin plugin = new LanTcpPlugin(executor, clock, callback, 0, 0);
+		DuplexPlugin plugin =
+				new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
 		plugin.start();
 		// The plugin should have bound a socket and stored the port number
 		assertTrue(callback.propertiesLatch.await(5, SECONDS));
@@ -62,7 +63,8 @@ public class LanTcpPluginTest extends BriarTestCase {
 		Callback callback = new Callback();
 		Executor executor = Executors.newCachedThreadPool();
 		Clock clock = new SystemClock();
-		DuplexPlugin plugin = new LanTcpPlugin(executor, clock, callback, 0, 0);
+		DuplexPlugin plugin =
+				new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
 		plugin.start();
 		// Listen on a local port
 		final ServerSocket ss = new ServerSocket();
diff --git a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
index f62573d84cb90bfa69784050dee16078776b940e..16d7d73f651879da2ab28fc165b32b62d9ab0402 100644
--- a/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
+++ b/briar-tests/src/net/sf/briar/plugins/tcp/LanTcpServerTest.java
@@ -7,6 +7,7 @@ import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
+import net.sf.briar.api.clock.Clock;
 import net.sf.briar.api.clock.SystemClock;
 import net.sf.briar.plugins.DuplexServerTest;
 
@@ -18,7 +19,8 @@ public class LanTcpServerTest extends DuplexServerTest {
 		callback = new ServerCallback(new TransportConfig(),
 				new TransportProperties(),
 				Collections.singletonMap(contactId, new TransportProperties()));
-		plugin = new LanTcpPlugin(executor, new SystemClock(), callback, 0, 0);
+		Clock clock = new SystemClock();
+		plugin = new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
 	}
 
 	public static void main(String[] args) throws Exception {
diff --git a/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java b/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java
index 8ef8c3b5dc7db784bfa56afe34ee0c8c6a042ca6..dd6d5adbcf5f7c984c126c77ce27d054cdaf1169 100644
--- a/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java
+++ b/briar-tests/src/net/sf/briar/transport/TransportIntegrationTest.java
@@ -1,6 +1,7 @@
 package net.sf.briar.transport;
 
 import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
 import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
@@ -129,7 +130,7 @@ public class TransportIntegrationTest extends BriarTestCase {
 		ConnectionContext ctx = new ConnectionContext(contactId, transportId,
 				secret, 0, true);
 		ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
-				MIN_CONNECTION_LENGTH, ctx, false, true);
+				MAX_FRAME_LENGTH, MIN_CONNECTION_LENGTH, ctx, false, true);
 		// Check that the connection writer thinks there's room for a packet
 		long capacity = w.getRemainingCapacity();
 		assertTrue(capacity > MAX_PACKET_LENGTH);
@@ -150,7 +151,7 @@ public class TransportIntegrationTest extends BriarTestCase {
 		ConnectionContext ctx = new ConnectionContext(contactId, transportId,
 				secret, 0, true);
 		ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
-				MIN_CONNECTION_LENGTH, ctx, false, false);
+				MAX_FRAME_LENGTH, MIN_CONNECTION_LENGTH, ctx, false, false);
 		// Check that the connection writer thinks there's room for a packet
 		long capacity = w.getRemainingCapacity();
 		assertTrue(capacity > MAX_PACKET_LENGTH);