diff --git a/api/net/sf/briar/api/transport/batch/BatchTransportReader.java b/api/net/sf/briar/api/transport/batch/BatchTransportReader.java
index 031fb754186c54dd989bb04a7d43b0bcc6d2aabb..e0e05dc50172661eb0790a1b3c80c77caf9a2cbb 100644
--- a/api/net/sf/briar/api/transport/batch/BatchTransportReader.java
+++ b/api/net/sf/briar/api/transport/batch/BatchTransportReader.java
@@ -13,14 +13,8 @@ public interface BatchTransportReader {
 	InputStream getInputStream();
 
 	/**
-	 * Finishes reading from the transport. This method should be called after
-	 * closing the input stream.
+	 * Closes the reader and disposes of any associated state. The argument
+	 * should be false if an exception was thrown while using the reader.
 	 */
-	void finish() throws IOException;
-
-	/**
-	 * Disposes of any associated state. This method must be called even if the
-	 * reader is not used, or if an exception is thrown while using the reader.
-	 */
-	void dispose() throws IOException;
+	void dispose(boolean success) throws IOException;
 }
diff --git a/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java b/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
index 4ea8763306272cee210317752179da3936889843..510d66a524cd5116d8cac910b7947e96ec4653ad 100644
--- a/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
+++ b/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
@@ -16,14 +16,8 @@ public interface BatchTransportWriter {
 	OutputStream getOutputStream();
 
 	/**
-	 * Finishes writing to the transport. This method should be called after
-	 * flushing and closing the output stream.
+	 * Closes the writer and disposes of any associated state. The argument
+	 * should be false if an exception was thrown while using the writer.
 	 */
-	void finish() throws IOException;
-
-	/**
-	 * Disposes of any associated state. This method must be called even if the
-	 * writer is not used, or if an exception is thrown while using the writer.
-	 */
-	void dispose() throws IOException;
+	void dispose(boolean success) throws IOException;
 }
diff --git a/api/net/sf/briar/api/transport/stream/StreamTransportConnection.java b/api/net/sf/briar/api/transport/stream/StreamTransportConnection.java
index aa3c25c81822aa909504114e285735d6a195f727..71ffa8da8750dbafe79f9e731ad1d9e413dad885 100644
--- a/api/net/sf/briar/api/transport/stream/StreamTransportConnection.java
+++ b/api/net/sf/briar/api/transport/stream/StreamTransportConnection.java
@@ -18,15 +18,8 @@ public interface StreamTransportConnection {
 	OutputStream getOutputStream() throws IOException;
 
 	/**
-	 * Finishes using the transport. This method should be called after closing
-	 * the input and output streams.
+	 * Closes the connection and disposes of any associated state. The argument
+	 * should be false if an exception was thrown while using the connection.
 	 */
-	void finish() throws IOException;
-
-	/**
-	 * Disposes of any associated state. This method must be called even if the
-	 * connection is not used, or if an exception is thrown while using the
-	 * connection.
-	 */
-	void dispose() throws IOException;
+	void dispose(boolean success) throws IOException;
 }
diff --git a/components/net/sf/briar/plugins/file/FileTransportReader.java b/components/net/sf/briar/plugins/file/FileTransportReader.java
index c44976ca5ac5a6dc0c5fee6404ad69e6b21ba781..a5fafef358c0146f50221cc2c4b8d6a99db2ec9d 100644
--- a/components/net/sf/briar/plugins/file/FileTransportReader.java
+++ b/components/net/sf/briar/plugins/file/FileTransportReader.java
@@ -12,8 +12,6 @@ class FileTransportReader implements BatchTransportReader {
 	private final InputStream in;
 	private final FilePlugin plugin;
 
-	private boolean streamInUse = false;
-
 	FileTransportReader(File file, InputStream in, FilePlugin plugin) {
 		this.file = file;
 		this.in = in;
@@ -21,17 +19,15 @@ class FileTransportReader implements BatchTransportReader {
 	}
 
 	public InputStream getInputStream() {
-		streamInUse = true;
 		return in;
 	}
 
-	public void finish() throws IOException {
-		streamInUse = false;
-		plugin.readerFinished(file);
-	}
-
-	public void dispose() throws IOException {
-		if(streamInUse) in.close();
-		file.delete();
+	public void dispose(boolean success) throws IOException {
+		try {
+			in.close();
+			if(success) plugin.readerFinished(file);
+		} finally {
+			file.delete();
+		}
 	}
 }
diff --git a/components/net/sf/briar/plugins/file/FileTransportWriter.java b/components/net/sf/briar/plugins/file/FileTransportWriter.java
index b5d3532555b6118fedb48ec9d5bb3063614d91d5..19bf88a1ce5b937823338b39081a23f8d1614ba3 100644
--- a/components/net/sf/briar/plugins/file/FileTransportWriter.java
+++ b/components/net/sf/briar/plugins/file/FileTransportWriter.java
@@ -13,8 +13,6 @@ class FileTransportWriter implements BatchTransportWriter {
 	private final long capacity;
 	private final FilePlugin plugin;
 
-	private boolean streamInUse = false;
-
 	FileTransportWriter(File file, OutputStream out, long capacity,
 			FilePlugin plugin) {
 		this.file = file;
@@ -28,17 +26,15 @@ class FileTransportWriter implements BatchTransportWriter {
 	}
 
 	public OutputStream getOutputStream() {
-		streamInUse = true;
 		return out;
 	}
 
-	public void finish() {
-		streamInUse = false;
-		plugin.writerFinished(file);
-	}
-
-	public void dispose() throws IOException {
-		if(streamInUse) out.close();
-		file.delete();
+	public void dispose(boolean success) throws IOException {
+		try {
+			out.close();
+			if(success) plugin.writerFinished(file);
+		} finally {
+			file.delete();
+		}
 	}
 }
diff --git a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
index be8d73dfe5599bbd8d4dc1115800f3f97915c694..7f5e915be79312d13543b45c01307d03f8206f15 100644
--- a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
@@ -12,7 +12,7 @@ import java.util.concurrent.Executor;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
 
-public class SimpleSocketPlugin extends SocketPlugin {
+class SimpleSocketPlugin extends SocketPlugin {
 
 	public static final int TRANSPORT_ID = 1;
 
diff --git a/components/net/sf/briar/plugins/socket/SocketPlugin.java b/components/net/sf/briar/plugins/socket/SocketPlugin.java
index ef693baa726bf4aa02293a3e7ade3668c7e8ce68..fc2cfaf374926ef56bc6c44ea9207aaa9a2996f5 100644
--- a/components/net/sf/briar/plugins/socket/SocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/SocketPlugin.java
@@ -135,6 +135,7 @@ implements StreamTransportPlugin {
 	}
 
 	public synchronized void poll() {
+		// Subclasses may not support polling
 		if(!shouldPoll()) throw new UnsupportedOperationException();
 		if(!started) return;
 		for(ContactId c : remoteProperties.keySet()) {
diff --git a/components/net/sf/briar/plugins/socket/SocketTransportConnection.java b/components/net/sf/briar/plugins/socket/SocketTransportConnection.java
index 92488fefff7c132fe208b971cdf18d6a553a7bde..bfc68198f4078453b8d4ebcd8473d48afabbc866 100644
--- a/components/net/sf/briar/plugins/socket/SocketTransportConnection.java
+++ b/components/net/sf/briar/plugins/socket/SocketTransportConnection.java
@@ -11,28 +11,19 @@ class SocketTransportConnection implements StreamTransportConnection {
 
 	private final Socket socket;
 
-	private boolean streamInUse = false;
-
 	SocketTransportConnection(Socket socket) {
 		this.socket = socket;
 	}
 
 	public InputStream getInputStream() throws IOException {
-		streamInUse = true;
 		return socket.getInputStream();
 	}
 
 	public OutputStream getOutputStream() throws IOException {
-		streamInUse = true;
 		return socket.getOutputStream();
 	}
 
-	public void finish() throws IOException {
-		// FIXME: Tell the plugin?
-		streamInUse = false;
-	}
-
-	public void dispose() throws IOException {
-		if(streamInUse) socket.close();
+	public void dispose(boolean success) throws IOException {
+		socket.close();
 	}
 }
diff --git a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
index 4c942a4a1be0705ba4584302671c30669f3fb220..2bede141746f9f0c646779a5e3ba6833a5da404d 100644
--- a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
+++ b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
@@ -289,10 +289,9 @@ public class RemovableDrivePluginTest extends TestCase {
 		out.write(new byte[123]);
 		out.flush();
 		out.close();
-		writer.finish();
 		assertEquals(123L, files[0].length());
 		// Disposing of the writer should delete the file
-		writer.dispose();
+		writer.dispose(true);
 		files = drive1.listFiles();
 		assertTrue(files == null || files.length == 0);
 
diff --git a/test/net/sf/briar/plugins/socket/SimpleSocketPluginTest.java b/test/net/sf/briar/plugins/socket/SimpleSocketPluginTest.java
index 6ea3fbf492b6f52a831c071fccce8c0fcbec118b..6093a7e3604602a35a552b7dec57cf8c90bfe292 100644
--- a/test/net/sf/briar/plugins/socket/SimpleSocketPluginTest.java
+++ b/test/net/sf/briar/plugins/socket/SimpleSocketPluginTest.java
@@ -107,7 +107,7 @@ public class SimpleSocketPluginTest extends TestCase {
 		assertTrue(latch.await(1, TimeUnit.SECONDS));
 		assertFalse(error.get());
 		// Clean up
-		conn.getInputStream().close(); // FIXME: Change the API
+		conn.dispose(true);
 		ss.close();
 		plugin.stop();
 	}