mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Refactor connection registry implementation.
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.connection;
|
package org.briarproject.bramble.connection;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Multiset;
|
|
||||||
import org.briarproject.bramble.api.Pair;
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
@@ -22,6 +21,7 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -41,22 +41,30 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
getLogger(ConnectionRegistryImpl.class.getName());
|
getLogger(ConnectionRegistryImpl.class.getName());
|
||||||
|
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final List<Pair<TransportId, TransportId>> preferences;
|
private final Map<TransportId, List<TransportId>> betterTransports;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final Map<TransportId, Multiset<ContactId>> contactConnections;
|
private final Map<ContactId, List<ConnectionRecord>> contactConnections;
|
||||||
@GuardedBy("lock")
|
|
||||||
private final Multiset<ContactId> contactCounts;
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final Set<PendingContactId> connectedPendingContacts;
|
private final Set<PendingContactId> connectedPendingContacts;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ConnectionRegistryImpl(EventBus eventBus, PluginConfig pluginConfig) {
|
ConnectionRegistryImpl(EventBus eventBus, PluginConfig pluginConfig) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
preferences = pluginConfig.getTransportPreferences();
|
betterTransports = new HashMap<>();
|
||||||
|
for (Pair<TransportId, TransportId> pair :
|
||||||
|
pluginConfig.getTransportPreferences()) {
|
||||||
|
TransportId better = pair.getFirst();
|
||||||
|
TransportId worse = pair.getSecond();
|
||||||
|
List<TransportId> list = betterTransports.get(worse);
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
betterTransports.put(worse, list);
|
||||||
|
}
|
||||||
|
list.add(better);
|
||||||
|
}
|
||||||
contactConnections = new HashMap<>();
|
contactConnections = new HashMap<>();
|
||||||
contactCounts = new Multiset<>();
|
|
||||||
connectedPendingContacts = new HashSet<>();
|
connectedPendingContacts = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,13 +77,13 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
}
|
}
|
||||||
boolean firstConnection = false;
|
boolean firstConnection = false;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
Multiset<ContactId> m = contactConnections.get(t);
|
List<ConnectionRecord> recs = contactConnections.get(c);
|
||||||
if (m == null) {
|
if (recs == null) {
|
||||||
m = new Multiset<>();
|
recs = new ArrayList<>();
|
||||||
contactConnections.put(t, m);
|
contactConnections.put(c, recs);
|
||||||
}
|
}
|
||||||
m.add(c);
|
if (recs.isEmpty()) firstConnection = true;
|
||||||
if (contactCounts.add(c) == 1) firstConnection = true;
|
recs.add(new ConnectionRecord(t));
|
||||||
}
|
}
|
||||||
eventBus.broadcast(new ConnectionOpenedEvent(c, t, incoming));
|
eventBus.broadcast(new ConnectionOpenedEvent(c, t, incoming));
|
||||||
if (firstConnection) {
|
if (firstConnection) {
|
||||||
@@ -93,11 +101,10 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
}
|
}
|
||||||
boolean lastConnection = false;
|
boolean lastConnection = false;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
Multiset<ContactId> m = contactConnections.get(t);
|
List<ConnectionRecord> recs = contactConnections.get(c);
|
||||||
if (m == null || !m.contains(c))
|
if (recs == null || !recs.remove(new ConnectionRecord(t)))
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
m.remove(c);
|
if (recs.isEmpty()) lastConnection = true;
|
||||||
if (contactCounts.remove(c) == 0) lastConnection = true;
|
|
||||||
}
|
}
|
||||||
eventBus.broadcast(new ConnectionClosedEvent(c, t, incoming));
|
eventBus.broadcast(new ConnectionClosedEvent(c, t, incoming));
|
||||||
if (lastConnection) {
|
if (lastConnection) {
|
||||||
@@ -109,12 +116,20 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
@Override
|
@Override
|
||||||
public Collection<ContactId> getConnectedContacts(TransportId t) {
|
public Collection<ContactId> getConnectedContacts(TransportId t) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
Multiset<ContactId> m = contactConnections.get(t);
|
List<ContactId> contactIds = new ArrayList<>();
|
||||||
if (m == null) return emptyList();
|
for (Entry<ContactId, List<ConnectionRecord>> e :
|
||||||
List<ContactId> ids = new ArrayList<>(m.keySet());
|
contactConnections.entrySet()) {
|
||||||
if (LOG.isLoggable(INFO))
|
for (ConnectionRecord rec : e.getValue()) {
|
||||||
LOG.info(ids.size() + " contacts connected: " + t);
|
if (rec.transportId.equals(t)) {
|
||||||
return ids;
|
contactIds.add(e.getKey());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info(contactIds.size() + " contacts connected: " + t);
|
||||||
|
}
|
||||||
|
return contactIds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,34 +137,43 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
public Collection<ContactId> getConnectedOrPreferredContacts(
|
public Collection<ContactId> getConnectedOrPreferredContacts(
|
||||||
TransportId t) {
|
TransportId t) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
Multiset<ContactId> m = contactConnections.get(t);
|
List<TransportId> better = betterTransports.get(t);
|
||||||
if (m == null) return emptyList();
|
if (better == null) better = emptyList();
|
||||||
Set<ContactId> ids = new HashSet<>(m.keySet());
|
List<ContactId> contactIds = new ArrayList<>();
|
||||||
for (Pair<TransportId, TransportId> pair : preferences) {
|
for (Entry<ContactId, List<ConnectionRecord>> e :
|
||||||
if (pair.getSecond().equals(t)) {
|
contactConnections.entrySet()) {
|
||||||
TransportId better = pair.getFirst();
|
for (ConnectionRecord rec : e.getValue()) {
|
||||||
Multiset<ContactId> m1 = contactConnections.get(better);
|
if (rec.transportId.equals(t) ||
|
||||||
if (m1 != null) ids.addAll(m1.keySet());
|
better.contains(rec.transportId)) {
|
||||||
|
contactIds.add(e.getKey());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info(ids.size() + " contacts connected or preferred: " + t);
|
LOG.info(contactIds.size()
|
||||||
return ids;
|
+ " contacts connected or preferred: " + t);
|
||||||
|
}
|
||||||
|
return contactIds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConnected(ContactId c, TransportId t) {
|
public boolean isConnected(ContactId c, TransportId t) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
Multiset<ContactId> m = contactConnections.get(t);
|
List<ConnectionRecord> recs = contactConnections.get(c);
|
||||||
return m != null && m.contains(c);
|
if (recs == null) return false;
|
||||||
|
for (ConnectionRecord rec : recs) {
|
||||||
|
if (rec.transportId.equals(t)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConnected(ContactId c) {
|
public boolean isConnected(ContactId c) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
return contactCounts.contains(c);
|
return contactConnections.containsKey(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,4 +195,27 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
}
|
}
|
||||||
eventBus.broadcast(new RendezvousConnectionClosedEvent(p, success));
|
eventBus.broadcast(new RendezvousConnectionClosedEvent(p, success));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ConnectionRecord {
|
||||||
|
|
||||||
|
private final TransportId transportId;
|
||||||
|
|
||||||
|
private ConnectionRecord(TransportId transportId) {
|
||||||
|
this.transportId = transportId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof ConnectionRecord) {
|
||||||
|
ConnectionRecord rec = (ConnectionRecord) o;
|
||||||
|
return transportId.equals(rec.transportId);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return transportId.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.junit.Test;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.emptyMap;
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getContactId;
|
import static org.briarproject.bramble.test.TestUtils.getContactId;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
@@ -45,7 +44,7 @@ public class ConnectionRegistryImplTest extends BrambleMockTestCase {
|
|||||||
public void testRegisterAndUnregister() {
|
public void testRegisterAndUnregister() {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(pluginConfig).getTransportPreferences();
|
allowing(pluginConfig).getTransportPreferences();
|
||||||
will(returnValue(emptyMap()));
|
will(returnValue(emptyList()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
ConnectionRegistry c =
|
ConnectionRegistry c =
|
||||||
@@ -133,7 +132,7 @@ public class ConnectionRegistryImplTest extends BrambleMockTestCase {
|
|||||||
public void testRegisterAndUnregisterPendingContacts() {
|
public void testRegisterAndUnregisterPendingContacts() {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(pluginConfig).getTransportPreferences();
|
allowing(pluginConfig).getTransportPreferences();
|
||||||
will(returnValue(emptyMap()));
|
will(returnValue(emptyList()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
ConnectionRegistry c =
|
ConnectionRegistry c =
|
||||||
|
|||||||
Reference in New Issue
Block a user