Implement contact manager methods for pending contacts.

This commit is contained in:
akwizgran
2019-04-17 17:00:59 +01:00
parent fc8ca872a8
commit fa562b40bc
9 changed files with 158 additions and 37 deletions

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
@@ -20,19 +21,19 @@ import org.briarproject.bramble.api.transport.KeyManager;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.BASE32_LINK_BYTES;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.briarproject.bramble.util.StringUtils.getRandomBase32String;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@ThreadSafe
@@ -40,19 +41,22 @@ import static org.briarproject.bramble.util.StringUtils.toUtf8;
class ContactManagerImpl implements ContactManager {
private static final String REMOTE_CONTACT_LINK =
"briar://" + getRandomBase32String(LINK_LENGTH);
"briar://" + getRandomBase32String(BASE32_LINK_BYTES);
private final DatabaseComponent db;
private final KeyManager keyManager;
private final IdentityManager identityManager;
private final PendingContactFactory pendingContactFactory;
private final List<ContactHook> hooks;
@Inject
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
IdentityManager identityManager) {
IdentityManager identityManager,
PendingContactFactory pendingContactFactory) {
this.db = db;
this.keyManager = keyManager;
this.identityManager = identityManager;
this.pendingContactFactory = pendingContactFactory;
hooks = new CopyOnWriteArrayList<>();
}
@@ -96,34 +100,23 @@ class ContactManagerImpl implements ContactManager {
return REMOTE_CONTACT_LINK;
}
// TODO replace with real implementation
@SuppressWarnings("SameParameterValue")
private static String getRandomBase32String(int length) {
Random random = new Random();
char[] c = new char[length];
for (int i = 0; i < length; i++) {
int character = random.nextInt(32);
if (character < 26) c[i] = (char) ('a' + character);
else c[i] = (char) ('2' + (character - 26));
}
return new String(c);
@Override
public PendingContact addPendingContact(String link, String alias)
throws DbException, FormatException {
PendingContact p =
pendingContactFactory.createPendingContact(link, alias);
db.transaction(false, txn -> db.addPendingContact(txn, p));
return p;
}
@Override
public void addPendingContact(String link, String alias)
throws DbException {
// TODO replace with real implementation
public Collection<PendingContact> getPendingContacts() throws DbException {
return db.transactionWithResult(true, db::getPendingContacts);
}
@Override
public Collection<PendingContact> getPendingContacts() {
// TODO replace with real implementation
return emptyList();
}
@Override
public void removePendingContact(PendingContactId id) throws DbException {
// TODO replace with real implementation
public void removePendingContact(PendingContactId p) throws DbException {
db.transaction(false, txn -> db.removePendingContact(txn, p));
}
@Override

View File

@@ -28,4 +28,10 @@ public class ContactModule {
ContactExchangeTaskImpl contactExchangeTask) {
return contactExchangeTask;
}
@Provides
PendingContactFactory providePendingContactFactory(
PendingContactFactoryImpl pendingContactFactory) {
return pendingContactFactory;
}
}

View File

@@ -0,0 +1,10 @@
package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.PendingContact;
interface PendingContactFactory {
PendingContact createPendingContact(String link, String alias)
throws FormatException;
}

View File

@@ -0,0 +1,67 @@
package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.Base32;
import java.security.GeneralSecurityException;
import java.util.regex.Matcher;
import javax.inject.Inject;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.FORMAT_VERSION;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.ID_LABEL;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.RAW_LINK_BYTES;
class PendingContactFactoryImpl implements PendingContactFactory {
private final CryptoComponent crypto;
private final Clock clock;
@Inject
PendingContactFactoryImpl(CryptoComponent crypto, Clock clock) {
this.crypto = crypto;
this.clock = clock;
}
@Override
public PendingContact createPendingContact(String link, String alias)
throws FormatException {
PublicKey publicKey = parseHandshakeLink(link);
PendingContactId id = getPendingContactId(publicKey);
long timestamp = clock.currentTimeMillis();
return new PendingContact(id, publicKey.getEncoded(), alias,
PendingContactState.WAITING_FOR_CONNECTION, timestamp);
}
private PublicKey parseHandshakeLink(String link) throws FormatException {
Matcher matcher = LINK_REGEX.matcher(link);
if (!matcher.matches()) throw new FormatException();
link = matcher.group(); // Discard anything before or after the link
if (link.startsWith("briar://")) link = link.substring(8);
byte[] base32 = Base32.decode(link, false);
if (base32.length != RAW_LINK_BYTES) throw new AssertionError();
if (base32[0] != FORMAT_VERSION) throw new FormatException();
byte[] publicKeyBytes = new byte[base32.length - 1];
arraycopy(base32, 1, publicKeyBytes, 0, publicKeyBytes.length);
try {
KeyParser parser = crypto.getAgreementKeyParser();
return parser.parsePublicKey(publicKeyBytes);
} catch (GeneralSecurityException e) {
throw new FormatException();
}
}
private PendingContactId getPendingContactId(PublicKey publicKey) {
byte[] hash = crypto.hash(ID_LABEL, publicKey.getEncoded());
return new PendingContactId(hash);
}
}

View File

@@ -47,6 +47,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
private final KeyManager keyManager = context.mock(KeyManager.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final PendingContactFactory pendingContactFactory =
context.mock(PendingContactFactory.class);
private final ContactManager contactManager;
private final Author remote = getAuthor();
private final LocalAuthor localAuthor = getLocalAuthor();
@@ -56,8 +58,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
private final ContactId contactId = contact.getId();
public ContactManagerImplTest() {
contactManager =
new ContactManagerImpl(db, keyManager, identityManager);
contactManager = new ContactManagerImpl(db, keyManager,
identityManager, pendingContactFactory);
}
@Test