Deduplicate contact exchange protocol

ContactExchangeTask was originally extracted from the Bluetooth invitation
task; this completes the refactoring.
This commit is contained in:
str4d
2016-05-19 13:52:01 +00:00
parent 4176f592df
commit b71a303bf8
8 changed files with 74 additions and 322 deletions

View File

@@ -39,6 +39,8 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH; import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
@@ -73,6 +75,7 @@ public class ContactExchangeTaskImpl extends Thread
private volatile SecretKey masterSecret; private volatile SecretKey masterSecret;
private volatile boolean alice; private volatile boolean alice;
@Inject
public ContactExchangeTaskImpl(DatabaseComponent db, public ContactExchangeTaskImpl(DatabaseComponent db,
AuthorFactory authorFactory, BdfReaderFactory bdfReaderFactory, AuthorFactory authorFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, Clock clock, BdfWriterFactory bdfWriterFactory, Clock clock,

View File

@@ -24,7 +24,8 @@ import dagger.Provides;
public class ContactModule { public class ContactModule {
public static class EagerSingletons { public static class EagerSingletons {
@Inject ContactManager contactManager; @Inject
ContactManager contactManager;
} }
@Provides @Provides
@@ -36,16 +37,8 @@ public class ContactModule {
} }
@Provides @Provides
ContactExchangeTask provideContactExchangeTask(DatabaseComponent db, ContactExchangeTask provideContactExchangeTask(
AuthorFactory authorFactory, BdfReaderFactory bdfReaderFactory, ContactExchangeTaskImpl contactExchangeTask) {
BdfWriterFactory bdfWriterFactory, Clock clock, return contactExchangeTask;
ConnectionManager connectionManager, ContactManager contactManager,
TransportPropertyManager transportPropertyManager,
CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory) {
return new ContactExchangeTaskImpl(db, authorFactory, bdfReaderFactory,
bdfWriterFactory, clock, connectionManager, contactManager,
transportPropertyManager, crypto, streamReaderFactory,
streamWriterFactory);
} }
} }

View File

@@ -1,6 +1,6 @@
package org.briarproject.invitation; package org.briarproject.invitation;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactExchangeTask;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
@@ -8,16 +8,9 @@ import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriter; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.LocalAuthor; 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.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.system.Clock;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -28,24 +21,20 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
/** A connection thread for the peer being Alice in the invitation protocol. */ /**
* A connection thread for the peer being Alice in the invitation protocol.
*/
class AliceConnector extends Connector { class AliceConnector extends Connector {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(AliceConnector.class.getName()); Logger.getLogger(AliceConnector.class.getName());
AliceConnector(CryptoComponent crypto, AliceConnector(CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, ContactExchangeTask contactExchangeTask, ConnectorGroup group,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, ConnectionManager connectionManager,
ContactManager contactManager, Clock clock, ConnectorGroup group,
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) { DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory, super(crypto, bdfReaderFactory, bdfWriterFactory, contactExchangeTask,
streamWriterFactory, authorFactory, group, plugin, localAuthor, random);
connectionManager, contactManager, clock, group, plugin,
localAuthor, random);
} }
@Override @Override
@@ -119,65 +108,11 @@ class AliceConnector extends Connector {
tryToClose(conn, false); tryToClose(conn, false);
return; return;
} }
// The timestamp is taken after exchanging confirmation results
long localTimestamp = clock.currentTimeMillis();
// Confirmation succeeded - upgrade to a secure connection // Confirmation succeeded - upgrade to a secure connection
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info(pluginName + " confirmation succeeded"); LOG.info(pluginName + " confirmation succeeded");
// Derive the header keys contactExchangeTask
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master, true); .startExchange(group, localAuthor, master, conn, plugin.getId(),
SecretKey bobHeaderKey = crypto.deriveHeaderKey(master, false); true);
// Create the readers
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,
bobHeaderKey);
r = bdfReaderFactory.createReader(streamReader);
// Create the writers
OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out,
aliceHeaderKey);
w = bdfWriterFactory.createWriter(streamWriter);
// Derive the invitation nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
byte[] bobNonce = crypto.deriveSignatureNonce(master, false);
// Exchange pseudonyms, signed nonces, and timestamps
Author remoteAuthor;
long remoteTimestamp;
try {
sendPseudonym(w, aliceNonce);
sendTimestamp(w, localTimestamp);
remoteAuthor = receivePseudonym(r, bobNonce);
remoteTimestamp = receiveTimestamp(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");
} catch (GeneralSecurityException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
group.pseudonymExchangeFailed();
tryToClose(conn, true);
return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
group.pseudonymExchangeFailed();
tryToClose(conn, true);
return;
}
// The agreed timestamp is the minimum of the peers' timestamps
long timestamp = Math.min(localTimestamp, remoteTimestamp);
// Add the contact
try {
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
reuseConnection(conn);
// Pseudonym exchange succeeded
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " pseudonym exchange succeeded");
group.pseudonymExchangeSucceeded(remoteAuthor);
} }
} }

View File

@@ -1,6 +1,6 @@
package org.briarproject.invitation; package org.briarproject.invitation;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactExchangeTask;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
@@ -8,16 +8,10 @@ import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriter; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.LocalAuthor; 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.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -28,24 +22,20 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
/** A connection thread for the peer being Bob in the invitation protocol. */ /**
* A connection thread for the peer being Bob in the invitation protocol.
*/
class BobConnector extends Connector { class BobConnector extends Connector {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(BobConnector.class.getName()); Logger.getLogger(BobConnector.class.getName());
BobConnector(CryptoComponent crypto, BobConnector(CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, ContactExchangeTask contactExchangeTask, ConnectorGroup group,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, ConnectionManager connectionManager,
ContactManager contactManager, Clock clock, ConnectorGroup group,
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) { DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory, super(crypto, bdfReaderFactory, bdfWriterFactory, contactExchangeTask,
streamWriterFactory, authorFactory, group, plugin, localAuthor, random);
connectionManager, contactManager, clock, group, plugin,
localAuthor, random);
} }
@Override @Override
@@ -119,69 +109,11 @@ class BobConnector extends Connector {
tryToClose(conn, false); tryToClose(conn, false);
return; return;
} }
// The timestamp is taken after exchanging confirmation results
long localTimestamp = clock.currentTimeMillis();
// Confirmation succeeded - upgrade to a secure connection // Confirmation succeeded - upgrade to a secure connection
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info(pluginName + " confirmation succeeded"); LOG.info(pluginName + " confirmation succeeded");
// Derive the header keys contactExchangeTask
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master, .startExchange(group, localAuthor, master, conn, plugin.getId(),
true); false);
SecretKey bobHeaderKey = crypto.deriveHeaderKey(master,
false);
// Create the readers
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,
aliceHeaderKey);
r = bdfReaderFactory.createReader(streamReader);
// Create the writers
OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out,
bobHeaderKey);
w = bdfWriterFactory.createWriter(streamWriter);
// Derive the nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master,
true);
byte[] bobNonce = crypto.deriveSignatureNonce(master,
false);
// Exchange pseudonyms, signed nonces and timestamps
Author remoteAuthor;
long remoteTimestamp;
try {
remoteAuthor = receivePseudonym(r, aliceNonce);
remoteTimestamp = receiveTimestamp(r);
sendPseudonym(w, bobNonce);
sendTimestamp(w, localTimestamp);
// Close the outgoing stream and expect EOF on the incoming stream
w.close();
if (!r.eof()) LOG.warning("Unexpected data at end of connection");
} catch (GeneralSecurityException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
group.pseudonymExchangeFailed();
tryToClose(conn, true);
return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
group.pseudonymExchangeFailed();
tryToClose(conn, true);
return;
}
// The agreed timestamp is the minimum of the peers' timestamps
long timestamp = Math.min(localTimestamp, remoteTimestamp);
// Add the contact
try {
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
reuseConnection(conn);
// Pseudonym exchange succeeded
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " pseudonym exchange succeeded");
group.pseudonymExchangeSucceeded(remoteAuthor);
} }
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.invitation;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactExchangeTask;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
@@ -47,12 +48,7 @@ abstract class Connector extends Thread {
protected final CryptoComponent crypto; protected final CryptoComponent crypto;
protected final BdfReaderFactory bdfReaderFactory; protected final BdfReaderFactory bdfReaderFactory;
protected final BdfWriterFactory bdfWriterFactory; protected final BdfWriterFactory bdfWriterFactory;
protected final StreamReaderFactory streamReaderFactory; protected final ContactExchangeTask contactExchangeTask;
protected final StreamWriterFactory streamWriterFactory;
protected final AuthorFactory authorFactory;
protected final ConnectionManager connectionManager;
protected final ContactManager contactManager;
protected final Clock clock;
protected final ConnectorGroup group; protected final ConnectorGroup group;
protected final DuplexPlugin plugin; protected final DuplexPlugin plugin;
protected final LocalAuthor localAuthor; protected final LocalAuthor localAuthor;
@@ -63,26 +59,15 @@ abstract class Connector extends Thread {
private final KeyParser keyParser; private final KeyParser keyParser;
private final MessageDigest messageDigest; private final MessageDigest messageDigest;
private volatile ContactId contactId = null; Connector(CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
Connector(CryptoComponent crypto,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, ContactExchangeTask contactExchangeTask, ConnectorGroup group,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, ConnectionManager connectionManager,
ContactManager contactManager, Clock clock, ConnectorGroup group,
DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) { DuplexPlugin plugin, LocalAuthor localAuthor, PseudoRandom random) {
super("Connector"); super("Connector");
this.crypto = crypto; this.crypto = crypto;
this.bdfReaderFactory = bdfReaderFactory; this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.contactExchangeTask = contactExchangeTask;
this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory;
this.connectionManager = connectionManager;
this.contactManager = contactManager;
this.clock = clock;
this.group = group; this.group = group;
this.plugin = plugin; this.plugin = plugin;
this.localAuthor = localAuthor; this.localAuthor = localAuthor;
@@ -159,65 +144,6 @@ abstract class Connector extends Thread {
return confirmed; return confirmed;
} }
protected void sendPseudonym(BdfWriter w, byte[] nonce)
throws GeneralSecurityException, IOException {
// Sign the nonce
Signature signature = crypto.getSignature();
KeyParser keyParser = crypto.getSignatureKeyParser();
byte[] privateKey = localAuthor.getPrivateKey();
signature.initSign(keyParser.parsePrivateKey(privateKey));
signature.update(nonce);
byte[] sig = signature.sign();
// Write the name, public key and signature
w.writeString(localAuthor.getName());
w.writeRaw(localAuthor.getPublicKey());
w.writeRaw(sig);
w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent pseudonym");
}
protected Author receivePseudonym(BdfReader r, byte[] nonce)
throws GeneralSecurityException, IOException {
// Read the name, public key and signature
String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
byte[] sig = r.readRaw(MAX_SIGNATURE_LENGTH);
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received pseudonym");
// Verify the signature
Signature signature = crypto.getSignature();
KeyParser keyParser = crypto.getSignatureKeyParser();
signature.initVerify(keyParser.parsePublicKey(publicKey));
signature.update(nonce);
if (!signature.verify(sig)) {
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " invalid signature");
throw new GeneralSecurityException();
}
return authorFactory.createAuthor(name, publicKey);
}
protected void sendTimestamp(BdfWriter w, long timestamp)
throws IOException {
w.writeLong(timestamp);
w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent timestamp");
}
protected long receiveTimestamp(BdfReader r) throws IOException {
long timestamp = r.readLong();
if (timestamp < 0) throw new FormatException();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received timestamp");
return timestamp;
}
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(), master, timestamp, alice, true);
return contactId;
}
protected void tryToClose(DuplexTransportConnection conn, protected void tryToClose(DuplexTransportConnection conn,
boolean exception) { boolean exception) {
try { try {
@@ -228,10 +154,4 @@ abstract class Connector extends Thread {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }
} }
protected void reuseConnection(DuplexTransportConnection conn) {
if (contactId == null) throw new IllegalStateException();
TransportId t = plugin.getId();
connectionManager.manageOutgoingConnection(contactId, t, conn);
}
} }

View File

@@ -1,5 +1,7 @@
package org.briarproject.invitation; package org.briarproject.invitation;
import org.briarproject.api.contact.ContactExchangeListener;
import org.briarproject.api.contact.ContactExchangeTask;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
@@ -34,8 +36,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.invitation.InvitationConstants.CONFIRMATION_TIMEOUT; import static org.briarproject.api.invitation.InvitationConstants.CONFIRMATION_TIMEOUT;
/** A task consisting of one or more parallel connection attempts. */ /**
class ConnectorGroup extends Thread implements InvitationTask { * A task consisting of one or more parallel connection attempts.
*/
class ConnectorGroup extends Thread implements InvitationTask,
ContactExchangeListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(ConnectorGroup.class.getName()); Logger.getLogger(ConnectorGroup.class.getName());
@@ -43,13 +48,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final BdfReaderFactory bdfReaderFactory; private final BdfReaderFactory bdfReaderFactory;
private final BdfWriterFactory bdfWriterFactory; private final BdfWriterFactory bdfWriterFactory;
private final StreamReaderFactory streamReaderFactory; private final ContactExchangeTask contactExchangeTask;
private final StreamWriterFactory streamWriterFactory;
private final AuthorFactory authorFactory;
private final ConnectionManager connectionManager;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final ContactManager contactManager;
private final Clock clock;
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final AuthorId localAuthorId; private final AuthorId localAuthorId;
private final int localInvitationCode, remoteInvitationCode; private final int localInvitationCode, remoteInvitationCode;
@@ -65,26 +65,18 @@ class ConnectorGroup extends Thread implements InvitationTask {
private boolean localMatched = false, remoteMatched = false; private boolean localMatched = false, remoteMatched = false;
private String remoteName = null; private String remoteName = null;
ConnectorGroup(CryptoComponent crypto, ConnectorGroup(CryptoComponent crypto, BdfReaderFactory bdfReaderFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, ContactExchangeTask contactExchangeTask,
StreamWriterFactory streamWriterFactory, IdentityManager identityManager, PluginManager pluginManager,
AuthorFactory authorFactory, ConnectionManager connectionManager, AuthorId localAuthorId, int localInvitationCode,
IdentityManager identityManager, ContactManager contactManager, int remoteInvitationCode) {
Clock clock, PluginManager pluginManager, AuthorId localAuthorId,
int localInvitationCode, int remoteInvitationCode) {
super("ConnectorGroup"); super("ConnectorGroup");
this.crypto = crypto; this.crypto = crypto;
this.bdfReaderFactory = bdfReaderFactory; this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.contactExchangeTask = contactExchangeTask;
this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory;
this.connectionManager = connectionManager;
this.identityManager = identityManager; this.identityManager = identityManager;
this.contactManager = contactManager;
this.clock = clock;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
this.localAuthorId = localAuthorId; this.localAuthorId = localAuthorId;
this.localInvitationCode = localInvitationCode; this.localInvitationCode = localInvitationCode;
@@ -143,7 +135,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
c.start(); c.start();
} }
} else { } else {
for (DuplexPlugin plugin: pluginManager.getInvitationPlugins()) { for (DuplexPlugin plugin : pluginManager.getInvitationPlugins()) {
Connector c = createBobConnector(plugin, localAuthor); Connector c = createBobConnector(plugin, localAuthor);
connectors.add(c); connectors.add(c);
c.start(); c.start();
@@ -173,9 +165,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
PseudoRandom random = crypto.getPseudoRandom(localInvitationCode, PseudoRandom random = crypto.getPseudoRandom(localInvitationCode,
remoteInvitationCode); remoteInvitationCode);
return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory, return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, contactExchangeTask, this, plugin, localAuthor, random);
connectionManager, contactManager, clock, this, plugin,
localAuthor, random);
} }
private Connector createBobConnector(DuplexPlugin plugin, private Connector createBobConnector(DuplexPlugin plugin,
@@ -183,9 +173,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
PseudoRandom random = crypto.getPseudoRandom(remoteInvitationCode, PseudoRandom random = crypto.getPseudoRandom(remoteInvitationCode,
localInvitationCode); localInvitationCode);
return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory, return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, contactExchangeTask, this, plugin, localAuthor, random);
connectionManager, contactManager, clock, this, plugin,
localAuthor, random);
} }
public void localConfirmationSucceeded() { public void localConfirmationSucceeded() {
@@ -265,7 +253,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
for (InvitationListener l : listeners) l.remoteConfirmationFailed(); for (InvitationListener l : listeners) l.remoteConfirmationFailed();
} }
void pseudonymExchangeSucceeded(Author remoteAuthor) { @Override
public void contactExchangeSucceeded(Author remoteAuthor) {
String name = remoteAuthor.getName(); String name = remoteAuthor.getName();
lock.lock(); lock.lock();
try { try {
@@ -277,7 +266,14 @@ class ConnectorGroup extends Thread implements InvitationTask {
l.pseudonymExchangeSucceeded(name); l.pseudonymExchangeSucceeded(name);
} }
void pseudonymExchangeFailed() { @Override
public void duplicateContact(Author remoteAuthor) {
// TODO differentiate
for (InvitationListener l : listeners) l.pseudonymExchangeFailed();
}
@Override
public void contactExchangeFailed() {
for (InvitationListener l : listeners) l.pseudonymExchangeFailed(); for (InvitationListener l : listeners) l.pseudonymExchangeFailed();
} }
} }

View File

@@ -25,17 +25,8 @@ public class InvitationModule {
@Provides @Provides
@Singleton @Singleton
InvitationTaskFactory provideInvitationTaskFactory(CryptoComponent crypto, InvitationTaskFactory provideInvitationTaskFactory(
BdfReaderFactory bdfReaderFactory, InvitationTaskFactoryImpl invitationTaskFactory) {
BdfWriterFactory bdfWriterFactory, return invitationTaskFactory;
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, ConnectionManager connectionManager,
IdentityManager identityManager, ContactManager contactManager,
Clock clock, PluginManager pluginManager) {
return new InvitationTaskFactoryImpl(crypto, bdfReaderFactory,
bdfWriterFactory, streamReaderFactory, streamWriterFactory,
authorFactory, connectionManager, identityManager,
contactManager, clock, pluginManager);
} }
} }

View File

@@ -1,19 +1,14 @@
package org.briarproject.invitation; package org.briarproject.invitation;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactExchangeTask;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.data.BdfReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.invitation.InvitationTask; import org.briarproject.api.invitation.InvitationTask;
import org.briarproject.api.invitation.InvitationTaskFactory; import org.briarproject.api.invitation.InvitationTaskFactory;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.PluginManager; import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.system.Clock;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
import javax.inject.Inject; import javax.inject.Inject;
@@ -22,41 +17,28 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final BdfReaderFactory bdfReaderFactory; private final BdfReaderFactory bdfReaderFactory;
private final BdfWriterFactory bdfWriterFactory; private final BdfWriterFactory bdfWriterFactory;
private final StreamReaderFactory streamReaderFactory; private final ContactExchangeTask contactExchangeTask;
private final StreamWriterFactory streamWriterFactory;
private final AuthorFactory authorFactory;
private final ConnectionManager connectionManager;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final ContactManager contactManager;
private final Clock clock;
private final PluginManager pluginManager; private final PluginManager pluginManager;
@Inject @Inject
InvitationTaskFactoryImpl(CryptoComponent crypto, InvitationTaskFactoryImpl(CryptoComponent crypto,
BdfReaderFactory bdfReaderFactory, BdfWriterFactory bdfWriterFactory, BdfReaderFactory bdfReaderFactory,
StreamReaderFactory streamReaderFactory, BdfWriterFactory bdfWriterFactory,
StreamWriterFactory streamWriterFactory, ContactExchangeTask contactExchangeTask,
AuthorFactory authorFactory, ConnectionManager connectionManager, IdentityManager identityManager, PluginManager pluginManager) {
IdentityManager identityManager, ContactManager contactManager,
Clock clock, PluginManager pluginManager) {
this.crypto = crypto; this.crypto = crypto;
this.bdfReaderFactory = bdfReaderFactory; this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.contactExchangeTask = contactExchangeTask;
this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory;
this.connectionManager = connectionManager;
this.identityManager = identityManager; this.identityManager = identityManager;
this.contactManager = contactManager;
this.clock = clock;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
} }
public InvitationTask createTask(AuthorId localAuthorId, int localCode, public InvitationTask createTask(AuthorId localAuthorId, int localCode,
int remoteCode) { int remoteCode) {
return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory, return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, contactExchangeTask, identityManager, pluginManager,
connectionManager, identityManager, contactManager, clock, localAuthorId, localCode, remoteCode);
pluginManager, localAuthorId, localCode, remoteCode);
} }
} }