Add contact exchange method for pending contacts.

This commit is contained in:
akwizgran
2019-05-27 14:53:25 +01:00
parent 7c3f2c0bed
commit 60155f146a
4 changed files with 73 additions and 27 deletions

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import java.io.IOException; import java.io.IOException;
@@ -13,12 +12,26 @@ import java.io.IOException;
public interface ContactExchangeManager { public interface ContactExchangeManager {
/** /**
* Exchanges contact information with a remote peer. * Exchanges contact information with a remote peer and adds the peer
* as a contact.
* *
* @param alice Whether the local peer takes the role of Alice * @param alice Whether the local peer takes the role of Alice
* @return The newly added contact * @return The newly added contact
* @throws ContactExistsException If the contact already exists * @throws ContactExistsException If the contact already exists
*/ */
Contact exchangeContacts(TransportId t, DuplexTransportConnection conn, Contact exchangeContacts(DuplexTransportConnection conn,
SecretKey masterKey, boolean alice) throws IOException, DbException; SecretKey masterKey, boolean alice, boolean verified)
throws IOException, DbException;
/**
* Exchanges contact information with a remote peer and adds the peer
* as a contact, replacing the given pending contact.
*
* @param alice Whether the local peer takes the role of Alice
* @return The newly added contact
* @throws ContactExistsException If the contact already exists
*/
Contact exchangeContacts(PendingContactId p, DuplexTransportConnection conn,
SecretKey masterKey, boolean alice, boolean verified)
throws IOException, DbException;
} }

View File

@@ -7,17 +7,18 @@ import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactExchangeManager; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
@@ -36,20 +37,23 @@ import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@MethodsNotNullByDefault @Immutable
@ParametersNotNullByDefault @NotNullByDefault
class ContactExchangeManagerImpl implements ContactExchangeManager { class ContactExchangeManagerImpl implements ContactExchangeManager {
private static final Logger LOG = private static final Logger LOG =
@@ -104,9 +108,22 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
} }
@Override @Override
public Contact exchangeContacts(TransportId t, public Contact exchangeContacts(DuplexTransportConnection conn,
DuplexTransportConnection conn, SecretKey masterKey, boolean alice) SecretKey masterKey, boolean alice,
throws IOException, DbException { boolean verified) throws IOException, DbException {
return exchange(null, conn, masterKey, alice, verified);
}
@Override
public Contact exchangeContacts(PendingContactId p,
DuplexTransportConnection conn, SecretKey masterKey, boolean alice,
boolean verified) throws IOException, DbException {
return exchange(p, conn, masterKey, alice, verified);
}
private Contact exchange(@Nullable PendingContactId p,
DuplexTransportConnection conn, SecretKey masterKey, boolean alice,
boolean verified) throws IOException, DbException {
// Get the transport connection's input and output streams // Get the transport connection's input and output streams
InputStream in = conn.getReader().getInputStream(); InputStream in = conn.getReader().getInputStream();
OutputStream out = conn.getWriter().getOutputStream(); OutputStream out = conn.getWriter().getOutputStream();
@@ -169,8 +186,8 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
long timestamp = Math.min(localTimestamp, remoteInfo.timestamp); long timestamp = Math.min(localTimestamp, remoteInfo.timestamp);
// Add the contact // Add the contact
Contact contact = addContact(remoteInfo.author, localAuthor, Contact contact = addContact(p, remoteInfo.author, localAuthor,
masterKey, timestamp, alice, remoteInfo.properties); masterKey, timestamp, alice, verified, remoteInfo.properties);
// Contact exchange succeeded // Contact exchange succeeded
LOG.info("Contact exchange succeeded"); LOG.info("Contact exchange succeeded");
@@ -207,18 +224,34 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
return new ContactInfo(author, properties, signature, timestamp); return new ContactInfo(author, properties, signature, timestamp);
} }
private Contact addContact(Author remoteAuthor, LocalAuthor localAuthor, private Contact addContact(@Nullable PendingContactId pendingContactId,
SecretKey masterKey, long timestamp, boolean alice, Author remoteAuthor, LocalAuthor localAuthor, SecretKey masterKey,
long timestamp, boolean alice, boolean verified,
Map<TransportId, TransportProperties> remoteProperties) Map<TransportId, TransportProperties> remoteProperties)
throws DbException { throws DbException, FormatException {
return db.transactionWithResult(false, txn -> { Transaction txn = db.startTransaction(false);
ContactId contactId = contactManager.addContact(txn, remoteAuthor, try {
localAuthor.getId(), masterKey, timestamp, alice, ContactId contactId;
true, true); if (pendingContactId == null) {
contactId = contactManager.addContact(txn, remoteAuthor,
localAuthor.getId(), masterKey, timestamp, alice,
verified, true);
} else {
contactId = contactManager.addContact(txn, pendingContactId,
remoteAuthor, localAuthor.getId(), masterKey,
timestamp, alice, verified, true);
}
transportPropertyManager.addRemoteProperties(txn, contactId, transportPropertyManager.addRemoteProperties(txn, contactId,
remoteProperties); remoteProperties);
return contactManager.getContact(txn, contactId); Contact contact = contactManager.getContact(txn, contactId);
}); db.commitTransaction(txn);
return contact;
} catch (GeneralSecurityException e) {
// Pending contact's public key is invalid
throw new FormatException();
} finally {
db.endTransaction(txn);
}
} }
private static class ContactInfo { private static class ContactInfo {

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.contact;
/** /**
* Record types for the contact exchange protocol. * Record types for the contact exchange protocol.
*/ */
public interface RecordTypes { interface ContactExchangeRecordTypes {
byte CONTACT_INFO = 0; byte CONTACT_INFO = 0;
} }

View File

@@ -58,8 +58,8 @@ class ContactExchangeViewModel extends AndroidViewModel {
SecretKey masterKey, boolean alice) { SecretKey masterKey, boolean alice) {
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
try { try {
Contact contact = contactExchangeManager.exchangeContacts(t, Contact contact = contactExchangeManager.exchangeContacts(conn,
conn, masterKey, alice); masterKey, alice, true);
// Reuse the connection as a transport connection // Reuse the connection as a transport connection
connectionManager.manageOutgoingConnection(contact.getId(), connectionManager.manageOutgoingConnection(contact.getId(),
t, conn); t, conn);