diff --git a/api/net/sf/briar/api/protocol/AuthorId.java b/api/net/sf/briar/api/protocol/AuthorId.java
index b5136c222ff5ede7e84913e29859b6048b9d07c2..9cefbfc5f5a2e4f0e539c14f4c0a9053353c1d18 100644
--- a/api/net/sf/briar/api/protocol/AuthorId.java
+++ b/api/net/sf/briar/api/protocol/AuthorId.java
@@ -13,7 +13,7 @@ public class AuthorId extends UniqueId {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.AUTHOR_ID);
+		w.writeUserDefinedId(Types.AUTHOR_ID);
 		w.writeBytes(id);
 	}
 
diff --git a/api/net/sf/briar/api/protocol/BatchId.java b/api/net/sf/briar/api/protocol/BatchId.java
index f2b2f542ffed2bf3cae881b631f247b78c41ae9e..a3d573bc9b2f559dce8e2c007fee9646618ae3ac 100644
--- a/api/net/sf/briar/api/protocol/BatchId.java
+++ b/api/net/sf/briar/api/protocol/BatchId.java
@@ -16,7 +16,7 @@ public class BatchId extends UniqueId {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.BATCH_ID);
+		w.writeUserDefinedId(Types.BATCH_ID);
 		w.writeBytes(id);
 	}
 
diff --git a/api/net/sf/briar/api/protocol/GroupId.java b/api/net/sf/briar/api/protocol/GroupId.java
index aa34e728acf85402d2ca40572eee38289188754c..0ea39e3b0fc6e58f2cdc1b6d94528d766d971701 100644
--- a/api/net/sf/briar/api/protocol/GroupId.java
+++ b/api/net/sf/briar/api/protocol/GroupId.java
@@ -16,7 +16,7 @@ public class GroupId extends UniqueId {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.GROUP_ID);
+		w.writeUserDefinedId(Types.GROUP_ID);
 		w.writeBytes(id);
 	}
 
diff --git a/api/net/sf/briar/api/protocol/MessageId.java b/api/net/sf/briar/api/protocol/MessageId.java
index e559be69de8fcedec16208fdf49e3882a61f04e4..5f1bd67c0477982e968468d4c5ba03585d0c55c4 100644
--- a/api/net/sf/briar/api/protocol/MessageId.java
+++ b/api/net/sf/briar/api/protocol/MessageId.java
@@ -13,7 +13,7 @@ public class MessageId extends UniqueId {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.MESSAGE_ID);
+		w.writeUserDefinedId(Types.MESSAGE_ID);
 		w.writeBytes(id);
 	}
 
diff --git a/api/net/sf/briar/api/serial/Writer.java b/api/net/sf/briar/api/serial/Writer.java
index 8f2d187d2ed37e0ee28668bf8f850b7f5856e7d2..887c1e51b32383fcb2486b13557ecb93e130331a 100644
--- a/api/net/sf/briar/api/serial/Writer.java
+++ b/api/net/sf/briar/api/serial/Writer.java
@@ -6,8 +6,6 @@ import java.util.Map;
 
 public interface Writer {
 
-	long getBytesWritten();
-
 	void writeBoolean(boolean b) throws IOException;
 
 	void writeUint7(byte b) throws IOException;
@@ -33,5 +31,5 @@ public interface Writer {
 
 	void writeNull() throws IOException;
 
-	void writeUserDefinedTag(int tag) throws IOException;
+	void writeUserDefinedId(int tag) throws IOException;
 }
diff --git a/components/net/sf/briar/protocol/AuthorImpl.java b/components/net/sf/briar/protocol/AuthorImpl.java
index 9596dffbba6c5bba539b986da6c8600bd8ee173b..f232f932f5dba876c2162e55e096ba56316c50e7 100644
--- a/components/net/sf/briar/protocol/AuthorImpl.java
+++ b/components/net/sf/briar/protocol/AuthorImpl.java
@@ -32,7 +32,7 @@ class AuthorImpl implements Author {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.AUTHOR);
+		w.writeUserDefinedId(Types.AUTHOR);
 		w.writeString(name);
 		w.writeBytes(publicKey);
 	}
diff --git a/components/net/sf/briar/protocol/GroupImpl.java b/components/net/sf/briar/protocol/GroupImpl.java
index ad265d51d5637cdae0bdbc87c2d29eb4bb4b7436..4f6f613e904d83c1ed46f823a09600bf980ca28d 100644
--- a/components/net/sf/briar/protocol/GroupImpl.java
+++ b/components/net/sf/briar/protocol/GroupImpl.java
@@ -32,7 +32,7 @@ class GroupImpl implements Group {
 	}
 
 	public void writeTo(Writer w) throws IOException {
-		w.writeUserDefinedTag(Types.GROUP);
+		w.writeUserDefinedId(Types.GROUP);
 		w.writeString(name);
 		if(publicKey == null) w.writeNull();
 		else w.writeBytes(publicKey);
diff --git a/components/net/sf/briar/protocol/MessageEncoderImpl.java b/components/net/sf/briar/protocol/MessageEncoderImpl.java
index 1c3a386c3b48ccadbee800c4c8475b27ab1cb9e1..326faf07d07ed40b2fa5766dc875425dca4f865b 100644
--- a/components/net/sf/briar/protocol/MessageEncoderImpl.java
+++ b/components/net/sf/briar/protocol/MessageEncoderImpl.java
@@ -74,7 +74,7 @@ class MessageEncoderImpl implements MessageEncoder {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
 		// Write the message
-		w.writeUserDefinedTag(Types.MESSAGE);
+		w.writeUserDefinedId(Types.MESSAGE);
 		if(parent == null) w.writeNull();
 		else parent.writeTo(w);
 		if(group == null) w.writeNull();
diff --git a/components/net/sf/briar/protocol/writers/AckWriterImpl.java b/components/net/sf/briar/protocol/writers/AckWriterImpl.java
index f1d9722cb40c10cc8228bc86902aeb495affec73..ade9ef6bf02d1463e75bfe1af04642d587011dcf 100644
--- a/components/net/sf/briar/protocol/writers/AckWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/AckWriterImpl.java
@@ -55,7 +55,7 @@ class AckWriterImpl implements AckWriter {
 	}
 
 	private void start() throws IOException {
-		w.writeUserDefinedTag(Types.ACK);
+		w.writeUserDefinedId(Types.ACK);
 		w.writeListStart();
 		capacity -= headerLength;
 		started = true;
diff --git a/components/net/sf/briar/protocol/writers/BatchWriterImpl.java b/components/net/sf/briar/protocol/writers/BatchWriterImpl.java
index bc6bfb0f8e09ac45380175cef7200350ab6fa17e..e6c9c8a5df4ea5ef3bca4e91cad55ff21888f07b 100644
--- a/components/net/sf/briar/protocol/writers/BatchWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/BatchWriterImpl.java
@@ -61,7 +61,7 @@ class BatchWriterImpl implements BatchWriter {
 
 	private void start() throws IOException {
 		messageDigest.reset();
-		w.writeUserDefinedTag(Types.BATCH);
+		w.writeUserDefinedId(Types.BATCH);
 		w.writeListStart();
 		capacity -= headerLength;
 		started = true;
diff --git a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java
index 04303fbf4d2fbaf1f926a8341e8559f3159ed7c0..0aa54a6d0f8a9b0b6c25dd6c7f8ab5fba3a46b9b 100644
--- a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java
@@ -55,7 +55,7 @@ class OfferWriterImpl implements OfferWriter {
 	}
 
 	private void start() throws IOException {
-		w.writeUserDefinedTag(Types.OFFER);
+		w.writeUserDefinedId(Types.OFFER);
 		w.writeListStart();
 		capacity -= headerLength;
 		started = true;
diff --git a/components/net/sf/briar/protocol/writers/RequestWriterImpl.java b/components/net/sf/briar/protocol/writers/RequestWriterImpl.java
index a3ceb5e50c70f50adc644fad23f4690ff987e7fe..7f831eff64339b1ebdf763af8e6809b30de2cd71 100644
--- a/components/net/sf/briar/protocol/writers/RequestWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/RequestWriterImpl.java
@@ -21,7 +21,7 @@ class RequestWriterImpl implements RequestWriter {
 
 	public void writeRequest(BitSet b, int length)
 	throws IOException {
-		w.writeUserDefinedTag(Types.REQUEST);
+		w.writeUserDefinedId(Types.REQUEST);
 		// If the number of bits isn't a multiple of 8, round up to a byte
 		int bytes = length % 8 == 0 ? length / 8 : length / 8 + 1;
 		byte[] bitmap = new byte[bytes];
diff --git a/components/net/sf/briar/protocol/writers/SubscriptionWriterImpl.java b/components/net/sf/briar/protocol/writers/SubscriptionWriterImpl.java
index 97b2e8aa0992c8bbfd604c69fb50a8413cda7652..82440ba4c312fb1ee54fe3a78981b4b2bed6b354 100644
--- a/components/net/sf/briar/protocol/writers/SubscriptionWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/SubscriptionWriterImpl.java
@@ -22,7 +22,7 @@ class SubscriptionWriterImpl implements SubscriptionWriter {
 
 	public void writeSubscriptions(Map<Group, Long> subs, long timestamp)
 	throws IOException {
-		w.writeUserDefinedTag(Types.SUBSCRIPTION_UPDATE);
+		w.writeUserDefinedId(Types.SUBSCRIPTION_UPDATE);
 		w.writeMap(subs);
 		w.writeInt64(timestamp);
 		out.flush();
diff --git a/components/net/sf/briar/protocol/writers/TransportWriterImpl.java b/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
index 1d346fdabb059177eda39c0e4a9c5432f2b4e7a0..1ddcae6ce31b99a9960976fe7d31d19b4d0b6592 100644
--- a/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
@@ -22,10 +22,10 @@ class TransportWriterImpl implements TransportWriter {
 
 	public void writeTransports(Map<String, Map<String, String>> transports,
 			long timestamp) throws IOException {
-		w.writeUserDefinedTag(Types.TRANSPORT_UPDATE);
+		w.writeUserDefinedId(Types.TRANSPORT_UPDATE);
 		w.writeListStart();
 		for(Entry<String, Map<String, String>> e : transports.entrySet()) {
-			w.writeUserDefinedTag(Types.TRANSPORT_PROPERTIES);
+			w.writeUserDefinedId(Types.TRANSPORT_PROPERTIES);
 			w.writeString(e.getKey());
 			w.writeMap(e.getValue());
 		}
diff --git a/components/net/sf/briar/serial/WriterImpl.java b/components/net/sf/briar/serial/WriterImpl.java
index d27eebabb1f62870166b29191c106c751f4acb45..ac786c57fdc55654af68964bd9b8df16c357f7ee 100644
--- a/components/net/sf/briar/serial/WriterImpl.java
+++ b/components/net/sf/briar/serial/WriterImpl.java
@@ -14,45 +14,35 @@ import net.sf.briar.api.serial.Writer;
 class WriterImpl implements Writer {
 
 	private final OutputStream out;
-	private long bytesWritten = 0L;
 
 	WriterImpl(OutputStream out) {
 		this.out = out;
 	}
 
-	public long getBytesWritten() {
-		return bytesWritten;
-	}
-
 	public void writeBoolean(boolean b) throws IOException {
 		if(b) out.write(Tag.TRUE);
 		else out.write(Tag.FALSE);
-		bytesWritten++;
 	}
 
 	public void writeUint7(byte b) throws IOException {
 		if(b < 0) throw new IllegalArgumentException();
 		out.write(b);
-		bytesWritten++;
 	}
 
 	public void writeInt8(byte b) throws IOException {
 		out.write(Tag.INT8);
 		out.write(b);
-		bytesWritten += 2;
 	}
 
 	public void writeInt16(short s) throws IOException {
 		out.write(Tag.INT16);
 		out.write((byte) (s >> 8));
 		out.write((byte) ((s << 8) >> 8));
-		bytesWritten += 3;
 	}
 
 	public void writeInt32(int i) throws IOException {
 		out.write(Tag.INT32);
 		writeInt32Bits(i);
-		bytesWritten += 5;
 	}
 
 	private void writeInt32Bits(int i) throws IOException {
@@ -65,7 +55,6 @@ class WriterImpl implements Writer {
 	public void writeInt64(long l) throws IOException {
 		out.write(Tag.INT64);
 		writeInt64Bits(l);
-		bytesWritten += 9;
 	}
 
 	private void writeInt64Bits(long l) throws IOException {
@@ -94,13 +83,11 @@ class WriterImpl implements Writer {
 	public void writeFloat32(float f) throws IOException {
 		out.write(Tag.FLOAT32);
 		writeInt32Bits(Float.floatToRawIntBits(f));
-		bytesWritten += 5;
 	}
 
 	public void writeFloat64(double d) throws IOException {
 		out.write(Tag.FLOAT64);
 		writeInt64Bits(Double.doubleToRawLongBits(d));
-		bytesWritten += 9;
 	}
 
 	public void writeString(String s) throws IOException {
@@ -111,7 +98,6 @@ class WriterImpl implements Writer {
 			writeLength(b.length);
 		}
 		out.write(b);
-		bytesWritten += b.length + 1;
 	}
 
 	private void writeLength(int i) throws IOException {
@@ -129,7 +115,6 @@ class WriterImpl implements Writer {
 			writeLength(b.length);
 		}
 		out.write(b);
-		bytesWritten += b.length + 1;
 	}
 
 	public void writeList(Collection<?> c) throws IOException {
@@ -140,7 +125,6 @@ class WriterImpl implements Writer {
 			writeLength(length);
 		}
 		for(Object o : c) writeObject(o);
-		bytesWritten++;
 	}
 
 	private void writeObject(Object o) throws IOException {
@@ -162,12 +146,10 @@ class WriterImpl implements Writer {
 
 	public void writeListStart() throws IOException {
 		out.write(Tag.LIST_START);
-		bytesWritten++;
 	}
 
 	public void writeListEnd() throws IOException {
 		out.write(Tag.END);
-		bytesWritten++;
 	}
 
 	public void writeMap(Map<?, ?> m) throws IOException {
@@ -181,33 +163,27 @@ class WriterImpl implements Writer {
 			writeObject(e.getKey());
 			writeObject(e.getValue());
 		}
-		bytesWritten++;
 	}
 
 	public void writeMapStart() throws IOException {
 		out.write(Tag.MAP_START);
-		bytesWritten++;
 	}
 
 	public void writeMapEnd() throws IOException {
 		out.write(Tag.END);
-		bytesWritten++;
 	}
 
 	public void writeNull() throws IOException {
 		out.write(Tag.NULL);
-		bytesWritten++;
 	}
 
-	public void writeUserDefinedTag(int tag) throws IOException {
-		if(tag < 0 || tag > 255) throw new IllegalArgumentException();
-		if(tag < 32) {
-			out.write((byte) (Tag.SHORT_USER | tag));
-			bytesWritten++;
+	public void writeUserDefinedId(int id) throws IOException {
+		if(id < 0 || id > 255) throw new IllegalArgumentException();
+		if(id < 32) {
+			out.write((byte) (Tag.SHORT_USER | id));
 		} else {
 			out.write(Tag.USER);
-			out.write((byte) tag);
-			bytesWritten += 2;
+			out.write((byte) id);
 		}
 	}
 }
diff --git a/test/net/sf/briar/protocol/AckReaderTest.java b/test/net/sf/briar/protocol/AckReaderTest.java
index 32ffedd83a2a9a1afda262e17e6b5335d41c9c87..ba604af07a5948c32abe452000bf2ee63d2e2986 100644
--- a/test/net/sf/briar/protocol/AckReaderTest.java
+++ b/test/net/sf/briar/protocol/AckReaderTest.java
@@ -100,18 +100,18 @@ public class AckReaderTest extends TestCase {
 	private byte[] createAck(boolean tooBig) throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.ACK);
+		w.writeUserDefinedId(Types.ACK);
 		w.writeListStart();
 		byte[] b = new byte[UniqueId.LENGTH];
 		Random random = new Random();
 		while(out.size() + BatchId.LENGTH + 3
 				< ProtocolConstants.MAX_PACKET_LENGTH) {
-			w.writeUserDefinedTag(Types.BATCH_ID);
+			w.writeUserDefinedId(Types.BATCH_ID);
 			random.nextBytes(b);
 			w.writeBytes(b);
 		}
 		if(tooBig) {
-			w.writeUserDefinedTag(Types.BATCH_ID);
+			w.writeUserDefinedId(Types.BATCH_ID);
 			random.nextBytes(b);
 			w.writeBytes(b);
 		}
@@ -123,7 +123,7 @@ public class AckReaderTest extends TestCase {
 	private byte[] createEmptyAck() throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.ACK);
+		w.writeUserDefinedId(Types.ACK);
 		w.writeListStart();
 		w.writeListEnd();
 		return out.toByteArray();
diff --git a/test/net/sf/briar/protocol/BatchReaderTest.java b/test/net/sf/briar/protocol/BatchReaderTest.java
index f969446421ecd77ac90ca26c5ec0837405df83f7..c6727e2749f5a8f3a5cf8c20d0ab6086ac9bba3c 100644
--- a/test/net/sf/briar/protocol/BatchReaderTest.java
+++ b/test/net/sf/briar/protocol/BatchReaderTest.java
@@ -143,10 +143,10 @@ public class BatchReaderTest extends TestCase {
 	private byte[] createBatch(int size) throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream(size);
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.BATCH);
+		w.writeUserDefinedId(Types.BATCH);
 		w.writeListStart();
 		// We're using a fake message reader, so it's OK to use a fake message
-		w.writeUserDefinedTag(Types.MESSAGE);
+		w.writeUserDefinedId(Types.MESSAGE);
 		w.writeBytes(new byte[size - 10]);
 		w.writeListEnd();
 		byte[] b = out.toByteArray();
@@ -157,7 +157,7 @@ public class BatchReaderTest extends TestCase {
 	private byte[] createEmptyBatch() throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.BATCH);
+		w.writeUserDefinedId(Types.BATCH);
 		w.writeListStart();
 		w.writeListEnd();
 		return out.toByteArray();
diff --git a/test/net/sf/briar/protocol/RequestReaderTest.java b/test/net/sf/briar/protocol/RequestReaderTest.java
index 1f4a97fba2af07b742f719c855a891c569f3f65b..e3f8ddcb5dd26e7d8d184d36ec75247746df937b 100644
--- a/test/net/sf/briar/protocol/RequestReaderTest.java
+++ b/test/net/sf/briar/protocol/RequestReaderTest.java
@@ -115,7 +115,7 @@ public class RequestReaderTest extends TestCase {
 	private byte[] createRequest(boolean tooBig) throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.REQUEST);
+		w.writeUserDefinedId(Types.REQUEST);
 		// Allow one byte for the REQUEST tag, one byte for the BYTES tag,
 		// and five bytes for the length as an int32
 		int size = ProtocolConstants.MAX_PACKET_LENGTH - 7;
@@ -128,7 +128,7 @@ public class RequestReaderTest extends TestCase {
 	private byte[] createRequest(byte[] bitmap) throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
-		w.writeUserDefinedTag(Types.REQUEST);
+		w.writeUserDefinedId(Types.REQUEST);
 		w.writeBytes(bitmap);
 		return out.toByteArray();
 	}
diff --git a/test/net/sf/briar/serial/WriterImplTest.java b/test/net/sf/briar/serial/WriterImplTest.java
index 7e26cc347761c72ef5376962ee32a81038d82dde..8bd773a2e9cc1a3fe4a4a4e8b3de55edd7567a9c 100644
--- a/test/net/sf/briar/serial/WriterImplTest.java
+++ b/test/net/sf/briar/serial/WriterImplTest.java
@@ -269,8 +269,8 @@ public class WriterImplTest extends TestCase {
 
 	@Test
 	public void testWriteShortUserDefinedTag() throws IOException {
-		w.writeUserDefinedTag(0);
-		w.writeUserDefinedTag(31);
+		w.writeUserDefinedId(0);
+		w.writeUserDefinedId(31);
 		// SHORT_USER tag (3 bits), 0 (5 bits), SHORT_USER tag (3 bits),
 		// 31 (5 bits)
 		checkContents("C0" + "DF");
@@ -278,8 +278,8 @@ public class WriterImplTest extends TestCase {
 
 	@Test
 	public void testWriteUserDefinedTag() throws IOException {
-		w.writeUserDefinedTag(32);
-		w.writeUserDefinedTag(255);
+		w.writeUserDefinedId(32);
+		w.writeUserDefinedId(255);
 		// USER tag, 32 as uint8, USER tag, 255 as uint8
 		checkContents("EF" + "20" + "EF" + "FF");
 	}
@@ -288,7 +288,7 @@ public class WriterImplTest extends TestCase {
 	public void testWriteCollectionOfWritables() throws IOException {
 		Writable writable = new Writable() {
 			public void writeTo(Writer w) throws IOException {
-				w.writeUserDefinedTag(0);
+				w.writeUserDefinedId(0);
 				w.writeString("foo");
 			}
 		};