mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Use ClientHelper in ForumSharingManagerImpl.
This commit is contained in:
@@ -3,18 +3,14 @@ package org.briarproject.forum;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.briarproject.api.FormatException;
|
import org.briarproject.api.FormatException;
|
||||||
|
import org.briarproject.api.clients.ClientHelper;
|
||||||
import org.briarproject.api.clients.PrivateGroupFactory;
|
import org.briarproject.api.clients.PrivateGroupFactory;
|
||||||
import org.briarproject.api.contact.Contact;
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.contact.ContactManager.AddContactHook;
|
import org.briarproject.api.contact.ContactManager.AddContactHook;
|
||||||
import org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
import org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
||||||
import org.briarproject.api.data.BdfDictionary;
|
import org.briarproject.api.data.BdfDictionary;
|
||||||
import org.briarproject.api.data.BdfReader;
|
import org.briarproject.api.data.BdfList;
|
||||||
import org.briarproject.api.data.BdfReaderFactory;
|
|
||||||
import org.briarproject.api.data.BdfWriter;
|
|
||||||
import org.briarproject.api.data.BdfWriterFactory;
|
|
||||||
import org.briarproject.api.data.MetadataEncoder;
|
|
||||||
import org.briarproject.api.data.MetadataParser;
|
|
||||||
import org.briarproject.api.db.DatabaseComponent;
|
import org.briarproject.api.db.DatabaseComponent;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.db.Metadata;
|
import org.briarproject.api.db.Metadata;
|
||||||
@@ -27,14 +23,11 @@ import org.briarproject.api.sync.Group;
|
|||||||
import org.briarproject.api.sync.GroupFactory;
|
import org.briarproject.api.sync.GroupFactory;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageFactory;
|
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
import org.briarproject.api.sync.ValidationManager.ValidationHook;
|
import org.briarproject.api.sync.ValidationManager.ValidationHook;
|
||||||
import org.briarproject.api.system.Clock;
|
import org.briarproject.api.system.Clock;
|
||||||
import org.briarproject.util.StringUtils;
|
import org.briarproject.util.StringUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -61,33 +54,23 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final ForumManager forumManager;
|
private final ForumManager forumManager;
|
||||||
|
private final ClientHelper clientHelper;
|
||||||
private final GroupFactory groupFactory;
|
private final GroupFactory groupFactory;
|
||||||
private final PrivateGroupFactory privateGroupFactory;
|
private final PrivateGroupFactory privateGroupFactory;
|
||||||
private final MessageFactory messageFactory;
|
|
||||||
private final BdfReaderFactory bdfReaderFactory;
|
|
||||||
private final BdfWriterFactory bdfWriterFactory;
|
|
||||||
private final MetadataEncoder metadataEncoder;
|
|
||||||
private final MetadataParser metadataParser;
|
|
||||||
private final SecureRandom random;
|
private final SecureRandom random;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final Group localGroup;
|
private final Group localGroup;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ForumSharingManagerImpl(DatabaseComponent db,
|
ForumSharingManagerImpl(DatabaseComponent db, ForumManager forumManager,
|
||||||
ForumManager forumManager, GroupFactory groupFactory,
|
ClientHelper clientHelper, GroupFactory groupFactory,
|
||||||
PrivateGroupFactory privateGroupFactory,
|
PrivateGroupFactory privateGroupFactory, SecureRandom random,
|
||||||
MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory,
|
Clock clock) {
|
||||||
BdfWriterFactory bdfWriterFactory, MetadataEncoder metadataEncoder,
|
|
||||||
MetadataParser metadataParser, SecureRandom random, Clock clock) {
|
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.forumManager = forumManager;
|
this.forumManager = forumManager;
|
||||||
|
this.clientHelper = clientHelper;
|
||||||
this.groupFactory = groupFactory;
|
this.groupFactory = groupFactory;
|
||||||
this.privateGroupFactory = privateGroupFactory;
|
this.privateGroupFactory = privateGroupFactory;
|
||||||
this.messageFactory = messageFactory;
|
|
||||||
this.bdfReaderFactory = bdfReaderFactory;
|
|
||||||
this.bdfWriterFactory = bdfWriterFactory;
|
|
||||||
this.metadataEncoder = metadataEncoder;
|
|
||||||
this.metadataParser = metadataParser;
|
|
||||||
this.random = random;
|
this.random = random;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
localGroup = groupFactory.createGroup(CLIENT_ID,
|
localGroup = groupFactory.createGroup(CLIENT_ID,
|
||||||
@@ -103,9 +86,9 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
db.addGroup(txn, g);
|
db.addGroup(txn, g);
|
||||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||||
// Attach the contact ID to the group
|
// Attach the contact ID to the group
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
d.put("contactId", c.getId().getInt());
|
meta.put("contactId", c.getId().getInt());
|
||||||
db.mergeGroupMetadata(txn, g.getId(), metadataEncoder.encode(d));
|
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||||
// Share any forums that are shared with all contacts
|
// Share any forums that are shared with all contacts
|
||||||
List<Forum> shared = getForumsSharedWithAllContacts(txn);
|
List<Forum> shared = getForumsSharedWithAllContacts(txn);
|
||||||
storeMessage(txn, g.getId(), shared, 0);
|
storeMessage(txn, g.getId(), shared, 0);
|
||||||
@@ -193,8 +176,9 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
LatestUpdate latest = findLatest(txn, g.getId(), false);
|
LatestUpdate latest = findLatest(txn, g.getId(), false);
|
||||||
if (latest != null) {
|
if (latest != null) {
|
||||||
// Retrieve and parse the latest update
|
// Retrieve and parse the latest update
|
||||||
byte[] raw = db.getRawMessage(txn, latest.messageId);
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
for (Forum f : parseForumList(raw)) {
|
latest.messageId);
|
||||||
|
for (Forum f : parseForumList(message)) {
|
||||||
if (!subscribed.contains(f.getGroup()))
|
if (!subscribed.contains(f.getGroup()))
|
||||||
available.add(f);
|
available.add(f);
|
||||||
}
|
}
|
||||||
@@ -321,94 +305,64 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), true);
|
LatestUpdate latest = findLatest(txn, localGroup.getId(), true);
|
||||||
if (latest == null) return Collections.emptyList();
|
if (latest == null) return Collections.emptyList();
|
||||||
// Retrieve and parse the latest update
|
// Retrieve and parse the latest update
|
||||||
return parseForumList(db.getRawMessage(txn, latest.messageId));
|
BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
|
||||||
|
return parseForumList(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
|
private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
LatestUpdate latest = null;
|
LatestUpdate latest = null;
|
||||||
Map<MessageId, Metadata> metadata = db.getMessageMetadata(txn, g);
|
Map<MessageId, BdfDictionary> metadata =
|
||||||
for (Entry<MessageId, Metadata> e : metadata.entrySet()) {
|
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
||||||
BdfDictionary d = metadataParser.parse(e.getValue());
|
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
||||||
if (d.getBoolean("local") != local) continue;
|
BdfDictionary meta = e.getValue();
|
||||||
long version = d.getLong("version");
|
if (meta.getBoolean("local") != local) continue;
|
||||||
|
long version = meta.getLong("version");
|
||||||
if (latest == null || version > latest.version)
|
if (latest == null || version > latest.version)
|
||||||
latest = new LatestUpdate(e.getKey(), version);
|
latest = new LatestUpdate(e.getKey(), version);
|
||||||
}
|
}
|
||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Forum> parseForumList(byte[] raw) throws FormatException {
|
private List<Forum> parseForumList(BdfList message) throws FormatException {
|
||||||
List<Forum> forums = new ArrayList<Forum>();
|
// Version, forum list
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(raw,
|
BdfList forumList = message.getList(1);
|
||||||
MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
|
List<Forum> forums = new ArrayList<Forum>(forumList.size());
|
||||||
BdfReader r = bdfReaderFactory.createReader(in);
|
for (int i = 0; i < forumList.size(); i++) {
|
||||||
try {
|
// Name, salt
|
||||||
r.readListStart();
|
BdfList forum = forumList.getList(i);
|
||||||
r.skipLong(); // Version
|
forums.add(createForum(forum.getString(0), forum.getRaw(1)));
|
||||||
r.readListStart();
|
|
||||||
while (!r.hasListEnd()) {
|
|
||||||
r.readListStart();
|
|
||||||
String name = r.readString(MAX_FORUM_NAME_LENGTH);
|
|
||||||
byte[] salt = r.readRaw(FORUM_SALT_LENGTH);
|
|
||||||
r.readListEnd();
|
|
||||||
forums.add(createForum(name, salt));
|
|
||||||
}
|
|
||||||
r.readListEnd();
|
|
||||||
r.readListEnd();
|
|
||||||
if (!r.eof()) throw new FormatException();
|
|
||||||
return forums;
|
|
||||||
} catch (FormatException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Shouldn't happen with ByteArrayInputStream
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
return forums;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeMessage(Transaction txn, GroupId g, List<Forum> forums,
|
private void storeMessage(Transaction txn, GroupId g, List<Forum> forums,
|
||||||
long version) throws DbException {
|
long version) throws DbException {
|
||||||
try {
|
try {
|
||||||
byte[] body = encodeForumList(forums, version);
|
BdfList body = encodeForumList(forums, version);
|
||||||
long now = clock.currentTimeMillis();
|
long now = clock.currentTimeMillis();
|
||||||
Message m = messageFactory.createMessage(g, now, body);
|
Message m = clientHelper.createMessage(g, now, body);
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
d.put("version", version);
|
meta.put("version", version);
|
||||||
d.put("local", true);
|
meta.put("local", true);
|
||||||
Metadata meta = metadataEncoder.encode(d);
|
clientHelper.addLocalMessage(txn, m, CLIENT_ID, meta, true);
|
||||||
db.addLocalMessage(txn, m, CLIENT_ID, meta, true);
|
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] encodeForumList(List<Forum> forums, long version) {
|
private BdfList encodeForumList(List<Forum> forums, long version) {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
BdfList forumList = new BdfList();
|
||||||
BdfWriter w = bdfWriterFactory.createWriter(out);
|
for (Forum f : forums)
|
||||||
try {
|
forumList.add(BdfList.of(f.getName(), f.getSalt()));
|
||||||
w.writeListStart();
|
return BdfList.of(version, forumList);
|
||||||
w.writeLong(version);
|
|
||||||
w.writeListStart();
|
|
||||||
for (Forum f : forums) {
|
|
||||||
w.writeListStart();
|
|
||||||
w.writeString(f.getName());
|
|
||||||
w.writeRaw(f.getSalt());
|
|
||||||
w.writeListEnd();
|
|
||||||
}
|
|
||||||
w.writeListEnd();
|
|
||||||
w.writeListEnd();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Shouldn't happen with ByteArrayOutputStream
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return out.toByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
Metadata meta = db.getGroupMetadata(txn, contactGroupId);
|
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
|
||||||
BdfDictionary d = metadataParser.parse(meta);
|
contactGroupId);
|
||||||
return new ContactId(d.getLong("contactId").intValue());
|
return new ContactId(meta.getLong("contactId").intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<GroupId> getVisibleForums(Transaction txn,
|
private Set<GroupId> getVisibleForums(Transaction txn,
|
||||||
@@ -418,9 +372,13 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
// If there's no local update, no forums are visible
|
// If there's no local update, no forums are visible
|
||||||
if (local == null) return Collections.emptySet();
|
if (local == null) return Collections.emptySet();
|
||||||
// Intersect the sets of shared forums
|
// Intersect the sets of shared forums
|
||||||
byte[] localRaw = db.getRawMessage(txn, local.messageId);
|
BdfList localMessage = clientHelper.getMessageAsList(txn,
|
||||||
Set<Forum> shared = new HashSet<Forum>(parseForumList(localRaw));
|
local.messageId);
|
||||||
shared.retainAll(parseForumList(remoteUpdate.getRaw()));
|
Set<Forum> shared = new HashSet<Forum>(parseForumList(localMessage));
|
||||||
|
byte[] raw = remoteUpdate.getRaw();
|
||||||
|
BdfList remoteMessage = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
|
||||||
|
raw.length - MESSAGE_HEADER_LENGTH);
|
||||||
|
shared.retainAll(parseForumList(remoteMessage));
|
||||||
// Forums in the intersection should be visible
|
// Forums in the intersection should be visible
|
||||||
Set<GroupId> visible = new HashSet<GroupId>(shared.size());
|
Set<GroupId> visible = new HashSet<GroupId>(shared.size());
|
||||||
for (Forum f : shared) visible.add(f.getId());
|
for (Forum f : shared) visible.add(f.getId());
|
||||||
@@ -440,46 +398,30 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Forum createForum(String name, byte[] salt) {
|
private Forum createForum(String name, byte[] salt) {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
BdfWriter w = bdfWriterFactory.createWriter(out);
|
|
||||||
try {
|
try {
|
||||||
w.writeListStart();
|
BdfList forum = BdfList.of(name, salt);
|
||||||
w.writeString(name);
|
byte[] descriptor = clientHelper.toByteArray(forum);
|
||||||
w.writeRaw(salt);
|
Group g = groupFactory.createGroup(forumManager.getClientId(),
|
||||||
w.writeListEnd();
|
descriptor);
|
||||||
} catch (IOException e) {
|
return new Forum(g, name, salt);
|
||||||
// Shouldn't happen with ByteArrayOutputStream
|
} catch (FormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
Group g = groupFactory.createGroup(forumManager.getClientId(),
|
|
||||||
out.toByteArray());
|
|
||||||
return new Forum(g, name, salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Forum parseForum(Group g) throws FormatException {
|
private Forum parseForum(Group g) throws FormatException {
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(g.getDescriptor());
|
byte[] descriptor = g.getDescriptor();
|
||||||
BdfReader r = bdfReaderFactory.createReader(in);
|
// Name, salt
|
||||||
try {
|
BdfList forum = clientHelper.toList(descriptor, 0, descriptor.length);
|
||||||
r.readListStart();
|
return new Forum(g, forum.getString(0), forum.getRaw(1));
|
||||||
String name = r.readString(MAX_FORUM_NAME_LENGTH);
|
|
||||||
byte[] salt = r.readRaw(FORUM_SALT_LENGTH);
|
|
||||||
r.readListEnd();
|
|
||||||
if (!r.eof()) throw new FormatException();
|
|
||||||
return new Forum(g, name, salt);
|
|
||||||
} catch (FormatException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Shouldn't happen with ByteArrayInputStream
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean listContains(Transaction txn, GroupId g, GroupId forum,
|
private boolean listContains(Transaction txn, GroupId g, GroupId forum,
|
||||||
boolean local) throws DbException, FormatException {
|
boolean local) throws DbException, FormatException {
|
||||||
LatestUpdate latest = findLatest(txn, g, local);
|
LatestUpdate latest = findLatest(txn, g, local);
|
||||||
if (latest == null) return false;
|
if (latest == null) return false;
|
||||||
byte[] raw = db.getRawMessage(txn, latest.messageId);
|
BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
|
||||||
List<Forum> list = parseForumList(raw);
|
List<Forum> list = parseForumList(message);
|
||||||
for (Forum f : list) if (f.getId().equals(forum)) return true;
|
for (Forum f : list) if (f.getId().equals(forum)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -491,8 +433,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
storeMessage(txn, g, Collections.singletonList(f), 0);
|
storeMessage(txn, g, Collections.singletonList(f), 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
byte[] raw = db.getRawMessage(txn, latest.messageId);
|
BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
|
||||||
List<Forum> list = parseForumList(raw);
|
List<Forum> list = parseForumList(message);
|
||||||
if (list.contains(f)) return false;
|
if (list.contains(f)) return false;
|
||||||
list.add(f);
|
list.add(f);
|
||||||
storeMessage(txn, g, list, latest.version + 1);
|
storeMessage(txn, g, list, latest.version + 1);
|
||||||
@@ -503,8 +445,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
|||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
LatestUpdate latest = findLatest(txn, g, true);
|
LatestUpdate latest = findLatest(txn, g, true);
|
||||||
if (latest == null) return;
|
if (latest == null) return;
|
||||||
byte[] raw = db.getRawMessage(txn, latest.messageId);
|
BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
|
||||||
List<Forum> list = parseForumList(raw);
|
List<Forum> list = parseForumList(message);
|
||||||
if (list.remove(f)) storeMessage(txn, g, list, latest.version + 1);
|
if (list.remove(f)) storeMessage(txn, g, list, latest.version + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user