mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-22 07:39:53 +01:00
Add ContactManager support for pending contact states.
This commit is contained in:
@@ -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;
|
|||||||
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;
|
|||||||
|
|
||||||
@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 {
|
|||||||
} 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 {
|
|||||||
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 {
|
|||||||
@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 {
|
|||||||
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;
|
|||||||
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 {
|
|||||||
|
|
||||||
@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;
|
|||||||
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;
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user