mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Broadcast an event when remote transport properties are updated.
This commit is contained in:
@@ -35,4 +35,15 @@ public interface TransportPropertyConstants {
|
|||||||
* contact, as a BDF dictionary.
|
* contact, as a BDF dictionary.
|
||||||
*/
|
*/
|
||||||
String GROUP_KEY_DISCOVERED = "discovered";
|
String GROUP_KEY_DISCOVERED = "discovered";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group metadata key for the contact's ID as a BDF long.
|
||||||
|
*/
|
||||||
|
String GROUP_KEY_CONTACT_ID = "contactId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group metadata key for the local group, indicating that contact IDs have
|
||||||
|
* been stored in the group metadata of contact groups.
|
||||||
|
*/
|
||||||
|
String GROUP_KEY_CONTACT_IDS_STORED = "contactIdsStored";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.briarproject.bramble.api.properties.event;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event that is broadcast when {@link TransportProperties} are received
|
||||||
|
* from a contact.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
public class RemoteTransportPropertiesUpdatedEvent extends Event {
|
||||||
|
|
||||||
|
private final ContactId contactId;
|
||||||
|
private final TransportId transportId;
|
||||||
|
|
||||||
|
public RemoteTransportPropertiesUpdatedEvent(ContactId contactId,
|
||||||
|
TransportId transportId) {
|
||||||
|
this.contactId = contactId;
|
||||||
|
this.transportId = transportId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContactId getContactId() {
|
||||||
|
return contactId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransportId getTransportId() {
|
||||||
|
return transportId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||||
|
import org.briarproject.bramble.api.properties.event.RemoteTransportPropertiesUpdatedEvent;
|
||||||
import org.briarproject.bramble.api.sync.Group;
|
import org.briarproject.bramble.api.sync.Group;
|
||||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
@@ -37,6 +38,8 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_CONTACT_ID;
|
||||||
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_CONTACT_IDS_STORED;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
||||||
@@ -74,7 +77,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDatabaseOpened(Transaction txn) throws DbException {
|
public void onDatabaseOpened(Transaction txn) throws DbException {
|
||||||
if (db.containsGroup(txn, localGroup.getId())) return;
|
if (db.containsGroup(txn, localGroup.getId())) {
|
||||||
|
storeContactIdsForContactGroups(txn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
db.addGroup(txn, localGroup);
|
db.addGroup(txn, localGroup);
|
||||||
// Set things up for any pre-existing contacts
|
// Set things up for any pre-existing contacts
|
||||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
@@ -89,6 +95,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
Visibility client = clientVersioningManager.getClientVisibility(txn,
|
Visibility client = clientVersioningManager.getClientVisibility(txn,
|
||||||
c.getId(), CLIENT_ID, MAJOR_VERSION);
|
c.getId(), CLIENT_ID, MAJOR_VERSION);
|
||||||
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
|
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
|
||||||
|
// Attach the contact ID to the group
|
||||||
|
storeContactId(txn, c, g);
|
||||||
// Copy the latest local properties into the group
|
// Copy the latest local properties into the group
|
||||||
Map<TransportId, TransportProperties> local = getLocalProperties(txn);
|
Map<TransportId, TransportProperties> local = getLocalProperties(txn);
|
||||||
for (Entry<TransportId, TransportProperties> e : local.entrySet()) {
|
for (Entry<TransportId, TransportProperties> e : local.entrySet()) {
|
||||||
@@ -127,8 +135,11 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
// We've already received a newer update - delete this one
|
// We've already received a newer update - delete this one
|
||||||
db.deleteMessage(txn, m.getId());
|
db.deleteMessage(txn, m.getId());
|
||||||
db.deleteMessageMetadata(txn, m.getId());
|
db.deleteMessageMetadata(txn, m.getId());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ContactId c = getContactId(txn, m.getGroupId());
|
||||||
|
txn.attach(new RemoteTransportPropertiesUpdatedEvent(c, t));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new InvalidMessageException(e);
|
throw new InvalidMessageException(e);
|
||||||
}
|
}
|
||||||
@@ -224,6 +235,40 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeContactIdsForContactGroups(Transaction txn)
|
||||||
|
throws DbException {
|
||||||
|
try {
|
||||||
|
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
if (meta.containsKey(GROUP_KEY_CONTACT_IDS_STORED)) return;
|
||||||
|
for (Contact c : db.getContacts(txn)) {
|
||||||
|
storeContactId(txn, c, getContactGroup(c));
|
||||||
|
}
|
||||||
|
meta.put(GROUP_KEY_CONTACT_IDS_STORED, true);
|
||||||
|
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeContactId(Transaction txn, Contact c, Group contactGroup)
|
||||||
|
throws DbException {
|
||||||
|
BdfDictionary meta = new BdfDictionary();
|
||||||
|
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
|
||||||
|
try {
|
||||||
|
clientHelper.mergeGroupMetadata(txn, contactGroup.getId(), meta);
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
||||||
|
throws DbException, FormatException {
|
||||||
|
BdfDictionary meta =
|
||||||
|
clientHelper.getGroupMetadataAsDictionary(txn, contactGroupId);
|
||||||
|
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
||||||
TransportId t) throws DbException {
|
TransportId t) throws DbException {
|
||||||
Group g = getContactGroup(c);
|
Group g = getContactGroup(c);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import static java.util.Arrays.asList;
|
|||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_CONTACT_ID;
|
||||||
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_CONTACT_IDS_STORED;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
||||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
||||||
@@ -94,6 +96,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
Contact contact = getContact();
|
Contact contact = getContact();
|
||||||
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||||
|
BdfDictionary contactGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt())
|
||||||
|
);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).containsGroup(txn, localGroup.getId());
|
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||||
@@ -110,6 +115,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(SHARED));
|
will(returnValue(SHARED));
|
||||||
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
||||||
contactGroup.getId(), SHARED);
|
contactGroup.getId(), SHARED);
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||||
|
contactGroupMeta);
|
||||||
}});
|
}});
|
||||||
// Copy the latest local properties into the group
|
// Copy the latest local properties into the group
|
||||||
expectGetLocalProperties(txn);
|
expectGetLocalProperties(txn);
|
||||||
@@ -123,13 +130,57 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoesNotCreateGroupsAtStartupIfAlreadyCreated()
|
public void testAddsContactIdsToGroupsAtStartupIfAlreadyCreated()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact();
|
||||||
|
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||||
|
BdfDictionary contactGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt())
|
||||||
|
);
|
||||||
|
BdfDictionary localGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_IDS_STORED, true)
|
||||||
|
);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).containsGroup(txn, localGroup.getId());
|
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
|
// Contact IDs have not been added to contact groups
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(new BdfDictionary()));
|
||||||
|
// Add contact IDs to contact groups
|
||||||
|
oneOf(db).getContacts(txn);
|
||||||
|
will(returnValue(singletonList(contact)));
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||||
|
MAJOR_VERSION, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||||
|
contactGroupMeta);
|
||||||
|
// Remember that contact IDs have been added
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
|
||||||
|
localGroupMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.onDatabaseOpened(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotAddContactIdsToGroupsAtStartupIfAlreadyAdded()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
BdfDictionary localGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_IDS_STORED, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||||
|
will(returnValue(true));
|
||||||
|
// Contact IDs have already been added to contact groups
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(localGroupMeta));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
TransportPropertyManagerImpl t = createInstance();
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
@@ -141,6 +192,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
Contact contact = getContact();
|
Contact contact = getContact();
|
||||||
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||||
|
BdfDictionary contactGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt())
|
||||||
|
);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Create the group and share it with the contact
|
// Create the group and share it with the contact
|
||||||
@@ -153,6 +207,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(SHARED));
|
will(returnValue(SHARED));
|
||||||
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
||||||
contactGroup.getId(), SHARED);
|
contactGroup.getId(), SHARED);
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||||
|
contactGroupMeta);
|
||||||
}});
|
}});
|
||||||
// Copy the latest local properties into the group
|
// Copy the latest local properties into the group
|
||||||
expectGetLocalProperties(txn);
|
expectGetLocalProperties(txn);
|
||||||
@@ -186,7 +242,11 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
|
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact();
|
||||||
GroupId contactGroupId = new GroupId(getRandomId());
|
GroupId contactGroupId = new GroupId(getRandomId());
|
||||||
|
BdfDictionary contactGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt())
|
||||||
|
);
|
||||||
Message message = getMessage(contactGroupId);
|
Message message = getMessage(contactGroupId);
|
||||||
Metadata meta = new Metadata();
|
Metadata meta = new Metadata();
|
||||||
BdfDictionary metaDictionary = BdfDictionary.of(
|
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||||
@@ -217,6 +277,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
contactGroupId);
|
contactGroupId);
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
|
// Look up the contact ID to broadcast an event
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroupId);
|
||||||
|
will(returnValue(contactGroupMeta));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
TransportPropertyManagerImpl t = createInstance();
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
@@ -227,7 +291,11 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testDeletesOlderUpdatesWhenUpdateIsDelivered()
|
public void testDeletesOlderUpdatesWhenUpdateIsDelivered()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact();
|
||||||
GroupId contactGroupId = new GroupId(getRandomId());
|
GroupId contactGroupId = new GroupId(getRandomId());
|
||||||
|
BdfDictionary contactGroupMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt())
|
||||||
|
);
|
||||||
Message message = getMessage(contactGroupId);
|
Message message = getMessage(contactGroupId);
|
||||||
Metadata meta = new Metadata();
|
Metadata meta = new Metadata();
|
||||||
// Version 4 is being delivered
|
// Version 4 is being delivered
|
||||||
@@ -255,6 +323,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
// The previous update (version 3) should be deleted
|
// The previous update (version 3) should be deleted
|
||||||
oneOf(db).deleteMessage(txn, fooVersion3);
|
oneOf(db).deleteMessage(txn, fooVersion3);
|
||||||
oneOf(db).deleteMessageMetadata(txn, fooVersion3);
|
oneOf(db).deleteMessageMetadata(txn, fooVersion3);
|
||||||
|
// Look up the contact ID to broadcast an event
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroupId);
|
||||||
|
will(returnValue(contactGroupMeta));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
TransportPropertyManagerImpl t = createInstance();
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
@@ -292,6 +364,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
// The update being delivered (version 3) should be deleted
|
// The update being delivered (version 3) should be deleted
|
||||||
oneOf(db).deleteMessage(txn, message.getId());
|
oneOf(db).deleteMessage(txn, message.getId());
|
||||||
oneOf(db).deleteMessageMetadata(txn, message.getId());
|
oneOf(db).deleteMessageMetadata(txn, message.getId());
|
||||||
|
// No event should be broadcast
|
||||||
}});
|
}});
|
||||||
|
|
||||||
TransportPropertyManagerImpl t = createInstance();
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
|||||||
Reference in New Issue
Block a user