diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java index 40b6ab534..b213044aa 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java @@ -4,8 +4,10 @@ import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.UnsupportedVersionException; import org.briarproject.bramble.api.crypto.SecretKey; +import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.NoSuchContactException; +import org.briarproject.bramble.api.db.PendingContactExistsException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; @@ -117,9 +119,14 @@ public interface ContactManager { * @throws FormatException If the link is invalid * @throws GeneralSecurityException If the pending contact's handshake * public key is invalid + * @throws ContactExistsException If a contact with the same handshake + * public key already exists + * @throws PendingContactExistsException If a pending contact with the same + * handshake public key already exists */ PendingContact addPendingContact(String link, String alias) - throws DbException, FormatException, GeneralSecurityException; + throws DbException, FormatException, GeneralSecurityException, + ContactExistsException, PendingContactExistsException; /** * Returns the pending contact with the given ID. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 58f8a8f06..7c525bcd3 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -83,7 +83,7 @@ public interface DatabaseComponent extends TransactionManager { /** * Stores a pending contact. */ - void addPendingContact(Transaction txn, PendingContact p) + void addPendingContact(Transaction txn, PendingContact p, AuthorId local) throws DbException; /** diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java index cefca3f0a..2d073ac70 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java @@ -1,9 +1,21 @@ package org.briarproject.bramble.api.db; +import org.briarproject.bramble.api.contact.PendingContact; + /** * Thrown when a duplicate pending contact is added to the database. This * exception may occur due to concurrent updates and does not indicate a * database error. */ public class PendingContactExistsException extends DbException { + + private final PendingContact pendingContact; + + public PendingContactExistsException(PendingContact pendingContact) { + this.pendingContact = pendingContact; + } + + public PendingContact getPendingContact() { + return pendingContact; + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java index a03206ad2..2ebd2848b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java @@ -139,7 +139,8 @@ class ContactManagerImpl implements ContactManager, EventListener { pendingContactFactory.createPendingContact(link, alias); Transaction txn = db.startTransaction(false); try { - db.addPendingContact(txn, p); + AuthorId local = identityManager.getLocalAuthor(txn).getId(); + db.addPendingContact(txn, p, local); KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn); keyManager.addPendingContact(txn, p.getId(), p.getPublicKey(), ourKeyPair); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 1a73c89f0..6ec1760af 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -291,12 +291,17 @@ class DatabaseComponentImpl implements DatabaseComponent { } @Override - public void addPendingContact(Transaction transaction, PendingContact p) - throws DbException { + public void addPendingContact(Transaction transaction, PendingContact p, + AuthorId local) throws DbException { if (transaction.isReadOnly()) throw new IllegalArgumentException(); T txn = unbox(transaction); - if (db.containsPendingContact(txn, p.getId())) - throw new PendingContactExistsException(); + Contact contact = db.getContact(txn, p.getPublicKey(), local); + if (contact != null) + throw new ContactExistsException(local, contact.getAuthor()); + if (db.containsPendingContact(txn, p.getId())) { + PendingContact existing = db.getPendingContact(txn, p.getId()); + throw new PendingContactExistsException(existing); + } db.addPendingContact(txn, p); transaction.attach(new PendingContactAddedEvent(p)); }