diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java
index 1717f00ca9dbf22569a933bbe5f9af332cc4a907..f2df7b5cc2936b51a821218440cd5c126a33c8a8 100644
--- a/api/net/sf/briar/api/db/DatabaseComponent.java
+++ b/api/net/sf/briar/api/db/DatabaseComponent.java
@@ -28,6 +28,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
 import net.sf.briar.api.protocol.writers.RequestWriter;
 import net.sf.briar.api.protocol.writers.SubscriptionUpdateWriter;
 import net.sf.briar.api.protocol.writers.TransportUpdateWriter;
+import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionWindow;
 
 /**
@@ -114,10 +115,11 @@ public interface DatabaseComponent {
 	TransportConfig getConfig(TransportId t) throws DbException;
 
 	/**
-	 * Returns an outgoing connection number for the given contact and
+	 * Returns an outgoing connection context for the given contact and
 	 * transport.
 	 */
-	long getConnectionNumber(ContactId c, TransportIndex i) throws DbException;
+	ConnectionContext getConnectionContext(ContactId c, TransportIndex i)
+	throws DbException;
 
 	/**
 	 * Returns the connection reordering window for the given contact and
diff --git a/api/net/sf/briar/api/transport/ConnectionContextFactory.java b/api/net/sf/briar/api/transport/ConnectionContextFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..39ab561dce1f9ab8fed102ebfa1a13ad33a31d1c
--- /dev/null
+++ b/api/net/sf/briar/api/transport/ConnectionContextFactory.java
@@ -0,0 +1,10 @@
+package net.sf.briar.api.transport;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.protocol.TransportIndex;
+
+public interface ConnectionContextFactory {
+
+	ConnectionContext createConnectionContext(ContactId c, TransportIndex i,
+			long connection);
+}
diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index a3281c7973ed945524a8c1e1df5535c8ae73be79..fe1a6fc00510d6540759a5d1d846bbb4946259a5 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -20,6 +20,7 @@ import net.sf.briar.api.protocol.MessageId;
 import net.sf.briar.api.protocol.Transport;
 import net.sf.briar.api.protocol.TransportId;
 import net.sf.briar.api.protocol.TransportIndex;
+import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionWindow;
 
 /**
@@ -183,12 +184,12 @@ interface Database<T> {
 	TransportConfig getConfig(T txn, TransportId t) throws DbException;
 
 	/**
-	 * Allocates and returns a connection number for the given contact and
+	 * Returns an outgoing connection context for the given contact and
 	 * transport.
 	 * <p>
 	 * Locking: contact read, window write.
 	 */
-	long getConnectionNumber(T txn, ContactId c, TransportIndex i)
+	ConnectionContext getConnectionContext(T txn, ContactId c, TransportIndex i)
 	throws DbException;
 
 	/**
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index a671f95c1cd886afd5b893930108fa96b544b219..1fd216d55f5ba6b4d111eece42680832f5b176c6 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -60,6 +60,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
 import net.sf.briar.api.protocol.writers.RequestWriter;
 import net.sf.briar.api.protocol.writers.SubscriptionUpdateWriter;
 import net.sf.briar.api.protocol.writers.TransportUpdateWriter;
+import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionWindow;
 
 import com.google.inject.Inject;
@@ -700,7 +701,7 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public long getConnectionNumber(ContactId c, TransportIndex i)
+	public ConnectionContext getConnectionContext(ContactId c, TransportIndex i)
 	throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -709,9 +710,9 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					long outgoing = db.getConnectionNumber(txn, c, i);
+					ConnectionContext ctx = db.getConnectionContext(txn, c, i);
 					db.commitTransaction(txn);
-					return outgoing;
+					return ctx;
 				} catch(DbException e) {
 					db.abortTransaction(txn);
 					throw e;
diff --git a/components/net/sf/briar/db/DatabaseModule.java b/components/net/sf/briar/db/DatabaseModule.java
index 903fb43458772d61ca785b05757753a4412554a0..9df6352ecdad7be6c56b4ac7d66cbe3c7e2f725c 100644
--- a/components/net/sf/briar/db/DatabaseModule.java
+++ b/components/net/sf/briar/db/DatabaseModule.java
@@ -9,6 +9,7 @@ import net.sf.briar.api.db.DatabaseDirectory;
 import net.sf.briar.api.db.DatabaseMaxSize;
 import net.sf.briar.api.db.DatabasePassword;
 import net.sf.briar.api.protocol.GroupFactory;
+import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
 
 import com.google.inject.AbstractModule;
@@ -25,10 +26,11 @@ public class DatabaseModule extends AbstractModule {
 	@Provides
 	Database<Connection> getDatabase(@DatabaseDirectory File dir,
 			@DatabasePassword Password password, @DatabaseMaxSize long maxSize,
+			ConnectionContextFactory connectionContextFactory,
 			ConnectionWindowFactory connectionWindowFactory,
 			GroupFactory groupFactory) {
-		return new H2Database(dir, password, maxSize, connectionWindowFactory,
-				groupFactory);
+		return new H2Database(dir, password, maxSize, connectionContextFactory,
+				connectionWindowFactory, groupFactory);
 	}
 
 	@Provides @Singleton
diff --git a/components/net/sf/briar/db/H2Database.java b/components/net/sf/briar/db/H2Database.java
index 2922c8ff7dba182a868500bc28091b10d341ea7e..a721aa9a2e0749769ccf440083740c47f5bcb01a 100644
--- a/components/net/sf/briar/db/H2Database.java
+++ b/components/net/sf/briar/db/H2Database.java
@@ -16,6 +16,7 @@ import net.sf.briar.api.db.DatabaseMaxSize;
 import net.sf.briar.api.db.DatabasePassword;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.protocol.GroupFactory;
+import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
 
 import org.apache.commons.io.FileSystemUtils;
@@ -34,11 +35,13 @@ class H2Database extends JdbcDatabase {
 	private final long maxSize;
 
 	@Inject
-	H2Database(@DatabaseDirectory File dir, @DatabasePassword Password password,
+	H2Database(@DatabaseDirectory File dir,
+			@DatabasePassword Password password,
 			@DatabaseMaxSize long maxSize,
+			ConnectionContextFactory connectionContextFactory,
 			ConnectionWindowFactory connectionWindowFactory,
 			GroupFactory groupFactory) {
-		super(connectionWindowFactory, groupFactory,
+		super(connectionContextFactory, connectionWindowFactory, groupFactory,
 				"BINARY(32)", "BINARY", "INT NOT NULL AUTO_INCREMENT");
 		home = new File(dir, "db");
 		this.password = password;
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 0398d75e6a8fc9bd89e69b46f27ef5c799185eb2..6a874a16fd532bbaa28e8107b66c9b78d5f68ed0 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -35,6 +35,8 @@ import net.sf.briar.api.protocol.ProtocolConstants;
 import net.sf.briar.api.protocol.Transport;
 import net.sf.briar.api.protocol.TransportId;
 import net.sf.briar.api.protocol.TransportIndex;
+import net.sf.briar.api.transport.ConnectionContext;
+import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindow;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.util.FileUtils;
@@ -265,10 +267,11 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private static final Logger LOG =
 		Logger.getLogger(JdbcDatabase.class.getName());
 
-	// Different database libraries use different names for certain types
-	private final String hashType, binaryType, counterType;
+	private final ConnectionContextFactory connectionContextFactory;
 	private final ConnectionWindowFactory connectionWindowFactory;
 	private final GroupFactory groupFactory;
+	// Different database libraries use different names for certain types
+	private final String hashType, binaryType, counterType;
 
 	private final LinkedList<Connection> connections =
 		new LinkedList<Connection>(); // Locking: self
@@ -278,9 +281,11 @@ abstract class JdbcDatabase implements Database<Connection> {
 
 	protected abstract Connection createConnection() throws SQLException;
 
-	JdbcDatabase(ConnectionWindowFactory connectionWindowFactory,
+	JdbcDatabase(ConnectionContextFactory connectionContextFactory,
+			ConnectionWindowFactory connectionWindowFactory,
 			GroupFactory groupFactory, String hashType, String binaryType,
 			String counterType) {
+		this.connectionContextFactory = connectionContextFactory;
 		this.connectionWindowFactory = connectionWindowFactory;
 		this.groupFactory = groupFactory;
 		this.hashType = hashType;
@@ -939,7 +944,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public long getConnectionNumber(Connection txn, ContactId c,
+	public ConnectionContext getConnectionContext(Connection txn, ContactId c,
 			TransportIndex i) throws DbException {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
@@ -963,7 +968,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 			if(rs.next()) throw new DbStateException();
 			rs.close();
 			ps.close();
-			return outgoing;
+			return connectionContextFactory.createConnectionContext(c, i,
+					outgoing);
 		} catch(SQLException e) {
 			tryToClose(rs);
 			tryToClose(ps);
diff --git a/components/net/sf/briar/transport/ConnectionContextFactoryImpl.java b/components/net/sf/briar/transport/ConnectionContextFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..08116a58b79831d16315084985d6fc3de940dc45
--- /dev/null
+++ b/components/net/sf/briar/transport/ConnectionContextFactoryImpl.java
@@ -0,0 +1,14 @@
+package net.sf.briar.transport;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.protocol.TransportIndex;
+import net.sf.briar.api.transport.ConnectionContext;
+import net.sf.briar.api.transport.ConnectionContextFactory;
+
+class ConnectionContextFactoryImpl implements ConnectionContextFactory {
+
+	public ConnectionContext createConnectionContext(ContactId c,
+			TransportIndex i, long connection) {
+		return new ConnectionContextImpl(c, i, connection);
+	}
+}
diff --git a/components/net/sf/briar/transport/TransportModule.java b/components/net/sf/briar/transport/TransportModule.java
index 867b4e39f1cb167a75a21f5cb04e846d799c704b..3af8ef144be11de9d0776329ace96fac02b698bc 100644
--- a/components/net/sf/briar/transport/TransportModule.java
+++ b/components/net/sf/briar/transport/TransportModule.java
@@ -1,5 +1,6 @@
 package net.sf.briar.transport;
 
+import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionDispatcher;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionRecogniser;
@@ -12,6 +13,8 @@ public class TransportModule extends AbstractModule {
 
 	@Override
 	protected void configure() {
+		bind(ConnectionContextFactory.class).to(
+				ConnectionContextFactoryImpl.class);
 		bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class);
 		bind(ConnectionReaderFactory.class).to(
 				ConnectionReaderFactoryImpl.class);
diff --git a/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java b/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
index b9d8630b3530652bd64dc0cd05ed3b1645c24eb7..e00529eee13c4923ca9ac6754c02fb86fb1a67ea 100644
--- a/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
+++ b/components/net/sf/briar/transport/batch/OutgoingBatchConnection.java
@@ -17,6 +17,7 @@ import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
 import net.sf.briar.api.protocol.writers.SubscriptionUpdateWriter;
 import net.sf.briar.api.protocol.writers.TransportUpdateWriter;
 import net.sf.briar.api.transport.BatchTransportWriter;
+import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 
@@ -47,10 +48,11 @@ class OutgoingBatchConnection {
 	void write() {
 		try {
 			byte[] secret = db.getSharedSecret(contactId, false);
-			long connection = db.getConnectionNumber(contactId, transportIndex);
+			ConnectionContext ctx =
+				db.getConnectionContext(contactId, transportIndex);
 			ConnectionWriter conn = connFactory.createConnectionWriter(
 					writer.getOutputStream(), writer.getCapacity(),
-					transportIndex, connection, secret);
+					transportIndex, ctx.getConnectionNumber(), secret);
 			OutputStream out = conn.getOutputStream();
 			// There should be enough space for a packet
 			long capacity = conn.getRemainingCapacity();
diff --git a/components/net/sf/briar/transport/stream/OutgoingStreamConnection.java b/components/net/sf/briar/transport/stream/OutgoingStreamConnection.java
index 4af22e161ea9c24183d3cbc258c46ad117788ce4..b02e4600742393115b97cc4d8e4d7c9ca4814fc4 100644
--- a/components/net/sf/briar/transport/stream/OutgoingStreamConnection.java
+++ b/components/net/sf/briar/transport/stream/OutgoingStreamConnection.java
@@ -8,6 +8,7 @@ import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.protocol.ProtocolReaderFactory;
 import net.sf.briar.api.protocol.TransportIndex;
 import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
+import net.sf.briar.api.transport.ConnectionContext;
 import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriter;
@@ -16,7 +17,7 @@ import net.sf.briar.api.transport.StreamTransportConnection;
 
 public class OutgoingStreamConnection extends StreamConnection {
 
-	private long connectionNum = -1L; // Locking: this
+	private ConnectionContext ctx = null; // Locking: this
 
 	OutgoingStreamConnection(ConnectionReaderFactory connReaderFactory,
 			ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
@@ -32,29 +33,27 @@ public class OutgoingStreamConnection extends StreamConnection {
 	protected ConnectionReader createConnectionReader() throws DbException,
 	IOException {
 		synchronized(this) {
-			if(connectionNum == -1L) {
-				connectionNum = db.getConnectionNumber(contactId,
-						transportIndex);
+			if(ctx == null) {
+				ctx = db.getConnectionContext(contactId, transportIndex);
 			}
 		}
 		byte[] secret = db.getSharedSecret(contactId, true);
 		return connReaderFactory.createConnectionReader(
-				connection.getInputStream(), transportIndex, connectionNum,
-				secret);
+				connection.getInputStream(), transportIndex,
+				ctx.getConnectionNumber(), secret);
 	}
 
 	@Override
 	protected ConnectionWriter createConnectionWriter() throws DbException,
 	IOException {
 		synchronized(this) {
-			if(connectionNum == -1L) {
-				connectionNum = db.getConnectionNumber(contactId,
-						transportIndex);
+			if(ctx == null) {
+				ctx = db.getConnectionContext(contactId, transportIndex);
 			}
 		}
 		byte[] secret = db.getSharedSecret(contactId, false);
 		return connWriterFactory.createConnectionWriter(
 				connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
-				connectionNum, secret);
+				ctx.getConnectionNumber(), secret);
 	}
 }
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index 178f76d179ecdec65db381c8b7668e2005dcc75b..66c84b223e02f2e16273e41b51d9ba0fd1e9e9cd 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -561,7 +561,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		} catch(NoSuchContactException expected) {}
 
 		try {
-			db.getConnectionNumber(contactId, remoteIndex);
+			db.getConnectionContext(contactId, remoteIndex);
 			fail();
 		} catch(NoSuchContactException expected) {}
 
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index 48a7532dc40ed3d10d5a26c60f753dbcd66db9e3..3e860fc7ad113498676bc579326d6e836e11bfa3 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -37,6 +37,7 @@ import net.sf.briar.api.protocol.ProtocolConstants;
 import net.sf.briar.api.protocol.Transport;
 import net.sf.briar.api.protocol.TransportId;
 import net.sf.briar.api.protocol.TransportIndex;
+import net.sf.briar.api.transport.ConnectionContextFactory;
 import net.sf.briar.api.transport.ConnectionWindow;
 import net.sf.briar.api.transport.ConnectionWindowFactory;
 import net.sf.briar.crypto.CryptoModule;
@@ -65,6 +66,7 @@ public class H2DatabaseTest extends TestCase {
 	private final String passwordString = "foo bar";
 	private final Password password = new TestPassword();
 	private final Random random = new Random();
+	private final ConnectionContextFactory connectionContextFactory;
 	private final ConnectionWindowFactory connectionWindowFactory;
 	private final GroupFactory groupFactory;
 
@@ -94,6 +96,8 @@ public class H2DatabaseTest extends TestCase {
 				new ProtocolWritersModule(), new SerialModule(),
 				new TransportBatchModule(), new TransportModule(),
 				new TransportStreamModule(), new TestDatabaseModule(testDir));
+		connectionContextFactory =
+			i.getInstance(ConnectionContextFactory.class);
 		connectionWindowFactory = i.getInstance(ConnectionWindowFactory.class);
 		groupFactory = i.getInstance(GroupFactory.class);
 		authorId = new AuthorId(TestUtils.getRandomId());
@@ -1885,7 +1889,8 @@ public class H2DatabaseTest extends TestCase {
 
 	private Database<Connection> open(boolean resume) throws Exception {
 		Database<Connection> db = new H2Database(testDir, password, MAX_SIZE,
-				connectionWindowFactory, groupFactory);
+				connectionContextFactory, connectionWindowFactory,
+				groupFactory);
 		db.open(resume);
 		return db;
 	}