Merge branch 'message-tracker-refactoring' into 'master'

Factor MessageTracker out of BdfIncomingMessageHook

The branch moves the MessageTracker implementation from BdfIncomingMessageHook to a separate class. This will allow the private group invitation client to track messages from classes other than the one that implements the delivery hook.

I've also fixed a couple of bugs, removed some redundant code from the validation manager, and added null-safety annotations (which is how I noticed the bugs).

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

View File

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

View File

@@ -9,7 +9,7 @@ import static org.junit.Assert.assertEquals;
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)
throws DbException {
@@ -19,7 +19,7 @@ public abstract class BriarIntegrationTest extends BriarTestCase {
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 {
GroupCount c1 = tracker.getGroupCount(g);

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,15 @@
package org.briarproject.api.clients;
import org.briarproject.api.FormatException;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.MessageContext;
@NotNullByDefault
public interface MessageQueueManager {
/**
@@ -52,17 +53,17 @@ public interface MessageQueueManager {
*
* @throws DbException Should only be used for real database errors.
* 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.
* @throws FormatException for any non-database error
* @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Never rethrow DbException as FormatException!
* Never rethrow DbException as InvalidMessageException!
*/
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;
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;
@NotNullByDefault
public interface MessageTracker {
/**
@@ -13,11 +17,34 @@ public interface MessageTracker {
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;
class GroupCount {
private final int msgCount, unreadCount;
private final long latestMsgTime;

View File

@@ -1,10 +1,11 @@
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.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
@@ -12,43 +13,76 @@ import org.jetbrains.annotations.Nullable;
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");
/** Subscribes to a forum. */
/**
* Subscribes to a forum.
*/
Forum addForum(String name) throws DbException;
/** Unsubscribes from a forum. */
/**
* Unsubscribes from a forum.
*/
void removeForum(Forum f) throws DbException;
/** Creates a local forum post. */
/**
* Creates a local forum post.
*/
@CryptoExecutor
ForumPost createLocalPost(GroupId groupId, String body, long timestamp,
@Nullable MessageId parentId, LocalAuthor author);
/** Stores a local forum post. */
/**
* Stores a local forum post.
*/
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;
/** Returns the forum with the given ID. */
/**
* Returns the forum with the given ID.
*/
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;
/** 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;
/** 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;
/** 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);
/**
* 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 {
void removingForum(Transaction txn, Forum f) throws DbException;
}

View File

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

View File

@@ -1,10 +1,16 @@
package org.briarproject.api.messaging;
import org.briarproject.api.clients.MessageTracker.GroupCount;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
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 {
/**
@@ -13,11 +19,19 @@ public interface ConversationManager {
*/
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 {
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;
}

View File

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

View File

@@ -1,7 +1,7 @@
package org.briarproject.api.privategroup;
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.Transaction;
import org.briarproject.api.identity.Author;
@@ -14,7 +14,7 @@ import org.briarproject.api.sync.MessageId;
import java.util.Collection;
@NotNullByDefault
public interface PrivateGroupManager extends MessageTracker {
public interface PrivateGroupManager {
/**
* 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.
*
* @param group The private group to add
* @param joinMsg The creators's join message
* @param creator True if the group is added by its creator
* @param group The private group to add
* @param joinMsg The creators's join message
* @param creator True if the group is added by its creator
*/
void addPrivateGroup(PrivateGroup group, GroupMessage joinMsg,
boolean creator) throws DbException;
@@ -34,9 +34,9 @@ public interface PrivateGroupManager extends MessageTracker {
/**
* Adds a new private group and joins it.
*
* @param group The private group to add
* @param joinMsg The new member's join message
* @param creator True if the group is added by its creator
* @param group The private group to add
* @param joinMsg The new member's join message
* @param creator True if the group is added by its creator
*/
void addPrivateGroup(Transaction txn, PrivateGroup group,
GroupMessage joinMsg, boolean creator) throws DbException;
@@ -101,13 +101,23 @@ public interface PrivateGroupManager extends MessageTracker {
*/
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
* has been revealed between the user and the Author with AuthorId a
* in the Group identified by the GroupId g.
*
* @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,
boolean byContact) throws FormatException, DbException;

View File

@@ -1,15 +1,18 @@
package org.briarproject.api.sharing;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
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 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

View File

@@ -1,5 +1,8 @@
package org.briarproject.api.sync;
import org.briarproject.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MessageFactory {
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.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
/**
* Responsible for managing message validators and passing them messages to
* validate.
*/
@NotNullByDefault
public interface ValidationManager {
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.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
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.blogs.BlogPostValidator.authorToBdfDictionary;
@NotNullByDefault
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
AddContactHook, RemoveContactHook, Client {
@@ -127,10 +129,8 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@Override
public void removingContact(Transaction txn, Contact c) throws DbException {
if (c != null) {
Blog b = blogFactory.createBlog(c.getAuthor());
db.removeGroup(txn, b.getGroup());
}
Blog b = blogFactory.createBlog(c.getAuthor());
db.removeGroup(txn, b.getGroup());
}
@Override

View File

@@ -11,6 +11,7 @@ import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
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.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
@NotNullByDefault
class BlogPostValidator extends BdfMessageValidator {
private final GroupFactory groupFactory;
@@ -76,10 +78,10 @@ class BlogPostValidator extends BdfMessageValidator {
addMessageMetadata(c, m.getTimestamp());
break;
case WRAPPED_POST:
c = validateWrappedPost(m, g, body);
c = validateWrappedPost(body);
break;
case WRAPPED_COMMENT:
c = validateWrappedComment(m, g, body);
c = validateWrappedComment(body);
break;
default:
throw new InvalidMessageException("Unknown Message Type");
@@ -164,8 +166,8 @@ class BlogPostValidator extends BdfMessageValidator {
return new BdfMessageContext(meta, dependencies);
}
private BdfMessageContext validateWrappedPost(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException {
private BdfMessageContext validateWrappedPost(BdfList body)
throws InvalidMessageException, FormatException {
// p_group descriptor, p_timestamp, p_content, p_signature
checkSize(body, 4);
@@ -202,8 +204,8 @@ class BlogPostValidator extends BdfMessageValidator {
return new BdfMessageContext(meta);
}
private BdfMessageContext validateWrappedComment(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException {
private BdfMessageContext validateWrappedComment(BdfList body)
throws InvalidMessageException, FormatException {
// c_group descriptor, c_timestamp, c_comment, c_parent_original_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.clients.ClientHelper;
import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.QueueMessage;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata;
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.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
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.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,
IncomingQueueMessageHook, MessageTracker {
IncomingQueueMessageHook {
protected final DatabaseComponent db;
protected final ClientHelper clientHelper;
@@ -44,16 +38,16 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
* Called once for each incoming message that passes validation.
*
* @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
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as FormatException
* Never rethrow DbException as FormatException!
*/
protected abstract boolean incomingMessage(Transaction txn, Message m,
BdfList body, BdfDictionary meta) throws DbException,
@@ -71,8 +65,12 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
@Override
public void incomingMessage(Transaction txn, QueueMessage q, Metadata meta)
throws DbException, FormatException {
incomingMessage(txn, q, meta, QUEUE_MESSAGE_HEADER_LENGTH);
throws DbException, InvalidMessageException {
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,
@@ -84,102 +82,4 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
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.MetadataEncoder;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException;
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.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@NotNullByDefault
public abstract class BdfMessageValidator implements MessageValidator,
QueueMessageValidator {
@@ -108,7 +110,7 @@ public abstract class BdfMessageValidator implements MessageValidator,
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 {
if (list != null) {
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.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.QueueMessageFactory;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.data.BdfReaderFactory;
@@ -52,4 +53,8 @@ public class ClientsModule {
return new QueueMessageFactoryImpl(crypto);
}
@Provides
MessageTracker provideMessageTracker(MessageTrackerImpl messageTracker) {
return messageTracker;
}
}

View File

@@ -1,6 +1,8 @@
package org.briarproject.clients;
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.ContactId;
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.Transaction;
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.MessageId;
@NotNullByDefault
public abstract class ConversationClientImpl extends BdfIncomingMessageHook
implements ConversationClient {
protected ConversationClientImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser) {
super(db, clientHelper, metadataParser);
}
protected final MessageTracker messageTracker;
protected abstract Group getContactGroup(Contact contact);
protected ConversationClientImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser,
MessageTracker messageTracker) {
super(db, clientHelper, metadataParser);
this.messageTracker = messageTracker;
}
@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);
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.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
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.ValidationManager;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.api.sync.ValidationManager.MessageValidator;
import org.briarproject.util.ByteUtils;
import java.util.ArrayList;
@@ -29,12 +31,14 @@ import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
@NotNullByDefault
class MessageQueueManagerImpl implements MessageQueueManager {
private static final String OUTGOING_POSITION_KEY = "nextOut";
@@ -139,6 +143,7 @@ class MessageQueueManagerImpl implements MessageQueueManager {
this.pending = pending;
}
@Nullable
MessageId popIncomingMessageId() {
Iterator<Entry<Long, MessageId>> it = pending.entrySet().iterator();
if (!it.hasNext()) {
@@ -161,8 +166,9 @@ class MessageQueueManagerImpl implements MessageQueueManager {
}
}
@NotNullByDefault
private static class DelegatingMessageValidator
implements ValidationManager.MessageValidator {
implements MessageValidator {
private final QueueMessageValidator delegate;
@@ -174,21 +180,24 @@ class MessageQueueManagerImpl implements MessageQueueManager {
public MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException {
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,
MESSAGE_HEADER_LENGTH);
if (queuePosition < 0) return null;
if (queuePosition < 0) throw new InvalidMessageException();
QueueMessage q = new QueueMessage(m.getId(), m.getGroupId(),
m.getTimestamp(), queuePosition, raw);
return delegate.validateMessage(q, g);
}
}
@NotNullByDefault
private class DelegatingIncomingMessageHook implements IncomingMessageHook {
private final IncomingQueueMessageHook delegate;
private DelegatingIncomingMessageHook(IncomingQueueMessageHook delegate) {
private DelegatingIncomingMessageHook(
IncomingQueueMessageHook delegate) {
this.delegate = delegate;
}
@@ -227,20 +236,16 @@ class MessageQueueManagerImpl implements MessageQueueManager {
// Save the queue state before passing control to the delegate
saveQueueState(txn, m.getGroupId(), queueState);
// Deliver the messages to the delegate
try {
delegate.incomingMessage(txn, q, meta);
for (MessageId id : consecutive) {
byte[] raw = db.getRawMessage(txn, id);
meta = db.getMessageMetadata(txn, id);
q = queueMessageFactory.createMessage(id, raw);
if (LOG.isLoggable(INFO)) {
LOG.info("Delivering pending message with position "
+ q.getQueuePosition());
}
delegate.incomingMessage(txn, q, meta);
delegate.incomingMessage(txn, q, meta);
for (MessageId id : consecutive) {
byte[] raw = db.getRawMessage(txn, id);
meta = db.getMessageMetadata(txn, id);
q = queueMessageFactory.createMessage(id, raw);
if (LOG.isLoggable(INFO)) {
LOG.info("Delivering pending message with position "
+ q.getQueuePosition());
}
} catch (FormatException e) {
throw new InvalidMessageException(e);
delegate.incomingMessage(txn, q, meta);
}
}
// 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.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.BdfList;
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.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
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.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
private final IdentityManager identityManager;
private final ForumFactory forumFactory;
private final ForumPostFactory forumPostFactory;
private final MessageTracker messageTracker;
private final List<RemoveForumHook> removeHooks;
@Inject
ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager,
ClientHelper clientHelper, MetadataParser metadataParser,
ForumFactory forumFactory, ForumPostFactory forumPostFactory) {
ForumFactory forumFactory, ForumPostFactory forumPostFactory,
MessageTracker messageTracker) {
super(db, clientHelper, metadataParser);
this.identityManager = identityManager;
this.forumFactory = forumFactory;
this.forumPostFactory = forumPostFactory;
this.messageTracker = messageTracker;
removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
}
@@ -75,7 +81,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
BdfDictionary meta) throws DbException, FormatException {
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
ForumPostHeader post = getForumPostHeader(txn, m.getId(), meta);
ForumPostReceivedEvent event =
@@ -146,7 +152,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
meta.put(KEY_LOCAL, true);
meta.put(MSG_KEY_READ, true);
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
trackOutgoingMessage(txn, p.getMessage());
messageTracker.trackOutgoingMessage(txn, p.getMessage());
db.commitTransaction(txn);
} catch (FormatException e) {
throw new RuntimeException(e);
@@ -204,6 +210,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
try {
// Parent ID, author, forum post body, signature
BdfList message = clientHelper.getMessageAsList(m);
if (message == null) throw new DbException();
return message.getString(2);
} catch (FormatException e) {
throw new DbException(e);
@@ -253,6 +260,17 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
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 {
byte[] descriptor = g.getDescriptor();
// Name, salt

View File

@@ -9,6 +9,7 @@ import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException;
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_SIGNATURE_LENGTH;
@NotNullByDefault
class ForumPostValidator extends BdfMessageValidator {
private final AuthorFactory authorFactory;

View File

@@ -3,6 +3,7 @@ package org.briarproject.introduction;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact;
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.IntroductionRequest;
import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
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.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class IntroductionManagerImpl extends ConversationClientImpl
implements IntroductionManager, Client, AddContactHook,
RemoveContactHook {
@@ -86,11 +89,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
@Inject
IntroductionManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MetadataParser metadataParser, IntroducerManager introducerManager,
MetadataParser metadataParser, MessageTracker messageTracker,
IntroducerManager introducerManager,
IntroduceeManager introduceeManager,
IntroductionGroupFactory introductionGroupFactory) {
super(db, clientHelper, metadataParser);
super(db, clientHelper, metadataParser, messageTracker);
this.introducerManager = introducerManager;
this.introduceeManager = introduceeManager;
this.introductionGroupFactory = introductionGroupFactory;
@@ -213,7 +217,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
introduceeManager.initialize(txn, groupId, message);
try {
introduceeManager.incomingMessage(txn, state, message);
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
introduceeManager.abort(txn, state);
@@ -239,7 +243,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
LOG.warning("Unknown role '" + role + "'");
throw new DbException();
}
if (type == TYPE_RESPONSE) trackIncomingMessage(txn, m);
if (type == TYPE_RESPONSE)
messageTracker.trackIncomingMessage(txn, m);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state);
@@ -260,7 +265,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
}
@Override
protected Group getContactGroup(Contact contact) {
public Group getContactGroup(Contact contact) {
return introductionGroupFactory.createIntroductionGroup(contact);
}
@@ -274,8 +279,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
introducerManager.makeIntroduction(txn, c1, c2, msg, timestamp);
Group g1 = getContactGroup(c1);
Group g2 = getContactGroup(c2);
trackMessage(txn, g1.getId(), timestamp, true);
trackMessage(txn, g2.getId(), timestamp, true);
messageTracker.trackMessage(txn, g1.getId(), timestamp, true);
messageTracker.trackMessage(txn, g2.getId(), timestamp, true);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
@@ -295,7 +300,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
getSessionState(txn, g.getId(), sessionId.getBytes());
introduceeManager.acceptIntroduction(txn, state, timestamp);
trackMessage(txn, g.getId(), timestamp, true);
messageTracker.trackMessage(txn, g.getId(), timestamp, true);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
@@ -315,7 +320,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
getSessionState(txn, g.getId(), sessionId.getBytes());
introduceeManager.declineIntroduction(txn, state, timestamp);
trackMessage(txn, g.getId(), timestamp, true);
messageTracker.trackMessage(txn, g.getId(), timestamp, true);
db.commitTransaction(txn);
} finally {
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.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
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_PROPERTY_LENGTH;
@NotNullByDefault
class IntroductionValidator extends BdfMessageValidator {
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.Transaction;
import org.briarproject.api.messaging.ConversationManager;
import org.briarproject.api.nullsafety.NotNullByDefault;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.inject.Inject;
@NotNullByDefault
class ConversationManagerImpl implements ConversationManager {
private final DatabaseComponent db;
@@ -32,9 +34,7 @@ class ConversationManagerImpl implements ConversationManager {
}
@Override
public GroupCount getGroupCount(ContactId contactId)
throws DbException {
public GroupCount getGroupCount(ContactId contactId) throws DbException {
int msgCount = 0, unreadCount = 0;
long latestTime = 0;
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.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
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.PrivateMessage;
import org.briarproject.api.messaging.PrivateMessageHeader;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
@@ -33,6 +35,7 @@ import javax.inject.Inject;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class MessagingManagerImpl extends ConversationClientImpl
implements MessagingManager, Client, AddContactHook, RemoveContactHook {
@@ -40,9 +43,9 @@ class MessagingManagerImpl extends ConversationClientImpl
@Inject
MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MetadataParser metadataParser,
MetadataParser metadataParser, MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory) {
super(db, clientHelper, metadataParser);
super(db, clientHelper, metadataParser, messageTracker);
this.contactGroupFactory = contactGroupFactory;
}
@@ -72,7 +75,7 @@ class MessagingManagerImpl extends ConversationClientImpl
}
@Override
protected Group getContactGroup(Contact c) {
public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(CLIENT_ID, c);
}
@@ -95,7 +98,7 @@ class MessagingManagerImpl extends ConversationClientImpl
PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent(
header, contactId, groupId);
txn.attach(event);
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
// don't share message
return false;
@@ -110,7 +113,7 @@ class MessagingManagerImpl extends ConversationClientImpl
meta.put("local", true);
meta.put("read", true);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
trackOutgoingMessage(txn, m.getMessage());
messageTracker.trackOutgoingMessage(txn, m.getMessage());
db.commitTransaction(txn);
} catch (FormatException e) {
throw new RuntimeException(e);
@@ -195,20 +198,11 @@ class MessagingManagerImpl extends ConversationClientImpl
try {
// 0: private message body
BdfList message = clientHelper.getMessageAsList(m);
if (message == null) throw new DbException();
return message.getString(0);
} catch (FormatException 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.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
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.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
class PrivateMessageValidator extends BdfMessageValidator {
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.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.privategroup.MessageType;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory;
@@ -39,6 +40,7 @@ import static org.briarproject.privategroup.GroupConstants.KEY_READ;
import static org.briarproject.privategroup.GroupConstants.KEY_TIMESTAMP;
import static org.briarproject.privategroup.GroupConstants.KEY_TYPE;
@NotNullByDefault
class GroupMessageValidator extends BdfMessageValidator {
private final PrivateGroupFactory privateGroupFactory;

View File

@@ -2,6 +2,8 @@ package org.briarproject.privategroup;
import org.briarproject.api.FormatException;
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.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
@@ -76,17 +78,18 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
private final PrivateGroupFactory privateGroupFactory;
private final IdentityManager identityManager;
private final MessageTracker messageTracker;
private final List<PrivateGroupHook> hooks;
@Inject
PrivateGroupManagerImpl(ClientHelper clientHelper,
MetadataParser metadataParser, DatabaseComponent db,
PrivateGroupFactory privateGroupFactory,
IdentityManager identityManager) {
IdentityManager identityManager, MessageTracker messageTracker) {
super(db, clientHelper, metadataParser);
this.privateGroupFactory = privateGroupFactory;
this.identityManager = identityManager;
this.messageTracker = messageTracker;
hooks = new CopyOnWriteArrayList<PrivateGroupHook>();
}
@@ -128,7 +131,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
meta.put(KEY_INITIAL_JOIN_MSG, creator);
addMessageMetadata(meta, m, 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);
setPreviousMsgId(txn, m.getMessage().getGroupId(),
m.getMessage().getId());
@@ -210,7 +213,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
// track message
setPreviousMsgId(txn, g, m.getMessage().getId());
trackOutgoingMessage(txn, m.getMessage());
messageTracker.trackOutgoingMessage(txn, m.getMessage());
// broadcast event
attachGroupMessageAddedEvent(txn, m.getMessage(), meta, true);
@@ -430,6 +433,17 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
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
public void relationshipRevealed(Transaction txn, GroupId g, AuthorId a,
boolean byContact) throws FormatException, DbException {
@@ -498,7 +512,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
}
addMember(txn, m.getGroupId(), member, v);
// track message and broadcast event
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
attachJoinMessageAddedEvent(txn, m, meta, false, v);
}
@@ -535,7 +549,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
if (previousType != JOIN && previousType != POST)
throw new FormatException();
// track message and broadcast event
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
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.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
@@ -74,13 +75,14 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
@Inject
protected GroupInvitationManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser,
MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory,
PrivateGroupFactory privateGroupFactory,
PrivateGroupManager privateGroupManager,
MessageParser messageParser, SessionParser sessionParser,
SessionEncoder sessionEncoder,
ProtocolEngineFactory engineFactory) {
super(db, clientHelper, metadataParser);
super(db, clientHelper, metadataParser, messageTracker);
this.contactGroupFactory = contactGroupFactory;
this.privateGroupFactory = privateGroupFactory;
this.privateGroupManager = privateGroupManager;
@@ -131,7 +133,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}
@Override
protected Group getContactGroup(Contact c) {
public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(CLIENT_ID, c);
}

View File

@@ -1,11 +1,12 @@
package org.briarproject.properties;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
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_PROPERTY_LENGTH;
@NotNullByDefault
public class TransportPropertyValidator extends BdfMessageValidator {
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.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact;
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.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sync.ClientId;
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.RESPONSE_ID;
@NotNullByDefault
class BlogSharingManagerImpl extends
SharingManagerImpl<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
implements BlogSharingManager, RemoveBlogHook {
@@ -63,10 +66,11 @@ class BlogSharingManagerImpl extends
DatabaseComponent db, MessageQueueManager messageQueueManager,
MetadataEncoder metadataEncoder, MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory, SecureRandom random,
IdentityManager identityManager) {
IdentityManager identityManager, MessageTracker messageTracker) {
super(db, messageQueueManager, clientHelper, metadataParser,
metadataEncoder, random, contactGroupFactory, clock);
metadataEncoder, random, contactGroupFactory, messageTracker,
clock);
this.blogManager = blogManager;
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.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
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.TYPE;
@NotNullByDefault
class BlogSharingValidator extends BdfMessageValidator {
@Inject

View File

@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.ContactId;
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.ForumInvitationResponse;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumManager.RemoveForumHook;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.forum.ForumSharingMessage.ForumInvitation;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sync.ClientId;
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.RESPONSE_ID;
@NotNullByDefault
class ForumSharingManagerImpl extends
SharingManagerImpl<Forum, ForumInvitation, ForumInviteeSessionState, ForumSharerSessionState, ForumInvitationReceivedEvent, ForumInvitationResponseReceivedEvent>
implements ForumSharingManager, ForumManager.RemoveForumHook {
implements ForumSharingManager, RemoveForumHook {
private final SFactory sFactory;
private final IFactory iFactory;
@@ -57,9 +61,10 @@ class ForumSharingManagerImpl extends
MetadataEncoder metadataEncoder,
MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory,
SecureRandom random) {
SecureRandom random, MessageTracker messageTracker) {
super(db, messageQueueManager, clientHelper, metadataParser,
metadataEncoder, random, contactGroupFactory, clock);
metadataEncoder, random, contactGroupFactory, messageTracker,
clock);
sFactory = new SFactory(forumFactory, forumManager);
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.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
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.TYPE;
@NotNullByDefault
class ForumSharingValidator extends BdfMessageValidator {
@Inject

View File

@@ -6,6 +6,7 @@ import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.MessageTracker;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact;
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.InvitationResponseReceivedEvent;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sharing.InvitationMessage;
import org.briarproject.api.sharing.Shareable;
import org.briarproject.api.sharing.SharingInvitationItem;
@@ -52,6 +54,8 @@ import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
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.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>
extends ConversationClientImpl
implements SharingManager<S>, Client, AddContactHook,
@@ -105,9 +110,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
MessageQueueManager messageQueueManager, ClientHelper clientHelper,
MetadataParser metadataParser, MetadataEncoder metadataEncoder,
SecureRandom random, ContactGroupFactory contactGroupFactory,
Clock clock) {
super(db, clientHelper, metadataParser);
MessageTracker messageTracker, Clock clock) {
super(db, clientHelper, metadataParser, messageTracker);
this.messageQueueManager = messageQueueManager;
this.metadataEncoder = metadataEncoder;
this.random = random;
@@ -226,7 +230,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
new InviteeEngine<IS, IR>(getIRFactory(), clock);
processInviteeStateUpdate(txn, m.getId(),
engine.onMessageReceived(state, msg));
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
} else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT ||
msg.getType() == SHARE_MSG_TYPE_DECLINE) {
// 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);
processSharerStateUpdate(txn, m.getId(),
engine.onMessageReceived(state, msg));
trackIncomingMessage(txn, m);
messageTracker.trackIncomingMessage(txn, m);
} else if (msg.getType() == SHARE_MSG_TYPE_LEAVE ||
msg.getType() == SHARE_MSG_TYPE_ABORT) {
// 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
// TODO handle this properly without engine hacks (#376)
long time = update.toSend.get(0).getTime();
trackMessage(txn, localState.getGroupId(), time, true);
messageTracker.trackMessage(txn, localState.getGroupId(), time,
true);
db.commitTransaction(txn);
} catch (FormatException e) {
@@ -359,7 +364,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
// track message
// TODO handle this properly without engine hacks (#376)
long time = update.toSend.get(0).getTime();
trackMessage(txn, localState.getGroupId(), time, true);
messageTracker.trackMessage(txn, localState.getGroupId(), time, true);
}
@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 {
try {
for (Contact c : db.getContacts(txn)) {
@@ -827,7 +822,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
throw new FormatException();
}
private void processStateUpdate(Transaction txn, MessageId messageId,
private void processStateUpdate(Transaction txn,
@Nullable MessageId messageId,
StateUpdate<SharingSessionState, BaseMessage> result, S f)
throws DbException, FormatException {
@@ -859,8 +855,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
}
}
private void processSharerStateUpdate(Transaction txn, MessageId messageId,
StateUpdate<SS, BaseMessage> result)
private void processSharerStateUpdate(Transaction txn,
@Nullable MessageId messageId, StateUpdate<SS, BaseMessage> result)
throws DbException, FormatException {
StateUpdate<SharingSessionState, BaseMessage> r =
@@ -874,8 +870,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
processStateUpdate(txn, messageId, r, f);
}
private void processInviteeStateUpdate(Transaction txn, MessageId messageId,
StateUpdate<IS, BaseMessage> result)
private void processInviteeStateUpdate(Transaction txn,
@Nullable MessageId messageId, StateUpdate<IS, BaseMessage> result)
throws DbException, FormatException {
StateUpdate<SharingSessionState, BaseMessage> r =
@@ -947,7 +943,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
}
@Override
protected Group getContactGroup(Contact c) {
public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(getClientId(), c);
}

View File

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

View File

@@ -1,6 +1,5 @@
package org.briarproject.sync;
import org.briarproject.api.UniqueId;
import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DatabaseComponent;
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.MessageAddedEvent;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.util.ByteUtils;
import java.util.Collection;
import java.util.LinkedList;
@@ -33,15 +32,17 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
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.INVALID;
import static org.briarproject.api.sync.ValidationManager.State.PENDING;
@ThreadSafe
@NotNullByDefault
class ValidationManagerImpl implements ValidationManager, Service,
EventListener {
@@ -51,6 +52,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
private final DatabaseComponent db;
private final Executor dbExecutor;
private final Executor cryptoExecutor;
private final MessageFactory messageFactory;
private final Map<ClientId, MessageValidator> validators;
private final Map<ClientId, IncomingMessageHook> hooks;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -58,10 +60,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
@Inject
ValidationManagerImpl(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor,
@CryptoExecutor Executor cryptoExecutor) {
@CryptoExecutor Executor cryptoExecutor,
MessageFactory messageFactory) {
this.db = db;
this.dbExecutor = dbExecutor;
this.cryptoExecutor = cryptoExecutor;
this.messageFactory = messageFactory;
validators = new ConcurrentHashMap<ClientId, MessageValidator>();
hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>();
}
@@ -134,7 +138,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
try {
MessageId id = unvalidated.poll();
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());
db.commitTransaction(txn);
} finally {
@@ -210,7 +215,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
invalidateMessage(txn, id);
invalidate = getDependentsToInvalidate(txn, id);
} 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());
ClientId c = g.getClientId();
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) {
cryptoExecutor.execute(new Runnable() {
@Override
@@ -412,7 +410,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
/**
* Shares the next message from the toShare queue asynchronously.
*
* <p>
* This method should only be called for messages that have all their
* 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.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageContext;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
public class MessageQueueManagerImplTest extends BriarTestCase {
@@ -152,7 +153,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
MessageValidator delegate = captured.get();
assertNotNull(delegate);
// The message should be invalid
assertNull(delegate.validateMessage(message, group));
try {
delegate.validateMessage(message, group);
fail();
} catch (InvalidMessageException expected) {
// Expected
}
context.assertIsSatisfied();
}
@@ -193,7 +199,12 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
MessageValidator delegate = captured.get();
assertNotNull(delegate);
// The message should be invalid
assertNull(delegate.validateMessage(message, group));
try {
delegate.validateMessage(message, group);
fail();
} catch (InvalidMessageException expected) {
// Expected
}
context.assertIsSatisfied();
}

View File

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

View File

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