diff --git a/api/net/sf/briar/api/TransportId.java b/api/net/sf/briar/api/TransportId.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c5ab82ed4ef02c0cc22723417f86b5410b1bfe3
--- /dev/null
+++ b/api/net/sf/briar/api/TransportId.java
@@ -0,0 +1,47 @@
+package net.sf.briar.api;
+
+import java.io.IOException;
+
+import net.sf.briar.api.serial.Writable;
+import net.sf.briar.api.serial.Writer;
+
+/**
+ * Type-safe wrapper for an integer that uniquely identifies a transport plugin.
+ */
+public class TransportId implements Writable, Comparable<TransportId> {
+
+	public static final int MIN_ID = 0;
+	public static final int MAX_ID = 65535;
+
+	private final int id;
+
+	public TransportId(int id) {
+		if(id < MIN_ID || id > MAX_ID) throw new IllegalArgumentException();
+		this.id = id;
+	}
+
+	public int getInt() {
+		return id;
+	}
+
+	public void writeTo(Writer w) throws IOException {
+		w.writeInt32(id);
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if(o instanceof TransportId) return id == ((TransportId) o).id;
+		return false;
+	}
+
+	@Override
+	public int hashCode() {
+		return id;
+	}
+
+	public int compareTo(TransportId t) {
+		if(id < t.id) return -1;
+		if(id > t.id) return 1;
+		return 0;
+	}
+}
diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java
index 087b5a87b70ceb5adf3ce9cd136efd4e1177c4d5..67ebdcd2b0b99d1b243327952239eab2e185c3ad 100644
--- a/api/net/sf/briar/api/db/DatabaseComponent.java
+++ b/api/net/sf/briar/api/db/DatabaseComponent.java
@@ -6,6 +6,7 @@ import java.util.Map;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.Ack;
 import net.sf.briar.api.protocol.AuthorId;
 import net.sf.briar.api.protocol.Batch;
@@ -50,7 +51,7 @@ public interface DatabaseComponent {
 	 * Adds a new contact to the database with the given transport properties
 	 * and shared secret, returns an ID for the contact.
 	 */
-	ContactId addContact(Map<Integer, Map<String, String>> transports,
+	ContactId addContact(Map<TransportId, Map<String, String>> transports,
 			byte[] secret) throws DbException;
 
 	/** Adds a locally generated group message to the database. */
@@ -102,13 +103,13 @@ public interface DatabaseComponent {
 	 * Returns an outgoing connection number for the given contact and
 	 * transport.
 	 */
-	long getConnectionNumber(ContactId c, int transportId) throws DbException;
+	long getConnectionNumber(ContactId c, TransportId t) throws DbException;
 
 	/**
 	 * Returns the connection reordering window for the given contact and
 	 * transport.
 	 */
-	ConnectionWindow getConnectionWindow(ContactId c, int transportId)
+	ConnectionWindow getConnectionWindow(ContactId c, TransportId t)
 	throws DbException;
 
 	/** Returns the IDs of all contacts. */
@@ -124,13 +125,13 @@ public interface DatabaseComponent {
 	Collection<Group> getSubscriptions() throws DbException;
 
 	/** Returns the configuration for the given transport. */
-	Map<String, String> getTransportConfig(int transportId) throws DbException;
+	Map<String, String> getTransportConfig(TransportId t) throws DbException;
 
 	/** Returns all local transport properties. */
-	Map<Integer, Map<String, String>> getTransports() throws DbException;
+	Map<TransportId, Map<String, String>> getTransports() throws DbException;
 
 	/** Returns all transport properties for the given contact. */
-	Map<Integer, Map<String, String>> getTransports(ContactId c)
+	Map<TransportId, Map<String, String>> getTransports(ContactId c)
 	throws DbException;
 
 	/** Returns the contacts to which the given group is visible. */
@@ -171,7 +172,7 @@ public interface DatabaseComponent {
 	 * Sets the connection reordering window for the given contact and
 	 * transport.
 	 */
-	void setConnectionWindow(ContactId c, int transportId, ConnectionWindow w)
+	void setConnectionWindow(ContactId c, TransportId t, ConnectionWindow w)
 	throws DbException;
 
 	/** Records the user's rating for the given author. */
@@ -184,14 +185,14 @@ public interface DatabaseComponent {
 	 * Sets the configuration for the given transport, replacing any existing
 	 * configuration for that transport.
 	 */
-	void setTransportConfig(int transportId, Map<String, String> config)
+	void setTransportConfig(TransportId t, Map<String, String> config)
 	throws DbException;
 
 	/**
 	 * Sets the transport properties for the given transport, replacing any
 	 * existing properties for that transport.
 	 */
-	void setTransportProperties(int transportId, Map<String, String> properties)
+	void setTransportProperties(TransportId t, Map<String, String> properties)
 	throws DbException;
 
 	/**
diff --git a/api/net/sf/briar/api/protocol/TransportUpdate.java b/api/net/sf/briar/api/protocol/TransportUpdate.java
index b04940fe5d73dbdb06a229e92f2a5861bf6edc52..bb1680a1e4a13dc1de70e32415bd5cd54c941d67 100644
--- a/api/net/sf/briar/api/protocol/TransportUpdate.java
+++ b/api/net/sf/briar/api/protocol/TransportUpdate.java
@@ -2,6 +2,8 @@ package net.sf.briar.api.protocol;
 
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
+
 /** A packet updating the sender's transport properties. */
 public interface TransportUpdate {
 
@@ -15,7 +17,7 @@ public interface TransportUpdate {
 	static final int MAX_PLUGINS_PER_UPDATE = 50;
 
 	/** Returns the transport properties contained in the update. */
-	Map<Integer, Map<String, String>> getTransports();
+	Map<TransportId, Map<String, String>> getTransports();
 
 	/**
 	 * Returns the update's timestamp. Updates that are older than the newest
diff --git a/api/net/sf/briar/api/protocol/writers/TransportWriter.java b/api/net/sf/briar/api/protocol/writers/TransportWriter.java
index 9878de2ccfb2e96b6e21ce154557282e08fd8139..a3367badf74940da82e6b545f2c7fd00fa709e7f 100644
--- a/api/net/sf/briar/api/protocol/writers/TransportWriter.java
+++ b/api/net/sf/briar/api/protocol/writers/TransportWriter.java
@@ -3,10 +3,12 @@ package net.sf.briar.api.protocol.writers;
 import java.io.IOException;
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
+
 /** An interface for creating a transport update. */
 public interface TransportWriter {
 
 	/** Writes the contents of the update. */
-	void writeTransports(Map<Integer, Map<String, String>> transports,
+	void writeTransports(Map<TransportId, Map<String, String>> transports,
 			long timestamp) throws IOException;
 }
diff --git a/api/net/sf/briar/api/transport/ConnectionRecogniserFactory.java b/api/net/sf/briar/api/transport/ConnectionRecogniserFactory.java
index a0a122087952c35ae461c67102f58bb60b92cd99..688b453dbf9462de8e1edb70ebe7288ed623e03a 100644
--- a/api/net/sf/briar/api/transport/ConnectionRecogniserFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionRecogniserFactory.java
@@ -1,6 +1,8 @@
 package net.sf.briar.api.transport;
 
+import net.sf.briar.api.TransportId;
+
 public interface ConnectionRecogniserFactory {
 
-	ConnectionRecogniser createConnectionRecogniser(int transportId);
+	ConnectionRecogniser createConnectionRecogniser(TransportId t);
 }
diff --git a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
index a8d58e808540e033897b93585b04ae6bc3c5dce9..a543e2df7703d51589a783f5fef00e78eabebff5 100644
--- a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
@@ -2,9 +2,11 @@ package net.sf.briar.api.transport;
 
 import java.io.OutputStream;
 
+import net.sf.briar.api.TransportId;
+
 public interface ConnectionWriterFactory {
 
 	ConnectionWriter createConnectionWriter(OutputStream out, 
-			long capacity, boolean initiator, int transportId, long connection,
+			long capacity, boolean initiator, TransportId t, long connection,
 			byte[] secret);
 }
diff --git a/api/net/sf/briar/api/transport/batch/BatchTransportPlugin.java b/api/net/sf/briar/api/transport/batch/BatchTransportPlugin.java
index 26d07fcf22f7e562a9359acf95779744c16a6f0c..f217b4691b77745880fb8bca5c99dbf8f47c732f 100644
--- a/api/net/sf/briar/api/transport/batch/BatchTransportPlugin.java
+++ b/api/net/sf/briar/api/transport/batch/BatchTransportPlugin.java
@@ -3,6 +3,7 @@ package net.sf.briar.api.transport.batch;
 import java.util.Map;
 
 import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.transport.InvalidConfigException;
 import net.sf.briar.api.transport.InvalidTransportException;
 
@@ -13,7 +14,7 @@ import net.sf.briar.api.transport.InvalidTransportException;
 public interface BatchTransportPlugin {
 
 	/** Returns the plugin's transport identifier. */
-	int getTransportId();
+	TransportId getId();
 
 	/**
 	 * Starts the plugin. Any connections that are later initiated by contacts
diff --git a/api/net/sf/briar/api/transport/stream/StreamTransportPlugin.java b/api/net/sf/briar/api/transport/stream/StreamTransportPlugin.java
index 786635c7c04c8556cad4d1038c49ba369a48d705..970d58b2c4c0e1b0be3d3df210b0e91d8f5a4e7b 100644
--- a/api/net/sf/briar/api/transport/stream/StreamTransportPlugin.java
+++ b/api/net/sf/briar/api/transport/stream/StreamTransportPlugin.java
@@ -3,6 +3,7 @@ package net.sf.briar.api.transport.stream;
 import java.util.Map;
 
 import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.transport.InvalidConfigException;
 import net.sf.briar.api.transport.InvalidTransportException;
 
@@ -13,7 +14,7 @@ import net.sf.briar.api.transport.InvalidTransportException;
 public interface StreamTransportPlugin {
 
 	/** Returns the plugin's transport identifier. */
-	int getTransportId();
+	TransportId getId();
 
 	/**
 	 * Starts the plugin. Any connections that are later initiated by contacts
diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index 3da87919f8705d3356311bf01526b56c8d3d0afc..560f38a3d429007bf09bb68c495e230ed213f1cb 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -5,6 +5,7 @@ import java.util.Map;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
 import net.sf.briar.api.protocol.AuthorId;
@@ -83,8 +84,9 @@ interface Database<T> {
 	 * <p>
 	 * Locking: contacts write, transports write.
 	 */
-	ContactId addContact(T txn, Map<Integer, Map<String, String>> transports,
-			byte[] secret) throws DbException;
+	ContactId addContact(T txn,
+			Map<TransportId, Map<String, String>> transports, byte[] secret)
+	throws DbException;
 
 	/**
 	 * Returns false if the given message is already in the database. Otherwise
@@ -171,7 +173,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: contacts read, windows write.
 	 */
-	long getConnectionNumber(T txn, ContactId c, int transportId)
+	long getConnectionNumber(T txn, ContactId c, TransportId t)
 	throws DbException;
 
 	/**
@@ -180,7 +182,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: contacts read, windows read.
 	 */
-	ConnectionWindow getConnectionWindow(T txn, ContactId c, int transportId)
+	ConnectionWindow getConnectionWindow(T txn, ContactId c, TransportId t)
 	throws DbException;
 
 	/**
@@ -319,7 +321,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: transports read.
 	 */
-	Map<String, String> getTransportConfig(T txn, int transportId)
+	Map<String, String> getTransportConfig(T txn, TransportId t)
 	throws DbException;
 
 	/**
@@ -327,14 +329,15 @@ interface Database<T> {
 	 * <p>
 	 * Locking: transports read.
 	 */
-	Map<Integer, Map<String, String>> getTransports(T txn) throws DbException;
+	Map<TransportId, Map<String, String>> getTransports(T txn)
+	throws DbException;
 
 	/**
 	 * Returns all transport properties for the given contact.
 	 * <p>
 	 * Locking: contacts read, transports read.
 	 */
-	Map<Integer, Map<String, String>> getTransports(T txn, ContactId c)
+	Map<TransportId, Map<String, String>> getTransports(T txn, ContactId c)
 	throws DbException;
 
 	/**
@@ -415,7 +418,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: contacts read, windows write.
 	 */
-	void setConnectionWindow(T txn, ContactId c, int transportId,
+	void setConnectionWindow(T txn, ContactId c, TransportId t,
 			ConnectionWindow w) throws DbException;
 
 	/**
@@ -476,7 +479,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: transports write.
 	 */
-	void setTransportConfig(T txn, int transportId, Map<String, String> config)
+	void setTransportConfig(T txn, TransportId t, Map<String, String> config)
 	throws DbException;
 
 	/**
@@ -485,7 +488,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: transports write.
 	 */
-	void setTransportProperties(T txn, int transportId,
+	void setTransportProperties(T txn, TransportId t,
 			Map<String, String> properties) throws DbException;
 
 	/**
@@ -496,7 +499,7 @@ interface Database<T> {
 	 * Locking: contacts read, transports write.
 	 */
 	void setTransports(T txn, ContactId c,
-			Map<Integer, Map<String, String>> transports, long timestamp)
+			Map<TransportId, Map<String, String>> transports, long timestamp)
 	throws DbException;
 
 	/**
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index 82f307fda33aa4258531b004236334a23b9f5b37..33ba3e8325bb9609795d1c2dde670ea1a34a447f 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -21,6 +21,7 @@ import java.util.logging.Logger;
 import net.sf.briar.api.Bytes;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DatabaseListener;
 import net.sf.briar.api.db.DatabaseListener.Event;
@@ -117,8 +118,9 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public ContactId addContact(Map<Integer, Map<String, String>> transports,
-			byte[] secret) throws DbException {
+	public ContactId addContact(
+			Map<TransportId, Map<String, String>> transports, byte[] secret)
+	throws DbException {
 		if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
 		ContactId c;
 		contactLock.writeLock().lock();
@@ -604,7 +606,7 @@ DatabaseCleaner.Callback {
 
 	public void generateTransportUpdate(ContactId c, TransportWriter t)
 	throws DbException, IOException {
-		Map<Integer, Map<String, String>> transports;
+		Map<TransportId, Map<String, String>> transports;
 		long timestamp;
 		contactLock.readLock().lock();
 		try {
@@ -632,7 +634,7 @@ DatabaseCleaner.Callback {
 			LOG.fine("Added " + transports.size() + " transports to update");
 	}
 
-	public long getConnectionNumber(ContactId c, int transportId)
+	public long getConnectionNumber(ContactId c, TransportId t)
 	throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -641,7 +643,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					long outgoing = db.getConnectionNumber(txn, c, transportId);
+					long outgoing = db.getConnectionNumber(txn, c, t);
 					db.commitTransaction(txn);
 					return outgoing;
 				} catch(DbException e) {
@@ -656,7 +658,7 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public ConnectionWindow getConnectionWindow(ContactId c, int transportId)
+	public ConnectionWindow getConnectionWindow(ContactId c, TransportId t)
 	throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -665,8 +667,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					ConnectionWindow w =
-						db.getConnectionWindow(txn, c, transportId);
+					ConnectionWindow w = db.getConnectionWindow(txn, c, t);
 					db.commitTransaction(txn);
 					return w;
 				} catch(DbException e) {
@@ -750,14 +751,13 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public Map<String, String> getTransportConfig(int transportId)
+	public Map<String, String> getTransportConfig(TransportId t)
 	throws DbException {
 		transportLock.readLock().lock();
 		try {
 			T txn = db.startTransaction();
 			try {
-				Map<String, String> config =
-					db.getTransportConfig(txn, transportId);
+				Map<String, String> config = db.getTransportConfig(txn, t);
 				db.commitTransaction(txn);
 				return config;
 			} catch(DbException e) {
@@ -769,13 +769,13 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public Map<Integer, Map<String, String>> getTransports()
+	public Map<TransportId, Map<String, String>> getTransports()
 	throws DbException {
 		transportLock.readLock().lock();
 		try {
 			T txn = db.startTransaction();
 			try {
-				Map<Integer, Map<String, String>> transports =
+				Map<TransportId, Map<String, String>> transports =
 					db.getTransports(txn);
 				db.commitTransaction(txn);
 				return transports;
@@ -788,7 +788,7 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public Map<Integer, Map<String, String>> getTransports(ContactId c)
+	public Map<TransportId, Map<String, String>> getTransports(ContactId c)
 	throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -797,7 +797,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					Map<Integer, Map<String, String>> transports =
+					Map<TransportId, Map<String, String>> transports =
 						db.getTransports(txn, c);
 					db.commitTransaction(txn);
 					return transports;
@@ -1046,7 +1046,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					Map<Integer, Map<String, String>> transports =
+					Map<TransportId, Map<String, String>> transports =
 						t.getTransports();
 					db.setTransports(txn, c, transports, t.getTimestamp());
 					if(LOG.isLoggable(Level.FINE))
@@ -1104,7 +1104,7 @@ DatabaseCleaner.Callback {
 		callListeners(Event.CONTACTS_UPDATED);
 	}
 
-	public void setConnectionWindow(ContactId c, int transportId,
+	public void setConnectionWindow(ContactId c, TransportId t,
 			ConnectionWindow w) throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -1113,7 +1113,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					db.setConnectionWindow(txn, c, transportId, w);
+					db.setConnectionWindow(txn, c, t, w);
 					db.commitTransaction(txn);
 				} catch(DbException e) {
 					db.abortTransaction(txn);
@@ -1220,17 +1220,16 @@ DatabaseCleaner.Callback {
 					+ indirect + " indirectly");
 	}
 
-	public void setTransportConfig(int transportId,
+	public void setTransportConfig(TransportId t,
 			Map<String, String> config) throws DbException {
 		boolean changed = false;
 		transportLock.writeLock().lock();
 		try {
 			T txn = db.startTransaction();
 			try {
-				Map<String, String> old =
-					db.getTransportConfig(txn, transportId);
+				Map<String, String> old = db.getTransportConfig(txn, t);
 				if(!config.equals(old)) {
-					db.setTransportConfig(txn, transportId, config);
+					db.setTransportConfig(txn, t, config);
 					changed = true;
 				}
 				db.commitTransaction(txn);
@@ -1245,18 +1244,18 @@ DatabaseCleaner.Callback {
 		if(changed) callListeners(Event.TRANSPORTS_UPDATED);
 	}
 
-	public void setTransportProperties(int transportId,
+	public void setTransportProperties(TransportId t,
 			Map<String, String> properties) throws DbException {
 		boolean changed = false;
 		transportLock.writeLock().lock();
 		try {
 			T txn = db.startTransaction();
 			try {
-				Map<Integer, Map<String, String>> transports =
+				Map<TransportId, Map<String, String>> transports =
 					db.getTransports(txn);
-				Map<String, String> old = transports.get(transportId);
+				Map<String, String> old = transports.get(t);
 				if(!properties.equals(old)) {
-					db.setTransportProperties(txn, transportId, properties);
+					db.setTransportProperties(txn, t, properties);
 					changed = true;
 				}
 				db.commitTransaction(txn);
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 2b84f47d3518ed9ba249892e3987272f12fcb6fc..01ed4367886b8fe9a0be85257d9d53968b573490 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -21,6 +21,7 @@ import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
 import net.sf.briar.api.protocol.AuthorId;
@@ -455,7 +456,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	}
 
 	public ContactId addContact(Connection txn,
-			Map<Integer, Map<String, String>> transports, byte[] secret)
+			Map<TransportId, Map<String, String>> transports, byte[] secret)
 	throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
@@ -486,8 +487,9 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
 			int batchSize = 0;
-			for(Entry<Integer, Map<String, String>> e : transports.entrySet()) {
-				ps.setInt(2, e.getKey());
+			for(Entry<TransportId, Map<String, String>> e
+					: transports.entrySet()) {
+				ps.setInt(2, e.getKey().getInt());
 				for(Entry<String, String> e1 : e.getValue().entrySet()) {
 					ps.setString(3, e1.getKey());
 					ps.setString(4, e1.getValue());
@@ -807,7 +809,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	}
 
 	public long getConnectionNumber(Connection txn, ContactId c,
-			int transportId) throws DbException {
+			TransportId t) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
@@ -815,7 +817,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 				+ " WHERE contactId = ? AND transportId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
-			ps.setInt(2, transportId);
+			ps.setInt(2, t.getInt());
 			rs = ps.executeQuery();
 			if(rs.next()) {
 				long outgoing = rs.getLong(1);
@@ -827,7 +829,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 				ps = txn.prepareStatement(sql);
 				ps.setLong(1, outgoing + 1);
 				ps.setInt(2, c.getInt());
-				ps.setInt(3, transportId);
+				ps.setInt(3, t.getInt());
 				int affected = ps.executeUpdate();
 				if(affected != 1) throw new DbStateException();
 				ps.close();
@@ -840,7 +842,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 					+ " VALUES(?, ?, ?, ?, ?)";
 				ps = txn.prepareStatement(sql);
 				ps.setInt(1, c.getInt());
-				ps.setInt(2, transportId);
+				ps.setInt(2, t.getInt());
 				ps.setLong(3, 0L);
 				ps.setInt(4, 0);
 				ps.setLong(5, 0L);
@@ -857,7 +859,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	}
 
 	public ConnectionWindow getConnectionWindow(Connection txn, ContactId c,
-			int transportId) throws DbException {
+			TransportId t) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
@@ -865,7 +867,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 				+ " WHERE contactId = ? AND transportId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
-			ps.setInt(2, transportId);
+			ps.setInt(2, t.getInt());
 			rs = ps.executeQuery();
 			long centre = 0L;
 			int bitmap = 0;
@@ -1394,14 +1396,14 @@ abstract class JdbcDatabase implements Database<Connection> {
 	}
 
 	public Map<String, String> getTransportConfig(Connection txn,
-			int transportId) throws DbException {
+			TransportId t) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
 			String sql = "SELECT key, value FROM transportConfig"
 				+ " WHERE transportId = ?";
 			ps = txn.prepareStatement(sql);
-			ps.setInt(1, transportId);
+			ps.setInt(1, t.getInt());
 			rs = ps.executeQuery();
 			Map<String, String> config = new TreeMap<String, String>();
 			while(rs.next()) config.put(rs.getString(1), rs.getString(2));
@@ -1415,7 +1417,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public Map<Integer, Map<String, String>> getTransports(Connection txn)
+	public Map<TransportId, Map<String, String>> getTransports(Connection txn)
 	throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
@@ -1424,15 +1426,15 @@ abstract class JdbcDatabase implements Database<Connection> {
 				+ " ORDER BY transportId";
 			ps = txn.prepareStatement(sql);
 			rs = ps.executeQuery();
-			Map<Integer, Map<String, String>> transports =
-				new TreeMap<Integer, Map<String, String>>();
+			Map<TransportId, Map<String, String>> transports =
+				new TreeMap<TransportId, Map<String, String>>();
 			Map<String, String> properties = null;
-			Integer lastId = null;
+			TransportId lastId = null;
 			while(rs.next()) {
-				Integer transportId = rs.getInt(1);
-				if(!transportId.equals(lastId)) {
+				TransportId id = new TransportId(rs.getInt(1));
+				if(!id.equals(lastId)) {
 					properties = new TreeMap<String, String>();
-					transports.put(transportId, properties);
+					transports.put(id, properties);
 				}
 				properties.put(rs.getString(2), rs.getString(3));
 			}
@@ -1446,7 +1448,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public Map<Integer, Map<String, String>> getTransports(Connection txn,
+	public Map<TransportId, Map<String, String>> getTransports(Connection txn,
 			ContactId c) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
@@ -1457,15 +1459,15 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
 			rs = ps.executeQuery();
-			Map<Integer, Map<String, String>> transports =
-				new TreeMap<Integer, Map<String, String>>();
+			Map<TransportId, Map<String, String>> transports =
+				new TreeMap<TransportId, Map<String, String>>();
 			Map<String, String> properties = null;
-			Integer lastId = null;
+			TransportId lastId = null;
 			while(rs.next()) {
-				Integer transportId = rs.getInt(1);
-				if(!transportId.equals(lastId)) {
+				TransportId id = new TransportId(rs.getInt(1));
+				if(!id.equals(lastId)) {
 					properties = new TreeMap<String, String>();
-					transports.put(transportId, properties);
+					transports.put(id, properties);
 				}
 				properties.put(rs.getString(2), rs.getString(3));
 			}
@@ -1767,7 +1769,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 	}
 
 	public void setConnectionWindow(Connection txn, ContactId c,
-			int transportId, ConnectionWindow w) throws DbException {
+			TransportId t, ConnectionWindow w) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
@@ -1775,7 +1777,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 				+ " WHERE contactId = ? AND transportId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
-			ps.setInt(2, transportId);
+			ps.setInt(2, t.getInt());
 			rs = ps.executeQuery();
 			if(rs.next()) {
 				if(rs.next()) throw new DbStateException();
@@ -1787,7 +1789,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 				ps.setLong(1, w.getCentre());
 				ps.setInt(2, w.getBitmap());
 				ps.setInt(3, c.getInt());
-				ps.setInt(4, transportId);
+				ps.setInt(4, t.getInt());
 				int affected = ps.executeUpdate();
 				if(affected != 1) throw new DbStateException();
 				ps.close();
@@ -1799,7 +1801,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 					+ " VALUES(?, ?, ?, ?, ?)";
 				ps = txn.prepareStatement(sql);
 				ps.setInt(1, c.getInt());
-				ps.setInt(2, transportId);
+				ps.setInt(2, t.getInt());
 				ps.setLong(3, w.getCentre());
 				ps.setInt(4, w.getBitmap());
 				ps.setLong(5, 0L);
@@ -2039,26 +2041,26 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public void setTransportConfig(Connection txn, int transportId,
+	public void setTransportConfig(Connection txn, TransportId t,
 			Map<String, String> config) throws DbException {
-		setTransportDetails(txn, transportId, config, "transportConfig");
+		setTransportDetails(txn, t, config, "transportConfig");
 	}
 
-	private void setTransportDetails(Connection txn, int transportId,
+	private void setTransportDetails(Connection txn, TransportId t,
 			Map<String, String> details, String table) throws DbException {
 		PreparedStatement ps = null;
 		try {
 			// Delete any existing details for the given transport
 			String sql = "DELETE FROM " + table + " WHERE transportId = ?";
 			ps = txn.prepareStatement(sql);
-			ps.setInt(1, transportId);
+			ps.setInt(1, t.getInt());
 			ps.executeUpdate();
 			ps.close();
 			// Store the new details
 			sql = "INSERT INTO " + table + " (transportId, key, value)"
 			+ " VALUES (?, ?, ?)";
 			ps = txn.prepareStatement(sql);
-			ps.setInt(1, transportId);
+			ps.setInt(1, t.getInt());
 			for(Entry<String, String> e : details.entrySet()) {
 				ps.setString(2, e.getKey());
 				ps.setString(3, e.getValue());
@@ -2077,13 +2079,13 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public void setTransportProperties(Connection txn, int transportId,
+	public void setTransportProperties(Connection txn, TransportId t,
 			Map<String, String> properties) throws DbException {
-		setTransportDetails(txn, transportId, properties, "transports");
+		setTransportDetails(txn, t, properties, "transports");
 	}
 
 	public void setTransports(Connection txn, ContactId c,
-			Map<Integer, Map<String, String>> transports, long timestamp)
+			Map<TransportId, Map<String, String>> transports, long timestamp)
 	throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
@@ -2113,8 +2115,9 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
 			int batchSize = 0;
-			for(Entry<Integer, Map<String, String>> e : transports.entrySet()) {
-				ps.setInt(2, e.getKey());
+			for(Entry<TransportId, Map<String, String>> e
+					: transports.entrySet()) {
+				ps.setInt(2, e.getKey().getInt());
 				for(Entry<String, String> e1 : e.getValue().entrySet()) {
 					ps.setString(3, e1.getKey());
 					ps.setString(4, e1.getValue());
diff --git a/components/net/sf/briar/invitation/InvitationWorker.java b/components/net/sf/briar/invitation/InvitationWorker.java
index 23e883dd9192274612ca07ed0266fab3bb23995e..68b323f8f07a244dda17aafcbc370387df1049ab 100644
--- a/components/net/sf/briar/invitation/InvitationWorker.java
+++ b/components/net/sf/briar/invitation/InvitationWorker.java
@@ -8,6 +8,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.invitation.InvitationCallback;
@@ -70,7 +71,7 @@ class InvitationWorker implements Runnable {
 		File invitationDat = new File(dir, "invitation.dat");
 		callback.encryptingFile(invitationDat);
 		// FIXME: Create a real invitation
-		Map<Integer, Map<String, String>> transports;
+		Map<TransportId, Map<String, String>> transports;
 		try {
 			transports = db.getTransports();
 		} catch(DbException e) {
diff --git a/components/net/sf/briar/protocol/TransportFactory.java b/components/net/sf/briar/protocol/TransportFactory.java
index ba39a82d659f28753c9cc214e3e1d1497ebc7327..39e9792315bf6defa51b7a64b5044e538835fc47 100644
--- a/components/net/sf/briar/protocol/TransportFactory.java
+++ b/components/net/sf/briar/protocol/TransportFactory.java
@@ -2,10 +2,11 @@ package net.sf.briar.protocol;
 
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.TransportUpdate;
 
 interface TransportFactory {
 
 	TransportUpdate createTransportUpdate(
-			Map<Integer, Map<String, String>> transports, long timestamp);
+			Map<TransportId, Map<String, String>> transports, long timestamp);
 }
diff --git a/components/net/sf/briar/protocol/TransportFactoryImpl.java b/components/net/sf/briar/protocol/TransportFactoryImpl.java
index 268dbbb520c3e0dc5645f67ea741b9f55fcb5710..8f8d310c1298a0f54f8d38d81e77817c89377aae 100644
--- a/components/net/sf/briar/protocol/TransportFactoryImpl.java
+++ b/components/net/sf/briar/protocol/TransportFactoryImpl.java
@@ -2,12 +2,13 @@ package net.sf.briar.protocol;
 
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.TransportUpdate;
 
 class TransportFactoryImpl implements TransportFactory {
 
 	public TransportUpdate createTransportUpdate(
-			Map<Integer, Map<String, String>> transports, long timestamp) {
+			Map<TransportId, Map<String, String>> transports, long timestamp) {
 		return new TransportUpdateImpl(transports, timestamp);
 	}
 }
diff --git a/components/net/sf/briar/protocol/TransportReader.java b/components/net/sf/briar/protocol/TransportReader.java
index 55604447b1a2256c04d590699eeec7480501e9b7..7041154bfdb58d460db1e53ca345b31f79a41f82 100644
--- a/components/net/sf/briar/protocol/TransportReader.java
+++ b/components/net/sf/briar/protocol/TransportReader.java
@@ -6,9 +6,10 @@ import java.util.Map;
 import java.util.TreeMap;
 
 import net.sf.briar.api.FormatException;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.ProtocolConstants;
-import net.sf.briar.api.protocol.Types;
 import net.sf.briar.api.protocol.TransportUpdate;
+import net.sf.briar.api.protocol.Types;
 import net.sf.briar.api.serial.Consumer;
 import net.sf.briar.api.serial.ObjectReader;
 import net.sf.briar.api.serial.Reader;
@@ -37,11 +38,11 @@ class TransportReader implements ObjectReader<TransportUpdate> {
 		r.removeObjectReader(Types.TRANSPORT_PROPERTIES);
 		if(l.size() > TransportUpdate.MAX_PLUGINS_PER_UPDATE)
 			throw new FormatException();
-		Map<Integer, Map<String, String>> transports =
-			new TreeMap<Integer, Map<String, String>>();
+		Map<TransportId, Map<String, String>> transports =
+			new TreeMap<TransportId, Map<String, String>>();
 		for(TransportProperties t : l) {
-			if(transports.put(t.transportId, t.properties) != null)
-				throw new FormatException(); // Duplicate plugin name
+			if(transports.put(t.id, t.properties) != null)
+				throw new FormatException(); // Duplicate transport ID
 		}
 		long timestamp = r.readInt64();
 		r.removeConsumer(counting);
@@ -51,11 +52,11 @@ class TransportReader implements ObjectReader<TransportUpdate> {
 
 	private static class TransportProperties {
 
-		private final int transportId;
+		private final TransportId id;
 		private final Map<String, String> properties;
 
-		TransportProperties(int transportId, Map<String, String> properties) {
-			this.transportId = transportId;
+		TransportProperties(TransportId id, Map<String, String> properties) {
+			this.id = id;
 			this.properties = properties;
 		}
 	}
@@ -65,14 +66,17 @@ class TransportReader implements ObjectReader<TransportUpdate> {
 
 		public TransportProperties readObject(Reader r) throws IOException {
 			r.readUserDefinedId(Types.TRANSPORT_PROPERTIES);
-			int transportId = r.readInt32();
+			int i = r.readInt32();
+			if(i < TransportId.MIN_ID || i > TransportId.MAX_ID)
+				throw new FormatException();
+			TransportId id = new TransportId(i);
 			r.setMaxStringLength(TransportUpdate.MAX_KEY_OR_VALUE_LENGTH);
 			Map<String, String> properties =
 				r.readMap(String.class, String.class);
 			r.resetMaxStringLength();
 			if(properties.size() > TransportUpdate.MAX_PROPERTIES_PER_PLUGIN)
 				throw new FormatException();
-			return new TransportProperties(transportId, properties);
+			return new TransportProperties(id, properties);
 		}
 	}
 }
diff --git a/components/net/sf/briar/protocol/TransportUpdateImpl.java b/components/net/sf/briar/protocol/TransportUpdateImpl.java
index f89c9ef9dd9aa50f8f56c8bcf1e230cf5c82240e..98cf0465b9a20f5edb80a8720c2ea82f1fc7b129 100644
--- a/components/net/sf/briar/protocol/TransportUpdateImpl.java
+++ b/components/net/sf/briar/protocol/TransportUpdateImpl.java
@@ -2,20 +2,21 @@ package net.sf.briar.protocol;
 
 import java.util.Map;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.TransportUpdate;
 
 class TransportUpdateImpl implements TransportUpdate {
 
-	private final Map<Integer, Map<String, String>> transports;
+	private final Map<TransportId, Map<String, String>> transports;
 	private final long timestamp;
 
-	TransportUpdateImpl(Map<Integer, Map<String, String>> transports,
+	TransportUpdateImpl(Map<TransportId, Map<String, String>> transports,
 			long timestamp) {
 		this.transports = transports;
 		this.timestamp = timestamp;
 	}
 
-	public Map<Integer, Map<String, String>> getTransports() {
+	public Map<TransportId, Map<String, String>> getTransports() {
 		return transports;
 	}
 
diff --git a/components/net/sf/briar/protocol/writers/TransportWriterImpl.java b/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
index 5b7e87e38a2b7ec3cbdef4a5bb23efe6343a9c60..f89528c472a2b2001b13f9ba855a2fa96d17ff5f 100644
--- a/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
+++ b/components/net/sf/briar/protocol/writers/TransportWriterImpl.java
@@ -5,6 +5,7 @@ import java.io.OutputStream;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.Types;
 import net.sf.briar.api.protocol.writers.TransportWriter;
 import net.sf.briar.api.serial.Writer;
@@ -20,13 +21,14 @@ class TransportWriterImpl implements TransportWriter {
 		w = writerFactory.createWriter(out);
 	}
 
-	public void writeTransports(Map<Integer, Map<String, String>> transports,
-			long timestamp) throws IOException {
+	public void writeTransports(
+			Map<TransportId, Map<String, String>> transports, long timestamp)
+	throws IOException {
 		w.writeUserDefinedId(Types.TRANSPORT_UPDATE);
 		w.writeListStart();
-		for(Entry<Integer, Map<String, String>> e : transports.entrySet()) {
+		for(Entry<TransportId, Map<String, String>> e : transports.entrySet()) {
 			w.writeUserDefinedId(Types.TRANSPORT_PROPERTIES);
-			w.writeInt32(e.getKey());
+			w.writeInt32(e.getKey().getInt());
 			w.writeMap(e.getValue());
 		}
 		w.writeListEnd();
diff --git a/components/net/sf/briar/transport/ConnectionRecogniserFactoryImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserFactoryImpl.java
index 1a404399710f7b80cc71085db255dd63b79abdde..ed86ff5f942f5fcf3eef866d46a4dd4dfc29f826 100644
--- a/components/net/sf/briar/transport/ConnectionRecogniserFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionRecogniserFactoryImpl.java
@@ -1,5 +1,6 @@
 package net.sf.briar.transport;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.transport.ConnectionRecogniser;
@@ -19,7 +20,7 @@ class ConnectionRecogniserFactoryImpl implements ConnectionRecogniserFactory {
 		this.db = db;
 	}
 
-	public ConnectionRecogniser createConnectionRecogniser(int transportId) {
-		return new ConnectionRecogniserImpl(transportId, crypto, db);
+	public ConnectionRecogniser createConnectionRecogniser(TransportId t) {
+		return new ConnectionRecogniserImpl(t, crypto, db);
 	}
 }
diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
index 12664ef7afbfe8eab4aed41d2280d13d120ce35a..db36cca7796c7bf66bdb206337934377e3a6118e 100644
--- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
+++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
@@ -13,6 +13,7 @@ import javax.crypto.SecretKey;
 
 import net.sf.briar.api.Bytes;
 import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DatabaseListener;
@@ -24,7 +25,7 @@ import net.sf.briar.api.transport.ConnectionWindow;
 class ConnectionRecogniserImpl implements ConnectionRecogniser,
 DatabaseListener {
 
-	private final int transportId;
+	private final TransportId id;
 	private final CryptoComponent crypto;
 	private final DatabaseComponent db;
 	private final Map<Bytes, ContactId> ivToContact;
@@ -34,9 +35,9 @@ DatabaseListener {
 	private final Map<ContactId, ConnectionWindow> contactToWindow;
 	private boolean initialised = false;
 
-	ConnectionRecogniserImpl(int transportId, CryptoComponent crypto,
+	ConnectionRecogniserImpl(TransportId id, CryptoComponent crypto,
 			DatabaseComponent db) {
-		this.transportId = transportId;
+		this.id = id;
 		this.crypto = crypto;
 		this.db = db;
 		// FIXME: There's probably a tidier way of maintaining all this state
@@ -62,7 +63,7 @@ DatabaseListener {
 				}
 				contactToCipher.put(c, cipher);
 				// Calculate the IVs for the contact's connection window
-				ConnectionWindow w = db.getConnectionWindow(c, transportId);
+				ConnectionWindow w = db.getConnectionWindow(c, id);
 				Map<Long, Bytes> ivs = new HashMap<Long, Bytes>();
 				for(Long unseen : w.getUnseenConnectionNumbers()) {
 					Bytes expectedIv = new Bytes(encryptIv(c, unseen));
@@ -81,7 +82,7 @@ DatabaseListener {
 	}
 
 	private synchronized byte[] encryptIv(ContactId c, long connection) {
-		byte[] iv = IvEncoder.encodeIv(true, transportId, connection);
+		byte[] iv = IvEncoder.encodeIv(true, id, connection);
 		Cipher cipher = contactToCipher.get(c);
 		assert cipher != null;
 		try {
@@ -107,7 +108,7 @@ DatabaseListener {
 		ConnectionWindow w = contactToWindow.get(contactId);
 		assert w != null;
 		w.setSeen(connection);
-		db.setConnectionWindow(contactId, transportId, w);
+		db.setConnectionWindow(contactId, id, w);
 		// Update the set of expected IVs
 		Map<Long, Bytes> oldIvs = contactToIvs.remove(contactId);
 		assert oldIvs != null;
diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
index d5ca4310db1c812adf070533991472006f9a4fd3..ab3b3e3de8d46295e988a35f622ebc91e5340363 100644
--- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
@@ -6,6 +6,7 @@ import javax.crypto.Cipher;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
@@ -22,14 +23,14 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 	}
 
 	public ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, boolean initiator, int transportId, long connection,
+			long capacity, boolean initiator, TransportId t, long connection,
 			byte[] secret) {
 		// Create the encrypter
 		Cipher ivCipher = crypto.getIvCipher();
 		Cipher frameCipher = crypto.getFrameCipher();
 		SecretKey ivKey = crypto.deriveOutgoingIvKey(secret);
 		SecretKey frameKey = crypto.deriveOutgoingFrameKey(secret);
-		byte[] iv = IvEncoder.encodeIv(initiator, transportId, connection);
+		byte[] iv = IvEncoder.encodeIv(initiator, t, connection);
 		ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
 				capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
 		// Create the writer
diff --git a/components/net/sf/briar/transport/IvEncoder.java b/components/net/sf/briar/transport/IvEncoder.java
index 6744b044950f70dc42bc9c2e7efa9578e1732a64..48276760ca0deb635161dc439d220a00cf58ce72 100644
--- a/components/net/sf/briar/transport/IvEncoder.java
+++ b/components/net/sf/briar/transport/IvEncoder.java
@@ -1,17 +1,18 @@
 package net.sf.briar.transport;
 
 import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.util.ByteUtils;
 
 class IvEncoder {
 
-	static byte[] encodeIv(boolean initiator, int transportId,
+	static byte[] encodeIv(boolean initiator, TransportId transport,
 			long connection) {
 		byte[] iv = new byte[IV_LENGTH];
 		// Bit 31 is the initiator flag
 		if(initiator) iv[3] = 1;
 		// Encode the transport identifier as an unsigned 16-bit integer
-		ByteUtils.writeUint16(transportId, iv, 4);
+		ByteUtils.writeUint16(transport.getInt(), iv, 4);
 		// Encode the connection number as an unsigned 32-bit integer
 		ByteUtils.writeUint32(connection, iv, 6);
 		return iv;
diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java
index a75b1e9bec929009c796b0c971ceb84d9972ff6c..6e41f67ff0934f05faf304e537863610b293fd60 100644
--- a/test/net/sf/briar/ProtocolIntegrationTest.java
+++ b/test/net/sf/briar/ProtocolIntegrationTest.java
@@ -14,6 +14,7 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 
 import junit.framework.TestCase;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.protocol.Ack;
 import net.sf.briar.api.protocol.Author;
@@ -66,14 +67,14 @@ public class ProtocolIntegrationTest extends TestCase {
 	private final ProtocolWriterFactory protocolWriterFactory;
 	private final CryptoComponent crypto;
 	private final byte[] aliceSecret, bobSecret;
-	private final int transportId = 123;
-	private final long connection = 234L;
+	private final TransportId transportId = new TransportId(123);
+	private final long connection = 12345L;
 	private final Author author;
 	private final Group group, group1;
 	private final Message message, message1, message2, message3;
 	private final String authorName = "Alice";
 	private final String messageBody = "Hello world";
-	private final Map<Integer, Map<String, String>> transports;
+	private final Map<TransportId, Map<String, String>> transports;
 
 	public ProtocolIntegrationTest() throws Exception {
 		super();
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index 197a980a9357673322db6734cbc23da5b7a33a03..510b9737df5f6fd93c52fe7b92c846fe597925d2 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -10,6 +10,7 @@ import junit.framework.TestCase;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DatabaseListener;
 import net.sf.briar.api.db.DatabaseListener.Event;
@@ -53,7 +54,8 @@ public abstract class DatabaseComponentTest extends TestCase {
 	private final byte[] raw;
 	private final Message message, privateMessage;
 	private final Group group;
-	private final Map<Integer, Map<String, String>> transports;
+	private final TransportId transportId;
+	private final Map<TransportId, Map<String, String>> transports;
 	private final byte[] secret;
 
 	public DatabaseComponentTest() {
@@ -72,7 +74,8 @@ public abstract class DatabaseComponentTest extends TestCase {
 		privateMessage =
 			new TestMessage(messageId, null, null, null, timestamp, raw);
 		group = new TestGroup(groupId, "The really exciting group", null);
-		transports = Collections.singletonMap(123,
+		transportId = new TransportId(123);
+		transports = Collections.singletonMap(transportId,
 				Collections.singletonMap("bar", "baz"));
 		secret = new byte[123];
 	}
@@ -112,7 +115,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			// getConnectionWindow(contactId, 123)
 			oneOf(database).containsContact(txn, contactId);
 			will(returnValue(true));
-			oneOf(database).getConnectionWindow(txn, contactId, 123);
+			oneOf(database).getConnectionWindow(txn, contactId, transportId);
 			will(returnValue(connectionWindow));
 			// getSharedSecret(contactId)
 			oneOf(database).containsContact(txn, contactId);
@@ -150,7 +153,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			// setConnectionWindow(contactId, 123, connectionWindow)
 			oneOf(database).containsContact(txn, contactId);
 			will(returnValue(true));
-			oneOf(database).setConnectionWindow(txn, contactId, 123,
+			oneOf(database).setConnectionWindow(txn, contactId, transportId,
 					connectionWindow);
 			// removeContact(contactId)
 			oneOf(database).removeContact(txn, contactId);
@@ -166,7 +169,8 @@ public abstract class DatabaseComponentTest extends TestCase {
 		assertEquals(Rating.UNRATED, db.getRating(authorId));
 		assertEquals(contactId, db.addContact(transports, secret));
 		assertEquals(Collections.singletonList(contactId), db.getContacts());
-		assertEquals(connectionWindow, db.getConnectionWindow(contactId, 123));
+		assertEquals(connectionWindow,
+				db.getConnectionWindow(contactId, transportId));
 		assertEquals(secret, db.getSharedSecret(contactId));
 		assertEquals(transports, db.getTransports(contactId));
 		db.subscribe(group); // First time - check listeners are called
@@ -174,7 +178,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		assertEquals(Collections.singletonList(groupId), db.getSubscriptions());
 		db.unsubscribe(groupId); // First time - check listeners are called
 		db.unsubscribe(groupId); // Second time - check listeners aren't called
-		db.setConnectionWindow(contactId, 123, connectionWindow);
+		db.setConnectionWindow(contactId, transportId, connectionWindow);
 		db.removeContact(contactId);
 		db.removeListener(listener);
 		db.close();
@@ -510,7 +514,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		} catch(NoSuchContactException expected) {}
 
 		try {
-			db.getConnectionWindow(contactId, 123);
+			db.getConnectionWindow(contactId, transportId);
 			fail();
 		} catch(NoSuchContactException expected) {}
 
@@ -555,7 +559,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		} catch(NoSuchContactException expected) {}
 
 		try {
-			db.setConnectionWindow(contactId, 123, null);
+			db.setConnectionWindow(contactId, transportId, null);
 			fail();
 		} catch(NoSuchContactException expected) {}
 
@@ -1284,15 +1288,17 @@ public abstract class DatabaseComponentTest extends TestCase {
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).getTransports(txn);
-			will(returnValue(Collections.singletonMap(123, properties)));
-			oneOf(database).setTransportProperties(txn, 123, properties1);
+			will(returnValue(Collections.singletonMap(transportId,
+					properties)));
+			oneOf(database).setTransportProperties(txn, transportId,
+					properties1);
 			oneOf(database).commitTransaction(txn);
 			oneOf(listener).eventOccurred(Event.TRANSPORTS_UPDATED);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
 
 		db.addListener(listener);
-		db.setTransportProperties(123, properties1);
+		db.setTransportProperties(transportId, properties1);
 
 		context.assertIsSatisfied();
 	}
@@ -1311,13 +1317,14 @@ public abstract class DatabaseComponentTest extends TestCase {
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
 			oneOf(database).getTransports(txn);
-			will(returnValue(Collections.singletonMap(123, properties)));
+			will(returnValue(Collections.singletonMap(transportId,
+					properties)));
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
 
 		db.addListener(listener);
-		db.setTransportProperties(123, properties);
+		db.setTransportProperties(transportId, properties);
 
 		context.assertIsSatisfied();
 	}
@@ -1336,16 +1343,16 @@ public abstract class DatabaseComponentTest extends TestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
-			oneOf(database).getTransportConfig(txn, 123);
+			oneOf(database).getTransportConfig(txn, transportId);
 			will(returnValue(config));
-			oneOf(database).setTransportConfig(txn, 123, config1);
+			oneOf(database).setTransportConfig(txn, transportId, config1);
 			oneOf(database).commitTransaction(txn);
 			oneOf(listener).eventOccurred(Event.TRANSPORTS_UPDATED);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
 
 		db.addListener(listener);
-		db.setTransportConfig(123, config1);
+		db.setTransportConfig(transportId, config1);
 
 		context.assertIsSatisfied();
 	}
@@ -1363,14 +1370,14 @@ public abstract class DatabaseComponentTest extends TestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
-			oneOf(database).getTransportConfig(txn, 123);
+			oneOf(database).getTransportConfig(txn, transportId);
 			will(returnValue(config));
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
 
 		db.addListener(listener);
-		db.setTransportConfig(123, config);
+		db.setTransportConfig(transportId, config);
 
 		context.assertIsSatisfied();
 	}
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index 339ee475fa12a32867467ba1163787542e0ab9e1..406d49c9918e1af28ad53dbedf82aae2012005ef 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -17,6 +17,7 @@ import net.sf.briar.TestDatabaseModule;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.Rating;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.Password;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.db.Status;
@@ -65,7 +66,8 @@ public class H2DatabaseTest extends TestCase {
 	private final byte[] raw;
 	private final Message message, privateMessage;
 	private final Group group;
-	private final Map<Integer, Map<String, String>> transports;
+	private final TransportId transportId;
+	private final Map<TransportId, Map<String, String>> transports;
 	private final Map<Group, Long> subscriptions;
 	private final byte[] secret;
 
@@ -91,7 +93,8 @@ public class H2DatabaseTest extends TestCase {
 		privateMessage =
 			new TestMessage(privateMessageId, null, null, null, timestamp, raw);
 		group = groupFactory.createGroup(groupId, "Group name", null);
-		transports = Collections.singletonMap(123,
+		transportId = new TransportId(0);
+		transports = Collections.singletonMap(transportId,
 				Collections.singletonMap("bar", "baz"));
 		subscriptions = Collections.singletonMap(group, 0L);
 		secret = new byte[123];
@@ -991,28 +994,29 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(transports, db.getTransports(txn, contactId));
 
 		// Replace the transport properties
-		Map<Integer, Map<String, String>> transports1 =
-			new TreeMap<Integer, Map<String, String>>();
-		transports1.put(123, Collections.singletonMap("bar", "baz"));
-		transports1.put(456, Collections.singletonMap("baz", "quux"));
+		TransportId transportId1 = new TransportId(1);
+		Map<TransportId, Map<String, String>> transports1 =
+			new TreeMap<TransportId, Map<String, String>>();
+		transports1.put(transportId, Collections.singletonMap("bar", "baz"));
+		transports1.put(transportId1, Collections.singletonMap("baz", "quux"));
 		db.setTransports(txn, contactId, transports1, 1);
 		assertEquals(transports1, db.getTransports(txn, contactId));
 
 		// Remove the transport properties
 		db.setTransports(txn, contactId,
-				Collections.<Integer, Map<String, String>>emptyMap(), 2);
+				Collections.<TransportId, Map<String, String>>emptyMap(), 2);
 		assertEquals(Collections.emptyMap(), db.getTransports(txn, contactId));
 
 		// Set the local transport properties
-		for(Integer transportId : transports.keySet()) {
-			Map<String, String> properties = transports.get(transportId);
+		for(TransportId t : transports.keySet()) {
+			Map<String, String> properties = transports.get(t);
 			db.setTransportProperties(txn, transportId, properties);
 		}
 		assertEquals(transports, db.getTransports(txn));
 
 		// Remove the local transport properties
-		for(Integer transportId : transports.keySet()) {
-			db.setTransportProperties(txn, transportId,
+		for(TransportId t : transports.keySet()) {
+			db.setTransportProperties(txn, t,
 					Collections.<String, String>emptyMap());
 		}
 		assertEquals(Collections.emptyMap(), db.getTransports(txn));
@@ -1030,17 +1034,18 @@ public class H2DatabaseTest extends TestCase {
 		Connection txn = db.startTransaction();
 
 		// Set the transport config
-		db.setTransportConfig(txn, 123, config);
-		assertEquals(config, db.getTransportConfig(txn, 123));
+		db.setTransportConfig(txn, transportId, config);
+		assertEquals(config, db.getTransportConfig(txn, transportId));
 
 		// Update the transport config
-		db.setTransportConfig(txn, 123, config1);
-		assertEquals(config1, db.getTransportConfig(txn, 123));
+		db.setTransportConfig(txn, transportId, config1);
+		assertEquals(config1, db.getTransportConfig(txn, transportId));
 
 		// Remove the transport config
-		db.setTransportConfig(txn, 123,
+		db.setTransportConfig(txn, transportId,
 				Collections.<String, String>emptyMap());
-		assertEquals(Collections.emptyMap(), db.getTransportConfig(txn, 123));
+		assertEquals(Collections.emptyMap(),
+				db.getTransportConfig(txn, transportId));
 
 		db.commitTransaction(txn);
 		db.close();
@@ -1056,18 +1061,20 @@ public class H2DatabaseTest extends TestCase {
 		assertEquals(transports, db.getTransports(txn, contactId));
 
 		// Replace the transport properties using a timestamp of 2
-		Map<Integer, Map<String, String>> transports1 =
-			new TreeMap<Integer, Map<String, String>>();
-		transports1.put(123, Collections.singletonMap("bar", "baz"));
-		transports1.put(456, Collections.singletonMap("baz", "quux"));
+		TransportId transportId1 = new TransportId(1);
+		Map<TransportId, Map<String, String>> transports1 =
+			new TreeMap<TransportId, Map<String, String>>();
+		transports1.put(transportId, Collections.singletonMap("bar", "baz"));
+		transports1.put(transportId1, Collections.singletonMap("baz", "quux"));
 		db.setTransports(txn, contactId, transports1, 2);
 		assertEquals(transports1, db.getTransports(txn, contactId));
 
 		// Try to replace the transport properties using a timestamp of 1
-		Map<Integer, Map<String, String>> transports2 =
-			new TreeMap<Integer, Map<String, String>>();
-		transports2.put(456, Collections.singletonMap("baz", "quux"));
-		transports2.put(789, Collections.singletonMap("quux", "fnord"));
+		TransportId transportId2 = new TransportId(2);
+		Map<TransportId, Map<String, String>> transports2 =
+			new TreeMap<TransportId, Map<String, String>>();
+		transports2.put(transportId1, Collections.singletonMap("baz", "quux"));
+		transports2.put(transportId2, Collections.singletonMap("quux", "etc"));
 		db.setTransports(txn, contactId, transports2, 1);
 
 		// The old properties should still be there
@@ -1395,7 +1402,8 @@ public class H2DatabaseTest extends TestCase {
 		// Add a contact
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		// Get the connection window for a new transport
-		ConnectionWindow w = db.getConnectionWindow(txn, contactId, 123);
+		ConnectionWindow w = db.getConnectionWindow(txn, contactId,
+				transportId);
 		// The connection window should exist and be in the initial state
 		assertNotNull(w);
 		assertEquals(0L, w.getCentre());
@@ -1413,16 +1421,17 @@ public class H2DatabaseTest extends TestCase {
 		// Add a contact
 		assertEquals(contactId, db.addContact(txn, transports, secret));
 		// Get the connection window for a new transport
-		ConnectionWindow w = db.getConnectionWindow(txn, contactId, 123);
+		ConnectionWindow w = db.getConnectionWindow(txn, contactId,
+				transportId);
 		// The connection window should exist and be in the initial state
 		assertNotNull(w);
 		assertEquals(0L, w.getCentre());
 		assertEquals(0, w.getBitmap());
 		// Update the connection window and store it
 		w.setSeen(5L);
-		db.setConnectionWindow(txn, contactId, 123, w);
+		db.setConnectionWindow(txn, contactId, transportId, w);
 		// Check that the connection window was stored
-		w = db.getConnectionWindow(txn, contactId, 123);
+		w = db.getConnectionWindow(txn, contactId, transportId);
 		assertNotNull(w);
 		assertEquals(6L, w.getCentre());
 		assertTrue(w.isSeen(5L));
diff --git a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
index 2bb232d510d1068e2f7deaf37af2953453909484..2938af94cdbe5a082ef3839ede3360ad9065d02f 100644
--- a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
+++ b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
@@ -8,6 +8,7 @@ import java.util.Map;
 
 import junit.framework.TestCase;
 import net.sf.briar.TestUtils;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.protocol.Ack;
 import net.sf.briar.api.protocol.Batch;
 import net.sf.briar.api.protocol.BatchId;
@@ -47,7 +48,8 @@ public class ProtocolReadWriteTest extends TestCase {
 	private final String messageBody = "Hello world";
 	private final BitSet bitSet;
 	private final Map<Group, Long> subscriptions;
-	private final Map<Integer, Map<String, String>> transports;
+	private final TransportId transportId;
+	private final Map<TransportId, Map<String, String>> transports;
 	private final long timestamp = System.currentTimeMillis();
 
 	public ProtocolReadWriteTest() throws Exception {
@@ -67,7 +69,8 @@ public class ProtocolReadWriteTest extends TestCase {
 		bitSet.set(3);
 		bitSet.set(7);
 		subscriptions = Collections.singletonMap(group, 123L);
-		transports = Collections.singletonMap(123,
+		transportId = new TransportId(123);
+		transports = Collections.singletonMap(transportId,
 				Collections.singletonMap("bar", "baz"));
 	}
 
diff --git a/test/net/sf/briar/protocol/writers/ConstantsTest.java b/test/net/sf/briar/protocol/writers/ConstantsTest.java
index e1ce9d8510c40fc47520f4b822126e85112e396e..24b0b02db7d36d0468699047de95113d697cb550 100644
--- a/test/net/sf/briar/protocol/writers/ConstantsTest.java
+++ b/test/net/sf/briar/protocol/writers/ConstantsTest.java
@@ -8,6 +8,7 @@ import java.util.TreeMap;
 
 import junit.framework.TestCase;
 import net.sf.briar.TestUtils;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.protocol.Author;
 import net.sf.briar.api.protocol.AuthorFactory;
@@ -190,8 +191,8 @@ public class ConstantsTest extends TestCase {
 	public void testTransportsFitIntoUpdate() throws Exception {
 		// Create the maximum number of plugins, each with the maximum number
 		// of maximum-length properties
-		Map<Integer, Map<String, String>> transports =
-			new TreeMap<Integer, Map<String, String>>();
+		Map<TransportId, Map<String, String>> transports =
+			new TreeMap<TransportId, Map<String, String>>();
 		for(int i = 0; i < TransportUpdate.MAX_PLUGINS_PER_UPDATE; i++) {
 			Map<String, String> properties = new TreeMap<String, String>();
 			for(int j = 0; j < TransportUpdate.MAX_PROPERTIES_PER_PLUGIN; j++) {
@@ -201,7 +202,7 @@ public class ConstantsTest extends TestCase {
 						TransportUpdate.MAX_KEY_OR_VALUE_LENGTH);
 				properties.put(key, value);
 			}
-			transports.put(i, properties);
+			transports.put(new TransportId(i), properties);
 		}
 		// Add the transports to an update
 		ByteArrayOutputStream out = new ByteArrayOutputStream(
diff --git a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
index 62acd4369963245ebab51bcf2e0aeb582c36eb17..a09c26de07a40a8fa4c8d617c4255697e5bed26f 100644
--- a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
@@ -11,6 +11,7 @@ import javax.crypto.spec.IvParameterSpec;
 
 import junit.framework.TestCase;
 import net.sf.briar.TestUtils;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.crypto.CryptoModule;
 
@@ -26,7 +27,7 @@ public class ConnectionDecrypterImplTest extends TestCase {
 
 	private final Cipher ivCipher, frameCipher;
 	private final SecretKey ivKey, frameKey;
-	private final int transportId = 1234;
+	private final TransportId transportId = new TransportId(123);
 	private final long connection = 12345L;
 
 	public ConnectionDecrypterImplTest() {
diff --git a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
index 49aa4e31fc1190496481f5a68636dd4407671fc2..d60748676f03c5908e077a60031d3a9d328a1f94 100644
--- a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
@@ -10,6 +10,7 @@ import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
 
 import junit.framework.TestCase;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.crypto.CryptoModule;
 
@@ -24,7 +25,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
 
 	private final Cipher ivCipher, frameCipher;
 	private final SecretKey ivKey, frameKey;
-	private final int transportId = 1234;
+	private final TransportId transportId = new TransportId(123);
 	private final long connection = 12345L;
 
 	public ConnectionEncrypterImplTest() {
diff --git a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
index de66b5438a96c265666765edf5f0755b9067fe20..bd5d1b0cef48542f557d7ccc3b636883353137de 100644
--- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
@@ -10,6 +10,7 @@ import javax.crypto.SecretKey;
 
 import junit.framework.TestCase;
 import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.transport.ConnectionWindow;
@@ -27,7 +28,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
 	private final CryptoComponent crypto;
 	private final ContactId contactId;
 	private final byte[] secret;
-	private final int transportId;
+	private final TransportId transportId;
 	private final ConnectionWindow connectionWindow;
 
 	public ConnectionRecogniserImplTest() {
@@ -36,7 +37,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		crypto = i.getInstance(CryptoComponent.class);
 		contactId = new ContactId(1);
 		secret = new byte[18];
-		transportId = 123;
+		transportId = new TransportId(123);
 		connectionWindow = new ConnectionWindowImpl(0L, 0);
 	}
 
diff --git a/test/net/sf/briar/transport/ConnectionWriterTest.java b/test/net/sf/briar/transport/ConnectionWriterTest.java
index 2db8571d0097645f66d99211b170929ffe8ba10c..e8bdcc825bc507d0b077657862bb1fbc8231ec7c 100644
--- a/test/net/sf/briar/transport/ConnectionWriterTest.java
+++ b/test/net/sf/briar/transport/ConnectionWriterTest.java
@@ -7,6 +7,7 @@ import java.io.ByteArrayOutputStream;
 
 import junit.framework.TestCase;
 import net.sf.briar.TestDatabaseModule;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 import net.sf.briar.crypto.CryptoModule;
@@ -23,8 +24,8 @@ public class ConnectionWriterTest extends TestCase {
 
 	private final ConnectionWriterFactory connectionWriterFactory;
 	private final byte[] secret = new byte[100];
-	private final int transportId = 999;
-	private final long connection = 1234L;
+	private final TransportId transportId = new TransportId(123);
+	private final long connection = 12345L;
 
 	public ConnectionWriterTest() throws Exception {
 		super();
diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java
index 2752a5277ad1cb495b86fcd2ac90585fd2674034..197c660e027ae19b8637da3e34fb496f2a0a3153 100644
--- a/test/net/sf/briar/transport/FrameReadWriteTest.java
+++ b/test/net/sf/briar/transport/FrameReadWriteTest.java
@@ -14,6 +14,7 @@ import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 
 import junit.framework.TestCase;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionWriter;
@@ -32,8 +33,8 @@ public class FrameReadWriteTest extends TestCase {
 	private final Mac mac;
 	private final Random random;
 	private final byte[] secret = new byte[100];
-	private final int transportId = 999;
-	private final long connection = 1234L;
+	private final TransportId transportId = new TransportId(123);
+	private final long connection = 12345L;
 
 	public FrameReadWriteTest() {
 		super();
diff --git a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
index 8a65f3227a6c80b95bc4de1520e9260d5237ae7f..adf43ad701fd369f6e7ec9ae54ceac182737c2a2 100644
--- a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
+++ b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
@@ -12,6 +12,7 @@ import junit.framework.TestCase;
 import net.sf.briar.TestDatabaseModule;
 import net.sf.briar.TestUtils;
 import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportId;
 import net.sf.briar.api.db.DatabaseComponent;
 import net.sf.briar.api.db.DatabaseListener;
 import net.sf.briar.api.protocol.Message;
@@ -43,10 +44,10 @@ public class BatchConnectionReadWriteTest extends TestCase {
 	private final File testDir = TestUtils.getTestDirectory();
 	private final File aliceDir = new File(testDir, "alice");
 	private final File bobDir = new File(testDir, "bob");
-	private final Map<Integer, Map<String, String>> transports =
+	private final TransportId transportId = new TransportId(123);
+	private final Map<TransportId, Map<String, String>> transports =
 		Collections.emptyMap();
 	private final byte[] aliceSecret, bobSecret;
-	private final int transportId = 123;
 
 	private Injector alice, bob;