Split transport identifiers into two: TransportId (globally unique)

and TransportIndex (locally unique).

This is the first step towards forward secrecy. Also removed the
Writable interface and unnecessary user-defined types, moved various
constants to ProtocolConstants and renamed some classes.
This commit is contained in:
akwizgran
2011-11-14 21:40:05 +00:00
parent 7d09102c4d
commit 73aa7d14d7
113 changed files with 1610 additions and 1121 deletions

View File

@@ -0,0 +1,38 @@
package net.sf.briar.transport;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.transport.ConnectionContext;
class ConnectionContextImpl implements ConnectionContext {
private final ContactId contactId;
private final TransportId transportId;
private final TransportIndex transportIndex;
private final long connectionNumber;
ConnectionContextImpl(ContactId contactId, TransportId transportId,
TransportIndex transportIndex, long connectionNumber) {
this.contactId = contactId;
this.transportId = transportId;
this.transportIndex = transportIndex;
this.connectionNumber = connectionNumber;
}
public ContactId getContactId() {
return contactId;
}
public TransportId getTransportId() {
return transportId;
}
public TransportIndex getTransportIndex() {
return transportIndex;
}
public long getConnectionNumber() {
return connectionNumber;
}
}

View File

@@ -2,41 +2,41 @@ package net.sf.briar.transport;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportId;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.transport.BatchConnectionFactory;
import net.sf.briar.api.transport.BatchTransportReader;
import net.sf.briar.api.transport.BatchTransportWriter;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionDispatcher;
import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionRecogniserFactory;
import net.sf.briar.api.transport.StreamConnectionFactory;
import net.sf.briar.api.transport.StreamTransportConnection;
import net.sf.briar.api.transport.TransportConstants;
import com.google.inject.Inject;
public class ConnectionDispatcherImpl implements ConnectionDispatcher {
private static final Logger LOG =
Logger.getLogger(ConnectionDispatcherImpl.class.getName());
private final ConnectionRecogniserFactory recFactory;
private final ConnectionRecogniser recogniser;
private final BatchConnectionFactory batchConnFactory;
private final StreamConnectionFactory streamConnFactory;
private final Map<TransportId, ConnectionRecogniser> recognisers;
ConnectionDispatcherImpl(ConnectionRecogniserFactory recFactory,
@Inject
ConnectionDispatcherImpl(ConnectionRecogniser recogniser,
BatchConnectionFactory batchConnFactory,
StreamConnectionFactory streamConnFactory) {
this.recFactory = recFactory;
this.recogniser = recogniser;
this.batchConnFactory = batchConnFactory;
this.streamConnFactory = streamConnFactory;
recognisers = new HashMap<TransportId, ConnectionRecogniser>();
}
public void dispatchReader(TransportId t, BatchTransportReader r) {
@@ -49,21 +49,27 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
r.dispose(false);
return;
}
// Get the contact ID, or null if the IV wasn't expected
ContactId c;
// Get the connection context, or null if the IV wasn't expected
ConnectionContext ctx;
try {
ConnectionRecogniser rec = getRecogniser(t);
c = rec.acceptConnection(encryptedIv);
ctx = recogniser.acceptConnection(encryptedIv);
} catch(DbException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
r.dispose(false);
return;
}
if(c == null) {
if(ctx == null) {
r.dispose(false);
return;
}
batchConnFactory.createIncomingConnection(t, c, r, encryptedIv);
if(!t.equals(ctx.getTransportId())) {
if(LOG.isLoggable(Level.WARNING))
LOG.warning("Connection has unexpected transport ID");
r.dispose(false);
return;
}
batchConnFactory.createIncomingConnection(ctx.getTransportIndex(),
ctx.getContactId(), r, encryptedIv);
}
private byte[] readIv(InputStream in) throws IOException {
@@ -77,20 +83,9 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
return b;
}
private ConnectionRecogniser getRecogniser(TransportId t) {
synchronized(recognisers) {
ConnectionRecogniser rec = recognisers.get(t);
if(rec == null) {
rec = recFactory.createConnectionRecogniser(t);
recognisers.put(t, rec);
}
return rec;
}
}
public void dispatchWriter(TransportId t, ContactId c,
public void dispatchWriter(TransportIndex i, ContactId c,
BatchTransportWriter w) {
batchConnFactory.createOutgoingConnection(t, c, w);
batchConnFactory.createOutgoingConnection(i, c, w);
}
public void dispatchIncomingConnection(TransportId t,
@@ -104,25 +99,31 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
s.dispose(false);
return;
}
// Get the contact ID, or null if the IV wasn't expected
ContactId c;
// Get the connection context, or null if the IV wasn't expected
ConnectionContext ctx;
try {
ConnectionRecogniser rec = getRecogniser(t);
c = rec.acceptConnection(encryptedIv);
ctx = recogniser.acceptConnection(encryptedIv);
} catch(DbException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
s.dispose(false);
return;
}
if(c == null) {
if(ctx == null) {
s.dispose(false);
return;
}
streamConnFactory.createIncomingConnection(t, c, s, encryptedIv);
if(!t.equals(ctx.getTransportId())) {
if(LOG.isLoggable(Level.WARNING))
LOG.warning("Connection has unexpected transport ID");
s.dispose(false);
return;
}
streamConnFactory.createIncomingConnection(ctx.getTransportIndex(),
ctx.getContactId(), s, encryptedIv);
}
public void dispatchOutgoingConnection(TransportId t, ContactId c,
public void dispatchOutgoingConnection(TransportIndex i, ContactId c,
StreamTransportConnection s) {
streamConnFactory.createOutgoingConnection(t, c, s);
streamConnFactory.createOutgoingConnection(i, c, s);
}
}

View File

@@ -9,8 +9,8 @@ import javax.crypto.IllegalBlockSizeException;
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.protocol.TransportIndex;
import net.sf.briar.api.transport.ConnectionReader;
import net.sf.briar.api.transport.ConnectionReaderFactory;
@@ -26,7 +26,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
}
public ConnectionReader createConnectionReader(InputStream in,
TransportId t, byte[] encryptedIv, byte[] secret) {
TransportIndex i, byte[] encryptedIv, byte[] secret) {
// Decrypt the IV
Cipher ivCipher = crypto.getIvCipher();
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
@@ -42,21 +42,22 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
throw new IllegalArgumentException(badKey);
}
// Validate the IV
if(!IvEncoder.validateIv(iv, true, t))
if(!IvEncoder.validateIv(iv, true, i))
throw new IllegalArgumentException();
// Copy the connection number
long connection = IvEncoder.getConnectionNumber(iv);
return createConnectionReader(in, true, t, connection, secret);
return createConnectionReader(in, true, i, connection, secret);
}
public ConnectionReader createConnectionReader(InputStream in,
TransportId t, long connection, byte[] secret) {
return createConnectionReader(in, false, t, connection, secret);
TransportIndex i, long connection, byte[] secret) {
return createConnectionReader(in, false, i, connection, secret);
}
private ConnectionReader createConnectionReader(InputStream in,
boolean initiator, TransportId t, long connection, byte[] secret) {
byte[] iv = IvEncoder.encodeIv(initiator, t, connection);
boolean initiator, TransportIndex i, long connection,
byte[] secret) {
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
// Create the decrypter
Cipher frameCipher = crypto.getFrameCipher();
SecretKey frameKey = crypto.deriveIncomingFrameKey(secret);

View File

@@ -1,26 +0,0 @@
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;
import net.sf.briar.api.transport.ConnectionRecogniserFactory;
import com.google.inject.Inject;
class ConnectionRecogniserFactoryImpl implements ConnectionRecogniserFactory {
private final CryptoComponent crypto;
private final DatabaseComponent db;
@Inject
ConnectionRecogniserFactoryImpl(CryptoComponent crypto,
DatabaseComponent db) {
this.crypto = crypto;
this.db = db;
}
public ConnectionRecogniser createConnectionRecogniser(TransportId t) {
return new ConnectionRecogniserImpl(t, crypto, db);
}
}

View File

@@ -3,8 +3,13 @@ package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@@ -13,128 +18,178 @@ 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.DbException;
import net.sf.briar.api.db.NoSuchContactException;
import net.sf.briar.api.db.event.ContactAddedEvent;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.TransportAddedEvent;
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
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.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionWindow;
import com.google.inject.Inject;
class ConnectionRecogniserImpl implements ConnectionRecogniser,
DatabaseListener {
private final TransportId id;
private static final Logger LOG =
Logger.getLogger(ConnectionRecogniserImpl.class.getName());
private final CryptoComponent crypto;
private final DatabaseComponent db;
private final Map<Bytes, ContactId> ivToContact;
private final Map<Bytes, Long> ivToConnectionNumber;
private final Map<ContactId, Map<Long, Bytes>> contactToIvs;
private final Map<ContactId, Cipher> contactToCipher;
private final Map<ContactId, ConnectionWindow> contactToWindow;
private final Cipher ivCipher;
private final Map<Bytes, ConnectionContext> expected;
private final Collection<TransportId> localTransportIds;
private boolean initialised = false;
ConnectionRecogniserImpl(TransportId id, CryptoComponent crypto,
DatabaseComponent db) {
this.id = id;
@Inject
ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db) {
this.crypto = crypto;
this.db = db;
// FIXME: There's probably a tidier way of maintaining all this state
ivToContact = new HashMap<Bytes, ContactId>();
ivToConnectionNumber = new HashMap<Bytes, Long>();
contactToIvs = new HashMap<ContactId, Map<Long, Bytes>>();
contactToCipher = new HashMap<ContactId, Cipher>();
contactToWindow = new HashMap<ContactId, ConnectionWindow>();
ivCipher = crypto.getIvCipher();
expected = new HashMap<Bytes, ConnectionContext>();
localTransportIds = new ArrayList<TransportId>();
db.addListener(this);
}
private synchronized void initialise() throws DbException {
for(Transport t : db.getLocalTransports()) {
localTransportIds.add(t.getId());
}
for(ContactId c : db.getContacts()) {
try {
// Initialise and store the contact's IV cipher
byte[] secret = db.getSharedSecret(c);
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
Cipher cipher = crypto.getIvCipher();
try {
cipher.init(Cipher.ENCRYPT_MODE, ivKey);
} catch(InvalidKeyException badKey) {
throw new RuntimeException(badKey);
}
contactToCipher.put(c, cipher);
// Calculate the IVs for the contact's connection window
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));
ivToContact.put(expectedIv, c);
ivToConnectionNumber.put(expectedIv, unseen);
ivs.put(unseen, expectedIv);
}
contactToIvs.put(c, ivs);
contactToWindow.put(c, w);
calculateIvs(c);
} catch(NoSuchContactException e) {
// The contact was removed after the call to getContacts()
continue;
// The contact was removed - clean up in eventOccurred()
}
}
initialised = true;
}
private synchronized byte[] encryptIv(ContactId c, long connection) {
byte[] iv = IvEncoder.encodeIv(true, id, connection);
Cipher cipher = contactToCipher.get(c);
assert cipher != null;
private synchronized void calculateIvs(ContactId c) throws DbException {
SecretKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
for(TransportId t : localTransportIds) {
TransportIndex i = db.getRemoteIndex(c, t);
if(i != null) {
ConnectionWindow w = db.getConnectionWindow(c, i);
calculateIvs(c, t, i, ivKey, w);
}
}
}
private synchronized void calculateIvs(ContactId c, TransportId t,
TransportIndex i, SecretKey ivKey, ConnectionWindow w)
throws DbException {
for(Long unseen : w.getUnseenConnectionNumbers()) {
Bytes iv = new Bytes(encryptIv(i, unseen, ivKey));
expected.put(iv, new ConnectionContextImpl(c, t, i, unseen));
}
}
private synchronized byte[] encryptIv(TransportIndex i, long connection,
SecretKey ivKey) {
byte[] iv = IvEncoder.encodeIv(true, i, connection);
try {
return cipher.doFinal(iv);
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
return ivCipher.doFinal(iv);
} catch(BadPaddingException badCipher) {
throw new RuntimeException(badCipher);
} catch(IllegalBlockSizeException badCipher) {
throw new RuntimeException(badCipher);
} catch(InvalidKeyException badKey) {
throw new RuntimeException(badKey);
}
}
public synchronized ContactId acceptConnection(byte[] encryptedIv)
public synchronized ConnectionContext acceptConnection(byte[] encryptedIv)
throws DbException {
if(encryptedIv.length != IV_LENGTH)
throw new IllegalArgumentException();
if(!initialised) initialise();
Bytes b = new Bytes(encryptedIv);
ContactId contactId = ivToContact.remove(b);
Long connection = ivToConnectionNumber.remove(b);
assert (contactId == null) == (connection == null);
if(contactId == null) return null;
// The IV was expected - update and save the connection window
ConnectionWindow w = contactToWindow.get(contactId);
assert w != null;
w.setSeen(connection);
db.setConnectionWindow(contactId, id, w);
// Update the set of expected IVs
Map<Long, Bytes> oldIvs = contactToIvs.remove(contactId);
assert oldIvs != null;
assert oldIvs.containsKey(connection);
Map<Long, Bytes> newIvs = new HashMap<Long, Bytes>();
for(Long unseen : w.getUnseenConnectionNumbers()) {
Bytes expectedIv = oldIvs.get(unseen);
if(expectedIv == null) {
expectedIv = new Bytes(encryptIv(contactId, unseen));
ivToContact.put(expectedIv, contactId);
ivToConnectionNumber.put(expectedIv, connection);
ConnectionContext ctx = expected.remove(new Bytes(encryptedIv));
if(ctx == null) return null; // The IV was not expected
try {
ContactId c = ctx.getContactId();
TransportIndex i = ctx.getTransportIndex();
// Update the connection window
ConnectionWindow w = db.getConnectionWindow(c, i);
w.setSeen(ctx.getConnectionNumber());
db.setConnectionWindow(c, i, w);
// Update the set of expected IVs
Iterator<ConnectionContext> it = expected.values().iterator();
while(it.hasNext()) {
ConnectionContext ctx1 = it.next();
ContactId c1 = ctx1.getContactId();
TransportIndex i1 = ctx1.getTransportIndex();
if(c1.equals(c) && i1.equals(i)) it.remove();
}
newIvs.put(unseen, expectedIv);
SecretKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
calculateIvs(c, ctx.getTransportId(), i, ivKey, w);
} catch(NoSuchContactException e) {
// The contact was removed - clean up when we get the event
}
contactToIvs.put(contactId, newIvs);
return contactId;
return ctx;
}
public void eventOccurred(DatabaseEvent e) {
// When the set of contacts changes we need to re-initialise everything
if(e instanceof ContactAddedEvent || e instanceof ContactRemovedEvent) {
if(e instanceof ContactRemovedEvent) {
// Remove the expected IVs for the ex-contact
removeIvs(((ContactRemovedEvent) e).getContactId());
} else if(e instanceof TransportAddedEvent) {
// Calculate the expected IVs for the new transport
TransportId t = ((TransportAddedEvent) e).getTransportId();
synchronized(this) {
initialised = false;
if(!initialised) return;
try {
localTransportIds.add(t);
calculateIvs(t);
} catch(DbException e1) {
if(LOG.isLoggable(Level.WARNING))
LOG.warning(e1.getMessage());
}
}
} else if(e instanceof RemoteTransportsUpdatedEvent) {
// Remove and recalculate the expected IVs for the contact
ContactId c = ((RemoteTransportsUpdatedEvent) e).getContactId();
synchronized(this) {
if(!initialised) return;
removeIvs(c);
try {
calculateIvs(c);
} catch(DbException e1) {
if(LOG.isLoggable(Level.WARNING))
LOG.warning(e1.getMessage());
}
}
}
}
private synchronized void removeIvs(ContactId c) {
if(!initialised) return;
Iterator<ConnectionContext> it = expected.values().iterator();
while(it.hasNext()) if(it.next().getContactId().equals(c)) it.remove();
}
private synchronized void calculateIvs(TransportId t) throws DbException {
for(ContactId c : db.getContacts()) {
try {
byte[] secret = db.getSharedSecret(c);
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
TransportIndex i = db.getRemoteIndex(c, t);
if(i != null) {
ConnectionWindow w = db.getConnectionWindow(c, i);
calculateIvs(c, t, i, ivKey, w);
}
} catch(NoSuchContactException e) {
// The contact was removed - clean up when we get the event
}
}
}

View File

@@ -9,8 +9,8 @@ import javax.crypto.IllegalBlockSizeException;
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.protocol.TransportIndex;
import net.sf.briar.api.transport.ConnectionWriter;
import net.sf.briar.api.transport.ConnectionWriterFactory;
@@ -26,13 +26,14 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
}
public ConnectionWriter createConnectionWriter(OutputStream out,
long capacity, TransportId t, long connection, byte[] secret) {
return createConnectionWriter(out, capacity, true, t, connection,
long capacity, TransportIndex i, long connection, byte[] secret) {
return createConnectionWriter(out, capacity, true, i, connection,
secret);
}
public ConnectionWriter createConnectionWriter(OutputStream out,
long capacity, TransportId t, byte[] encryptedIv, byte[] secret) {
long capacity, TransportIndex i, byte[] encryptedIv,
byte[] secret) {
// Decrypt the IV
Cipher ivCipher = crypto.getIvCipher();
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
@@ -48,23 +49,23 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
throw new RuntimeException(badKey);
}
// Validate the IV
if(!IvEncoder.validateIv(iv, true, t))
if(!IvEncoder.validateIv(iv, true, i))
throw new IllegalArgumentException();
// Copy the connection number
long connection = IvEncoder.getConnectionNumber(iv);
return createConnectionWriter(out, capacity, false, t, connection,
return createConnectionWriter(out, capacity, false, i, connection,
secret);
}
private ConnectionWriter createConnectionWriter(OutputStream out,
long capacity, boolean initiator, TransportId t, long connection,
long capacity, boolean initiator, TransportIndex i, 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, t, connection);
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
// Create the writer

View File

@@ -1,18 +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.api.protocol.TransportIndex;
import net.sf.briar.util.ByteUtils;
class IvEncoder {
static byte[] encodeIv(boolean initiator, TransportId transport,
static byte[] encodeIv(boolean initiator, TransportIndex i,
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(transport.getInt(), iv, 4);
ByteUtils.writeUint16(i.getInt(), iv, 4);
// Encode the connection number as an unsigned 32-bit integer
ByteUtils.writeUint32(connection, iv, 6);
return iv;
@@ -24,16 +24,16 @@ class IvEncoder {
ByteUtils.writeUint32(frame, iv, 10);
}
static boolean validateIv(byte[] iv, boolean initiator, TransportId t) {
static boolean validateIv(byte[] iv, boolean initiator, TransportIndex i) {
if(iv.length != IV_LENGTH) return false;
// Check that the reserved bits are all zero
for(int i = 0; i < 2; i++) if(iv[i] != 0) return false;
for(int j = 0; j < 2; j++) if(iv[j] != 0) return false;
if(iv[3] != 0 && iv[3] != 1) return false;
for(int i = 10; i < iv.length; i++) if(iv[i] != 0) return false;
for(int j = 10; j < iv.length; j++) if(iv[j] != 0) return false;
// Check that the initiator flag matches
if(initiator != getInitiatorFlag(iv)) return false;
// Check that the transport ID matches
if(t.getInt() != getTransportId(iv)) return false;
if(i.getInt() != getTransportId(iv)) return false;
// The IV is valid
return true;
}

View File

@@ -1,23 +0,0 @@
package net.sf.briar.transport;
import javax.crypto.Mac;
import net.sf.briar.api.serial.Consumer;
/** A consumer that passes its input through a MAC. */
class MacConsumer implements Consumer {
private final Mac mac;
MacConsumer(Mac mac) {
this.mac = mac;
}
public void write(byte b) {
mac.update(b);
}
public void write(byte[] b, int off, int len) {
mac.update(b, off, len);
}
}

View File

@@ -1,7 +1,8 @@
package net.sf.briar.transport;
import net.sf.briar.api.transport.ConnectionDispatcher;
import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRecogniserFactory;
import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.ConnectionWindowFactory;
import net.sf.briar.api.transport.ConnectionWriterFactory;
@@ -11,10 +12,10 @@ public class TransportModule extends AbstractModule {
@Override
protected void configure() {
bind(ConnectionDispatcher.class).to(ConnectionDispatcherImpl.class);
bind(ConnectionReaderFactory.class).to(
ConnectionReaderFactoryImpl.class);
bind(ConnectionRecogniserFactory.class).to(
ConnectionRecogniserFactoryImpl.class);
bind(ConnectionRecogniser.class).to(ConnectionRecogniserImpl.class);
bind(ConnectionWindowFactory.class).to(
ConnectionWindowFactoryImpl.class);
bind(ConnectionWriterFactory.class).to(

View File

@@ -1,9 +1,9 @@
package net.sf.briar.transport.batch;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportId;
import net.sf.briar.api.db.DatabaseComponent;
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.BatchConnectionFactory;
import net.sf.briar.api.transport.BatchTransportReader;
@@ -33,10 +33,10 @@ class BatchConnectionFactoryImpl implements BatchConnectionFactory {
this.protoWriterFactory = protoWriterFactory;
}
public void createIncomingConnection(TransportId t, ContactId c,
public void createIncomingConnection(TransportIndex i, ContactId c,
BatchTransportReader r, byte[] encryptedIv) {
final IncomingBatchConnection conn = new IncomingBatchConnection(
connReaderFactory, db, protoReaderFactory, t, c, r,
connReaderFactory, db, protoReaderFactory, i, c, r,
encryptedIv);
Runnable read = new Runnable() {
public void run() {
@@ -46,10 +46,10 @@ class BatchConnectionFactoryImpl implements BatchConnectionFactory {
new Thread(read).start();
}
public void createOutgoingConnection(TransportId t, ContactId c,
public void createOutgoingConnection(TransportIndex i, ContactId c,
BatchTransportWriter w) {
final OutgoingBatchConnection conn = new OutgoingBatchConnection(
connWriterFactory, db, protoWriterFactory, t, c, w);
connWriterFactory, db, protoWriterFactory, i, c, w);
Runnable write = new Runnable() {
public void run() {
conn.write();

View File

@@ -6,7 +6,6 @@ import java.util.logging.Logger;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.FormatException;
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.protocol.Ack;
@@ -14,6 +13,7 @@ import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.BatchTransportReader;
import net.sf.briar.api.transport.ConnectionReader;
@@ -27,19 +27,19 @@ class IncomingBatchConnection {
private final ConnectionReaderFactory connFactory;
private final DatabaseComponent db;
private final ProtocolReaderFactory protoFactory;
private final TransportId transportId;
private final TransportIndex transportIndex;
private final ContactId contactId;
private final BatchTransportReader reader;
private final byte[] encryptedIv;
IncomingBatchConnection(ConnectionReaderFactory connFactory,
DatabaseComponent db, ProtocolReaderFactory protoFactory,
TransportId transportId, ContactId contactId,
TransportIndex transportIndex, ContactId contactId,
BatchTransportReader reader, byte[] encryptedIv) {
this.connFactory = connFactory;
this.db = db;
this.protoFactory = protoFactory;
this.transportId = transportId;
this.transportIndex = transportIndex;
this.contactId = contactId;
this.reader = reader;
this.encryptedIv = encryptedIv;
@@ -49,7 +49,8 @@ class IncomingBatchConnection {
try {
byte[] secret = db.getSharedSecret(contactId);
ConnectionReader conn = connFactory.createConnectionReader(
reader.getInputStream(), transportId, encryptedIv, secret);
reader.getInputStream(), transportIndex, encryptedIv,
secret);
ProtocolReader proto = protoFactory.createProtocolReader(
conn.getInputStream());
// Read packets until EOF

View File

@@ -8,9 +8,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
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.DbException;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.protocol.writers.AckWriter;
import net.sf.briar.api.protocol.writers.BatchWriter;
import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
@@ -28,18 +28,18 @@ class OutgoingBatchConnection {
private final ConnectionWriterFactory connFactory;
private final DatabaseComponent db;
private final ProtocolWriterFactory protoFactory;
private final TransportId transportId;
private final TransportIndex transportIndex;
private final ContactId contactId;
private final BatchTransportWriter writer;
OutgoingBatchConnection(ConnectionWriterFactory connFactory,
DatabaseComponent db, ProtocolWriterFactory protoFactory,
TransportId transportId, ContactId contactId,
TransportIndex transportIndex, ContactId contactId,
BatchTransportWriter writer) {
this.connFactory = connFactory;
this.db = db;
this.protoFactory = protoFactory;
this.transportId = transportId;
this.transportIndex = transportIndex;
this.contactId = contactId;
this.writer = writer;
}
@@ -47,10 +47,10 @@ class OutgoingBatchConnection {
void write() {
try {
byte[] secret = db.getSharedSecret(contactId);
long connection = db.getConnectionNumber(contactId, transportId);
long connection = db.getConnectionNumber(contactId, transportIndex);
ConnectionWriter conn = connFactory.createConnectionWriter(
writer.getOutputStream(), writer.getCapacity(), transportId,
connection, secret);
writer.getOutputStream(), writer.getCapacity(),
transportIndex, connection, secret);
OutputStream out = conn.getOutputStream();
// There should be enough space for a packet
long capacity = conn.getRemainingCapacity();

View File

@@ -3,10 +3,10 @@ package net.sf.briar.transport.stream;
import java.io.IOException;
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.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.ConnectionReader;
import net.sf.briar.api.transport.ConnectionReaderFactory;
@@ -21,11 +21,12 @@ public class IncomingStreamConnection extends StreamConnection {
IncomingStreamConnection(ConnectionReaderFactory connReaderFactory,
ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
ProtocolReaderFactory protoReaderFactory,
ProtocolWriterFactory protoWriterFactory, TransportId transportId,
ContactId contactId, StreamTransportConnection connection,
ProtocolWriterFactory protoWriterFactory,
TransportIndex transportIndex, ContactId contactId,
StreamTransportConnection connection,
byte[] encryptedIv) {
super(connReaderFactory, connWriterFactory, db, protoReaderFactory,
protoWriterFactory, transportId, contactId, connection);
protoWriterFactory, transportIndex, contactId, connection);
this.encryptedIv = encryptedIv;
}
@@ -34,7 +35,8 @@ public class IncomingStreamConnection extends StreamConnection {
IOException {
byte[] secret = db.getSharedSecret(contactId);
return connReaderFactory.createConnectionReader(
connection.getInputStream(), transportId, encryptedIv, secret);
connection.getInputStream(), transportIndex, encryptedIv,
secret);
}
@Override
@@ -42,7 +44,7 @@ public class IncomingStreamConnection extends StreamConnection {
IOException {
byte[] secret = db.getSharedSecret(contactId);
return connWriterFactory.createConnectionWriter(
connection.getOutputStream(), Long.MAX_VALUE, transportId,
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
encryptedIv, secret);
}
}

View File

@@ -3,10 +3,10 @@ package net.sf.briar.transport.stream;
import java.io.IOException;
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.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.ConnectionReader;
import net.sf.briar.api.transport.ConnectionReaderFactory;
@@ -21,22 +21,25 @@ public class OutgoingStreamConnection extends StreamConnection {
OutgoingStreamConnection(ConnectionReaderFactory connReaderFactory,
ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
ProtocolReaderFactory protoReaderFactory,
ProtocolWriterFactory protoWriterFactory, TransportId transportId,
ContactId contactId, StreamTransportConnection connection) {
ProtocolWriterFactory protoWriterFactory,
TransportIndex transportIndex, ContactId contactId,
StreamTransportConnection connection) {
super(connReaderFactory, connWriterFactory, db, protoReaderFactory,
protoWriterFactory, transportId, contactId, connection);
protoWriterFactory, transportIndex, contactId, connection);
}
@Override
protected ConnectionReader createConnectionReader() throws DbException,
IOException {
synchronized(this) {
if(connectionNum == -1L)
connectionNum = db.getConnectionNumber(contactId, transportId);
if(connectionNum == -1L) {
connectionNum = db.getConnectionNumber(contactId,
transportIndex);
}
}
byte[] secret = db.getSharedSecret(contactId);
return connReaderFactory.createConnectionReader(
connection.getInputStream(), transportId, connectionNum,
connection.getInputStream(), transportIndex, connectionNum,
secret);
}
@@ -44,12 +47,14 @@ public class OutgoingStreamConnection extends StreamConnection {
protected ConnectionWriter createConnectionWriter() throws DbException,
IOException {
synchronized(this) {
if(connectionNum == -1L)
connectionNum = db.getConnectionNumber(contactId, transportId);
if(connectionNum == -1L) {
connectionNum = db.getConnectionNumber(contactId,
transportIndex);
}
}
byte[] secret = db.getSharedSecret(contactId);
return connWriterFactory.createConnectionWriter(
connection.getOutputStream(), Long.MAX_VALUE, transportId,
connection.getOutputStream(), Long.MAX_VALUE, transportIndex,
connectionNum, secret);
}
}

View File

@@ -12,16 +12,15 @@ import java.util.logging.Logger;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.FormatException;
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.db.event.BatchReceivedEvent;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
import net.sf.briar.api.db.event.MessagesAddedEvent;
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
import net.sf.briar.api.db.event.TransportsUpdatedEvent;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.MessageId;
@@ -30,6 +29,7 @@ import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportIndex;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.writers.AckWriter;
import net.sf.briar.api.protocol.writers.BatchWriter;
@@ -56,7 +56,7 @@ abstract class StreamConnection implements DatabaseListener {
protected final DatabaseComponent db;
protected final ProtocolReaderFactory protoReaderFactory;
protected final ProtocolWriterFactory protoWriterFactory;
protected final TransportId transportId;
protected final TransportIndex transportIndex;
protected final ContactId contactId;
protected final StreamTransportConnection connection;
@@ -69,14 +69,15 @@ abstract class StreamConnection implements DatabaseListener {
StreamConnection(ConnectionReaderFactory connReaderFactory,
ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
ProtocolReaderFactory protoReaderFactory,
ProtocolWriterFactory protoWriterFactory, TransportId transportId,
ContactId contactId, StreamTransportConnection connection) {
ProtocolWriterFactory protoWriterFactory,
TransportIndex transportIndex, ContactId contactId,
StreamTransportConnection connection) {
this.connReaderFactory = connReaderFactory;
this.connWriterFactory = connWriterFactory;
this.db = db;
this.protoReaderFactory = protoReaderFactory;
this.protoWriterFactory = protoWriterFactory;
this.transportId = transportId;
this.transportIndex = transportIndex;
this.contactId = contactId;
this.connection = connection;
}
@@ -108,7 +109,7 @@ abstract class StreamConnection implements DatabaseListener {
writerFlags |= Flags.SUBSCRIPTIONS_UPDATED;
notifyAll();
}
} else if(e instanceof TransportsUpdatedEvent) {
} else if(e instanceof LocalTransportsUpdatedEvent) {
writerFlags |= Flags.TRANSPORTS_UPDATED;
notifyAll();
}

View File

@@ -1,9 +1,9 @@
package net.sf.briar.transport.stream;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportId;
import net.sf.briar.api.db.DatabaseComponent;
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.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionWriterFactory;
@@ -32,11 +32,11 @@ public class StreamConnectionFactoryImpl implements StreamConnectionFactory {
this.protoWriterFactory = protoWriterFactory;
}
public void createIncomingConnection(TransportId t, ContactId c,
public void createIncomingConnection(TransportIndex i, ContactId c,
StreamTransportConnection s, byte[] encryptedIv) {
final StreamConnection conn = new IncomingStreamConnection(
connReaderFactory, connWriterFactory, db, protoReaderFactory,
protoWriterFactory, t, c, s, encryptedIv);
protoWriterFactory, i, c, s, encryptedIv);
Runnable write = new Runnable() {
public void run() {
conn.write();
@@ -51,11 +51,11 @@ public class StreamConnectionFactoryImpl implements StreamConnectionFactory {
new Thread(read).start();
}
public void createOutgoingConnection(TransportId t, ContactId c,
public void createOutgoingConnection(TransportIndex i, ContactId c,
StreamTransportConnection s) {
final StreamConnection conn = new OutgoingStreamConnection(
connReaderFactory, connWriterFactory, db, protoReaderFactory,
protoWriterFactory, t, c, s);
protoWriterFactory, i, c, s);
Runnable write = new Runnable() {
public void run() {
conn.write();