Commit 98191fb0 authored by akwizgran's avatar akwizgran

Add ContactManager support for pending contact states.

parent b9283ea6
...@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.ContactManager; ...@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.contact.PendingContactState; import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
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;
...@@ -15,24 +16,35 @@ import org.briarproject.bramble.api.db.DatabaseComponent; ...@@ -15,24 +16,35 @@ 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.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.AuthorInfo;
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.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionClosedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionOpenedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousFailedEvent;
import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.api.transport.KeyManager;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.contact.PendingContactState.ADDING_CONTACT;
import static org.briarproject.bramble.api.contact.PendingContactState.FAILED;
import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; 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.OURSELVES;
...@@ -43,24 +55,31 @@ import static org.briarproject.bramble.util.StringUtils.toUtf8; ...@@ -43,24 +55,31 @@ import static org.briarproject.bramble.util.StringUtils.toUtf8;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
class ContactManagerImpl implements ContactManager { class ContactManagerImpl implements ContactManager, EventListener {
private final DatabaseComponent db; private final DatabaseComponent db;
private final KeyManager keyManager; private final KeyManager keyManager;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final PendingContactFactory pendingContactFactory; private final PendingContactFactory pendingContactFactory;
private final EventBus eventBus;
private final List<ContactHook> hooks; private final List<ContactHook> hooks = new CopyOnWriteArrayList<>();
private final Object statesLock = new Object();
@GuardedBy("statesLock")
private final Map<PendingContactId, PendingContactState> states =
new HashMap<>();
@Inject @Inject
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager, ContactManagerImpl(DatabaseComponent db,
KeyManager keyManager,
IdentityManager identityManager, IdentityManager identityManager,
PendingContactFactory pendingContactFactory) { PendingContactFactory pendingContactFactory,
EventBus eventBus) {
this.db = db; this.db = db;
this.keyManager = keyManager; this.keyManager = keyManager;
this.identityManager = identityManager; this.identityManager = identityManager;
this.pendingContactFactory = pendingContactFactory; this.pendingContactFactory = pendingContactFactory;
hooks = new CopyOnWriteArrayList<>(); this.eventBus = eventBus;
} }
@Override @Override
...@@ -139,6 +158,7 @@ class ContactManagerImpl implements ContactManager { ...@@ -139,6 +158,7 @@ class ContactManagerImpl implements ContactManager {
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }
setState(p.getId(), WAITING_FOR_CONNECTION);
return p; return p;
} }
...@@ -156,7 +176,12 @@ class ContactManagerImpl implements ContactManager { ...@@ -156,7 +176,12 @@ class ContactManagerImpl implements ContactManager {
List<Pair<PendingContact, PendingContactState>> pairs = List<Pair<PendingContact, PendingContactState>> pairs =
new ArrayList<>(pendingContacts.size()); new ArrayList<>(pendingContacts.size());
for (PendingContact p : pendingContacts) { for (PendingContact p : pendingContacts) {
pairs.add(new Pair<>(p, WAITING_FOR_CONNECTION)); // TODO PendingContactState state;
synchronized (statesLock) {
state = states.get(p.getId());
}
if (state == null) state = WAITING_FOR_CONNECTION;
pairs.add(new Pair<>(p, state));
} }
return pairs; return pairs;
} }
...@@ -164,6 +189,9 @@ class ContactManagerImpl implements ContactManager { ...@@ -164,6 +189,9 @@ class ContactManagerImpl implements ContactManager {
@Override @Override
public void removePendingContact(PendingContactId p) throws DbException { public void removePendingContact(PendingContactId p) throws DbException {
db.transaction(false, txn -> db.removePendingContact(txn, p)); db.transaction(false, txn -> db.removePendingContact(txn, p));
synchronized (statesLock) {
states.remove(p);
}
} }
@Override @Override
...@@ -263,4 +291,34 @@ class ContactManagerImpl implements ContactManager { ...@@ -263,4 +291,34 @@ class ContactManagerImpl implements ContactManager {
else return new AuthorInfo(UNVERIFIED, c.getAlias()); else return new AuthorInfo(UNVERIFIED, c.getAlias());
} }
@Override
public void eventOccurred(Event e) {
if (e instanceof RendezvousConnectionOpenedEvent) {
RendezvousConnectionOpenedEvent r =
(RendezvousConnectionOpenedEvent) e;
setState(r.getPendingContactId(), ADDING_CONTACT);
} else if (e instanceof RendezvousConnectionClosedEvent) {
RendezvousConnectionClosedEvent r =
(RendezvousConnectionClosedEvent) e;
// We're only interested in failures - if the rendezvous succeeds
// the pending contact will be removed
if (!r.isSuccess())
setState(r.getPendingContactId(), WAITING_FOR_CONNECTION);
} else if (e instanceof RendezvousFailedEvent) {
RendezvousFailedEvent r = (RendezvousFailedEvent) e;
setState(r.getPendingContactId(), FAILED);
}
}
/*
* Sets the state of the given pending contact and broadcasts an event,
* unless the current state is FAILED.
*/
private void setState(PendingContactId p, PendingContactState state) {
synchronized (statesLock) {
if (states.get(p) == FAILED) return;
states.put(p, state);
eventBus.broadcast(new PendingContactStateChangedEvent(p, state));
}
}
} }
...@@ -3,6 +3,7 @@ package org.briarproject.bramble.contact; ...@@ -3,6 +3,7 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.contact.ContactExchangeManager; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager; import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.event.EventBus;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
...@@ -20,7 +21,9 @@ public class ContactModule { ...@@ -20,7 +21,9 @@ public class ContactModule {
@Provides @Provides
@Singleton @Singleton
ContactManager provideContactManager(ContactManagerImpl contactManager) { ContactManager provideContactManager(EventBus eventBus,
ContactManagerImpl contactManager) {
eventBus.addListener(contactManager);
return contactManager; return contactManager;
} }
......
...@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent; ...@@ -11,6 +11,7 @@ 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.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.AuthorInfo;
...@@ -20,6 +21,7 @@ import org.briarproject.bramble.api.transport.KeyManager; ...@@ -20,6 +21,7 @@ import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations; import org.briarproject.bramble.test.DbExpectations;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.Collection; import java.util.Collection;
...@@ -54,7 +56,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase { ...@@ -54,7 +56,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
context.mock(IdentityManager.class); context.mock(IdentityManager.class);
private final PendingContactFactory pendingContactFactory = private final PendingContactFactory pendingContactFactory =
context.mock(PendingContactFactory.class); context.mock(PendingContactFactory.class);
private final ContactManager contactManager; private final EventBus eventBus = context.mock(EventBus.class);
private final Author remote = getAuthor(); private final Author remote = getAuthor();
private final LocalAuthor localAuthor = getLocalAuthor(); private final LocalAuthor localAuthor = getLocalAuthor();
private final AuthorId local = localAuthor.getId(); private final AuthorId local = localAuthor.getId();
...@@ -62,9 +65,12 @@ public class ContactManagerImplTest extends BrambleMockTestCase { ...@@ -62,9 +65,12 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
private final Contact contact = getContact(remote, local, verified); private final Contact contact = getContact(remote, local, verified);
private final ContactId contactId = contact.getId(); private final ContactId contactId = contact.getId();
public ContactManagerImplTest() { private ContactManager contactManager;
@Before
public void setUp() {
contactManager = new ContactManagerImpl(db, keyManager, contactManager = new ContactManagerImpl(db, keyManager,
identityManager, pendingContactFactory); identityManager, pendingContactFactory, eventBus);
} }
@Test @Test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment