mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Transport properties client. #229
This commit is contained in:
@@ -10,6 +10,7 @@ import org.briarproject.api.crypto.StreamDecrypterFactory;
|
||||
import org.briarproject.api.crypto.StreamEncrypterFactory;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -57,4 +58,9 @@ public class CryptoModule extends AbstractModule {
|
||||
lifecycleManager.registerForShutdown(cryptoExecutor);
|
||||
return cryptoExecutor;
|
||||
}
|
||||
|
||||
@Provides
|
||||
SecureRandom getSecureRandom(CryptoComponent crypto) {
|
||||
return crypto.getSecureRandom();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.db;
|
||||
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
@@ -10,6 +9,7 @@ import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.db;
|
||||
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
@@ -35,6 +34,7 @@ import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.lifecycle.ShutdownManager;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.sync.Ack;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.briarproject.db;
|
||||
|
||||
import org.briarproject.api.settings.Settings;
|
||||
|
||||
interface DatabaseConstants {
|
||||
|
||||
/**
|
||||
@@ -8,4 +10,34 @@ interface DatabaseConstants {
|
||||
* limit is reached, additional offers will not be stored.
|
||||
*/
|
||||
int MAX_OFFERED_MESSAGES = 1000;
|
||||
|
||||
/**
|
||||
* The namespace of the {@link Settings Settings}
|
||||
* where the database schema version is stored.
|
||||
*/
|
||||
String DB_SETTINGS_NAMESPACE = "db";
|
||||
|
||||
/**
|
||||
* The {@link Settings Settings} key under which the
|
||||
* database schema version is stored.
|
||||
*/
|
||||
String SCHEMA_VERSION_KEY = "schemaVersion";
|
||||
|
||||
/**
|
||||
* The {@link Settings Settings} key under which the
|
||||
* minimum supported database schema version is stored.
|
||||
*/
|
||||
String MIN_SCHEMA_VERSION_KEY = "minSchemaVersion";
|
||||
|
||||
/**
|
||||
* The namespace of the {@link Settings Settings}
|
||||
* where the unique device ID is stored.
|
||||
*/
|
||||
String DEVICE_SETTINGS_NAMESPACE = "device";
|
||||
|
||||
/**
|
||||
* The {@link Settings Settings} key under which the
|
||||
* unique device ID is stored.
|
||||
*/
|
||||
String DEVICE_ID_KEY = "deviceId";
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.lifecycle.ShutdownManager;
|
||||
import org.briarproject.system.SystemClock;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Connection;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -39,13 +40,12 @@ public class DatabaseModule extends AbstractModule {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
// Nothing to bind
|
||||
}
|
||||
protected void configure() {}
|
||||
|
||||
@Provides @Singleton
|
||||
Database<Connection> getDatabase(DatabaseConfig config) {
|
||||
return new H2Database(config, new SystemClock());
|
||||
Database<Connection> getDatabase(DatabaseConfig config,
|
||||
SecureRandom random, Clock clock) {
|
||||
return new H2Database(config, random, clock);
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
@@ -25,13 +26,13 @@ class H2Database extends JdbcDatabase {
|
||||
private final String url;
|
||||
|
||||
@Inject
|
||||
H2Database(DatabaseConfig config, Clock clock) {
|
||||
super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, clock);
|
||||
H2Database(DatabaseConfig config, SecureRandom random, Clock clock) {
|
||||
super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, random, clock);
|
||||
this.config = config;
|
||||
File dir = config.getDatabaseDirectory();
|
||||
String path = new File(dir, "db").getAbsolutePath();
|
||||
url = "jdbc:h2:split:" + path + ";CIPHER=AES;MULTI_THREADED=1"
|
||||
+ ";DB_CLOSE_ON_EXIT=false";
|
||||
+ ";WRITE_DELAY=0;DB_CLOSE_ON_EXIT=false";
|
||||
}
|
||||
|
||||
public boolean open() throws DbException {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.db;
|
||||
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
@@ -12,6 +12,7 @@ import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
@@ -24,7 +25,9 @@ import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.IncomingKeys;
|
||||
import org.briarproject.api.transport.OutgoingKeys;
|
||||
import org.briarproject.api.transport.TransportKeys;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -53,6 +56,11 @@ import static org.briarproject.api.sync.SyncConstants.MAX_SUBSCRIPTIONS;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.INVALID;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.UNKNOWN;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.VALID;
|
||||
import static org.briarproject.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.db.DatabaseConstants.DEVICE_ID_KEY;
|
||||
import static org.briarproject.db.DatabaseConstants.DEVICE_SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.db.DatabaseConstants.MIN_SCHEMA_VERSION_KEY;
|
||||
import static org.briarproject.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||
import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
|
||||
|
||||
/**
|
||||
@@ -61,8 +69,8 @@ import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
|
||||
*/
|
||||
abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
private static final int SCHEMA_VERSION = 17;
|
||||
private static final int MIN_SCHEMA_VERSION = 17;
|
||||
private static final int SCHEMA_VERSION = 18;
|
||||
private static final int MIN_SCHEMA_VERSION = 18;
|
||||
|
||||
private static final String CREATE_SETTINGS =
|
||||
"CREATE TABLE settings"
|
||||
@@ -244,6 +252,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
// Different database libraries use different names for certain types
|
||||
private final String hashType, binaryType, counterType, secretType;
|
||||
private final SecureRandom random;
|
||||
private final Clock clock;
|
||||
|
||||
private final LinkedList<Connection> connections =
|
||||
@@ -260,11 +269,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private final Condition connectionsChanged = connectionsLock.newCondition();
|
||||
|
||||
JdbcDatabase(String hashType, String binaryType, String counterType,
|
||||
String secretType, Clock clock) {
|
||||
String secretType, SecureRandom random, Clock clock) {
|
||||
this.hashType = hashType;
|
||||
this.binaryType = binaryType;
|
||||
this.counterType = counterType;
|
||||
this.secretType = secretType;
|
||||
this.random = random;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -283,6 +293,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
} else {
|
||||
createTables(txn);
|
||||
storeSchemaVersion(txn);
|
||||
storeDeviceId(txn);
|
||||
}
|
||||
commitTransaction(txn);
|
||||
} catch (DbException e) {
|
||||
@@ -292,19 +303,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
private boolean checkSchemaVersion(Connection txn) throws DbException {
|
||||
Settings s = getSettings(txn, "db");
|
||||
int schemaVersion = s.getInt("schemaVersion", -1);
|
||||
Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||
int schemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1);
|
||||
if (schemaVersion == SCHEMA_VERSION) return true;
|
||||
if (schemaVersion < MIN_SCHEMA_VERSION) return false;
|
||||
int minSchemaVersion = s.getInt("minSchemaVersion", -1);
|
||||
int minSchemaVersion = s.getInt(MIN_SCHEMA_VERSION_KEY, -1);
|
||||
return SCHEMA_VERSION >= minSchemaVersion;
|
||||
}
|
||||
|
||||
private void storeSchemaVersion(Connection txn) throws DbException {
|
||||
Settings s = new Settings();
|
||||
s.putInt("schemaVersion", SCHEMA_VERSION);
|
||||
s.putInt("minSchemaVersion", MIN_SCHEMA_VERSION);
|
||||
mergeSettings(txn, s, "db");
|
||||
s.putInt(SCHEMA_VERSION_KEY, SCHEMA_VERSION);
|
||||
s.putInt(MIN_SCHEMA_VERSION_KEY, MIN_SCHEMA_VERSION);
|
||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||
}
|
||||
|
||||
private void storeDeviceId(Connection txn) throws DbException {
|
||||
byte[] deviceId = new byte[UniqueId.LENGTH];
|
||||
random.nextBytes(deviceId);
|
||||
Settings s = new Settings();
|
||||
s.put(DEVICE_ID_KEY, StringUtils.toHexString(deviceId));
|
||||
mergeSettings(txn, s, DEVICE_SETTINGS_NAMESPACE);
|
||||
}
|
||||
|
||||
private void tryToClose(ResultSet rs) {
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.briarproject.api.system.Clock;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.briarproject.forum.ForumManagerImpl.CLIENT_ID;
|
||||
|
||||
public class ForumModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
@@ -26,16 +28,14 @@ public class ForumModule extends AbstractModule {
|
||||
|
||||
@Provides @Singleton
|
||||
ForumPostValidator getValidator(ValidationManager validationManager,
|
||||
ForumManager forumManager, CryptoComponent crypto,
|
||||
BdfReaderFactory bdfReaderFactory,
|
||||
CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
|
||||
BdfWriterFactory bdfWriterFactory,
|
||||
ObjectReader<Author> authorReader, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
ForumPostValidator validator = new ForumPostValidator(crypto,
|
||||
bdfReaderFactory, bdfWriterFactory, authorReader,
|
||||
metadataEncoder, clock);
|
||||
validationManager.registerMessageValidator(forumManager.getClientId(),
|
||||
validator);
|
||||
validationManager.registerMessageValidator(CLIENT_ID, validator);
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.briarproject.invitation;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
@@ -17,7 +15,6 @@ import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -28,7 +25,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
@@ -47,17 +43,12 @@ class AliceConnector extends Connector {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
Map<TransportId, TransportProperties> localProps,
|
||||
PseudoRandom random) {
|
||||
ContactManager contactManager, Clock clock, ConnectorGroup group,
|
||||
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
|
||||
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
|
||||
streamWriterFactory, authorFactory, groupFactory,
|
||||
keyManager, connectionManager, contactManager,
|
||||
transportPropertyManager, clock, reuseConnection, group,
|
||||
plugin, localAuthor, localProps, random);
|
||||
streamWriterFactory, authorFactory, groupFactory, keyManager,
|
||||
connectionManager, contactManager, clock, group, plugin,
|
||||
localAuthor, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,20 +143,14 @@ class AliceConnector extends Connector {
|
||||
// Derive the invitation nonces
|
||||
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
|
||||
byte[] bobNonce = crypto.deriveSignatureNonce(master, false);
|
||||
// Exchange pseudonyms, signed nonces, timestamps and transports
|
||||
// Exchange pseudonyms, signed nonces, and timestamps
|
||||
Author remoteAuthor;
|
||||
long remoteTimestamp;
|
||||
Map<TransportId, TransportProperties> remoteProps;
|
||||
boolean remoteReuseConnection;
|
||||
try {
|
||||
sendPseudonym(w, aliceNonce);
|
||||
sendTimestamp(w, localTimestamp);
|
||||
sendTransportProperties(w);
|
||||
sendConfirmation(w, reuseConnection);
|
||||
remoteAuthor = receivePseudonym(r, bobNonce);
|
||||
remoteTimestamp = receiveTimestamp(r);
|
||||
remoteProps = receiveTransportProperties(r);
|
||||
remoteReuseConnection = receiveConfirmation(r);
|
||||
// Close the outgoing stream and expect EOF on the incoming stream
|
||||
w.close();
|
||||
if (!r.eof()) LOG.warning("Unexpected data at end of connection");
|
||||
@@ -182,18 +167,17 @@ class AliceConnector extends Connector {
|
||||
}
|
||||
// The agreed timestamp is the minimum of the peers' timestamps
|
||||
long timestamp = Math.min(localTimestamp, remoteTimestamp);
|
||||
// Add the contact and store the transports
|
||||
// Add the contact
|
||||
try {
|
||||
addContact(remoteAuthor, remoteProps, master, timestamp, true);
|
||||
addContact(remoteAuthor, master, timestamp, true);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
tryToClose(conn, true);
|
||||
group.pseudonymExchangeFailed();
|
||||
return;
|
||||
}
|
||||
// Reuse the connection as a transport connection if both peers agree
|
||||
if (reuseConnection && remoteReuseConnection) reuseConnection(conn);
|
||||
else tryToClose(conn, false);
|
||||
// Reuse the connection as a transport connection
|
||||
reuseConnection(conn);
|
||||
// Pseudonym exchange succeeded
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(pluginName + " pseudonym exchange succeeded");
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.briarproject.invitation;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
@@ -17,7 +15,6 @@ import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -28,7 +25,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
@@ -47,17 +43,12 @@ class BobConnector extends Connector {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
Map<TransportId, TransportProperties> localProps,
|
||||
PseudoRandom random) {
|
||||
ContactManager contactManager, Clock clock, ConnectorGroup group,
|
||||
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
|
||||
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
|
||||
streamWriterFactory, authorFactory, groupFactory,
|
||||
keyManager, connectionManager, contactManager,
|
||||
transportPropertyManager, clock, reuseConnection, group,
|
||||
plugin, localAuthor, localProps, random);
|
||||
streamWriterFactory, authorFactory, groupFactory, keyManager,
|
||||
connectionManager, contactManager, clock, group, plugin,
|
||||
localAuthor, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,20 +143,14 @@ class BobConnector extends Connector {
|
||||
// Derive the nonces
|
||||
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
|
||||
byte[] bobNonce = crypto.deriveSignatureNonce(master, false);
|
||||
// Exchange pseudonyms, signed nonces, timestamps and transports
|
||||
// Exchange pseudonyms, signed nonces and timestamps
|
||||
Author remoteAuthor;
|
||||
long remoteTimestamp;
|
||||
Map<TransportId, TransportProperties> remoteProps;
|
||||
boolean remoteReuseConnection;
|
||||
try {
|
||||
remoteAuthor = receivePseudonym(r, aliceNonce);
|
||||
remoteTimestamp = receiveTimestamp(r);
|
||||
remoteProps = receiveTransportProperties(r);
|
||||
remoteReuseConnection = receiveConfirmation(r);
|
||||
sendPseudonym(w, bobNonce);
|
||||
sendTimestamp(w, localTimestamp);
|
||||
sendTransportProperties(w);
|
||||
sendConfirmation(w, reuseConnection);
|
||||
// Close the outgoing stream and expect EOF on the incoming stream
|
||||
w.close();
|
||||
if (!r.eof()) LOG.warning("Unexpected data at end of connection");
|
||||
@@ -182,18 +167,17 @@ class BobConnector extends Connector {
|
||||
}
|
||||
// The agreed timestamp is the minimum of the peers' timestamps
|
||||
long timestamp = Math.min(localTimestamp, remoteTimestamp);
|
||||
// Add the contact and store the transports
|
||||
// Add the contact
|
||||
try {
|
||||
addContact(remoteAuthor, remoteProps, master, timestamp, false);
|
||||
addContact(remoteAuthor, master, timestamp, false);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
tryToClose(conn, true);
|
||||
group.pseudonymExchangeFailed();
|
||||
return;
|
||||
}
|
||||
// Reuse the connection as a transport connection if both peers agree
|
||||
if (reuseConnection && remoteReuseConnection) reuseConnection(conn);
|
||||
else tryToClose(conn, false);
|
||||
// Reuse the connection as a transport connection
|
||||
reuseConnection(conn);
|
||||
// Pseudonym exchange succeeded
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(pluginName + " pseudonym exchange succeeded");
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.briarproject.invitation;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
@@ -23,7 +22,6 @@ import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -33,16 +31,10 @@ import org.briarproject.api.transport.StreamWriterFactory;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_TRANSPORT_ID_LENGTH;
|
||||
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||
@@ -64,13 +56,10 @@ abstract class Connector extends Thread {
|
||||
protected final KeyManager keyManager;
|
||||
protected final ConnectionManager connectionManager;
|
||||
protected final ContactManager contactManager;
|
||||
protected final TransportPropertyManager transportPropertyManager;
|
||||
protected final Clock clock;
|
||||
protected final boolean reuseConnection;
|
||||
protected final ConnectorGroup group;
|
||||
protected final DuplexPlugin plugin;
|
||||
protected final LocalAuthor localAuthor;
|
||||
protected final Map<TransportId, TransportProperties> localProps;
|
||||
protected final PseudoRandom random;
|
||||
protected final String pluginName;
|
||||
|
||||
@@ -87,12 +76,8 @@ abstract class Connector extends Thread {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
Map<TransportId, TransportProperties> localProps,
|
||||
PseudoRandom random) {
|
||||
ContactManager contactManager, Clock clock, ConnectorGroup group,
|
||||
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
|
||||
super("Connector");
|
||||
this.crypto = crypto;
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
@@ -104,13 +89,10 @@ abstract class Connector extends Thread {
|
||||
this.keyManager = keyManager;
|
||||
this.connectionManager = connectionManager;
|
||||
this.contactManager = contactManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.reuseConnection = reuseConnection;
|
||||
this.group = group;
|
||||
this.plugin = plugin;
|
||||
this.localAuthor = localAuthor;
|
||||
this.localProps = localProps;
|
||||
this.random = random;
|
||||
pluginName = plugin.getClass().getName();
|
||||
keyPair = crypto.generateAgreementKeyPair();
|
||||
@@ -233,57 +215,14 @@ abstract class Connector extends Thread {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
protected void sendTransportProperties(BdfWriter w) throws IOException {
|
||||
w.writeListStart();
|
||||
for (Entry<TransportId, TransportProperties> e :
|
||||
localProps.entrySet()) {
|
||||
w.writeString(e.getKey().getString());
|
||||
w.writeDictionary(e.getValue());
|
||||
}
|
||||
w.writeListEnd();
|
||||
w.flush();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(pluginName + " sent transport properties");
|
||||
}
|
||||
|
||||
protected Map<TransportId, TransportProperties> receiveTransportProperties(
|
||||
BdfReader r) throws IOException {
|
||||
Map<TransportId, TransportProperties> remoteProps =
|
||||
new HashMap<TransportId, TransportProperties>();
|
||||
r.readListStart();
|
||||
while (!r.hasListEnd()) {
|
||||
String idString = r.readString(MAX_TRANSPORT_ID_LENGTH);
|
||||
if (idString.length() == 0) throw new FormatException();
|
||||
TransportId id = new TransportId(idString);
|
||||
Map<String, String> p = new HashMap<String, String>();
|
||||
r.readDictionaryStart();
|
||||
for (int i = 0; !r.hasDictionaryEnd(); i++) {
|
||||
if (i == MAX_PROPERTIES_PER_TRANSPORT)
|
||||
throw new FormatException();
|
||||
String key = r.readString(MAX_PROPERTY_LENGTH);
|
||||
String value = r.readString(MAX_PROPERTY_LENGTH);
|
||||
p.put(key, value);
|
||||
}
|
||||
r.readDictionaryEnd();
|
||||
remoteProps.put(id, new TransportProperties(p));
|
||||
}
|
||||
r.readListEnd();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(pluginName + " received transport properties");
|
||||
return remoteProps;
|
||||
}
|
||||
|
||||
protected void addContact(Author remoteAuthor,
|
||||
Map<TransportId, TransportProperties> remoteProps, SecretKey master,
|
||||
protected ContactId addContact(Author remoteAuthor, SecretKey master,
|
||||
long timestamp, boolean alice) throws DbException {
|
||||
// Add the contact to the database
|
||||
contactId = contactManager.addContact(remoteAuthor,
|
||||
localAuthor.getId());
|
||||
// Store the remote transport properties
|
||||
transportPropertyManager.setRemoteProperties(contactId, remoteProps);
|
||||
// Derive transport keys for each transport shared with the contact
|
||||
keyManager.addContact(contactId, remoteProps.keySet(), master,
|
||||
timestamp, alice);
|
||||
// Derive transport keys
|
||||
keyManager.addContact(contactId, master, timestamp, alice);
|
||||
return contactId;
|
||||
}
|
||||
|
||||
protected void tryToClose(DuplexTransportConnection conn,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.briarproject.invitation;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
@@ -19,7 +17,6 @@ import org.briarproject.api.invitation.InvitationTask;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -28,7 +25,6 @@ import org.briarproject.api.transport.StreamWriterFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -57,12 +53,10 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
private final ConnectionManager connectionManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final ContactManager contactManager;
|
||||
private final TransportPropertyManager transportPropertyManager;
|
||||
private final Clock clock;
|
||||
private final PluginManager pluginManager;
|
||||
private final AuthorId localAuthorId;
|
||||
private final int localInvitationCode, remoteInvitationCode;
|
||||
private final boolean reuseConnection;
|
||||
private final Collection<InvitationListener> listeners;
|
||||
private final AtomicBoolean connected;
|
||||
private final CountDownLatch localConfirmationLatch;
|
||||
@@ -83,10 +77,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
IdentityManager identityManager, ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
PluginManager pluginManager, AuthorId localAuthorId,
|
||||
int localInvitationCode, int remoteInvitationCode,
|
||||
boolean reuseConnection) {
|
||||
Clock clock, PluginManager pluginManager, AuthorId localAuthorId,
|
||||
int localInvitationCode, int remoteInvitationCode) {
|
||||
super("ConnectorGroup");
|
||||
this.crypto = crypto;
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
@@ -99,13 +91,11 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
this.connectionManager = connectionManager;
|
||||
this.identityManager = identityManager;
|
||||
this.contactManager = contactManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.pluginManager = pluginManager;
|
||||
this.localAuthorId = localAuthorId;
|
||||
this.localInvitationCode = localInvitationCode;
|
||||
this.remoteInvitationCode = remoteInvitationCode;
|
||||
this.reuseConnection = reuseConnection;
|
||||
listeners = new CopyOnWriteArrayList<InvitationListener>();
|
||||
connected = new AtomicBoolean(false);
|
||||
localConfirmationLatch = new CountDownLatch(1);
|
||||
@@ -136,11 +126,9 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
@Override
|
||||
public void run() {
|
||||
LocalAuthor localAuthor;
|
||||
Map<TransportId, TransportProperties> localProps;
|
||||
// Load the local pseudonym and transport properties
|
||||
// Load the local pseudonym
|
||||
try {
|
||||
localAuthor = identityManager.getLocalAuthor(localAuthorId);
|
||||
localProps = transportPropertyManager.getLocalProperties();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
lock.lock();
|
||||
@@ -157,15 +145,13 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
// Alice is the party with the smaller invitation code
|
||||
if (localInvitationCode < remoteInvitationCode) {
|
||||
for (DuplexPlugin plugin : pluginManager.getInvitationPlugins()) {
|
||||
Connector c = createAliceConnector(plugin, localAuthor,
|
||||
localProps);
|
||||
Connector c = createAliceConnector(plugin, localAuthor);
|
||||
connectors.add(c);
|
||||
c.start();
|
||||
}
|
||||
} else {
|
||||
for (DuplexPlugin plugin: pluginManager.getInvitationPlugins()) {
|
||||
Connector c = createBobConnector(plugin, localAuthor,
|
||||
localProps);
|
||||
Connector c = createBobConnector(plugin, localAuthor);
|
||||
connectors.add(c);
|
||||
c.start();
|
||||
}
|
||||
@@ -190,27 +176,23 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
}
|
||||
|
||||
private Connector createAliceConnector(DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
Map<TransportId, TransportProperties> localProps) {
|
||||
LocalAuthor localAuthor) {
|
||||
PseudoRandom random = crypto.getPseudoRandom(localInvitationCode,
|
||||
remoteInvitationCode);
|
||||
return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, contactManager,
|
||||
transportPropertyManager, clock, reuseConnection, this, plugin,
|
||||
localAuthor, localProps, random);
|
||||
clock, this, plugin, localAuthor, random);
|
||||
}
|
||||
|
||||
private Connector createBobConnector(DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
Map<TransportId, TransportProperties> localProps) {
|
||||
LocalAuthor localAuthor) {
|
||||
PseudoRandom random = crypto.getPseudoRandom(remoteInvitationCode,
|
||||
localInvitationCode);
|
||||
return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, contactManager,
|
||||
transportPropertyManager, clock, reuseConnection, this, plugin,
|
||||
localAuthor, localProps, random);
|
||||
clock, this, plugin, localAuthor, random);
|
||||
}
|
||||
|
||||
public void localConfirmationSucceeded() {
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.api.invitation.InvitationTask;
|
||||
import org.briarproject.api.invitation.InvitationTaskFactory;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -33,7 +32,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
private final ConnectionManager connectionManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final ContactManager contactManager;
|
||||
private final TransportPropertyManager transportPropertyManager;
|
||||
private final Clock clock;
|
||||
private final PluginManager pluginManager;
|
||||
|
||||
@@ -45,7 +43,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
IdentityManager identityManager, ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
Clock clock, PluginManager pluginManager) {
|
||||
this.crypto = crypto;
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
@@ -58,17 +55,16 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
this.connectionManager = connectionManager;
|
||||
this.identityManager = identityManager;
|
||||
this.contactManager = contactManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.pluginManager = pluginManager;
|
||||
}
|
||||
|
||||
public InvitationTask createTask(AuthorId localAuthorId, int localCode,
|
||||
int remoteCode, boolean reuseConnection) {
|
||||
int remoteCode) {
|
||||
return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, identityManager,
|
||||
contactManager, transportPropertyManager, clock, pluginManager,
|
||||
localAuthorId, localCode, remoteCode, reuseConnection);
|
||||
contactManager, clock, pluginManager, localAuthorId, localCode,
|
||||
remoteCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.briarproject.api.system.Clock;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.briarproject.messaging.MessagingManagerImpl.CLIENT_ID;
|
||||
|
||||
public class MessagingModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
@@ -22,14 +24,11 @@ public class MessagingModule extends AbstractModule {
|
||||
|
||||
@Provides @Singleton
|
||||
PrivateMessageValidator getValidator(ValidationManager validationManager,
|
||||
MessagingManager messagingManager,
|
||||
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
PrivateMessageValidator validator = new PrivateMessageValidator(
|
||||
bdfReaderFactory, metadataEncoder, clock);
|
||||
validationManager.registerMessageValidator(
|
||||
messagingManager.getClientId(),
|
||||
validator);
|
||||
validationManager.registerMessageValidator(CLIENT_ID, validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,8 +73,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
ioExecutor.execute(new ManageOutgoingDuplexConnection(c, t, d));
|
||||
}
|
||||
|
||||
private byte[] readTag(TransportId t, TransportConnectionReader r)
|
||||
throws IOException {
|
||||
private byte[] readTag(TransportConnectionReader r) throws IOException {
|
||||
// Read the tag
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
InputStream in = r.getInputStream();
|
||||
@@ -128,7 +127,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
// Read and recognise the tag
|
||||
StreamContext ctx;
|
||||
try {
|
||||
byte[] tag = readTag(transportId, reader);
|
||||
byte[] tag = readTag(reader);
|
||||
ctx = keyManager.getStreamContext(transportId, tag);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -228,7 +227,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
// Read and recognise the tag
|
||||
StreamContext ctx;
|
||||
try {
|
||||
byte[] tag = readTag(transportId, reader);
|
||||
byte[] tag = readTag(reader);
|
||||
ctx = keyManager.getStreamContext(transportId, tag);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -353,7 +352,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
// Read and recognise the tag
|
||||
StreamContext ctx;
|
||||
try {
|
||||
byte[] tag = readTag(transportId, reader);
|
||||
byte[] tag = readTag(reader);
|
||||
ctx = keyManager.getStreamContext(transportId, tag);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.briarproject.plugins;
|
||||
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
@@ -26,7 +24,9 @@ import org.briarproject.api.plugins.simplex.SimplexPlugin;
|
||||
import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
|
||||
import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
|
||||
import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.ui.UiCallback;
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.briarproject.plugins.tcp;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -8,10 +12,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
|
||||
class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
static final TransportId ID = new TransportId("lan");
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package org.briarproject.plugins.tcp;
|
||||
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.briarproject.plugins.tcp;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -8,10 +12,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
|
||||
class WanTcpPlugin extends TcpPlugin {
|
||||
|
||||
static final TransportId ID = new TransportId("wan");
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.briarproject.properties;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.briarproject.properties.TransportPropertyManagerImpl.CLIENT_ID;
|
||||
|
||||
public class PropertiesModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {}
|
||||
|
||||
@Provides @Singleton
|
||||
TransportPropertyValidator getValidator(ValidationManager validationManager,
|
||||
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
TransportPropertyValidator validator = new TransportPropertyValidator(
|
||||
bdfReaderFactory, metadataEncoder, clock);
|
||||
validationManager.registerMessageValidator(CLIENT_ID, validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
TransportPropertyManager getTransportPropertyManager(
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManagerImpl transportPropertyManager) {
|
||||
contactManager.registerAddContactHook(transportPropertyManager);
|
||||
contactManager.registerRemoveContactHook(transportPropertyManager);
|
||||
return transportPropertyManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
package org.briarproject.properties;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager.AddContactHook;
|
||||
import org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfReader;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
import org.briarproject.api.data.BdfWriter;
|
||||
import org.briarproject.api.data.BdfWriterFactory;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.data.MetadataParser;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.NoSuchSubscriptionException;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageFactory;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
|
||||
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
AddContactHook, RemoveContactHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
"673ea091673561e28f70122f6a8ea8f4"
|
||||
+ "97c3624b86fa07f785bb15f09fb87b4b"));
|
||||
|
||||
private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(TransportPropertyManagerImpl.class.getName());
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final GroupFactory groupFactory;
|
||||
private final MessageFactory messageFactory;
|
||||
private final BdfReaderFactory bdfReaderFactory;
|
||||
private final BdfWriterFactory bdfWriterFactory;
|
||||
private final MetadataEncoder metadataEncoder;
|
||||
private final MetadataParser metadataParser;
|
||||
private final Clock clock;
|
||||
private final Group localGroup;
|
||||
|
||||
/** Ensures isolation between database reads and writes. */
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
@Inject
|
||||
TransportPropertyManagerImpl(DatabaseComponent db, GroupFactory groupFactory,
|
||||
MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory,
|
||||
BdfWriterFactory bdfWriterFactory, MetadataEncoder metadataEncoder,
|
||||
MetadataParser metadataParser, Clock clock) {
|
||||
this.db = db;
|
||||
this.groupFactory = groupFactory;
|
||||
this.messageFactory = messageFactory;
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
this.bdfWriterFactory = bdfWriterFactory;
|
||||
this.metadataEncoder = metadataEncoder;
|
||||
this.metadataParser = metadataParser;
|
||||
this.clock = clock;
|
||||
localGroup = groupFactory.createGroup(CLIENT_ID,
|
||||
LOCAL_GROUP_DESCRIPTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(ContactId c) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(db.getContact(c));
|
||||
// Subscribe to the group and share it with the contact
|
||||
db.addGroup(g);
|
||||
db.addContactGroup(c, g);
|
||||
db.setVisibility(g.getId(), Collections.singletonList(c));
|
||||
// Copy the latest local properties into the group
|
||||
Map<TransportId, TransportProperties> local = getLocalProperties();
|
||||
for (Entry<TransportId, TransportProperties> e : local.entrySet())
|
||||
storeMessage(g.getId(), e.getKey(), e.getValue(), 0);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Group getContactGroup(Contact c) {
|
||||
AuthorId local = c.getLocalAuthorId();
|
||||
AuthorId remote = c.getAuthor().getId();
|
||||
byte[] descriptor = encodeGroupDescriptor(local, remote);
|
||||
return groupFactory.createGroup(CLIENT_ID, descriptor);
|
||||
}
|
||||
|
||||
private byte[] encodeGroupDescriptor(AuthorId local, AuthorId remote) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
BdfWriter w = bdfWriterFactory.createWriter(out);
|
||||
try {
|
||||
w.writeListStart();
|
||||
if (UniqueId.IdComparator.INSTANCE.compare(local, remote) < 0) {
|
||||
w.writeRaw(local.getBytes());
|
||||
w.writeRaw(remote.getBytes());
|
||||
} else {
|
||||
w.writeRaw(remote.getBytes());
|
||||
w.writeRaw(local.getBytes());
|
||||
}
|
||||
w.writeListEnd();
|
||||
} catch (IOException e) {
|
||||
// Shouldn't happen with ByteArrayOutputStream
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private void storeMessage(GroupId g, TransportId t, TransportProperties p,
|
||||
long version) throws DbException, IOException {
|
||||
byte[] body = encodeProperties(t, p, version);
|
||||
long now = clock.currentTimeMillis();
|
||||
Message m = messageFactory.createMessage(g, now, body);
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put("transportId", t.getString());
|
||||
d.put("version", version);
|
||||
d.put("local", true);
|
||||
db.addLocalMessage(m, CLIENT_ID, metadataEncoder.encode(d));
|
||||
}
|
||||
|
||||
private byte[] encodeProperties(TransportId t, TransportProperties p,
|
||||
long version) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
BdfWriter w = bdfWriterFactory.createWriter(out);
|
||||
try {
|
||||
// TODO: Device ID
|
||||
w.writeListStart();
|
||||
w.writeString(t.getString());
|
||||
w.writeInteger(version);
|
||||
w.writeDictionary(p);
|
||||
w.writeListEnd();
|
||||
} catch (IOException e) {
|
||||
// Shouldn't happen with ByteArrayOutputStream
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removingContact(ContactId c) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
db.removeGroup(getContactGroup(db.getContact(c)));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||
throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
// Find the latest local version for each transport
|
||||
Map<TransportId, Latest> latest =
|
||||
findLatest(localGroup.getId(), true);
|
||||
// Retrieve and decode the latest local properties
|
||||
Map<TransportId, TransportProperties> local =
|
||||
new HashMap<TransportId, TransportProperties>();
|
||||
for (Entry<TransportId, Latest> e : latest.entrySet()) {
|
||||
byte[] raw = db.getRawMessage(e.getValue().messageId);
|
||||
local.put(e.getKey(), decodeProperties(raw));
|
||||
}
|
||||
return Collections.unmodifiableMap(local);
|
||||
} catch (NoSuchSubscriptionException e) {
|
||||
// Local group doesn't exist - there are no local properties
|
||||
return Collections.emptyMap();
|
||||
} catch (IOException e) {
|
||||
throw new DbException(e);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<TransportId, Latest> findLatest(GroupId g, boolean local)
|
||||
throws DbException, FormatException {
|
||||
// TODO: Use metadata queries
|
||||
Map<TransportId, Latest> latest = new HashMap<TransportId, Latest>();
|
||||
Map<MessageId, Metadata> metadata = db.getMessageMetadata(g);
|
||||
for (Entry<MessageId, Metadata> e : metadata.entrySet()) {
|
||||
BdfDictionary mm = metadataParser.parse(e.getValue());
|
||||
if (mm.getBoolean("local") != local) continue;
|
||||
TransportId t = new TransportId(mm.getString("transportId"));
|
||||
long version = mm.getInteger("version");
|
||||
Latest l = latest.get(t);
|
||||
if (l == null || version > l.version)
|
||||
latest.put(t, new Latest(e.getKey(), version));
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
private TransportProperties decodeProperties(byte[] raw)
|
||||
throws IOException {
|
||||
TransportProperties p = new TransportProperties();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(raw,
|
||||
MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
|
||||
BdfReader r = bdfReaderFactory.createReader(in);
|
||||
// TODO: Device ID
|
||||
r.readListStart();
|
||||
r.skipString(); // Transport ID
|
||||
r.skipInteger(); // Version
|
||||
r.readDictionaryStart();
|
||||
while (!r.hasDictionaryEnd()) {
|
||||
String key = r.readString(MAX_PROPERTY_LENGTH);
|
||||
String value = r.readString(MAX_PROPERTY_LENGTH);
|
||||
p.put(key, value);
|
||||
}
|
||||
r.readDictionaryEnd();
|
||||
r.readListEnd();
|
||||
if (!r.eof()) throw new FormatException();
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProperties getLocalProperties(TransportId t)
|
||||
throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
// Find the latest local version
|
||||
Latest latest = findLatest(localGroup.getId(), true).get(t);
|
||||
if (latest == null) return null;
|
||||
// Retrieve and decode the latest local properties
|
||||
return decodeProperties(db.getRawMessage(latest.messageId));
|
||||
} catch (NoSuchSubscriptionException e) {
|
||||
// Local group doesn't exist - there are no local properties
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
throw new DbException(e);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||
TransportId t) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
Map<ContactId, TransportProperties> remote =
|
||||
new HashMap<ContactId, TransportProperties>();
|
||||
for (Contact c : db.getContacts()) {
|
||||
Group g = getContactGroup(c);
|
||||
// Find the latest remote version
|
||||
Latest latest = findLatest(g.getId(), false).get(t);
|
||||
if (latest != null) {
|
||||
// Retrieve and decode the latest remote properties
|
||||
byte[] raw = db.getRawMessage(latest.messageId);
|
||||
remote.put(c.getId(), decodeProperties(raw));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(remote);
|
||||
} catch (IOException e) {
|
||||
throw new DbException(e);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||
throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
// Create the local group if necessary
|
||||
db.addGroup(localGroup);
|
||||
// Merge the new properties with any existing properties
|
||||
Latest latest = findLatest(localGroup.getId(), true).get(t);
|
||||
if (latest != null) {
|
||||
byte[] raw = db.getRawMessage(latest.messageId);
|
||||
TransportProperties old = decodeProperties(raw);
|
||||
if (old.equals(p)) return; // Unchanged
|
||||
old.putAll(p);
|
||||
p = old;
|
||||
}
|
||||
// Store the merged properties in the local group
|
||||
long version = latest == null ? 0 : latest.version + 1;
|
||||
storeMessage(localGroup.getId(), t, p, version);
|
||||
// Store the merged properties in each contact's group
|
||||
for (Contact c : db.getContacts()) {
|
||||
Group g = getContactGroup(c);
|
||||
latest = findLatest(g.getId(), true).get(t);
|
||||
version = latest == null ? 0 : latest.version + 1;
|
||||
storeMessage(g.getId(), t, p, version);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new DbException(e);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Latest {
|
||||
|
||||
private final MessageId messageId;
|
||||
private final long version;
|
||||
|
||||
private Latest(MessageId messageId, long version) {
|
||||
this.messageId = messageId;
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.briarproject.properties;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfReader;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageValidator;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
|
||||
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
|
||||
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
|
||||
class TransportPropertyValidator implements MessageValidator {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(TransportPropertyValidator.class.getName());
|
||||
|
||||
private final BdfReaderFactory bdfReaderFactory;
|
||||
private final MetadataEncoder metadataEncoder;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
TransportPropertyValidator(BdfReaderFactory bdfReaderFactory,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
this.metadataEncoder = metadataEncoder;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(Message m) {
|
||||
// Reject the message if it's too far in the future
|
||||
long now = clock.currentTimeMillis();
|
||||
if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
|
||||
LOG.info("Timestamp is too far in the future");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// Parse the message body
|
||||
byte[] raw = m.getRaw();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(raw,
|
||||
MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
|
||||
BdfReader r = bdfReaderFactory.createReader(in);
|
||||
// TODO: Device ID
|
||||
r.readListStart();
|
||||
String id = r.readString(MAX_TRANSPORT_ID_LENGTH);
|
||||
if (id.length() == 0) throw new FormatException();
|
||||
long version = r.readInteger();
|
||||
if (version < 0) throw new FormatException();
|
||||
r.readDictionaryStart();
|
||||
for (int i = 0; !r.hasDictionaryEnd(); i++) {
|
||||
if (i == MAX_PROPERTIES_PER_TRANSPORT)
|
||||
throw new FormatException();
|
||||
r.readString(MAX_PROPERTY_LENGTH);
|
||||
r.readString(MAX_PROPERTY_LENGTH);
|
||||
}
|
||||
r.readDictionaryEnd();
|
||||
r.readListEnd();
|
||||
if (!r.eof()) throw new FormatException();
|
||||
// Return the metadata
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put("transportId", id);
|
||||
d.put("version", version);
|
||||
d.put("local", false);
|
||||
return metadataEncoder.encode(d);
|
||||
} catch (IOException e) {
|
||||
LOG.info("Invalid transport update");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.briarproject.property;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
|
||||
public class PropertyModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(TransportPropertyManager.class).to(
|
||||
TransportPropertyManagerImpl.class);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package org.briarproject.property;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
// Temporary facade during sync protocol refactoring
|
||||
class TransportPropertyManagerImpl implements TransportPropertyManager {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
|
||||
@Inject
|
||||
TransportPropertyManagerImpl(DatabaseComponent db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||
throws DbException {
|
||||
// TODO
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProperties getLocalProperties(TransportId t)
|
||||
throws DbException {
|
||||
// TODO
|
||||
return new TransportProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||
TransportId t) throws DbException {
|
||||
// TODO
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||
throws DbException {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoteProperties(ContactId c,
|
||||
Map<TransportId, TransportProperties> p) throws DbException {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package org.briarproject.settings;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.settings.SettingsManager;
|
||||
|
||||
class SettingsManagerImpl implements SettingsManager {
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.briarproject.api.system.Timer;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
import org.briarproject.api.transport.StreamContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -71,12 +70,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addContact(ContactId c, Collection<TransportId> transports,
|
||||
SecretKey master, long timestamp, boolean alice) {
|
||||
for (TransportId t : transports) {
|
||||
TransportKeyManager m = managers.get(t);
|
||||
if (m != null) m.addContact(c, master, timestamp, alice);
|
||||
}
|
||||
public void addContact(ContactId c, SecretKey master, long timestamp,
|
||||
boolean alice) {
|
||||
for (TransportKeyManager m : managers.values())
|
||||
m.addContact(c, master, timestamp, alice);
|
||||
}
|
||||
|
||||
public StreamContext getStreamContext(ContactId c, TransportId t) {
|
||||
|
||||
Reference in New Issue
Block a user