mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 04:39:54 +01:00
Implement the Mailbox property client
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.bramble.client;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.UniqueId;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
@@ -22,6 +23,9 @@ import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
@@ -29,6 +33,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.util.Base32;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -39,6 +44,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -46,6 +52,12 @@ import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KE
|
||||
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_COUNT;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_AUTHTOKEN;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_INBOXID;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_ONIONADDRESS;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_OUTBOXID;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_ONIONADDRESS_LENGTH;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
||||
@@ -399,6 +411,35 @@ class ClientHelperImpl implements ClientHelper {
|
||||
return tpMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public MailboxPropertiesUpdate parseAndValidateMailboxPropertiesUpdate(
|
||||
BdfDictionary properties) throws FormatException {
|
||||
if (properties.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// Accepting more props than we need, for forward compatibility
|
||||
if (properties.size() < PROP_COUNT) {
|
||||
throw new FormatException();
|
||||
}
|
||||
String onionAddress = properties.getString(PROP_KEY_ONIONADDRESS);
|
||||
checkLength(onionAddress, PROP_ONIONADDRESS_LENGTH);
|
||||
try {
|
||||
Base32.decode(onionAddress, true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new FormatException();
|
||||
}
|
||||
byte[] authToken = properties.getRaw(PROP_KEY_AUTHTOKEN);
|
||||
checkLength(authToken, UniqueId.LENGTH);
|
||||
byte[] inboxId = properties.getRaw(PROP_KEY_INBOXID);
|
||||
checkLength(inboxId, UniqueId.LENGTH);
|
||||
byte[] outboxId = properties.getRaw(PROP_KEY_OUTBOXID);
|
||||
checkLength(outboxId, UniqueId.LENGTH);
|
||||
return new MailboxPropertiesUpdate(onionAddress,
|
||||
new MailboxAuthToken(authToken), new MailboxFolderId(inboxId),
|
||||
new MailboxFolderId(outboxId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
||||
throws DbException {
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxManager;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.CLIENT_ID;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MAJOR_VERSION;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MINOR_VERSION;
|
||||
|
||||
@Module
|
||||
public class MailboxModule {
|
||||
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
MailboxPropertyValidator mailboxPropertyValidator;
|
||||
@Inject
|
||||
MailboxPropertyManager mailboxPropertyManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
MailboxManager providesMailboxManager(MailboxManagerImpl mailboxManager) {
|
||||
@@ -33,4 +53,34 @@ public class MailboxModule {
|
||||
MailboxApi providesMailboxApi(MailboxApiImpl mailboxApi) {
|
||||
return mailboxApi;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
MailboxPropertyValidator provideMailboxPropertyValidator(
|
||||
ValidationManager validationManager, ClientHelper clientHelper,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
MailboxPropertyValidator validator = new MailboxPropertyValidator(
|
||||
clientHelper, metadataEncoder, clock);
|
||||
validationManager.registerMessageValidator(CLIENT_ID, MAJOR_VERSION,
|
||||
validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
MailboxPropertyManager provideMailboxPropertyManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
ValidationManager validationManager, ContactManager contactManager,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
MailboxSettingsManager mailboxSettingsManager,
|
||||
MailboxPropertyManagerImpl mailboxPropertyManager) {
|
||||
lifecycleManager.registerOpenDatabaseHook(mailboxPropertyManager);
|
||||
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
|
||||
mailboxPropertyManager);
|
||||
contactManager.registerContactHook(mailboxPropertyManager);
|
||||
clientVersioningManager.registerClient(CLIENT_ID, MAJOR_VERSION,
|
||||
MINOR_VERSION, mailboxPropertyManager);
|
||||
mailboxSettingsManager.registerMailboxHook(mailboxPropertyManager);
|
||||
return mailboxPropertyManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.MetadataParser;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager.MailboxHook;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Group.Visibility;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE;
|
||||
|
||||
@NotNullByDefault
|
||||
class MailboxPropertyManagerImpl implements MailboxPropertyManager,
|
||||
OpenDatabaseHook, ContactHook, ClientVersioningHook,
|
||||
IncomingMessageHook, MailboxHook {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final ClientHelper clientHelper;
|
||||
private final ClientVersioningManager clientVersioningManager;
|
||||
private final MetadataParser metadataParser;
|
||||
private final ContactGroupFactory contactGroupFactory;
|
||||
private final Clock clock;
|
||||
private final MailboxSettingsManager mailboxSettingsManager;
|
||||
private final ContactManager contactManager;
|
||||
private final CryptoComponent crypto;
|
||||
private final Group localGroup;
|
||||
|
||||
@Inject
|
||||
MailboxPropertyManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
MetadataParser metadataParser,
|
||||
ContactGroupFactory contactGroupFactory, Clock clock,
|
||||
MailboxSettingsManager mailboxSettingsManager,
|
||||
ContactManager contactManager,
|
||||
CryptoComponent crypto) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.metadataParser = metadataParser;
|
||||
this.contactGroupFactory = contactGroupFactory;
|
||||
this.clock = clock;
|
||||
this.mailboxSettingsManager = mailboxSettingsManager;
|
||||
this.contactManager = contactManager;
|
||||
this.crypto = crypto;
|
||||
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
|
||||
MAJOR_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatabaseOpened(Transaction txn) throws DbException {
|
||||
if (db.containsGroup(txn, localGroup.getId())) {
|
||||
return;
|
||||
}
|
||||
db.addGroup(txn, localGroup);
|
||||
// Set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) {
|
||||
addingContact(txn, c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
db.addGroup(txn, g);
|
||||
// Apply the client's visibility to the contact group
|
||||
Visibility client = clientVersioningManager
|
||||
.getClientVisibility(txn, c.getId(), CLIENT_ID, MAJOR_VERSION);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
|
||||
// If we are paired, create and send props to the newly added contact
|
||||
MailboxProperties ownProps =
|
||||
mailboxSettingsManager.getOwnMailboxProperties(txn);
|
||||
if (ownProps != null) {
|
||||
createAndSendProperties(txn, c, ownProps.getOnion());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removingContact(Transaction txn, Contact c) throws DbException {
|
||||
db.removeGroup(txn, getContactGroup(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mailboxPaired(Transaction txn, String ownOnion)
|
||||
throws DbException {
|
||||
for (Contact c : contactManager.getContacts()) {
|
||||
createAndSendProperties(txn, c, ownOnion);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mailboxUnpaired(Transaction txn) throws DbException {
|
||||
for (Contact c : contactManager.getContacts()) {
|
||||
sendEmptyProperties(txn, c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientVisibilityChanging(Transaction txn, Contact c,
|
||||
Visibility v) throws DbException {
|
||||
// Apply the client's visibility to the contact group
|
||||
Group g = getContactGroup(c);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeliveryAction incomingMessage(Transaction txn, Message m,
|
||||
Metadata meta) throws DbException, InvalidMessageException {
|
||||
try {
|
||||
BdfDictionary d = metadataParser.parse(meta);
|
||||
// Get latest non-local update in the same group (from same contact)
|
||||
LatestUpdate latest = findLatest(txn, m.getGroupId(), false);
|
||||
if (latest != null) {
|
||||
if (d.getLong(MSG_KEY_VERSION) > latest.version) {
|
||||
db.deleteMessage(txn, latest.messageId);
|
||||
db.deleteMessageMetadata(txn, latest.messageId);
|
||||
} else {
|
||||
// Delete this update, we already have a newer one
|
||||
db.deleteMessage(txn, m.getId());
|
||||
db.deleteMessageMetadata(txn, m.getId());
|
||||
return ACCEPT_DO_NOT_SHARE;
|
||||
}
|
||||
}
|
||||
// TODO should probably broadcast an event that a contact's mailbox
|
||||
// properties were updated
|
||||
} catch (FormatException e) {
|
||||
throw new InvalidMessageException(e);
|
||||
}
|
||||
return ACCEPT_DO_NOT_SHARE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public MailboxPropertiesUpdate getLocalProperties(Transaction txn,
|
||||
ContactId c) throws DbException {
|
||||
return getProperties(txn, db.getContact(txn, c), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public MailboxPropertiesUpdate getRemoteProperties(Transaction txn,
|
||||
ContactId c) throws DbException {
|
||||
return getProperties(txn, db.getContact(txn, c), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and sends an update message to the given contact. The message
|
||||
* holds our own mailbox's onion, and generated unique properties. All of
|
||||
* which the contact needs to communicate with our Mailbox.
|
||||
*/
|
||||
private void createAndSendProperties(Transaction txn,
|
||||
Contact c, String ownOnion) throws DbException {
|
||||
MailboxPropertiesUpdate p = new MailboxPropertiesUpdate(ownOnion,
|
||||
new MailboxAuthToken(crypto.generateUniqueId().getBytes()),
|
||||
new MailboxFolderId(crypto.generateUniqueId().getBytes()),
|
||||
new MailboxFolderId(crypto.generateUniqueId().getBytes()));
|
||||
Group g = getContactGroup(c);
|
||||
storeMessageReplaceLatest(txn, g.getId(), p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an empty update message to the given contact. The empty update
|
||||
* indicates for the receiving contact that we no longer have a Mailbox that
|
||||
* they can use.
|
||||
*/
|
||||
private void sendEmptyProperties(Transaction txn, Contact c)
|
||||
throws DbException {
|
||||
Group g = getContactGroup(c);
|
||||
storeMessageReplaceLatest(txn, g.getId(), null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MailboxPropertiesUpdate getProperties(Transaction txn,
|
||||
Contact c, boolean local) throws DbException {
|
||||
MailboxPropertiesUpdate p = null;
|
||||
Group g = getContactGroup(c);
|
||||
try {
|
||||
LatestUpdate latest = findLatest(txn, g.getId(), local);
|
||||
if (latest != null) {
|
||||
BdfList body =
|
||||
clientHelper.getMessageAsList(txn, latest.messageId);
|
||||
p = parseProperties(body);
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private void storeMessageReplaceLatest(Transaction txn, GroupId g,
|
||||
@Nullable MailboxPropertiesUpdate p) throws DbException {
|
||||
try {
|
||||
LatestUpdate latest = findLatest(txn, g, true);
|
||||
long version = latest == null ? 1 : latest.version + 1;
|
||||
Message m = clientHelper.createMessage(g, clock.currentTimeMillis(),
|
||||
encodeProperties(version, p));
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(MSG_KEY_VERSION, version);
|
||||
meta.put(MSG_KEY_LOCAL, true);
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
if (latest != null) {
|
||||
db.removeMessage(txn, latest.messageId);
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
|
||||
throws DbException, FormatException {
|
||||
Map<MessageId, BdfDictionary> metadata =
|
||||
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
||||
// We should have at most 1 local and 1 remote
|
||||
if (metadata.size() > 2) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
||||
BdfDictionary meta = e.getValue();
|
||||
if (meta.getBoolean(MSG_KEY_LOCAL) == local) {
|
||||
return new LatestUpdate(e.getKey(),
|
||||
meta.getLong(MSG_KEY_VERSION));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private BdfList encodeProperties(long version,
|
||||
@Nullable MailboxPropertiesUpdate p) {
|
||||
BdfDictionary dict = new BdfDictionary();
|
||||
if (p != null) {
|
||||
dict.put(PROP_KEY_ONIONADDRESS, p.getOnionAddress());
|
||||
dict.put(PROP_KEY_AUTHTOKEN, p.getAuthToken().getBytes());
|
||||
dict.put(PROP_KEY_INBOXID, p.getInboxId().getBytes());
|
||||
dict.put(PROP_KEY_OUTBOXID, p.getOutboxId().getBytes());
|
||||
}
|
||||
return BdfList.of(version, dict);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MailboxPropertiesUpdate parseProperties(BdfList body)
|
||||
throws FormatException {
|
||||
BdfDictionary dict = body.getDictionary(1);
|
||||
return clientHelper.parseAndValidateMailboxPropertiesUpdate(dict);
|
||||
}
|
||||
|
||||
private Group getContactGroup(Contact c) {
|
||||
return contactGroupFactory.createContactGroup(CLIENT_ID, MAJOR_VERSION,
|
||||
c);
|
||||
}
|
||||
|
||||
private static class LatestUpdate {
|
||||
|
||||
private final MessageId messageId;
|
||||
private final long version;
|
||||
|
||||
private LatestUpdate(MessageId messageId, long version) {
|
||||
this.messageId = messageId;
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.BdfMessageContext;
|
||||
import org.briarproject.bramble.api.client.BdfMessageValidator;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_VERSION;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class MailboxPropertyValidator extends BdfMessageValidator {
|
||||
|
||||
MailboxPropertyValidator(ClientHelper clientHelper,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
super(clientHelper, metadataEncoder, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws InvalidMessageException, FormatException {
|
||||
// Version, properties
|
||||
checkSize(body, 2);
|
||||
// Version
|
||||
long version = body.getLong(0);
|
||||
if (version < 0) throw new FormatException();
|
||||
// Properties
|
||||
BdfDictionary dictionary = body.getDictionary(1);
|
||||
clientHelper.parseAndValidateMailboxPropertiesUpdate(dictionary);
|
||||
// Return the metadata
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(MSG_KEY_VERSION, version);
|
||||
meta.put(MSG_KEY_LOCAL, false);
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.settings.Settings;
|
||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
@@ -32,12 +35,18 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
|
||||
static final String SETTINGS_UPLOADS_NAMESPACE = "mailbox-uploads";
|
||||
|
||||
private final SettingsManager settingsManager;
|
||||
private final List<MailboxHook> hooks = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Inject
|
||||
MailboxSettingsManagerImpl(SettingsManager settingsManager) {
|
||||
this.settingsManager = settingsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerMailboxHook(MailboxHook hook) {
|
||||
hooks.add(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MailboxProperties getOwnMailboxProperties(Transaction txn)
|
||||
throws DbException {
|
||||
@@ -60,6 +69,9 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
|
||||
s.put(SETTINGS_KEY_ONION, p.getBaseUrl());
|
||||
s.put(SETTINGS_KEY_TOKEN, p.getAuthToken().toString());
|
||||
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
|
||||
for (MailboxHook hook : hooks) {
|
||||
hook.mailboxPaired(txn, p.getOnion());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user