Factor MessageTracker out of BdfIncomingMessageHook.

This commit is contained in:
akwizgran
2016-11-11 16:55:06 +00:00
parent ab16ee7465
commit aa210fc555
46 changed files with 628 additions and 379 deletions

View File

@@ -9,6 +9,7 @@ import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.blogs.BlogPostFactory;
import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageTracker;
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; import org.briarproject.api.contact.ContactManager;
@@ -70,6 +71,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
lifecycleManager2; lifecycleManager2;
private SyncSessionFactory sync0, sync1; private SyncSessionFactory sync0, sync1;
private BlogManager blogManager0, blogManager1; private BlogManager blogManager0, blogManager1;
private MessageTracker messageTracker0, messageTracker1;
private ContactManager contactManager0, contactManager1, contactManager2; private ContactManager contactManager0, contactManager1, contactManager2;
private Contact contact1, contact2, contact01, contact02; private Contact contact1, contact2, contact01, contact02;
private ContactId contactId1, contactId01; private ContactId contactId1, contactId01;
@@ -142,6 +144,8 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
contactManager2 = t2.getContactManager(); contactManager2 = t2.getContactManager();
blogManager0 = t0.getBlogManager(); blogManager0 = t0.getBlogManager();
blogManager1 = t1.getBlogManager(); blogManager1 = t1.getBlogManager();
messageTracker0 = t0.getMessageTracker();
messageTracker1 = t1.getMessageTracker();
blogSharingManager0 = t0.getBlogSharingManager(); blogSharingManager0 = t0.getBlogSharingManager();
blogSharingManager1 = t1.getBlogSharingManager(); blogSharingManager1 = t1.getBlogSharingManager();
blogSharingManager2 = t2.getBlogSharingManager(); blogSharingManager2 = t2.getBlogSharingManager();
@@ -192,19 +196,19 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
// get sharing group and assert group message count // get sharing group and assert group message count
GroupId g = contactGroupFactory.createContactGroup(CLIENT_ID, contact1) GroupId g = contactGroupFactory.createContactGroup(CLIENT_ID, contact1)
.getId(); .getId();
assertGroupCount(blogSharingManager0, g, 1, 0); assertGroupCount(messageTracker0, g, 1, 0);
// sync first request message // sync first request message
sync0To1(); sync0To1();
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived); assertTrue(listener1.requestReceived);
assertGroupCount(blogSharingManager1, g, 2, 1); assertGroupCount(messageTracker1, g, 2, 1);
// sync response back // sync response back
sync1To0(); sync1To0();
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived); assertTrue(listener0.responseReceived);
assertGroupCount(blogSharingManager0, g, 2, 1); assertGroupCount(messageTracker0, g, 2, 1);
// blog was added successfully // blog was added successfully
assertEquals(0, blogSharingManager0.getInvitations().size()); assertEquals(0, blogSharingManager0.getInvitations().size());
@@ -242,8 +246,8 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest {
assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01)); assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01));
// group message count is still correct // group message count is still correct
assertGroupCount(blogSharingManager0, g, 2, 1); assertGroupCount(messageTracker0, g, 2, 1);
assertGroupCount(blogSharingManager1, g, 2, 1); assertGroupCount(messageTracker1, g, 2, 1);
stopLifecycles(); stopLifecycles();
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject;
import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
@@ -82,6 +83,8 @@ interface BlogSharingIntegrationTestComponent {
BlogManager getBlogManager(); BlogManager getBlogManager();
MessageTracker getMessageTracker();
SyncSessionFactory getSyncSessionFactory(); SyncSessionFactory getSyncSessionFactory();
} }

View File

@@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals;
public abstract class BriarIntegrationTest extends BriarTestCase { public abstract class BriarIntegrationTest extends BriarTestCase {
protected void assertGroupCount(MessageTracker tracker, GroupId g, protected static void assertGroupCount(MessageTracker tracker, GroupId g,
long msgCount, long unreadCount, long latestMsg) long msgCount, long unreadCount, long latestMsg)
throws DbException { throws DbException {
@@ -19,7 +19,7 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
assertEquals(latestMsg, groupCount.getLatestMsgTime()); assertEquals(latestMsg, groupCount.getLatestMsgTime());
} }
protected void assertGroupCount(MessageTracker tracker, GroupId g, protected static void assertGroupCount(MessageTracker tracker, GroupId g,
long msgCount, long unreadCount) throws DbException { long msgCount, long unreadCount) throws DbException {
GroupCount c1 = tracker.getGroupCount(g); GroupCount c1 = tracker.getGroupCount(g);

View File

@@ -4,11 +4,11 @@ import junit.framework.Assert;
import net.jodah.concurrentunit.Waiter; import net.jodah.concurrentunit.Waiter;
import org.briarproject.api.clients.MessageTracker;
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; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.KeyPair;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.event.Event; import org.briarproject.api.event.Event;
@@ -66,6 +66,7 @@ public class ForumManagerTest extends BriarIntegrationTest {
private SyncSessionFactory sync0, sync1; private SyncSessionFactory sync0, sync1;
private ForumManager forumManager0, forumManager1; private ForumManager forumManager0, forumManager1;
private ContactManager contactManager0, contactManager1; private ContactManager contactManager0, contactManager1;
private MessageTracker messageTracker0, messageTracker1;
private ContactId contactId0,contactId1; private ContactId contactId0,contactId1;
private IdentityManager identityManager0, identityManager1; private IdentityManager identityManager0, identityManager1;
private LocalAuthor author0, author1; private LocalAuthor author0, author1;
@@ -118,6 +119,8 @@ public class ForumManagerTest extends BriarIntegrationTest {
identityManager1 = t1.getIdentityManager(); identityManager1 = t1.getIdentityManager();
contactManager0 = t0.getContactManager(); contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager(); contactManager1 = t1.getContactManager();
messageTracker0 = t0.getMessageTracker();
messageTracker1 = t1.getMessageTracker();
forumManager0 = t0.getForumManager(); forumManager0 = t0.getForumManager();
forumManager1 = t1.getForumManager(); forumManager1 = t1.getForumManager();
forumSharingManager0 = t0.getForumSharingManager(); forumSharingManager0 = t0.getForumSharingManager();
@@ -156,16 +159,16 @@ public class ForumManagerTest extends BriarIntegrationTest {
forumManager0.addLocalPost(post1); forumManager0.addLocalPost(post1);
forumManager0.setReadFlag(forum.getGroup().getId(), forumManager0.setReadFlag(forum.getGroup().getId(),
post1.getMessage().getId(), true); post1.getMessage().getId(), true);
assertGroupCount(forumManager0, forum.getGroup().getId(), 1, 0, assertGroupCount(messageTracker0, forum.getGroup().getId(), 1, 0,
post1.getMessage().getTimestamp()); post1.getMessage().getTimestamp());
forumManager0.addLocalPost(post2); forumManager0.addLocalPost(post2);
forumManager0.setReadFlag(forum.getGroup().getId(), forumManager0.setReadFlag(forum.getGroup().getId(),
post2.getMessage().getId(), false); post2.getMessage().getId(), false);
assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1,
post2.getMessage().getTimestamp()); post2.getMessage().getTimestamp());
forumManager0.setReadFlag(forum.getGroup().getId(), forumManager0.setReadFlag(forum.getGroup().getId(),
post2.getMessage().getId(), false); post2.getMessage().getId(), false);
assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1,
post2.getMessage().getTimestamp()); post2.getMessage().getTimestamp());
Collection<ForumPostHeader> headers = Collection<ForumPostHeader> headers =
forumManager0.getPostHeaders(forum.getGroup().getId()); forumManager0.getPostHeaders(forum.getGroup().getId());
@@ -215,14 +218,14 @@ public class ForumManagerTest extends BriarIntegrationTest {
forumManager0.addLocalPost(post1); forumManager0.addLocalPost(post1);
assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).size()); assertEquals(0, forumManager1.getPostHeaders(g).size());
assertGroupCount(forumManager0, g, 1, 0, time); assertGroupCount(messageTracker0, g, 1, 0, time);
assertGroupCount(forumManager1, g, 0, 0, 0); assertGroupCount(messageTracker1, g, 0, 0, 0);
// send post to 1 // send post to 1
sync0To1(); sync0To1();
deliveryWaiter.await(TIMEOUT, 1); deliveryWaiter.await(TIMEOUT, 1);
assertEquals(1, forumManager1.getPostHeaders(g).size()); assertEquals(1, forumManager1.getPostHeaders(g).size());
assertGroupCount(forumManager1, g, 1, 1, time); assertGroupCount(messageTracker1, g, 1, 1, time);
// add another forum post // add another forum post
long time2 = clock.currentTimeMillis(); long time2 = clock.currentTimeMillis();
@@ -230,14 +233,14 @@ public class ForumManagerTest extends BriarIntegrationTest {
forumManager1.addLocalPost(post2); forumManager1.addLocalPost(post2);
assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(2, forumManager1.getPostHeaders(g).size()); assertEquals(2, forumManager1.getPostHeaders(g).size());
assertGroupCount(forumManager0, g, 1, 0, time); assertGroupCount(messageTracker0, g, 1, 0, time);
assertGroupCount(forumManager1, g, 2, 1, time2); assertGroupCount(messageTracker1, g, 2, 1, time2);
// send post to 0 // send post to 0
sync1To0(); sync1To0();
deliveryWaiter.await(TIMEOUT, 1); deliveryWaiter.await(TIMEOUT, 1);
assertEquals(2, forumManager1.getPostHeaders(g).size()); assertEquals(2, forumManager1.getPostHeaders(g).size());
assertGroupCount(forumManager0, g, 2, 1, time2); assertGroupCount(messageTracker0, g, 2, 1, time2);
stopLifecycles(); stopLifecycles();
} }

View File

@@ -1,5 +1,6 @@
package org.briarproject; package org.briarproject;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumManager;
@@ -78,6 +79,8 @@ interface ForumManagerTestComponent {
ContactManager getContactManager(); ContactManager getContactManager();
MessageTracker getMessageTracker();
ForumSharingManager getForumSharingManager(); ForumSharingManager getForumSharingManager();
ForumManager getForumManager(); ForumManager getForumManager();

View File

@@ -9,6 +9,7 @@ import org.briarproject.TestDatabaseModule;
import org.briarproject.TestUtils; import org.briarproject.TestUtils;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -105,6 +106,7 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
lifecycleManager2; lifecycleManager2;
private SyncSessionFactory sync0, sync1, sync2; private SyncSessionFactory sync0, sync1, sync2;
private ContactManager contactManager0, contactManager1, contactManager2; private ContactManager contactManager0, contactManager1, contactManager2;
private MessageTracker messageTracker0, messageTracker1, messageTracker2;
private ContactId contactId0, contactId1, contactId2; private ContactId contactId0, contactId1, contactId2;
private IdentityManager identityManager0, identityManager1, private IdentityManager identityManager0, identityManager1,
identityManager2; identityManager2;
@@ -172,6 +174,9 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
contactManager0 = t0.getContactManager(); contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager(); contactManager1 = t1.getContactManager();
contactManager2 = t2.getContactManager(); contactManager2 = t2.getContactManager();
messageTracker0 = t0.getMessageTracker();
messageTracker1 = t1.getMessageTracker();
messageTracker2 = t2.getMessageTracker();
introductionManager0 = t0.getIntroductionManager(); introductionManager0 = t0.getIntroductionManager();
introductionManager1 = t1.getIntroductionManager(); introductionManager1 = t1.getIntroductionManager();
introductionManager2 = t2.getIntroductionManager(); introductionManager2 = t2.getIntroductionManager();
@@ -205,38 +210,38 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
.createIntroductionGroup(introducee1); .createIntroductionGroup(introducee1);
Group g2 = introductionGroupFactory Group g2 = introductionGroupFactory
.createIntroductionGroup(introducee2); .createIntroductionGroup(introducee2);
assertGroupCount(introductionManager0, g1.getId(), 1, 0, time); assertGroupCount(messageTracker0, g1.getId(), 1, 0, time);
assertGroupCount(introductionManager0, g2.getId(), 1, 0, time); assertGroupCount(messageTracker0, g2.getId(), 1, 0, time);
// sync first request message // sync first request message
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived); assertTrue(listener1.requestReceived);
assertGroupCount(introductionManager1, g1.getId(), 2, 1); assertGroupCount(messageTracker1, g1.getId(), 2, 1);
// sync second request message // sync second request message
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener2.requestReceived); assertTrue(listener2.requestReceived);
assertGroupCount(introductionManager2, g2.getId(), 2, 1); assertGroupCount(messageTracker2, g2.getId(), 2, 1);
// sync first response // sync first response
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received); assertTrue(listener0.response1Received);
assertGroupCount(introductionManager0, g1.getId(), 2, 1); assertGroupCount(messageTracker0, g1.getId(), 2, 1);
// sync second response // sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
eventWaiter.await(TIMEOUT, 1); eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received); assertTrue(listener0.response2Received);
assertGroupCount(introductionManager0, g2.getId(), 2, 1); assertGroupCount(messageTracker0, g2.getId(), 2, 1);
// sync forwarded responses to introducees // sync forwarded responses to introducees
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
assertGroupCount(introductionManager1, g1.getId(), 3, 2); assertGroupCount(messageTracker1, g1.getId(), 3, 2);
assertGroupCount(introductionManager2, g2.getId(), 3, 2); assertGroupCount(messageTracker2, g2.getId(), 3, 2);
// sync first ACK and its forward // sync first ACK and its forward
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
@@ -269,10 +274,10 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest {
} }
assertDefaultUiMessages(); assertDefaultUiMessages();
assertGroupCount(introductionManager0, g1.getId(), 2, 1); assertGroupCount(messageTracker0, g1.getId(), 2, 1);
assertGroupCount(introductionManager0, g2.getId(), 2, 1); assertGroupCount(messageTracker0, g2.getId(), 2, 1);
assertGroupCount(introductionManager1, g1.getId(), 3, 2); assertGroupCount(messageTracker1, g1.getId(), 3, 2);
assertGroupCount(introductionManager2, g2.getId(), 3, 2); assertGroupCount(messageTracker2, g2.getId(), 3, 2);
} finally { } finally {
stopLifecycles(); stopLifecycles();
} }

View File

@@ -4,6 +4,7 @@ import org.briarproject.TestDatabaseModule;
import org.briarproject.TestPluginsModule; import org.briarproject.TestPluginsModule;
import org.briarproject.TestSeedProviderModule; import org.briarproject.TestSeedProviderModule;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventBus;
@@ -50,7 +51,7 @@ import dagger.Component;
PropertiesModule.class, PropertiesModule.class,
MessagingModule.class MessagingModule.class
}) })
public interface IntroductionIntegrationTestComponent { interface IntroductionIntegrationTestComponent {
void inject(IntroductionIntegrationTest testCase); void inject(IntroductionIntegrationTest testCase);
@@ -82,6 +83,8 @@ public interface IntroductionIntegrationTestComponent {
TransportPropertyManager getTransportPropertyManager(); TransportPropertyManager getTransportPropertyManager();
MessageTracker getMessageTracker();
SyncSessionFactory getSyncSessionFactory(); SyncSessionFactory getSyncSessionFactory();
/* the following methods are only needed to manually construct messages */ /* the following methods are only needed to manually construct messages */

View File

@@ -1,14 +1,15 @@
package org.briarproject.api.clients; package org.briarproject.api.clients;
import org.briarproject.api.FormatException;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageContext;
@NotNullByDefault
public interface MessageQueueManager { public interface MessageQueueManager {
/** /**
@@ -52,17 +53,17 @@ public interface MessageQueueManager {
* *
* @throws DbException Should only be used for real database errors. * @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup, * If this is thrown, delivery will be attempted again at next startup,
* whereas if an FormatException is thrown, * whereas if an InvalidMessageException is thrown,
* the message will be permanently invalidated. * the message will be permanently invalidated.
* @throws FormatException for any non-database error * @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data. * that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data * This includes errors that occur while handling locally created data
* in a context controlled by remotely created data * in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency * (for example, parsing the metadata of a dependency
* of an incoming message). * of an incoming message).
* Never rethrow DbException as FormatException! * Never rethrow DbException as InvalidMessageException!
*/ */
void incomingMessage(Transaction txn, QueueMessage q, Metadata meta) void incomingMessage(Transaction txn, QueueMessage q, Metadata meta)
throws DbException, FormatException; throws DbException, InvalidMessageException;
} }
} }

View File

@@ -1,9 +1,13 @@
package org.briarproject.api.clients; package org.briarproject.api.clients;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@NotNullByDefault
public interface MessageTracker { public interface MessageTracker {
/** /**
@@ -13,11 +17,34 @@ public interface MessageTracker {
GroupCount getGroupCount(GroupId g) throws DbException; GroupCount getGroupCount(GroupId g) throws DbException;
/** /**
* Marks a message as read or unread and updates the group counts in g. * Gets the number of visible and unread messages in the group
* as well as the timestamp of the latest message
**/ **/
GroupCount getGroupCount(Transaction txn, GroupId g) throws DbException;
/**
* Updates the group count for the given incoming message.
*/
void trackIncomingMessage(Transaction txn, Message m) throws DbException;
/**
* Updates the group count for the given outgoing message.
*/
void trackOutgoingMessage(Transaction txn, Message m) throws DbException;
/**
* Updates the group count for the given message.
*/
void trackMessage(Transaction txn, GroupId g, long timestamp, boolean read)
throws DbException;
/**
* Marks a message as read or unread and updates the group count.
*/
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
class GroupCount { class GroupCount {
private final int msgCount, unreadCount; private final int msgCount, unreadCount;
private final long latestMsgTime; private final long latestMsgTime;

View File

@@ -1,10 +1,11 @@
package org.briarproject.api.forum; package org.briarproject.api.forum;
import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@@ -12,43 +13,76 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection; import java.util.Collection;
public interface ForumManager extends MessageTracker { @NotNullByDefault
public interface ForumManager {
/** The unique ID of the forum client. */ /**
* The unique ID of the forum client.
*/
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.forum"); ClientId CLIENT_ID = new ClientId("org.briarproject.briar.forum");
/** Subscribes to a forum. */ /**
* Subscribes to a forum.
*/
Forum addForum(String name) throws DbException; Forum addForum(String name) throws DbException;
/** Unsubscribes from a forum. */ /**
* Unsubscribes from a forum.
*/
void removeForum(Forum f) throws DbException; void removeForum(Forum f) throws DbException;
/** Creates a local forum post. */ /**
* Creates a local forum post.
*/
@CryptoExecutor @CryptoExecutor
ForumPost createLocalPost(GroupId groupId, String body, long timestamp, ForumPost createLocalPost(GroupId groupId, String body, long timestamp,
@Nullable MessageId parentId, LocalAuthor author); @Nullable MessageId parentId, LocalAuthor author);
/** Stores a local forum post. */ /**
* Stores a local forum post.
*/
ForumPostHeader addLocalPost(ForumPost p) throws DbException; ForumPostHeader addLocalPost(ForumPost p) throws DbException;
/** Returns the forum with the given ID. */ /**
* Returns the forum with the given ID.
*/
Forum getForum(GroupId g) throws DbException; Forum getForum(GroupId g) throws DbException;
/** Returns the forum with the given ID. */ /**
* Returns the forum with the given ID.
*/
Forum getForum(Transaction txn, GroupId g) throws DbException; Forum getForum(Transaction txn, GroupId g) throws DbException;
/** Returns all forums to which the user subscribes. */ /**
* Returns all forums to which the user subscribes.
*/
Collection<Forum> getForums() throws DbException; Collection<Forum> getForums() throws DbException;
/** Returns the body of the forum post with the given ID. */ /**
* Returns the body of the forum post with the given ID.
*/
String getPostBody(MessageId m) throws DbException; String getPostBody(MessageId m) throws DbException;
/** Returns the headers of all posts in the given forum. */ /**
* Returns the headers of all posts in the given forum.
*/
Collection<ForumPostHeader> getPostHeaders(GroupId g) throws DbException; Collection<ForumPostHeader> getPostHeaders(GroupId g) throws DbException;
/** Registers a hook to be called whenever a forum is removed. */ /**
* Registers a hook to be called whenever a forum is removed.
*/
void registerRemoveForumHook(RemoveForumHook hook); void registerRemoveForumHook(RemoveForumHook hook);
/**
* Returns the group count for the given forum.
*/
GroupCount getGroupCount(GroupId g) throws DbException;
/**
* Marks a message as read or unread and updates the group count.
*/
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
interface RemoveForumHook { interface RemoveForumHook {
void removingForum(Transaction txn, Forum f) throws DbException; void removingForum(Transaction txn, Forum f) throws DbException;
} }

View File

@@ -1,16 +1,18 @@
package org.briarproject.api.introduction; package org.briarproject.api.introduction;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
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.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.messaging.ConversationManager.ConversationClient;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import java.util.Collection; import java.util.Collection;
public interface IntroductionManager extends MessageTracker { @NotNullByDefault
public interface IntroductionManager extends ConversationClient {
/** The unique ID of the introduction client. */ /** The unique ID of the introduction client. */
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction"); ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction");

View File

@@ -1,10 +1,16 @@
package org.briarproject.api.messaging; package org.briarproject.api.messaging;
import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
@NotNullByDefault
public interface ConversationManager { public interface ConversationManager {
/** /**
@@ -13,11 +19,19 @@ public interface ConversationManager {
*/ */
void registerConversationClient(ConversationClient client); void registerConversationClient(ConversationClient client);
/** Get the unified group count for all private conversation messages. */ /**
GroupCount getGroupCount(ContactId contactId) throws DbException; * Get the unified group count for all private conversation messages.
*/
GroupCount getGroupCount(ContactId c) throws DbException;
interface ConversationClient { interface ConversationClient {
GroupCount getGroupCount(Transaction txn, ContactId contactId)
Group getContactGroup(Contact c);
GroupCount getGroupCount(Transaction txn, ContactId c)
throws DbException;
void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException; throws DbException;
} }

View File

@@ -1,15 +1,17 @@
package org.briarproject.api.messaging; package org.briarproject.api.messaging;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.messaging.ConversationManager.ConversationClient;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import java.util.Collection; import java.util.Collection;
public interface MessagingManager extends MessageTracker { @NotNullByDefault
public interface MessagingManager extends ConversationClient {
/** The unique ID of the messaging client. */ /** The unique ID of the messaging client. */
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.messaging"); ClientId CLIENT_ID = new ClientId("org.briarproject.briar.messaging");

View File

@@ -1,7 +1,7 @@
package org.briarproject.api.privategroup; package org.briarproject.api.privategroup;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
@@ -14,7 +14,7 @@ import org.briarproject.api.sync.MessageId;
import java.util.Collection; import java.util.Collection;
@NotNullByDefault @NotNullByDefault
public interface PrivateGroupManager extends MessageTracker { public interface PrivateGroupManager {
/** /**
* The unique ID of the private group client. * The unique ID of the private group client.
@@ -24,9 +24,9 @@ public interface PrivateGroupManager extends MessageTracker {
/** /**
* Adds a new private group and joins it. * Adds a new private group and joins it.
* *
* @param group The private group to add * @param group The private group to add
* @param joinMsg The creators's join message * @param joinMsg The creators's join message
* @param creator True if the group is added by its creator * @param creator True if the group is added by its creator
*/ */
void addPrivateGroup(PrivateGroup group, GroupMessage joinMsg, void addPrivateGroup(PrivateGroup group, GroupMessage joinMsg,
boolean creator) throws DbException; boolean creator) throws DbException;
@@ -34,9 +34,9 @@ public interface PrivateGroupManager extends MessageTracker {
/** /**
* Adds a new private group and joins it. * Adds a new private group and joins it.
* *
* @param group The private group to add * @param group The private group to add
* @param joinMsg The new member's join message * @param joinMsg The new member's join message
* @param creator True if the group is added by its creator * @param creator True if the group is added by its creator
*/ */
void addPrivateGroup(Transaction txn, PrivateGroup group, void addPrivateGroup(Transaction txn, PrivateGroup group,
GroupMessage joinMsg, boolean creator) throws DbException; GroupMessage joinMsg, boolean creator) throws DbException;
@@ -107,13 +107,23 @@ public interface PrivateGroupManager extends MessageTracker {
*/ */
boolean isMember(Transaction txn, GroupId g, Author a) throws DbException; boolean isMember(Transaction txn, GroupId g, Author a) throws DbException;
/**
* Returns the group count for the given group.
*/
GroupCount getGroupCount(GroupId g) throws DbException;
/**
* Marks a message as read or unread and updates the group count.
*/
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
/** /**
* This method needs to be called when a contact relationship * This method needs to be called when a contact relationship
* has been revealed between the user and the Author with AuthorId a * has been revealed between the user and the Author with AuthorId a
* in the Group identified by the GroupId g. * in the Group identified by the GroupId g.
* *
* @param byContact true if the remote contact has revealed * @param byContact true if the remote contact has revealed
* the relationship first. Otherwise false. * the relationship first. Otherwise false.
*/ */
void relationshipRevealed(Transaction txn, GroupId g, AuthorId a, void relationshipRevealed(Transaction txn, GroupId g, AuthorId a,
boolean byContact) throws FormatException, DbException; boolean byContact) throws FormatException, DbException;

View File

@@ -1,15 +1,18 @@
package org.briarproject.api.sharing; package org.briarproject.api.sharing;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
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.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.messaging.ConversationManager.ConversationClient;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import java.util.Collection; import java.util.Collection;
public interface SharingManager<S extends Shareable> extends MessageTracker { @NotNullByDefault
public interface SharingManager<S extends Shareable>
extends ConversationClient {
/** /**
* Sends an invitation to share the given group with the given contact * Sends an invitation to share the given group with the given contact

View File

@@ -1,5 +1,8 @@
package org.briarproject.api.sync; package org.briarproject.api.sync;
import org.briarproject.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MessageFactory { public interface MessageFactory {
Message createMessage(GroupId g, long timestamp, byte[] body); Message createMessage(GroupId g, long timestamp, byte[] body);

View File

@@ -3,11 +3,13 @@ package org.briarproject.api.sync;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
/** /**
* Responsible for managing message validators and passing them messages to * Responsible for managing message validators and passing them messages to
* validate. * validate.
*/ */
@NotNullByDefault
public interface ValidationManager { public interface ValidationManager {
enum State { enum State {

View File

@@ -27,6 +27,7 @@ import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -69,6 +70,7 @@ import static org.briarproject.api.contact.ContactManager.AddContactHook;
import static org.briarproject.api.contact.ContactManager.RemoveContactHook; import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary; import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary;
@NotNullByDefault
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
AddContactHook, RemoveContactHook, Client { AddContactHook, RemoveContactHook, Client {
@@ -127,10 +129,8 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@Override @Override
public void removingContact(Transaction txn, Contact c) throws DbException { public void removingContact(Transaction txn, Contact c) throws DbException {
if (c != null) { Blog b = blogFactory.createBlog(c.getAuthor());
Blog b = blogFactory.createBlog(c.getAuthor()); db.removeGroup(txn, b.getGroup());
db.removeGroup(txn, b.getGroup());
}
} }
@Override @Override

View File

@@ -11,6 +11,7 @@ import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
@@ -42,6 +43,7 @@ import static org.briarproject.api.blogs.MessageType.COMMENT;
import static org.briarproject.api.blogs.MessageType.POST; import static org.briarproject.api.blogs.MessageType.POST;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
@NotNullByDefault
class BlogPostValidator extends BdfMessageValidator { class BlogPostValidator extends BdfMessageValidator {
private final GroupFactory groupFactory; private final GroupFactory groupFactory;
@@ -76,10 +78,10 @@ class BlogPostValidator extends BdfMessageValidator {
addMessageMetadata(c, m.getTimestamp()); addMessageMetadata(c, m.getTimestamp());
break; break;
case WRAPPED_POST: case WRAPPED_POST:
c = validateWrappedPost(m, g, body); c = validateWrappedPost(body);
break; break;
case WRAPPED_COMMENT: case WRAPPED_COMMENT:
c = validateWrappedComment(m, g, body); c = validateWrappedComment(body);
break; break;
default: default:
throw new InvalidMessageException("Unknown Message Type"); throw new InvalidMessageException("Unknown Message Type");
@@ -164,8 +166,8 @@ class BlogPostValidator extends BdfMessageValidator {
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
private BdfMessageContext validateWrappedPost(Message m, Group g, private BdfMessageContext validateWrappedPost(BdfList body)
BdfList body) throws InvalidMessageException, FormatException { throws InvalidMessageException, FormatException {
// p_group descriptor, p_timestamp, p_content, p_signature // p_group descriptor, p_timestamp, p_content, p_signature
checkSize(body, 4); checkSize(body, 4);
@@ -202,8 +204,8 @@ class BlogPostValidator extends BdfMessageValidator {
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
private BdfMessageContext validateWrappedComment(Message m, Group g, private BdfMessageContext validateWrappedComment(BdfList body)
BdfList body) throws InvalidMessageException, FormatException { throws InvalidMessageException, FormatException {
// c_group descriptor, c_timestamp, c_comment, c_parent_original_id, // c_group descriptor, c_timestamp, c_comment, c_parent_original_id,
// c_parent_id, c_signature, parent_id // c_parent_id, c_signature, parent_id

View File

@@ -3,31 +3,25 @@ package org.briarproject.clients;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook; import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.QueueMessage; import org.briarproject.api.clients.QueueMessage;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser; 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;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH; import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
public abstract class BdfIncomingMessageHook implements IncomingMessageHook, public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
IncomingQueueMessageHook, MessageTracker { IncomingQueueMessageHook {
protected final DatabaseComponent db; protected final DatabaseComponent db;
protected final ClientHelper clientHelper; protected final ClientHelper clientHelper;
@@ -44,16 +38,16 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* *
* @throws DbException Should only be used for real database errors. * @throws DbException Should only be used for real database errors.
* Do not rethrow * If this is thrown, delivery will be attempted again at next startup,
* whereas if a FormatException is thrown, the message will be permanently
* invalidated.
* @throws FormatException Use this for any non-database error * @throws FormatException Use this for any non-database error
* that occurs while handling remotely created data. * that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data * This includes errors that occur while handling locally created data
* in a context controlled by remotely created data * in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency * (for example, parsing the metadata of a dependency
* of an incoming message). * of an incoming message).
* Throwing this will delete the incoming message and its metadata * Never rethrow DbException as FormatException!
* marking it as invalid in the database.
* Never rethrow DbException as FormatException
*/ */
protected abstract boolean incomingMessage(Transaction txn, Message m, protected abstract boolean incomingMessage(Transaction txn, Message m,
BdfList body, BdfDictionary meta) throws DbException, BdfList body, BdfDictionary meta) throws DbException,
@@ -71,8 +65,12 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
@Override @Override
public void incomingMessage(Transaction txn, QueueMessage q, Metadata meta) public void incomingMessage(Transaction txn, QueueMessage q, Metadata meta)
throws DbException, FormatException { throws DbException, InvalidMessageException {
incomingMessage(txn, q, meta, QUEUE_MESSAGE_HEADER_LENGTH); try {
incomingMessage(txn, q, meta, QUEUE_MESSAGE_HEADER_LENGTH);
} catch (FormatException e) {
throw new InvalidMessageException(e);
}
} }
private boolean incomingMessage(Transaction txn, Message m, Metadata meta, private boolean incomingMessage(Transaction txn, Message m, Metadata meta,
@@ -84,102 +82,4 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
return incomingMessage(txn, m, body, metaDictionary); return incomingMessage(txn, m, body, metaDictionary);
} }
protected void trackIncomingMessage(Transaction txn, Message m)
throws DbException {
trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
}
protected void trackOutgoingMessage(Transaction txn, Message m)
throws DbException {
trackMessage(txn, m.getGroupId(), m.getTimestamp(), true);
}
protected void trackMessage(Transaction txn, GroupId g, long time,
boolean read) throws DbException {
GroupCount c = getGroupCount(txn, g);
int msgCount = c.getMsgCount() + 1;
int unreadCount = c.getUnreadCount() + (read ? 0 : 1);
long latestTime =
time > c.getLatestMsgTime() ? time : c.getLatestMsgTime();
storeGroupCount(txn, g,
new GroupCount(msgCount, unreadCount, latestTime));
}
@Override
public GroupCount getGroupCount(GroupId g) throws DbException {
GroupCount count;
Transaction txn = db.startTransaction(true);
try {
count = getGroupCount(txn, g);
db.commitTransaction(txn);
}
finally {
db.endTransaction(txn);
}
return count;
}
protected GroupCount getGroupCount(Transaction txn, GroupId g)
throws DbException {
GroupCount count;
try {
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
count = new GroupCount(
d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_LATEST_MSG, 0L)
);
} catch (FormatException e) {
throw new DbException(e);
}
return count;
}
private void storeGroupCount(Transaction txn, GroupId g, GroupCount c)
throws DbException{
try {
BdfDictionary d = BdfDictionary.of(
new BdfEntry(GROUP_KEY_MSG_COUNT, c.getMsgCount()),
new BdfEntry(GROUP_KEY_UNREAD_COUNT, c.getUnreadCount()),
new BdfEntry(GROUP_KEY_LATEST_MSG, c.getLatestMsgTime())
);
clientHelper.mergeGroupMetadata(txn, g, d);
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
Transaction txn = db.startTransaction(false);
try {
// check current read status of message
BdfDictionary old =
clientHelper.getMessageMetadataAsDictionary(txn, m);
boolean wasRead = old.getBoolean(MSG_KEY_READ, false);
// if status changed
if (wasRead != read) {
// mark individual message as read
BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_READ, read);
clientHelper.mergeMessageMetadata(txn, m, meta);
// update unread counter in group metadata
GroupCount c = getGroupCount(txn, g);
BdfDictionary d = new BdfDictionary();
int count = c.getUnreadCount() + (read ? -1 : 1);
if (count < 0) throw new DbException();
d.put(GROUP_KEY_UNREAD_COUNT, count);
clientHelper.mergeGroupMetadata(txn, g, d);
}
db.commitTransaction(txn);
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
}
} }

View File

@@ -9,6 +9,7 @@ import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Metadata;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -25,6 +26,7 @@ import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LEN
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE; import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@NotNullByDefault
public abstract class BdfMessageValidator implements MessageValidator, public abstract class BdfMessageValidator implements MessageValidator,
QueueMessageValidator { QueueMessageValidator {
@@ -108,7 +110,7 @@ public abstract class BdfMessageValidator implements MessageValidator,
if (b != null && b.length != length) throw new FormatException(); if (b != null && b.length != length) throw new FormatException();
} }
protected void checkSize(BdfList list, int minSize, int maxSize) protected void checkSize(@Nullable BdfList list, int minSize, int maxSize)
throws FormatException { throws FormatException {
if (list != null) { if (list != null) {
if (list.size() < minSize) throw new FormatException(); if (list.size() < minSize) throw new FormatException();

View File

@@ -3,6 +3,7 @@ package org.briarproject.clients;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.QueueMessageFactory; import org.briarproject.api.clients.QueueMessageFactory;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.data.BdfReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
@@ -52,4 +53,8 @@ public class ClientsModule {
return new QueueMessageFactoryImpl(crypto); return new QueueMessageFactoryImpl(crypto);
} }
@Provides
MessageTracker provideMessageTracker(MessageTrackerImpl messageTracker) {
return messageTracker;
}
} }

View File

@@ -1,6 +1,8 @@
package org.briarproject.clients; package org.briarproject.clients;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.MessageTracker.GroupCount;
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.data.MetadataParser; import org.briarproject.api.data.MetadataParser;
@@ -8,25 +10,34 @@ import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.messaging.ConversationManager.ConversationClient; import org.briarproject.api.messaging.ConversationManager.ConversationClient;
import org.briarproject.api.sync.Group; import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
@NotNullByDefault
public abstract class ConversationClientImpl extends BdfIncomingMessageHook public abstract class ConversationClientImpl extends BdfIncomingMessageHook
implements ConversationClient { implements ConversationClient {
protected ConversationClientImpl(DatabaseComponent db, protected final MessageTracker messageTracker;
ClientHelper clientHelper, MetadataParser metadataParser) {
super(db, clientHelper, metadataParser);
}
protected abstract Group getContactGroup(Contact contact); protected ConversationClientImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser,
MessageTracker messageTracker) {
super(db, clientHelper, metadataParser);
this.messageTracker = messageTracker;
}
@Override @Override
public GroupCount getGroupCount(Transaction txn, ContactId contactId) public GroupCount getGroupCount(Transaction txn, ContactId contactId)
throws DbException { throws DbException {
Contact contact = db.getContact(txn, contactId); Contact contact = db.getContact(txn, contactId);
GroupId groupId = getContactGroup(contact).getId(); GroupId groupId = getContactGroup(contact).getId();
return getGroupCount(txn, groupId); return messageTracker.getGroupCount(txn, groupId);
} }
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
messageTracker.setReadFlag(g, m, read);
}
} }

View File

@@ -11,6 +11,7 @@ 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;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -20,6 +21,7 @@ import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.api.sync.ValidationManager.MessageValidator;
import org.briarproject.util.ByteUtils; import org.briarproject.util.ByteUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -29,12 +31,14 @@ import java.util.Map.Entry;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH; import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
@NotNullByDefault
class MessageQueueManagerImpl implements MessageQueueManager { class MessageQueueManagerImpl implements MessageQueueManager {
private static final String OUTGOING_POSITION_KEY = "nextOut"; private static final String OUTGOING_POSITION_KEY = "nextOut";
@@ -139,6 +143,7 @@ class MessageQueueManagerImpl implements MessageQueueManager {
this.pending = pending; this.pending = pending;
} }
@Nullable
MessageId popIncomingMessageId() { MessageId popIncomingMessageId() {
Iterator<Entry<Long, MessageId>> it = pending.entrySet().iterator(); Iterator<Entry<Long, MessageId>> it = pending.entrySet().iterator();
if (!it.hasNext()) { if (!it.hasNext()) {
@@ -161,8 +166,9 @@ class MessageQueueManagerImpl implements MessageQueueManager {
} }
} }
@NotNullByDefault
private static class DelegatingMessageValidator private static class DelegatingMessageValidator
implements ValidationManager.MessageValidator { implements MessageValidator {
private final QueueMessageValidator delegate; private final QueueMessageValidator delegate;
@@ -174,21 +180,24 @@ class MessageQueueManagerImpl implements MessageQueueManager {
public MessageContext validateMessage(Message m, Group g) public MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException { throws InvalidMessageException {
byte[] raw = m.getRaw(); byte[] raw = m.getRaw();
if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH) return null; if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH)
throw new InvalidMessageException();
long queuePosition = ByteUtils.readUint64(raw, long queuePosition = ByteUtils.readUint64(raw,
MESSAGE_HEADER_LENGTH); MESSAGE_HEADER_LENGTH);
if (queuePosition < 0) return null; if (queuePosition < 0) throw new InvalidMessageException();
QueueMessage q = new QueueMessage(m.getId(), m.getGroupId(), QueueMessage q = new QueueMessage(m.getId(), m.getGroupId(),
m.getTimestamp(), queuePosition, raw); m.getTimestamp(), queuePosition, raw);
return delegate.validateMessage(q, g); return delegate.validateMessage(q, g);
} }
} }
@NotNullByDefault
private class DelegatingIncomingMessageHook implements IncomingMessageHook { private class DelegatingIncomingMessageHook implements IncomingMessageHook {
private final IncomingQueueMessageHook delegate; private final IncomingQueueMessageHook delegate;
private DelegatingIncomingMessageHook(IncomingQueueMessageHook delegate) { private DelegatingIncomingMessageHook(
IncomingQueueMessageHook delegate) {
this.delegate = delegate; this.delegate = delegate;
} }
@@ -227,20 +236,16 @@ class MessageQueueManagerImpl implements MessageQueueManager {
// Save the queue state before passing control to the delegate // Save the queue state before passing control to the delegate
saveQueueState(txn, m.getGroupId(), queueState); saveQueueState(txn, m.getGroupId(), queueState);
// Deliver the messages to the delegate // Deliver the messages to the delegate
try { delegate.incomingMessage(txn, q, meta);
delegate.incomingMessage(txn, q, meta); for (MessageId id : consecutive) {
for (MessageId id : consecutive) { byte[] raw = db.getRawMessage(txn, id);
byte[] raw = db.getRawMessage(txn, id); meta = db.getMessageMetadata(txn, id);
meta = db.getMessageMetadata(txn, id); q = queueMessageFactory.createMessage(id, raw);
q = queueMessageFactory.createMessage(id, raw); if (LOG.isLoggable(INFO)) {
if (LOG.isLoggable(INFO)) { LOG.info("Delivering pending message with position "
LOG.info("Delivering pending message with position " + q.getQueuePosition());
+ q.getQueuePosition());
}
delegate.incomingMessage(txn, q, meta);
} }
} catch (FormatException e) { delegate.incomingMessage(txn, q, meta);
throw new InvalidMessageException(e);
} }
} }
// message queues are only useful for groups with two members // message queues are only useful for groups with two members

View File

@@ -0,0 +1,132 @@
package org.briarproject.clients;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import javax.inject.Inject;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class MessageTrackerImpl implements MessageTracker {
private final DatabaseComponent db;
private final ClientHelper clientHelper;
@Inject
MessageTrackerImpl(DatabaseComponent db, ClientHelper clientHelper) {
this.db = db;
this.clientHelper = clientHelper;
}
@Override
public void trackIncomingMessage(Transaction txn, Message m)
throws DbException {
trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
}
@Override
public void trackOutgoingMessage(Transaction txn, Message m)
throws DbException {
trackMessage(txn, m.getGroupId(), m.getTimestamp(), true);
}
@Override
public void trackMessage(Transaction txn, GroupId g, long time,
boolean read) throws DbException {
GroupCount c = getGroupCount(txn, g);
int msgCount = c.getMsgCount() + 1;
int unreadCount = c.getUnreadCount() + (read ? 0 : 1);
long latestMsgTime = Math.max(c.getLatestMsgTime(), time);
storeGroupCount(txn, g, new GroupCount(msgCount, unreadCount,
latestMsgTime));
}
@Override
public GroupCount getGroupCount(GroupId g) throws DbException {
GroupCount count;
Transaction txn = db.startTransaction(true);
try {
count = getGroupCount(txn, g);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return count;
}
@Override
public GroupCount getGroupCount(Transaction txn, GroupId g)
throws DbException {
try {
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
return new GroupCount(
d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_LATEST_MSG, 0L)
);
} catch (FormatException e) {
throw new DbException(e);
}
}
private void storeGroupCount(Transaction txn, GroupId g, GroupCount c)
throws DbException {
try {
BdfDictionary d = BdfDictionary.of(
new BdfEntry(GROUP_KEY_MSG_COUNT, c.getMsgCount()),
new BdfEntry(GROUP_KEY_UNREAD_COUNT, c.getUnreadCount()),
new BdfEntry(GROUP_KEY_LATEST_MSG, c.getLatestMsgTime())
);
clientHelper.mergeGroupMetadata(txn, g, d);
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
Transaction txn = db.startTransaction(false);
try {
// check current read status of message
BdfDictionary old =
clientHelper.getMessageMetadataAsDictionary(txn, m);
boolean wasRead = old.getBoolean(MSG_KEY_READ, false);
// if status changed
if (wasRead != read) {
// mark individual message as read
BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_READ, read);
clientHelper.mergeMessageMetadata(txn, m, meta);
// update unread counter in group metadata
GroupCount c = getGroupCount(txn, g);
int unreadCount = c.getUnreadCount() + (read ? -1 : 1);
if (unreadCount < 0) throw new DbException();
storeGroupCount(txn, g, new GroupCount(c.getMsgCount(),
unreadCount, c.getLatestMsgTime()));
}
db.commitTransaction(txn);
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
}
}

View File

@@ -2,6 +2,8 @@ package org.briarproject.forum;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser; import org.briarproject.api.data.MetadataParser;
@@ -20,6 +22,7 @@ import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -52,22 +55,25 @@ import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
import static org.briarproject.api.identity.Author.Status.OURSELVES; import static org.briarproject.api.identity.Author.Status.OURSELVES;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final ForumFactory forumFactory; private final ForumFactory forumFactory;
private final ForumPostFactory forumPostFactory; private final ForumPostFactory forumPostFactory;
private final MessageTracker messageTracker;
private final List<RemoveForumHook> removeHooks; private final List<RemoveForumHook> removeHooks;
@Inject @Inject
ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager, ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager,
ClientHelper clientHelper, MetadataParser metadataParser, ClientHelper clientHelper, MetadataParser metadataParser,
ForumFactory forumFactory, ForumPostFactory forumPostFactory) { ForumFactory forumFactory, ForumPostFactory forumPostFactory,
MessageTracker messageTracker) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser);
this.identityManager = identityManager; this.identityManager = identityManager;
this.forumFactory = forumFactory; this.forumFactory = forumFactory;
this.forumPostFactory = forumPostFactory; this.forumPostFactory = forumPostFactory;
this.messageTracker = messageTracker;
removeHooks = new CopyOnWriteArrayList<RemoveForumHook>(); removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
} }
@@ -75,7 +81,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
protected boolean incomingMessage(Transaction txn, Message m, BdfList body, protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
BdfDictionary meta) throws DbException, FormatException { BdfDictionary meta) throws DbException, FormatException {
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
ForumPostHeader post = getForumPostHeader(txn, m.getId(), meta); ForumPostHeader post = getForumPostHeader(txn, m.getId(), meta);
ForumPostReceivedEvent event = ForumPostReceivedEvent event =
@@ -146,7 +152,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
meta.put(KEY_LOCAL, true); meta.put(KEY_LOCAL, true);
meta.put(MSG_KEY_READ, true); meta.put(MSG_KEY_READ, true);
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
trackOutgoingMessage(txn, p.getMessage()); messageTracker.trackOutgoingMessage(txn, p.getMessage());
db.commitTransaction(txn); db.commitTransaction(txn);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -204,6 +210,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
try { try {
// Parent ID, author, forum post body, signature // Parent ID, author, forum post body, signature
BdfList message = clientHelper.getMessageAsList(m); BdfList message = clientHelper.getMessageAsList(m);
if (message == null) throw new DbException();
return message.getString(2); return message.getString(2);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
@@ -253,6 +260,17 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
removeHooks.add(hook); removeHooks.add(hook);
} }
@Override
public GroupCount getGroupCount(GroupId g) throws DbException {
return messageTracker.getGroupCount(g);
}
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
messageTracker.setReadFlag(g, m, read);
}
private Forum parseForum(Group g) throws FormatException { private Forum parseForum(Group g) throws FormatException {
byte[] descriptor = g.getDescriptor(); byte[] descriptor = g.getDescriptor();
// Name, salt // Name, salt

View File

@@ -9,6 +9,7 @@ import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -25,6 +26,7 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENG
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
@NotNullByDefault
class ForumPostValidator extends BdfMessageValidator { class ForumPostValidator extends BdfMessageValidator {
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;

View File

@@ -3,6 +3,7 @@ package org.briarproject.introduction;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.Client; import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -23,6 +24,7 @@ import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.introduction.IntroductionMessage; import org.briarproject.api.introduction.IntroductionMessage;
import org.briarproject.api.introduction.IntroductionRequest; import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.IntroductionResponse; import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -73,6 +75,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class IntroductionManagerImpl extends ConversationClientImpl class IntroductionManagerImpl extends ConversationClientImpl
implements IntroductionManager, Client, AddContactHook, implements IntroductionManager, Client, AddContactHook,
RemoveContactHook { RemoveContactHook {
@@ -86,11 +89,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
@Inject @Inject
IntroductionManagerImpl(DatabaseComponent db, ClientHelper clientHelper, IntroductionManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MetadataParser metadataParser, IntroducerManager introducerManager, MetadataParser metadataParser, MessageTracker messageTracker,
IntroducerManager introducerManager,
IntroduceeManager introduceeManager, IntroduceeManager introduceeManager,
IntroductionGroupFactory introductionGroupFactory) { IntroductionGroupFactory introductionGroupFactory) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser, messageTracker);
this.introducerManager = introducerManager; this.introducerManager = introducerManager;
this.introduceeManager = introduceeManager; this.introduceeManager = introduceeManager;
this.introductionGroupFactory = introductionGroupFactory; this.introductionGroupFactory = introductionGroupFactory;
@@ -213,7 +217,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
introduceeManager.initialize(txn, groupId, message); introduceeManager.initialize(txn, groupId, message);
try { try {
introduceeManager.incomingMessage(txn, state, message); introduceeManager.incomingMessage(txn, state, message);
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
introduceeManager.abort(txn, state); introduceeManager.abort(txn, state);
@@ -239,7 +243,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
LOG.warning("Unknown role '" + role + "'"); LOG.warning("Unknown role '" + role + "'");
throw new DbException(); throw new DbException();
} }
if (type == TYPE_RESPONSE) trackIncomingMessage(txn, m); if (type == TYPE_RESPONSE)
messageTracker.trackIncomingMessage(txn, m);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state); if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state);
@@ -260,7 +265,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
} }
@Override @Override
protected Group getContactGroup(Contact contact) { public Group getContactGroup(Contact contact) {
return introductionGroupFactory.createIntroductionGroup(contact); return introductionGroupFactory.createIntroductionGroup(contact);
} }
@@ -274,8 +279,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
introducerManager.makeIntroduction(txn, c1, c2, msg, timestamp); introducerManager.makeIntroduction(txn, c1, c2, msg, timestamp);
Group g1 = getContactGroup(c1); Group g1 = getContactGroup(c1);
Group g2 = getContactGroup(c2); Group g2 = getContactGroup(c2);
trackMessage(txn, g1.getId(), timestamp, true); messageTracker.trackMessage(txn, g1.getId(), timestamp, true);
trackMessage(txn, g2.getId(), timestamp, true); messageTracker.trackMessage(txn, g2.getId(), timestamp, true);
db.commitTransaction(txn); db.commitTransaction(txn);
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
@@ -295,7 +300,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
getSessionState(txn, g.getId(), sessionId.getBytes()); getSessionState(txn, g.getId(), sessionId.getBytes());
introduceeManager.acceptIntroduction(txn, state, timestamp); introduceeManager.acceptIntroduction(txn, state, timestamp);
trackMessage(txn, g.getId(), timestamp, true); messageTracker.trackMessage(txn, g.getId(), timestamp, true);
db.commitTransaction(txn); db.commitTransaction(txn);
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
@@ -315,7 +320,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
getSessionState(txn, g.getId(), sessionId.getBytes()); getSessionState(txn, g.getId(), sessionId.getBytes());
introduceeManager.declineIntroduction(txn, state, timestamp); introduceeManager.declineIntroduction(txn, state, timestamp);
trackMessage(txn, g.getId(), timestamp, true); messageTracker.trackMessage(txn, g.getId(), timestamp, true);
db.commitTransaction(txn); db.commitTransaction(txn);
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);

View File

@@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
@@ -39,6 +40,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPO
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
@NotNullByDefault
class IntroductionValidator extends BdfMessageValidator { class IntroductionValidator extends BdfMessageValidator {
IntroductionValidator(ClientHelper clientHelper, IntroductionValidator(ClientHelper clientHelper,

View File

@@ -6,12 +6,14 @@ import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction; import org.briarproject.api.db.Transaction;
import org.briarproject.api.messaging.ConversationManager; import org.briarproject.api.messaging.ConversationManager;
import org.briarproject.api.nullsafety.NotNullByDefault;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import javax.inject.Inject; import javax.inject.Inject;
@NotNullByDefault
class ConversationManagerImpl implements ConversationManager { class ConversationManagerImpl implements ConversationManager {
private final DatabaseComponent db; private final DatabaseComponent db;
@@ -32,9 +34,7 @@ class ConversationManagerImpl implements ConversationManager {
} }
@Override @Override
public GroupCount getGroupCount(ContactId contactId) public GroupCount getGroupCount(ContactId contactId) throws DbException {
throws DbException {
int msgCount = 0, unreadCount = 0; int msgCount = 0, unreadCount = 0;
long latestTime = 0; long latestTime = 0;
Transaction txn = db.startTransaction(true); Transaction txn = db.startTransaction(true);

View File

@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.clients.Client; import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageTracker;
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;
@@ -18,6 +19,7 @@ import org.briarproject.api.event.PrivateMessageReceivedEvent;
import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessage; import org.briarproject.api.messaging.PrivateMessage;
import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.api.messaging.PrivateMessageHeader;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -33,6 +35,7 @@ import javax.inject.Inject;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class MessagingManagerImpl extends ConversationClientImpl class MessagingManagerImpl extends ConversationClientImpl
implements MessagingManager, Client, AddContactHook, RemoveContactHook { implements MessagingManager, Client, AddContactHook, RemoveContactHook {
@@ -40,9 +43,9 @@ class MessagingManagerImpl extends ConversationClientImpl
@Inject @Inject
MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MetadataParser metadataParser, MetadataParser metadataParser, MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory) { ContactGroupFactory contactGroupFactory) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser, messageTracker);
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
} }
@@ -72,7 +75,7 @@ class MessagingManagerImpl extends ConversationClientImpl
} }
@Override @Override
protected Group getContactGroup(Contact c) { public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(CLIENT_ID, c); return contactGroupFactory.createContactGroup(CLIENT_ID, c);
} }
@@ -95,7 +98,7 @@ class MessagingManagerImpl extends ConversationClientImpl
PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent( PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent(
header, contactId, groupId); header, contactId, groupId);
txn.attach(event); txn.attach(event);
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
// don't share message // don't share message
return false; return false;
@@ -110,7 +113,7 @@ class MessagingManagerImpl extends ConversationClientImpl
meta.put("local", true); meta.put("local", true);
meta.put("read", true); meta.put("read", true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage()); messageTracker.trackOutgoingMessage(txn, m.getMessage());
db.commitTransaction(txn); db.commitTransaction(txn);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -195,20 +198,11 @@ class MessagingManagerImpl extends ConversationClientImpl
try { try {
// 0: private message body // 0: private message body
BdfList message = clientHelper.getMessageAsList(m); BdfList message = clientHelper.getMessageAsList(m);
if (message == null) throw new DbException();
return message.getString(0); return message.getString(0);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
} }
@Override
public GroupCount getGroupCount(Transaction txn, ContactId contactId)
throws DbException {
Contact contact = db.getContact(txn, contactId);
GroupId groupId = getContactGroup(contact).getId();
return getGroupCount(txn, groupId);
}
} }

View File

@@ -6,6 +6,7 @@ import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
@@ -14,6 +15,7 @@ import org.briarproject.clients.BdfMessageValidator;
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class PrivateMessageValidator extends BdfMessageValidator { class PrivateMessageValidator extends BdfMessageValidator {
PrivateMessageValidator(ClientHelper clientHelper, PrivateMessageValidator(ClientHelper clientHelper,

View File

@@ -8,6 +8,7 @@ import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.privategroup.MessageType; import org.briarproject.api.privategroup.MessageType;
import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupFactory;
@@ -38,6 +39,7 @@ import static org.briarproject.privategroup.GroupConstants.KEY_READ;
import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP; import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP;
import static org.briarproject.privategroup.GroupConstants.KEY_TYPE; import static org.briarproject.privategroup.GroupConstants.KEY_TYPE;
@NotNullByDefault
class GroupMessageValidator extends BdfMessageValidator { class GroupMessageValidator extends BdfMessageValidator {
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;

View File

@@ -2,6 +2,8 @@ package org.briarproject.privategroup;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.clients.ProtocolStateException; import org.briarproject.api.clients.ProtocolStateException;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry; import org.briarproject.api.data.BdfEntry;
@@ -75,17 +77,18 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final MessageTracker messageTracker;
private final List<PrivateGroupHook> hooks; private final List<PrivateGroupHook> hooks;
@Inject @Inject
PrivateGroupManagerImpl(ClientHelper clientHelper, PrivateGroupManagerImpl(ClientHelper clientHelper,
MetadataParser metadataParser, DatabaseComponent db, MetadataParser metadataParser, DatabaseComponent db,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
IdentityManager identityManager) { IdentityManager identityManager, MessageTracker messageTracker) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser);
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.identityManager = identityManager; this.identityManager = identityManager;
this.messageTracker = messageTracker;
hooks = new CopyOnWriteArrayList<PrivateGroupHook>(); hooks = new CopyOnWriteArrayList<PrivateGroupHook>();
} }
@@ -126,7 +129,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
meta.put(KEY_TYPE, JOIN.getInt()); meta.put(KEY_TYPE, JOIN.getInt());
addMessageMetadata(meta, m, true); addMessageMetadata(meta, m, true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage()); messageTracker.trackOutgoingMessage(txn, m.getMessage());
addMember(txn, m.getMessage().getGroupId(), m.getMember(), VISIBLE); addMember(txn, m.getMessage().getGroupId(), m.getMember(), VISIBLE);
setPreviousMsgId(txn, m.getMessage().getGroupId(), setPreviousMsgId(txn, m.getMessage().getGroupId(),
m.getMessage().getId()); m.getMessage().getId());
@@ -218,7 +221,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
// track message // track message
setPreviousMsgId(txn, g, m.getMessage().getId()); setPreviousMsgId(txn, g, m.getMessage().getId());
trackOutgoingMessage(txn, m.getMessage()); messageTracker.trackOutgoingMessage(txn, m.getMessage());
// broadcast event // broadcast event
attachGroupMessageAddedEvent(txn, m.getMessage(), meta, true); attachGroupMessageAddedEvent(txn, m.getMessage(), meta, true);
@@ -437,6 +440,17 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
return false; return false;
} }
@Override
public GroupCount getGroupCount(GroupId g) throws DbException {
return messageTracker.getGroupCount(g);
}
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
messageTracker.setReadFlag(g, m, read);
}
@Override @Override
public void relationshipRevealed(Transaction txn, GroupId g, AuthorId a, public void relationshipRevealed(Transaction txn, GroupId g, AuthorId a,
boolean byContact) throws FormatException, DbException { boolean byContact) throws FormatException, DbException {
@@ -500,7 +514,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
} }
addMember(txn, m.getGroupId(), member, v); addMember(txn, m.getGroupId(), member, v);
// track message and broadcast event // track message and broadcast event
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
attachJoinMessageAddedEvent(txn, m, meta, false, v); attachJoinMessageAddedEvent(txn, m, meta, false, v);
} }
@@ -537,7 +551,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
if (previousType != JOIN && previousType != POST) if (previousType != JOIN && previousType != POST)
throw new FormatException(); throw new FormatException();
// track message and broadcast event // track message and broadcast event
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
attachGroupMessageAddedEvent(txn, m, meta, false); attachGroupMessageAddedEvent(txn, m, meta, false);
} }

View File

@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.clients.Client; import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -74,13 +75,14 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
@Inject @Inject
protected GroupInvitationManagerImpl(DatabaseComponent db, protected GroupInvitationManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser, ClientHelper clientHelper, MetadataParser metadataParser,
MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory, ContactGroupFactory contactGroupFactory,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
MessageParser messageParser, SessionParser sessionParser, MessageParser messageParser, SessionParser sessionParser,
SessionEncoder sessionEncoder, SessionEncoder sessionEncoder,
ProtocolEngineFactory engineFactory) { ProtocolEngineFactory engineFactory) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser, messageTracker);
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.privateGroupManager = privateGroupManager; this.privateGroupManager = privateGroupManager;
@@ -131,7 +133,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
} }
@Override @Override
protected Group getContactGroup(Contact c) { public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(CLIENT_ID, c); return contactGroupFactory.createContactGroup(CLIENT_ID, c);
} }

View File

@@ -1,11 +1,12 @@
package org.briarproject.properties; package org.briarproject.properties;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.BdfMessageContext; import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
@@ -15,6 +16,7 @@ import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
@NotNullByDefault
public class TransportPropertyValidator extends BdfMessageValidator { public class TransportPropertyValidator extends BdfMessageValidator {
TransportPropertyValidator(ClientHelper clientHelper, TransportPropertyValidator(ClientHelper clientHelper,

View File

@@ -12,6 +12,7 @@ import org.briarproject.api.blogs.BlogSharingMessage.BlogInvitation;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -28,6 +29,7 @@ import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -43,6 +45,7 @@ import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID; import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID;
import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID; import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID;
@NotNullByDefault
class BlogSharingManagerImpl extends class BlogSharingManagerImpl extends
SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent> SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
implements BlogSharingManager, RemoveBlogHook { implements BlogSharingManager, RemoveBlogHook {
@@ -63,10 +66,11 @@ class BlogSharingManagerImpl extends
DatabaseComponent db, MessageQueueManager messageQueueManager, DatabaseComponent db, MessageQueueManager messageQueueManager,
MetadataEncoder metadataEncoder, MetadataParser metadataParser, MetadataEncoder metadataEncoder, MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory, SecureRandom random, ContactGroupFactory contactGroupFactory, SecureRandom random,
IdentityManager identityManager) { IdentityManager identityManager, MessageTracker messageTracker) {
super(db, messageQueueManager, clientHelper, metadataParser, super(db, messageQueueManager, clientHelper, metadataParser,
metadataEncoder, random, contactGroupFactory, clock); metadataEncoder, random, contactGroupFactory, messageTracker,
clock);
this.blogManager = blogManager; this.blogManager = blogManager;
this.identityManager = identityManager; this.identityManager = identityManager;

View File

@@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
@@ -30,6 +31,7 @@ import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE
import static org.briarproject.api.sharing.SharingConstants.TIME; import static org.briarproject.api.sharing.SharingConstants.TIME;
import static org.briarproject.api.sharing.SharingConstants.TYPE; import static org.briarproject.api.sharing.SharingConstants.TYPE;
@NotNullByDefault
class BlogSharingValidator extends BdfMessageValidator { class BlogSharingValidator extends BdfMessageValidator {
@Inject @Inject

View File

@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
@@ -20,8 +21,10 @@ import org.briarproject.api.forum.ForumFactory;
import org.briarproject.api.forum.ForumInvitationRequest; import org.briarproject.api.forum.ForumInvitationRequest;
import org.briarproject.api.forum.ForumInvitationResponse; import org.briarproject.api.forum.ForumInvitationResponse;
import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumManager.RemoveForumHook;
import org.briarproject.api.forum.ForumSharingManager; import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation; import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -37,9 +40,10 @@ import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID; import static org.briarproject.api.sharing.SharingConstants.INVITATION_ID;
import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID; import static org.briarproject.api.sharing.SharingConstants.RESPONSE_ID;
@NotNullByDefault
class ForumSharingManagerImpl extends class ForumSharingManagerImpl extends
SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent> SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent>
implements ForumSharingManager, ForumManager.RemoveForumHook { implements ForumSharingManager, RemoveForumHook {
private final SFactory sFactory; private final SFactory sFactory;
private final IFactory iFactory; private final IFactory iFactory;
@@ -57,9 +61,10 @@ class ForumSharingManagerImpl extends
MetadataEncoder metadataEncoder, MetadataEncoder metadataEncoder,
MetadataParser metadataParser, MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory, ContactGroupFactory contactGroupFactory,
SecureRandom random) { SecureRandom random, MessageTracker messageTracker) {
super(db, messageQueueManager, clientHelper, metadataParser, super(db, messageQueueManager, clientHelper, metadataParser,
metadataEncoder, random, contactGroupFactory, clock); metadataEncoder, random, contactGroupFactory, messageTracker,
clock);
sFactory = new SFactory(forumFactory, forumManager); sFactory = new SFactory(forumFactory, forumManager);
iFactory = new IFactory(); iFactory = new IFactory();

View File

@@ -7,6 +7,7 @@ import org.briarproject.api.clients.SessionId;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
@@ -30,6 +31,7 @@ import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE
import static org.briarproject.api.sharing.SharingConstants.TIME; import static org.briarproject.api.sharing.SharingConstants.TIME;
import static org.briarproject.api.sharing.SharingConstants.TYPE; import static org.briarproject.api.sharing.SharingConstants.TYPE;
@NotNullByDefault
class ForumSharingValidator extends BdfMessageValidator { class ForumSharingValidator extends BdfMessageValidator {
@Inject @Inject

View File

@@ -6,6 +6,7 @@ import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -25,6 +26,7 @@ import org.briarproject.api.event.Event;
import org.briarproject.api.event.InvitationRequestReceivedEvent; import org.briarproject.api.event.InvitationRequestReceivedEvent;
import org.briarproject.api.event.InvitationResponseReceivedEvent; import org.briarproject.api.event.InvitationResponseReceivedEvent;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sharing.Shareable; import org.briarproject.api.sharing.Shareable;
import org.briarproject.api.sharing.SharingInvitationItem; import org.briarproject.api.sharing.SharingInvitationItem;
@@ -52,6 +54,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
@@ -86,6 +90,7 @@ import static org.briarproject.api.sharing.SharingMessage.Invitation;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE; import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
@NotNullByDefault
abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationRequestReceivedEvent, IRR extends InvitationResponseReceivedEvent> abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationRequestReceivedEvent, IRR extends InvitationResponseReceivedEvent>
extends ConversationClientImpl extends ConversationClientImpl
implements SharingManager<S>, Client, AddContactHook, implements SharingManager<S>, Client, AddContactHook,
@@ -105,9 +110,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
MessageQueueManager messageQueueManager, ClientHelper clientHelper, MessageQueueManager messageQueueManager, ClientHelper clientHelper,
MetadataParser metadataParser, MetadataEncoder metadataEncoder, MetadataParser metadataParser, MetadataEncoder metadataEncoder,
SecureRandom random, ContactGroupFactory contactGroupFactory, SecureRandom random, ContactGroupFactory contactGroupFactory,
Clock clock) { MessageTracker messageTracker, Clock clock) {
super(db, clientHelper, metadataParser); super(db, clientHelper, metadataParser, messageTracker);
this.messageQueueManager = messageQueueManager; this.messageQueueManager = messageQueueManager;
this.metadataEncoder = metadataEncoder; this.metadataEncoder = metadataEncoder;
this.random = random; this.random = random;
@@ -226,7 +230,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
new InviteeEngine<IS, IR>(getIRFactory(), clock); new InviteeEngine<IS, IR>(getIRFactory(), clock);
processInviteeStateUpdate(txn, m.getId(), processInviteeStateUpdate(txn, m.getId(),
engine.onMessageReceived(state, msg)); engine.onMessageReceived(state, msg));
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
} else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT || } else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT ||
msg.getType() == SHARE_MSG_TYPE_DECLINE) { msg.getType() == SHARE_MSG_TYPE_DECLINE) {
// we are a sharer who just received a response // we are a sharer who just received a response
@@ -237,7 +241,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
getIRRFactory(), clock); getIRRFactory(), clock);
processSharerStateUpdate(txn, m.getId(), processSharerStateUpdate(txn, m.getId(),
engine.onMessageReceived(state, msg)); engine.onMessageReceived(state, msg));
trackIncomingMessage(txn, m); messageTracker.trackIncomingMessage(txn, m);
} else if (msg.getType() == SHARE_MSG_TYPE_LEAVE || } else if (msg.getType() == SHARE_MSG_TYPE_LEAVE ||
msg.getType() == SHARE_MSG_TYPE_ABORT) { msg.getType() == SHARE_MSG_TYPE_ABORT) {
// we don't know who we are, so figure it out // we don't know who we are, so figure it out
@@ -296,7 +300,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
// track message // track message
// TODO handle this properly without engine hacks (#376) // TODO handle this properly without engine hacks (#376)
long time = update.toSend.get(0).getTime(); long time = update.toSend.get(0).getTime();
trackMessage(txn, localState.getGroupId(), time, true); messageTracker.trackMessage(txn, localState.getGroupId(), time,
true);
db.commitTransaction(txn); db.commitTransaction(txn);
} catch (FormatException e) { } catch (FormatException e) {
@@ -359,7 +364,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
// track message // track message
// TODO handle this properly without engine hacks (#376) // TODO handle this properly without engine hacks (#376)
long time = update.toSend.get(0).getTime(); long time = update.toSend.get(0).getTime();
trackMessage(txn, localState.getGroupId(), time, true); messageTracker.trackMessage(txn, localState.getGroupId(), time, true);
} }
@Override @Override
@@ -581,16 +586,6 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
} }
} }
@Override
public GroupCount getGroupCount(Transaction txn, ContactId contactId)
throws DbException {
Contact contact = db.getContact(txn, contactId);
GroupId groupId = getContactGroup(contact).getId();
return getGroupCount(txn, groupId);
}
void removingShareable(Transaction txn, S f) throws DbException { void removingShareable(Transaction txn, S f) throws DbException {
try { try {
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
@@ -827,7 +822,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
throw new FormatException(); throw new FormatException();
} }
private void processStateUpdate(Transaction txn, MessageId messageId, private void processStateUpdate(Transaction txn,
@Nullable MessageId messageId,
StateUpdate<SharingSessionState, BaseMessage> result, S f) StateUpdate<SharingSessionState, BaseMessage> result, S f)
throws DbException, FormatException { throws DbException, FormatException {
@@ -859,8 +855,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
} }
} }
private void processSharerStateUpdate(Transaction txn, MessageId messageId, private void processSharerStateUpdate(Transaction txn,
StateUpdate<SS, BaseMessage> result) @Nullable MessageId messageId, StateUpdate<SS, BaseMessage> result)
throws DbException, FormatException { throws DbException, FormatException {
StateUpdate<SharingSessionState, BaseMessage> r = StateUpdate<SharingSessionState, BaseMessage> r =
@@ -874,8 +870,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
processStateUpdate(txn, messageId, r, f); processStateUpdate(txn, messageId, r, f);
} }
private void processInviteeStateUpdate(Transaction txn, MessageId messageId, private void processInviteeStateUpdate(Transaction txn,
StateUpdate<IS, BaseMessage> result) @Nullable MessageId messageId, StateUpdate<IS, BaseMessage> result)
throws DbException, FormatException { throws DbException, FormatException {
StateUpdate<SharingSessionState, BaseMessage> r = StateUpdate<SharingSessionState, BaseMessage> r =
@@ -947,7 +943,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
} }
@Override @Override
protected Group getContactGroup(Contact c) { public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(getClientId(), c); return contactGroupFactory.createContactGroup(getClientId(), c);
} }

View File

@@ -1,19 +1,22 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.UniqueId; import org.briarproject.api.UniqueId;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.nullsafety.NotNullByDefault;
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.MessageFactory;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.util.ByteUtils; import org.briarproject.util.ByteUtils;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
@Immutable
@NotNullByDefault
class MessageFactoryImpl implements MessageFactory { class MessageFactoryImpl implements MessageFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;

View File

@@ -1,6 +1,5 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.UniqueId;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DatabaseExecutor;
@@ -13,15 +12,15 @@ import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener; import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageAddedEvent; import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.lifecycle.Service; import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.sync.ValidationManager;
import org.briarproject.util.ByteUtils;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
@@ -33,15 +32,17 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.briarproject.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.api.sync.ValidationManager.State.PENDING; import static org.briarproject.api.sync.ValidationManager.State.PENDING;
@ThreadSafe
@NotNullByDefault
class ValidationManagerImpl implements ValidationManager, Service, class ValidationManagerImpl implements ValidationManager, Service,
EventListener { EventListener {
@@ -51,6 +52,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
private final DatabaseComponent db; private final DatabaseComponent db;
private final Executor dbExecutor; private final Executor dbExecutor;
private final Executor cryptoExecutor; private final Executor cryptoExecutor;
private final MessageFactory messageFactory;
private final Map<ClientId, MessageValidator> validators; private final Map<ClientId, MessageValidator> validators;
private final Map<ClientId, IncomingMessageHook> hooks; private final Map<ClientId, IncomingMessageHook> hooks;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -58,10 +60,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
@Inject @Inject
ValidationManagerImpl(DatabaseComponent db, ValidationManagerImpl(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor, @DatabaseExecutor Executor dbExecutor,
@CryptoExecutor Executor cryptoExecutor) { @CryptoExecutor Executor cryptoExecutor,
MessageFactory messageFactory) {
this.db = db; this.db = db;
this.dbExecutor = dbExecutor; this.dbExecutor = dbExecutor;
this.cryptoExecutor = cryptoExecutor; this.cryptoExecutor = cryptoExecutor;
this.messageFactory = messageFactory;
validators = new ConcurrentHashMap<ClientId, MessageValidator>(); validators = new ConcurrentHashMap<ClientId, MessageValidator>();
hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>(); hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>();
} }
@@ -134,7 +138,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
try { try {
MessageId id = unvalidated.poll(); MessageId id = unvalidated.poll();
byte[] raw = db.getRawMessage(txn, id); byte[] raw = db.getRawMessage(txn, id);
m = parseMessage(id, raw); if (raw == null) throw new DbException();
m = messageFactory.createMessage(id, raw);
g = db.getGroup(txn, m.getGroupId()); g = db.getGroup(txn, m.getGroupId());
db.commitTransaction(txn); db.commitTransaction(txn);
} finally { } finally {
@@ -210,7 +215,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
invalidateMessage(txn, id); invalidateMessage(txn, id);
invalidate = getDependentsToInvalidate(txn, id); invalidate = getDependentsToInvalidate(txn, id);
} else if (allDelivered) { } else if (allDelivered) {
Message m = parseMessage(id, db.getRawMessage(txn, id)); byte[] raw = db.getRawMessage(txn, id);
if (raw == null) throw new DbException();
Message m = messageFactory.createMessage(id, raw);
Group g = db.getGroup(txn, m.getGroupId()); Group g = db.getGroup(txn, m.getGroupId());
ClientId c = g.getClientId(); ClientId c = g.getClientId();
Metadata meta = db.getMessageMetadataForValidator(txn, Metadata meta = db.getMessageMetadataForValidator(txn,
@@ -247,15 +254,6 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
} }
private Message parseMessage(MessageId id, byte[] raw) {
if (raw.length <= MESSAGE_HEADER_LENGTH)
throw new IllegalArgumentException();
byte[] groupId = new byte[UniqueId.LENGTH];
System.arraycopy(raw, 0, groupId, 0, UniqueId.LENGTH);
long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH);
return new Message(id, new GroupId(groupId), timestamp, raw);
}
private void validateMessageAsync(final Message m, final Group g) { private void validateMessageAsync(final Message m, final Group g) {
cryptoExecutor.execute(new Runnable() { cryptoExecutor.execute(new Runnable() {
@Override @Override
@@ -412,7 +410,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
/** /**
* Shares the next message from the toShare queue asynchronously. * Shares the next message from the toShare queue asynchronously.
* * <p>
* This method should only be called for messages that have all their * This method should only be called for messages that have all their
* dependencies delivered and have been delivered themselves. * dependencies delivered and have been delivered themselves.
*/ */

View File

@@ -16,6 +16,7 @@ import org.briarproject.api.db.Transaction;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@@ -37,8 +38,8 @@ import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LEN
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
public class MessageQueueManagerImplTest extends BriarTestCase { public class MessageQueueManagerImplTest extends BriarTestCase {
@@ -152,7 +153,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
MessageValidator delegate = captured.get(); MessageValidator delegate = captured.get();
assertNotNull(delegate); assertNotNull(delegate);
// The message should be invalid // The message should be invalid
assertNull(delegate.validateMessage(message, group)); try {
delegate.validateMessage(message, group);
fail();
} catch (InvalidMessageException expected) {
// Expected
}
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -193,7 +199,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
MessageValidator delegate = captured.get(); MessageValidator delegate = captured.get();
assertNotNull(delegate); assertNotNull(delegate);
// The message should be invalid // The message should be invalid
assertNull(delegate.validateMessage(message, group)); try {
delegate.validateMessage(message, group);
fail();
} catch (InvalidMessageException expected) {
// Expected
}
context.assertIsSatisfied(); context.assertIsSatisfied();
} }

View File

@@ -4,6 +4,7 @@ import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils; import org.briarproject.TestUtils;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -41,9 +42,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT;
import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
public class IntroductionManagerImplTest extends BriarTestCase { public class IntroductionManagerImplTest extends BriarTestCase {
@@ -54,6 +52,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
private final IntroduceeManager introduceeManager; private final IntroduceeManager introduceeManager;
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final MessageTracker messageTracker;
private final IntroductionGroupFactory introductionGroupFactory; private final IntroductionGroupFactory introductionGroupFactory;
private final SessionId sessionId = new SessionId(TestUtils.getRandomId()); private final SessionId sessionId = new SessionId(TestUtils.getRandomId());
private final long time = 42L; private final long time = 42L;
@@ -63,7 +62,6 @@ public class IntroductionManagerImplTest extends BriarTestCase {
private final Group introductionGroup2; private final Group introductionGroup2;
private final Message message1; private final Message message1;
private Transaction txn; private Transaction txn;
private BdfDictionary metadataBefore, metadataAfter;
public IntroductionManagerImplTest() { public IntroductionManagerImplTest() {
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
@@ -94,16 +92,6 @@ public class IntroductionManagerImplTest extends BriarTestCase {
time, time,
TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1) TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1)
); );
metadataBefore = BdfDictionary.of(
new BdfEntry(GROUP_KEY_MSG_COUNT, 41),
new BdfEntry(GROUP_KEY_UNREAD_COUNT, 0),
new BdfEntry(GROUP_KEY_LATEST_MSG, 0)
);
metadataAfter = BdfDictionary.of(
new BdfEntry(GROUP_KEY_MSG_COUNT, 42),
new BdfEntry(GROUP_KEY_UNREAD_COUNT, 0),
new BdfEntry(GROUP_KEY_LATEST_MSG, time)
);
// mock ALL THE THINGS!!! // mock ALL THE THINGS!!!
context = new Mockery(); context = new Mockery();
@@ -113,12 +101,12 @@ public class IntroductionManagerImplTest extends BriarTestCase {
db = context.mock(DatabaseComponent.class); db = context.mock(DatabaseComponent.class);
clientHelper = context.mock(ClientHelper.class); clientHelper = context.mock(ClientHelper.class);
MetadataParser metadataParser = context.mock(MetadataParser.class); MetadataParser metadataParser = context.mock(MetadataParser.class);
messageTracker = context.mock(MessageTracker.class);
introductionGroupFactory = context.mock(IntroductionGroupFactory.class); introductionGroupFactory = context.mock(IntroductionGroupFactory.class);
introductionManager = new IntroductionManagerImpl( introductionManager = new IntroductionManagerImpl(db, clientHelper,
db, clientHelper, metadataParser, introducerManager, metadataParser, messageTracker, introducerManager,
introduceeManager, introductionGroupFactory introduceeManager, introductionGroupFactory);
);
} }
@Test @Test
@@ -139,19 +127,11 @@ public class IntroductionManagerImplTest extends BriarTestCase {
.createIntroductionGroup(introducee2); .createIntroductionGroup(introducee2);
will(returnValue(introductionGroup2)); will(returnValue(introductionGroup2));
// track message for group 1 // track message for group 1
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackMessage(txn,
introductionGroup1.getId()); introductionGroup1.getId(), time, true);
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup1.getId(),
metadataAfter);
// track message for group 2 // track message for group 2
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackMessage(txn,
introductionGroup2.getId()); introductionGroup2.getId(), time, true);
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup2.getId(),
metadataAfter);
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -181,12 +161,8 @@ public class IntroductionManagerImplTest extends BriarTestCase {
will(returnValue(state)); will(returnValue(state));
oneOf(introduceeManager).acceptIntroduction(txn, state, time); oneOf(introduceeManager).acceptIntroduction(txn, state, time);
// track message // track message
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackMessage(txn,
introductionGroup1.getId()); introductionGroup1.getId(), time, true);
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup1.getId(),
metadataAfter);
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -216,12 +192,8 @@ public class IntroductionManagerImplTest extends BriarTestCase {
will(returnValue(state)); will(returnValue(state));
oneOf(introduceeManager).declineIntroduction(txn, state, time); oneOf(introduceeManager).declineIntroduction(txn, state, time);
// track message // track message
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackMessage(txn,
introductionGroup1.getId()); introductionGroup1.getId(), time, true);
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup1.getId(),
metadataAfter);
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -272,9 +244,6 @@ public class IntroductionManagerImplTest extends BriarTestCase {
final BdfDictionary state = new BdfDictionary(); final BdfDictionary state = new BdfDictionary();
txn = new Transaction(null, false); txn = new Transaction(null, false);
metadataBefore.put(GROUP_KEY_UNREAD_COUNT, 1);
metadataAfter.put(GROUP_KEY_UNREAD_COUNT, 2);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(introduceeManager) oneOf(introduceeManager)
.initialize(txn, introductionGroup1.getId(), msg); .initialize(txn, introductionGroup1.getId(), msg);
@@ -282,12 +251,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
oneOf(introduceeManager) oneOf(introduceeManager)
.incomingMessage(txn, state, msg); .incomingMessage(txn, state, msg);
// track message // track message
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackIncomingMessage(txn, message1);
introductionGroup1.getId());
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup1.getId(),
metadataAfter);
}}); }});
introductionManager introductionManager
@@ -313,20 +277,12 @@ public class IntroductionManagerImplTest extends BriarTestCase {
txn = new Transaction(null, false); txn = new Transaction(null, false);
metadataBefore.put(GROUP_KEY_UNREAD_COUNT, 41);
metadataAfter.put(GROUP_KEY_UNREAD_COUNT, 42);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId); oneOf(clientHelper).getMessageMetadataAsDictionary(txn, sessionId);
will(returnValue(state)); will(returnValue(state));
oneOf(introducerManager).incomingMessage(txn, state, msg); oneOf(introducerManager).incomingMessage(txn, state, msg);
// track message // track message
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(messageTracker).trackIncomingMessage(txn, message1);
introductionGroup1.getId());
will(returnValue(metadataBefore));
oneOf(clientHelper)
.mergeGroupMetadata(txn, introductionGroup1.getId(),
metadataAfter);
}}); }});
introductionManager introductionManager

View File

@@ -17,6 +17,7 @@ import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.InvalidMessageException; import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageContext; import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.api.sync.ValidationManager.MessageValidator; import org.briarproject.api.sync.ValidationManager.MessageValidator;
@@ -74,6 +75,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -97,6 +100,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
will(returnValue(txn1)); will(returnValue(txn1));
oneOf(db).getRawMessage(txn1, messageId); oneOf(db).getRawMessage(txn1, messageId);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId, raw);
will(returnValue(message));
oneOf(db).getGroup(txn1, groupId); oneOf(db).getGroup(txn1, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).commitTransaction(txn1); oneOf(db).commitTransaction(txn1);
@@ -122,6 +127,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
will(returnValue(txn3)); will(returnValue(txn3));
oneOf(db).getRawMessage(txn3, messageId1); oneOf(db).getRawMessage(txn3, messageId1);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId1, raw);
will(returnValue(message1));
oneOf(db).getGroup(txn3, groupId); oneOf(db).getGroup(txn3, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).commitTransaction(txn3); oneOf(db).commitTransaction(txn3);
@@ -159,7 +166,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.startService(); vm.startService();
@@ -173,6 +180,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -207,6 +216,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get the message and its metadata to deliver // Get the message and its metadata to deliver
oneOf(db).getRawMessage(txn2, messageId); oneOf(db).getRawMessage(txn2, messageId);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId, raw);
will(returnValue(message));
oneOf(db).getGroup(txn2, groupId); oneOf(db).getGroup(txn2, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn2, messageId); oneOf(db).getMessageMetadataForValidator(txn2, messageId);
@@ -230,6 +241,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get the dependent and its metadata to deliver // Get the dependent and its metadata to deliver
oneOf(db).getRawMessage(txn3, messageId2); oneOf(db).getRawMessage(txn3, messageId2);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId2, raw);
will(returnValue(message2));
oneOf(db).getGroup(txn3, groupId); oneOf(db).getGroup(txn3, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn3, messageId2); oneOf(db).getMessageMetadataForValidator(txn3, messageId2);
@@ -254,7 +267,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.startService(); vm.startService();
@@ -268,6 +281,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -319,7 +334,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.startService(); vm.startService();
@@ -333,6 +348,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -380,7 +397,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -395,6 +412,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -424,6 +443,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
will(returnValue(txn2)); will(returnValue(txn2));
oneOf(db).getRawMessage(txn2, messageId1); oneOf(db).getRawMessage(txn2, messageId1);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId1, raw);
will(returnValue(message1));
oneOf(db).getGroup(txn2, groupId); oneOf(db).getGroup(txn2, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).commitTransaction(txn2); oneOf(db).commitTransaction(txn2);
@@ -461,7 +482,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.startService(); vm.startService();
@@ -476,6 +497,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -498,6 +521,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
will(returnValue(txn1)); will(returnValue(txn1));
oneOf(db).getRawMessage(txn1, messageId); oneOf(db).getRawMessage(txn1, messageId);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId, raw);
will(returnValue(message));
// Load the group - *gasp* it's gone! // Load the group - *gasp* it's gone!
oneOf(db).getGroup(txn1, groupId); oneOf(db).getGroup(txn1, groupId);
will(throwException(new NoSuchGroupException())); will(throwException(new NoSuchGroupException()));
@@ -508,6 +533,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
will(returnValue(txn2)); will(returnValue(txn2));
oneOf(db).getRawMessage(txn2, messageId1); oneOf(db).getRawMessage(txn2, messageId1);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId1, raw);
will(returnValue(message1));
oneOf(db).getGroup(txn2, groupId); oneOf(db).getGroup(txn2, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).commitTransaction(txn2); oneOf(db).commitTransaction(txn2);
@@ -545,7 +572,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.startService(); vm.startService();
@@ -559,6 +586,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -591,7 +620,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -605,12 +634,14 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, null)); vm.eventOccurred(new MessageAddedEvent(message, null));
@@ -626,6 +657,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -656,7 +689,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -671,6 +704,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -707,7 +742,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -722,6 +757,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -773,7 +810,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -787,6 +824,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -888,7 +927,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -902,6 +941,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -958,6 +999,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get message 1 and its metadata // Get message 1 and its metadata
oneOf(db).getRawMessage(txn2, messageId1); oneOf(db).getRawMessage(txn2, messageId1);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId1, raw);
will(returnValue(message1));
oneOf(db).getGroup(txn2, groupId); oneOf(db).getGroup(txn2, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn2, messageId1); oneOf(db).getMessageMetadataForValidator(txn2, messageId1);
@@ -981,6 +1024,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get message 2 and its metadata // Get message 2 and its metadata
oneOf(db).getRawMessage(txn3, messageId2); oneOf(db).getRawMessage(txn3, messageId2);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId2, raw);
will(returnValue(message2));
oneOf(db).getGroup(txn3, groupId); oneOf(db).getGroup(txn3, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn3, messageId2); oneOf(db).getMessageMetadataForValidator(txn3, messageId2);
@@ -1004,6 +1049,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get message 3 and its metadata // Get message 3 and its metadata
oneOf(db).getRawMessage(txn4, messageId3); oneOf(db).getRawMessage(txn4, messageId3);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId3, raw);
will(returnValue(message3));
oneOf(db).getGroup(txn4, groupId); oneOf(db).getGroup(txn4, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn4, messageId3); oneOf(db).getMessageMetadataForValidator(txn4, messageId3);
@@ -1033,6 +1080,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
// Get message 4 and its metadata // Get message 4 and its metadata
oneOf(db).getRawMessage(txn6, messageId4); oneOf(db).getRawMessage(txn6, messageId4);
will(returnValue(raw)); will(returnValue(raw));
oneOf(messageFactory).createMessage(messageId4, raw);
will(returnValue(message4));
oneOf(db).getGroup(txn6, groupId); oneOf(db).getGroup(txn6, groupId);
will(returnValue(group)); will(returnValue(group));
oneOf(db).getMessageMetadataForValidator(txn6, messageId4); oneOf(db).getMessageMetadataForValidator(txn6, messageId4);
@@ -1049,7 +1098,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -1063,6 +1112,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -1108,7 +1159,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));
@@ -1125,6 +1176,8 @@ public class ValidationManagerImplTest extends BriarTestCase {
final DatabaseComponent db = context.mock(DatabaseComponent.class); final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Executor dbExecutor = new ImmediateExecutor(); final Executor dbExecutor = new ImmediateExecutor();
final Executor cryptoExecutor = new ImmediateExecutor(); final Executor cryptoExecutor = new ImmediateExecutor();
final MessageFactory messageFactory =
context.mock(MessageFactory.class);
final MessageValidator validator = context.mock(MessageValidator.class); final MessageValidator validator = context.mock(MessageValidator.class);
final IncomingMessageHook hook = final IncomingMessageHook hook =
context.mock(IncomingMessageHook.class); context.mock(IncomingMessageHook.class);
@@ -1178,7 +1231,7 @@ public class ValidationManagerImplTest extends BriarTestCase {
}}); }});
ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor, ValidationManagerImpl vm = new ValidationManagerImpl(db, dbExecutor,
cryptoExecutor); cryptoExecutor, messageFactory);
vm.registerMessageValidator(clientId, validator); vm.registerMessageValidator(clientId, validator);
vm.registerIncomingMessageHook(clientId, hook); vm.registerIncomingMessageHook(clientId, hook);
vm.eventOccurred(new MessageAddedEvent(message, contactId)); vm.eventOccurred(new MessageAddedEvent(message, contactId));