Use ConversationManager for timestamps and unread counts

This commit is contained in:
str4d
2016-06-02 04:06:56 +00:00
parent c333052396
commit 7a3bd86522
30 changed files with 411 additions and 293 deletions

View File

@@ -23,11 +23,7 @@ import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.conversation.ConversationForumInvitationItem; import org.briarproject.api.conversation.ConversationManager;
import org.briarproject.api.conversation.ConversationIntroductionRequestItem;
import org.briarproject.api.conversation.ConversationIntroductionResponseItem;
import org.briarproject.api.conversation.ConversationItem;
import org.briarproject.api.conversation.ConversationMessageItem;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchContactException; import org.briarproject.api.db.NoSuchContactException;
import org.briarproject.api.event.ContactAddedEvent; import org.briarproject.api.event.ContactAddedEvent;
@@ -40,22 +36,14 @@ import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener; import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageStateChangedEvent; import org.briarproject.api.event.MessageStateChangedEvent;
import org.briarproject.api.event.PrivateMessageReceivedEvent; import org.briarproject.api.event.PrivateMessageReceivedEvent;
import org.briarproject.api.forum.ForumInvitationMessage;
import org.briarproject.api.forum.ForumSharingManager;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.introduction.IntroductionMessage;
import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.api.messaging.PrivateMessageHeader;
import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.ConnectionRegistry;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -88,11 +76,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
@Inject @Inject
protected volatile IdentityManager identityManager; protected volatile IdentityManager identityManager;
@Inject @Inject
protected volatile MessagingManager messagingManager; protected volatile ConversationManager conversationManager;
@Inject
protected volatile IntroductionManager introductionManager;
@Inject
protected volatile ForumSharingManager forumSharingManager;
public static ContactListFragment newInstance() { public static ContactListFragment newInstance() {
@@ -208,15 +192,19 @@ public class ContactListFragment extends BaseFragment implements EventListener {
try { try {
ContactId id = c.getId(); ContactId id = c.getId();
GroupId groupId = GroupId groupId =
messagingManager.getConversationId(id); conversationManager.getConversationId(id);
Collection<ConversationItem> messages =
getMessages(id);
boolean connected = boolean connected =
connectionRegistry.isConnected(c.getId()); connectionRegistry.isConnected(c.getId());
LocalAuthor localAuthor = identityManager LocalAuthor localAuthor = identityManager
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
long timestamp = conversationManager.getTimestamp(id);
long now1 = System.currentTimeMillis();
int unread = conversationManager.getUnreadCount(id);
long duration = System.currentTimeMillis() - now1;
if (LOG.isLoggable(INFO))
LOG.info("Loading unread messages took " + duration + " ms");
contacts.add(new ContactListItem(c, localAuthor, contacts.add(new ContactListItem(c, localAuthor,
connected, groupId, messages)); connected, groupId, timestamp, unread));
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
// Continue // Continue
} }
@@ -264,13 +252,11 @@ public class ContactListFragment extends BaseFragment implements EventListener {
LOG.info("Message received, update contact"); LOG.info("Message received, update contact");
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e; PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
PrivateMessageHeader h = p.getMessageHeader(); PrivateMessageHeader h = p.getMessageHeader();
updateItem(p.getGroupId(), ConversationMessageItem.from(h)); updateItem(p.getGroupId(), h.getTimestamp(), h.isRead());
} else if (e instanceof MessageStateChangedEvent) { } else if (e instanceof MessageStateChangedEvent) {
MessageStateChangedEvent m = (MessageStateChangedEvent) e; MessageStateChangedEvent m = (MessageStateChangedEvent) e;
ClientId c = m.getClientId(); ClientId c = m.getClientId();
if (m.getState() == DELIVERED && if (m.getState() == DELIVERED && conversationManager.isWrappedClient(c)) {
(c.equals(introductionManager.getClientId()) ||
c.equals(forumSharingManager.getClientId()))) {
LOG.info("Message added, reloading"); LOG.info("Message added, reloading");
reloadConversation(m.getMessage().getGroupId()); reloadConversation(m.getMessage().getGroupId());
} }
@@ -282,10 +268,10 @@ public class ContactListFragment extends BaseFragment implements EventListener {
@Override @Override
public void run() { public void run() {
try { try {
ContactId c = messagingManager.getContactId(g); ContactId c = conversationManager.getContactId(g);
Collection<ConversationItem> messages = long timestamp = conversationManager.getTimestamp(c);
getMessages(c); int unread = conversationManager.getUnreadCount(c);
updateItem(c, messages); updateItem(c, timestamp, unread);
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
LOG.info("Contact removed"); LOG.info("Contact removed");
} catch (DbException e) { } catch (DbException e) {
@@ -296,29 +282,31 @@ public class ContactListFragment extends BaseFragment implements EventListener {
}); });
} }
private void updateItem(final ContactId c, private void updateItem(final ContactId c, final long timestamp, final int unread) {
final Collection<ConversationItem> messages) {
listener.runOnUiThread(new Runnable() { listener.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
int position = adapter.findItemPosition(c); int position = adapter.findItemPosition(c);
ContactListItem item = adapter.getItem(position); ContactListItem item = adapter.getItem(position);
if (item != null) { if (item != null) {
item.setMessages(messages); item.setTimestamp(timestamp);
item.setUnreadCount(unread);
adapter.updateItem(position, item); adapter.updateItem(position, item);
} }
} }
}); });
} }
private void updateItem(final GroupId g, final ConversationItem m) { private void updateItem(final GroupId g, final long timestamp, final boolean unread) {
listener.runOnUiThread(new Runnable() { listener.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
int position = adapter.findItemPosition(g); int position = adapter.findItemPosition(g);
ContactListItem item = adapter.getItem(position); ContactListItem item = adapter.getItem(position);
if (item != null) { if (item != null) {
item.addMessage(m); item.setTimestamp(timestamp);
if (unread)
item.setUnreadCount(item.getUnreadCount() + 1);
adapter.updateItem(position, item); adapter.updateItem(position, item);
} }
} }
@@ -349,50 +337,4 @@ public class ContactListFragment extends BaseFragment implements EventListener {
} }
}); });
} }
// This needs to be called from the DB thread
private Collection<ConversationItem> getMessages(ContactId id)
throws DbException {
long now = System.currentTimeMillis();
Collection<ConversationItem> messages = new ArrayList<>();
Collection<PrivateMessageHeader> headers =
messagingManager.getMessageHeaders(id);
for (PrivateMessageHeader h : headers) {
messages.add(ConversationMessageItem.from(h));
}
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading message headers took " + duration + " ms");
now = System.currentTimeMillis();
Collection<IntroductionMessage> introductions =
introductionManager
.getIntroductionMessages(id);
for (IntroductionMessage m : introductions) {
if (m instanceof IntroductionRequest)
messages.add(ConversationIntroductionRequestItem
.from((IntroductionRequest) m));
else
messages.add(ConversationIntroductionResponseItem
.from((IntroductionResponse) m));
}
duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading introduction messages took " + duration + " ms");
now = System.currentTimeMillis();
Collection<ForumInvitationMessage> invitations =
forumSharingManager.getInvitationMessages(id);
for (ForumInvitationMessage i : invitations) {
messages.add(ConversationForumInvitationItem.from(i));
}
duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading forum invitations took " + duration + " ms");
return messages;
}
} }

View File

@@ -2,6 +2,8 @@ package org.briarproject.android.contact;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.conversation.ConversationItem; import org.briarproject.api.conversation.ConversationItem;
import org.briarproject.api.conversation.ConversationManager;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -13,40 +15,20 @@ public class ContactListItem {
private final Contact contact; private final Contact contact;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
private final GroupId groupId; private final GroupId groupId;
private boolean connected, empty; private boolean connected;
private long timestamp; private long timestamp;
private int unread; private int unread;
public ContactListItem(Contact contact, LocalAuthor localAuthor, public ContactListItem(Contact contact, LocalAuthor localAuthor,
boolean connected, boolean connected,
GroupId groupId, GroupId groupId,
Collection<ConversationItem> messages) { long timestamp, int unread) {
this.contact = contact; this.contact = contact;
this.localAuthor = localAuthor; this.localAuthor = localAuthor;
this.groupId = groupId; this.groupId = groupId;
this.connected = connected; this.connected = connected;
setMessages(messages); this.timestamp = timestamp;
} this.unread = unread;
void setMessages(Collection<ConversationItem> messages) {
empty = messages == null || messages.isEmpty();
timestamp = 0;
unread = 0;
if (!empty) {
for (ConversationItem i : messages) {
addMessage(i);
}
}
}
void addMessage(ConversationItem message) {
empty = empty && message == null;
if (message != null) {
if (message.getTime() > timestamp) timestamp = message.getTime();
if (message instanceof ConversationItem.IncomingItem &&
!((ConversationItem.IncomingItem) message).isRead())
unread++;
}
} }
public Contact getContact() { public Contact getContact() {
@@ -70,14 +52,22 @@ public class ContactListItem {
} }
boolean isEmpty() { boolean isEmpty() {
return empty; return timestamp < 0;
} }
long getTimestamp() { long getTimestamp() {
return timestamp; return timestamp;
} }
void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
int getUnreadCount() { int getUnreadCount() {
return unread; return unread;
} }
void setUnreadCount(int unread) {
this.unread = unread;
}
} }

View File

@@ -38,7 +38,6 @@ import org.briarproject.api.conversation.ConversationIntroductionResponseItem;
import org.briarproject.api.conversation.ConversationItem; import org.briarproject.api.conversation.ConversationItem;
import org.briarproject.api.conversation.ConversationItem.IncomingItem; import org.briarproject.api.conversation.ConversationItem.IncomingItem;
import org.briarproject.api.conversation.ConversationManager; import org.briarproject.api.conversation.ConversationManager;
import org.briarproject.api.conversation.ConversationMessageItem;
import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchContactException; import org.briarproject.api.db.NoSuchContactException;
@@ -58,7 +57,6 @@ import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.IntroductionResponse; import org.briarproject.api.introduction.IntroductionResponse;
import org.briarproject.api.messaging.PrivateMessage; import org.briarproject.api.messaging.PrivateMessage;
import org.briarproject.api.messaging.PrivateMessageFactory; import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.messaging.PrivateMessageHeader;
import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.ConnectionRegistry;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@@ -366,7 +364,7 @@ public class ConversationActivity extends BriarActivity
SparseArray<IncomingItem> list = adapter.getIncomingMessages(); SparseArray<IncomingItem> list = adapter.getIncomingMessages();
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
IncomingItem item = list.valueAt(i); IncomingItem item = list.valueAt(i);
if (!item.isRead()) unread.add((ConversationItem) item); if (!item.isRead()) unread.add(item);
} }
if (unread.isEmpty()) return; if (unread.isEmpty()) return;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
@@ -381,7 +379,7 @@ public class ConversationActivity extends BriarActivity
try { try {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
for (ConversationItem item : unread) for (ConversationItem item : unread)
conversationManager.setReadFlag(item, true); conversationManager.setReadFlag(contactId, item, true);
long duration = System.currentTimeMillis() - now; long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Marking read took " + duration + " ms"); LOG.info("Marking read took " + duration + " ms");
@@ -488,7 +486,7 @@ public class ConversationActivity extends BriarActivity
@Override @Override
public void run() { public void run() {
try { try {
conversationManager.setReadFlag(item, true); conversationManager.setReadFlag(contactId, item, true);
loadMessages(); loadMessages();
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))

View File

@@ -103,7 +103,7 @@ public class ForumSharingStatusActivity extends BriarActivity {
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
ContactListItem item = ContactListItem item =
new ContactListItem(c, localAuthor, false, null, new ContactListItem(c, localAuthor, false, null,
null); -1, 0);
contactItems.add(item); contactItems.add(item);
} }
} catch (DbException e) { } catch (DbException e) {
@@ -141,7 +141,7 @@ public class ForumSharingStatusActivity extends BriarActivity {
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
ContactListItem item = ContactListItem item =
new ContactListItem(c, localAuthor, false, null, new ContactListItem(c, localAuthor, false, null,
null); -1, 0);
contactItems.add(item); contactItems.add(item);
} }
} catch (DbException e) { } catch (DbException e) {

View File

@@ -16,8 +16,7 @@ public class SelectableContactListItem extends ContactListItem {
public SelectableContactListItem(Contact contact, LocalAuthor localAuthor, public SelectableContactListItem(Contact contact, LocalAuthor localAuthor,
GroupId groupId, boolean selected, boolean disabled) { GroupId groupId, boolean selected, boolean disabled) {
super(contact, localAuthor, false, groupId, super(contact, localAuthor, false, groupId, -1, 0);
Collections.<ConversationItem>emptyList());
this.selected = selected; this.selected = selected;
this.disabled = disabled; this.disabled = disabled;

View File

@@ -162,14 +162,18 @@ public class ContactChooserFragment extends BaseFragment {
ContactId id = c.getId(); ContactId id = c.getId();
GroupId groupId = GroupId groupId =
conversationManager.getConversationId(id); conversationManager.getConversationId(id);
Collection<ConversationItem> messages =
getMessages(id);
boolean connected = boolean connected =
connectionRegistry.isConnected(c.getId()); connectionRegistry.isConnected(c.getId());
LocalAuthor localAuthor = identityManager LocalAuthor localAuthor = identityManager
.getLocalAuthor(c.getLocalAuthorId()); .getLocalAuthor(c.getLocalAuthorId());
long timestamp = conversationManager.getTimestamp(id);
long now1 = System.currentTimeMillis();
int unread = conversationManager.getUnreadCount(id);
long duration = System.currentTimeMillis() - now1;
if (LOG.isLoggable(INFO))
LOG.info("Loading unread messages took " + duration + " ms");
contacts.add(new ContactListItem(c, localAuthor, contacts.add(new ContactListItem(c, localAuthor,
connected, groupId, messages)); connected, groupId, timestamp, unread));
} }
} }
displayContacts(localAuthorId, contacts); displayContacts(localAuthorId, contacts);
@@ -213,21 +217,4 @@ public class ContactChooserFragment extends BaseFragment {
builder.setNegativeButton(android.R.string.cancel, null); builder.setNegativeButton(android.R.string.cancel, null);
builder.show(); builder.show();
} }
/**
* This needs to be called from the DbThread
*/
private Collection<ConversationItem> getMessages(ContactId id)
throws DbException {
long now = System.currentTimeMillis();
Collection<ConversationItem> messages =
conversationManager.getMessages(id, false);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading message headers took " + duration + " ms");
return messages;
}
} }

View File

@@ -0,0 +1,10 @@
package org.briarproject.api.clients;
public interface ReadableMessageConstants {
/* Readable Message Local State Metadata */
String LOCAL = "local";
String READ = "read";
String TIMESTAMP = "timestamp";
String UNREAD = "unread";
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.api.clients;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
import org.briarproject.api.sync.MessageId;
public interface ReadableMessageManager {
/**
* Returns the timestamp of the latest message in the group with the given
* contact, or -1 if the group is empty.
*/
long getTimestamp(ContactId c) throws DbException;
/**
* Returns the number of unread messages in the group with the given
* contact.
*/
int getUnreadCount(ContactId c) throws DbException;
/**
* Marks a message as read or unread.
*/
void setReadFlag(ContactId c, MessageId m, boolean local, boolean read)
throws DbException;
}

View File

@@ -17,6 +17,11 @@ public interface ConversationManager {
*/ */
ClientId getClientId(); ClientId getClientId();
/**
* Returns true if this is the id of a wrapped client.
*/
boolean isWrappedClient(ClientId clientId);
/** /**
* Stores a local private message, and returns the corresponding item. * Stores a local private message, and returns the corresponding item.
*/ */
@@ -38,10 +43,15 @@ public interface ConversationManager {
List<ConversationItem> getMessages(ContactId c) throws DbException; List<ConversationItem> getMessages(ContactId c) throws DbException;
/** /**
* Returns all messages in the given private conversation. * Returns the timestamp of the latest message in the given private
* conversation, or -1 if the conversation is empty.
*/ */
List<ConversationItem> getMessages(ContactId c, boolean content) long getTimestamp(ContactId c) throws DbException;
throws DbException;
/**
* Returns the number of unread messages in the given private conversation.
*/
int getUnreadCount(ContactId c) throws DbException;
/** /**
* Starts a background task to load the content of the given message. * Starts a background task to load the content of the given message.
@@ -57,5 +67,5 @@ public interface ConversationManager {
/** /**
* Marks a conversation item as read or unread. * Marks a conversation item as read or unread.
*/ */
void setReadFlag(ConversationItem item, boolean read) throws DbException; void setReadFlag(ContactId c, ConversationItem item, boolean read) throws DbException;
} }

View File

@@ -47,7 +47,4 @@ public interface ForumSharingManager extends SharingManager<Forum, ForumInvitati
/** Returns true if the forum not already shared and no invitation is open */ /** Returns true if the forum not already shared and no invitation is open */
boolean canBeShared(GroupId g, Contact c) throws DbException; boolean canBeShared(GroupId g, Contact c) throws DbException;
/** Marks a forum sharing message as read or unread. */
void setReadFlag(MessageId m, boolean read) throws DbException;
} }

View File

@@ -40,7 +40,6 @@ public interface IntroductionConstants {
String CONTACT_ID_2 = "contactId2"; String CONTACT_ID_2 = "contactId2";
String RESPONSE_1 = "response1"; String RESPONSE_1 = "response1";
String RESPONSE_2 = "response2"; String RESPONSE_2 = "response2";
String READ = "read";
/* Introduction Request Action */ /* Introduction Request Action */
String PUBLIC_KEY1 = "publicKey1"; String PUBLIC_KEY1 = "publicKey1";

View File

@@ -1,6 +1,7 @@
package org.briarproject.api.introduction; package org.briarproject.api.introduction;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ReadableMessageManager;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
@@ -10,7 +11,7 @@ import org.briarproject.api.sync.MessageId;
import java.util.Collection; import java.util.Collection;
public interface IntroductionManager { public interface IntroductionManager extends ReadableMessageManager {
/** Returns the unique ID of the introduction client. */ /** Returns the unique ID of the introduction client. */
ClientId getClientId(); ClientId getClientId();
@@ -42,7 +43,4 @@ public interface IntroductionManager {
Collection<IntroductionMessage> getIntroductionMessages(ContactId contactId) Collection<IntroductionMessage> getIntroductionMessages(ContactId contactId)
throws DbException; throws DbException;
/** Marks an introduction message as read or unread. */
void setReadFlag(MessageId m, boolean read) throws DbException;
} }

View File

@@ -1,5 +1,6 @@
package org.briarproject.api.messaging; package org.briarproject.api.messaging;
import org.briarproject.api.clients.ReadableMessageManager;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
@@ -8,7 +9,7 @@ import org.briarproject.api.sync.MessageId;
import java.util.Collection; import java.util.Collection;
public interface MessagingManager { public interface MessagingManager extends ReadableMessageManager {
/** Returns the unique ID of the messaging client. */ /** Returns the unique ID of the messaging client. */
ClientId getClientId(); ClientId getClientId();
@@ -30,7 +31,4 @@ public interface MessagingManager {
/** Returns the body of the private message with the given ID. */ /** Returns the body of the private message with the given ID. */
byte[] getMessageBody(MessageId m) throws DbException; byte[] getMessageBody(MessageId m) throws DbException;
/** Marks a private message as read or unread. */
void setReadFlag(MessageId m, boolean read) throws DbException;
} }

View File

@@ -14,9 +14,6 @@ public interface SharingConstants {
String SESSION_ID = "sessionId"; String SESSION_ID = "sessionId";
String STORAGE_ID = "storageId"; String STORAGE_ID = "storageId";
String STATE = "state"; String STATE = "state";
String LOCAL = "local";
String TIME = "time";
String READ = "read";
String IS_SHARER = "isSharer"; String IS_SHARER = "isSharer";
String SHAREABLE_ID = "shareableId"; String SHAREABLE_ID = "shareableId";
String INVITATION_MSG = "invitationMsg"; String INVITATION_MSG = "invitationMsg";

View File

@@ -46,7 +46,19 @@ public interface SharingManager<S extends Shareable, IM extends InvitationMessag
/** Returns true if the group not already shared and no invitation is open */ /** Returns true if the group not already shared and no invitation is open */
boolean canBeShared(GroupId g, Contact c) throws DbException; boolean canBeShared(GroupId g, Contact c) throws DbException;
/**
* Returns the timestamp of the latest sharing message sent by the given
* contact, or -1 if there are none.
*/
long getTimestamp(ContactId c) throws DbException;
/**
* Returns the number of unread sharing messages sent by the given contact.
*/
int getUnreadCount(ContactId c) throws DbException;
/** Marks a sharing message as read or unread. */ /** Marks a sharing message as read or unread. */
void setReadFlag(MessageId m, boolean read) throws DbException; void setReadFlag(ContactId c, MessageId m, boolean local, boolean read)
throws DbException;
} }

View File

@@ -0,0 +1,127 @@
package org.briarproject.clients;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.ReadableMessageManager;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.data.BdfDictionary;
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.Transaction;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.clients.ReadableMessageConstants.UNREAD;
public abstract class ReadableMessageManagerImpl
extends BdfIncomingMessageHook implements ReadableMessageManager {
protected final DatabaseComponent db;
protected ReadableMessageManagerImpl(ClientHelper clientHelper,
DatabaseComponent db, MetadataParser metadataParser) {
super(clientHelper, metadataParser);
this.db = db;
}
protected abstract Group getContactGroup(Contact c);
protected abstract boolean incomingReadableMessage(Transaction txn,
Message m, BdfList body, BdfDictionary meta)
throws DbException, FormatException;
@Override
protected void incomingMessage(Transaction txn, Message m, BdfList body,
BdfDictionary meta) throws DbException, FormatException {
// Check if we accept this message
if (incomingReadableMessage(txn, m, body, meta)) {
// Update the group timestamp and unread count
GroupId groupId = m.getGroupId();
long timestamp = meta.getLong(TIMESTAMP);
boolean local = meta.getBoolean(LOCAL);
boolean read = meta.getBoolean(READ);
updateGroupMetadata(txn, groupId, timestamp, local, read, read);
}
}
@Override
public long getTimestamp(ContactId c) throws DbException {
BdfDictionary meta;
Transaction txn = db.startTransaction(true);
try {
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
meta = clientHelper.getGroupMetadataAsDictionary(txn, g);
txn.setComplete();
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
return meta.getLong(TIMESTAMP, -1L);
}
@Override
public int getUnreadCount(ContactId c) throws DbException {
BdfDictionary meta;
Transaction txn = db.startTransaction(true);
try {
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
meta = clientHelper.getGroupMetadataAsDictionary(txn, g);
txn.setComplete();
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
return meta.getLong(UNREAD, 0L).intValue();
}
@Override
public void setReadFlag(ContactId c, MessageId m, boolean local,
boolean read) throws DbException {
Transaction txn = db.startTransaction(false);
try {
boolean wasRead =
clientHelper.getMessageMetadataAsDictionary(txn, m)
.getBoolean(READ);
BdfDictionary meta = new BdfDictionary();
meta.put(READ, read);
clientHelper.mergeMessageMetadata(txn, m, meta);
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
updateGroupMetadata(txn, g, -1, local, wasRead, read);
txn.setComplete();
} catch (FormatException e) {
throw new DbException(e);
} finally {
db.endTransaction(txn);
}
}
private void updateGroupMetadata(Transaction txn, GroupId groupId,
long timestamp, boolean local, boolean wasRead, boolean read)
throws DbException, FormatException {
BdfDictionary groupMeta =
clientHelper.getGroupMetadataAsDictionary(txn, groupId);
long groupTimestamp = groupMeta.getLong(TIMESTAMP, -1L);
int unread = groupMeta.getLong(UNREAD, 0L).intValue();
BdfDictionary d = new BdfDictionary();
if (timestamp > groupTimestamp) {
d.put(TIMESTAMP, timestamp);
}
if (!local && (wasRead != read)) {
d.put(UNREAD, read ? (unread > 0 ? unread - 1 : 0) : unread + 1);
}
clientHelper.mergeGroupMetadata(txn, groupId, d);
}
}

View File

@@ -7,6 +7,7 @@ import org.briarproject.api.conversation.ConversationForumInvitationItem;
import org.briarproject.api.conversation.ConversationIntroductionRequestItem; import org.briarproject.api.conversation.ConversationIntroductionRequestItem;
import org.briarproject.api.conversation.ConversationIntroductionResponseItem; import org.briarproject.api.conversation.ConversationIntroductionResponseItem;
import org.briarproject.api.conversation.ConversationItem; import org.briarproject.api.conversation.ConversationItem;
import org.briarproject.api.conversation.ConversationItem.OutgoingItem;
import org.briarproject.api.conversation.ConversationItem.Partial; import org.briarproject.api.conversation.ConversationItem.Partial;
import org.briarproject.api.conversation.ConversationManager; import org.briarproject.api.conversation.ConversationManager;
import org.briarproject.api.conversation.ConversationMessageItem; import org.briarproject.api.conversation.ConversationMessageItem;
@@ -73,6 +74,12 @@ public class ConversationManagerImpl implements ConversationManager {
return CLIENT_ID; return CLIENT_ID;
} }
@Override
public boolean isWrappedClient(ClientId clientId) {
return clientId.equals(introductionManager.getClientId()) ||
clientId.equals(forumSharingManager.getClientId());
}
@Override @Override
public ConversationItem addLocalMessage(PrivateMessage m, byte[] body) public ConversationItem addLocalMessage(PrivateMessage m, byte[] body)
throws DbException { throws DbException {
@@ -101,12 +108,6 @@ public class ConversationManagerImpl implements ConversationManager {
@Override @Override
public List<ConversationItem> getMessages(ContactId c) public List<ConversationItem> getMessages(ContactId c)
throws DbException { throws DbException {
return getMessages(c, true);
}
@Override
public List<ConversationItem> getMessages(ContactId c, boolean content)
throws DbException {
Collection<PrivateMessageHeader> headers = Collection<PrivateMessageHeader> headers =
messagingManager.getMessageHeaders(c); messagingManager.getMessageHeaders(c);
Collection<IntroductionMessage> introductions = Collection<IntroductionMessage> introductions =
@@ -116,11 +117,9 @@ public class ConversationManagerImpl implements ConversationManager {
List<ConversationItem> items = new ArrayList<ConversationItem>(); List<ConversationItem> items = new ArrayList<ConversationItem>();
for (PrivateMessageHeader h : headers) { for (PrivateMessageHeader h : headers) {
ConversationItem item = ConversationMessageItemImpl.from(h); ConversationItem item = ConversationMessageItemImpl.from(h);
if (content) { byte[] body = bodyCache.get(h.getId());
byte[] body = bodyCache.get(h.getId()); if (body == null) loadMessageContent((Partial) item);
if (body == null) loadMessageContent((Partial) item); else ((Partial) item).setContent(body);
else ((Partial) item).setContent(body);
}
items.add(item); items.add(item);
} }
for (IntroductionMessage m : introductions) { for (IntroductionMessage m : introductions) {
@@ -141,6 +140,27 @@ public class ConversationManagerImpl implements ConversationManager {
return items; return items;
} }
@Override
public long getTimestamp(ContactId c) throws DbException {
long timestamp = -1;
long t = messagingManager.getTimestamp(c);
if (t > timestamp) timestamp = t;
t = introductionManager.getTimestamp(c);
if (t > timestamp) timestamp = t;
t = forumSharingManager.getTimestamp(c);
if (t > timestamp) timestamp = t;
return timestamp;
}
@Override
public int getUnreadCount(ContactId c) throws DbException {
int unread = 0;
unread += messagingManager.getUnreadCount(c);
unread += introductionManager.getUnreadCount(c);
unread += forumSharingManager.getUnreadCount(c);
return unread;
}
@Override @Override
public void loadMessageContent(final Partial m) { public void loadMessageContent(final Partial m) {
dbExecutor.execute(new Runnable() { dbExecutor.execute(new Runnable() {
@@ -185,16 +205,17 @@ public class ConversationManagerImpl implements ConversationManager {
} }
@Override @Override
public void setReadFlag(ConversationItem item, boolean read) public void setReadFlag(ContactId c, ConversationItem item, boolean read)
throws DbException { throws DbException {
MessageId id = item.getId(); MessageId id = item.getId();
boolean local = item instanceof OutgoingItem;
if (item instanceof ConversationMessageItem) { if (item instanceof ConversationMessageItem) {
messagingManager.setReadFlag(id, read); messagingManager.setReadFlag(c, id, local, read);
} else if (item instanceof ConversationIntroductionRequestItem || } else if (item instanceof ConversationIntroductionRequestItem ||
item instanceof ConversationIntroductionResponseItem) { item instanceof ConversationIntroductionResponseItem) {
introductionManager.setReadFlag(id, read); introductionManager.setReadFlag(c, id, local, read);
} else if (item instanceof ConversationForumInvitationItem) { } else if (item instanceof ConversationForumInvitationItem) {
forumSharingManager.setReadFlag(id, read); forumSharingManager.setReadFlag(c, id, local, read);
} }
} }
} }

View File

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ABORT; import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ABORT;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ACCEPT; import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_DECLINE; import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_DECLINE;
@@ -112,7 +113,7 @@ public class IntroduceeEngine
msg.put(E_PUBLIC_KEY, localState.getRaw(OUR_PUBLIC_KEY)); msg.put(E_PUBLIC_KEY, localState.getRaw(OUR_PUBLIC_KEY));
msg.put(TRANSPORT, localAction.getDictionary(TRANSPORT)); msg.put(TRANSPORT, localAction.getDictionary(TRANSPORT));
} }
msg.put(MESSAGE_TIME, localAction.getLong(MESSAGE_TIME)); msg.put(TIMESTAMP, localAction.getLong(MESSAGE_TIME));
messages.add(msg); messages.add(msg);
logAction(currentState, localState, msg); logAction(currentState, localState, msg);
@@ -330,7 +331,7 @@ public class IntroduceeEngine
SessionId sessionId = new SessionId(localState.getRaw(SESSION_ID)); SessionId sessionId = new SessionId(localState.getRaw(SESSION_ID));
MessageId messageId = new MessageId(msg.getRaw(MESSAGE_ID)); MessageId messageId = new MessageId(msg.getRaw(MESSAGE_ID));
long time = msg.getLong(MESSAGE_TIME); long time = msg.getLong(TIMESTAMP);
String name = msg.getString(NAME); String name = msg.getString(NAME);
String message = msg.getOptionalString(MSG); String message = msg.getOptionalString(MSG);
boolean exists = localState.getBoolean(EXISTS); boolean exists = localState.getBoolean(EXISTS);

View File

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.introduction.IntroducerAction.LOCAL_ABORT; import static org.briarproject.api.introduction.IntroducerAction.LOCAL_ABORT;
import static org.briarproject.api.introduction.IntroducerAction.LOCAL_REQUEST; import static org.briarproject.api.introduction.IntroducerAction.LOCAL_REQUEST;
import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_1; import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
@@ -106,7 +107,7 @@ public class IntroducerEngine
if (localAction.containsKey(MSG)) { if (localAction.containsKey(MSG)) {
msg1.put(MSG, localAction.getString(MSG)); msg1.put(MSG, localAction.getString(MSG));
} }
msg1.put(MESSAGE_TIME, localAction.getLong(MESSAGE_TIME)); msg1.put(TIMESTAMP, localAction.getLong(MESSAGE_TIME));
messages.add(msg1); messages.add(msg1);
logLocalAction(currentState, localState, msg1); logLocalAction(currentState, localState, msg1);
BdfDictionary msg2 = new BdfDictionary(); BdfDictionary msg2 = new BdfDictionary();
@@ -118,7 +119,7 @@ public class IntroducerEngine
if (localAction.containsKey(MSG)) { if (localAction.containsKey(MSG)) {
msg2.put(MSG, localAction.getString(MSG)); msg2.put(MSG, localAction.getString(MSG));
} }
msg2.put(MESSAGE_TIME, localAction.getLong(MESSAGE_TIME)); msg2.put(TIMESTAMP, localAction.getLong(MESSAGE_TIME));
messages.add(msg2); messages.add(msg2);
logLocalAction(currentState, localState, msg2); logLocalAction(currentState, localState, msg2);
@@ -298,7 +299,7 @@ public class IntroducerEngine
SessionId sessionId = new SessionId(localState.getRaw(SESSION_ID)); SessionId sessionId = new SessionId(localState.getRaw(SESSION_ID));
MessageId messageId = new MessageId(msg.getRaw(MESSAGE_ID)); MessageId messageId = new MessageId(msg.getRaw(MESSAGE_ID));
long time = msg.getLong(MESSAGE_TIME); long time = msg.getLong(TIMESTAMP);
String name = getOtherContact(localState, msg); String name = getOtherContact(localState, msg);
boolean accept = msg.getBoolean(ACCEPT); boolean accept = msg.getBoolean(ACCEPT);

View File

@@ -29,7 +29,7 @@ import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus; import org.briarproject.api.sync.MessageStatus;
import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.clients.ReadableMessageManagerImpl;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
import java.io.IOException; import java.io.IOException;
@@ -42,6 +42,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.introduction.IntroduceeProtocolState.FINISHED; import static org.briarproject.api.introduction.IntroduceeProtocolState.FINISHED;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED; import static org.briarproject.api.introduction.IntroductionConstants.ANSWERED;
@@ -56,11 +58,9 @@ import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG; import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
import static org.briarproject.api.introduction.IntroductionConstants.READ;
import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID; import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US; import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_1; import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_1;
@@ -76,7 +76,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
class IntroductionManagerImpl extends BdfIncomingMessageHook class IntroductionManagerImpl extends ReadableMessageManagerImpl
implements IntroductionManager, Client, AddContactHook, implements IntroductionManager, Client, AddContactHook,
RemoveContactHook { RemoveContactHook {
@@ -87,7 +87,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(IntroductionManagerImpl.class.getName()); Logger.getLogger(IntroductionManagerImpl.class.getName());
private final DatabaseComponent db;
private final IntroducerManager introducerManager; private final IntroducerManager introducerManager;
private final IntroduceeManager introduceeManager; private final IntroduceeManager introduceeManager;
private final IntroductionGroupFactory introductionGroupFactory; private final IntroductionGroupFactory introductionGroupFactory;
@@ -98,8 +97,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
IntroduceeManager introduceeManager, IntroduceeManager introduceeManager,
IntroductionGroupFactory introductionGroupFactory) { IntroductionGroupFactory introductionGroupFactory) {
super(clientHelper, metadataParser); super(clientHelper, db, metadataParser);
this.db = db;
this.introducerManager = introducerManager; this.introducerManager = introducerManager;
this.introduceeManager = introduceeManager; this.introduceeManager = introduceeManager;
this.introductionGroupFactory = introductionGroupFactory; this.introductionGroupFactory = introductionGroupFactory;
@@ -166,8 +164,10 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
.getMessageMetadataAsDictionary(txn, gId, query); .getMessageMetadataAsDictionary(txn, gId, query);
for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) { for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) {
BdfDictionary d = entry.getValue(); BdfDictionary d = entry.getValue();
ContactId c1 = new ContactId(d.getLong(CONTACT_ID_1).intValue()); ContactId c1 =
ContactId c2 = new ContactId(d.getLong(CONTACT_ID_2).intValue()); new ContactId(d.getLong(CONTACT_ID_1).intValue());
ContactId c2 =
new ContactId(d.getLong(CONTACT_ID_2).intValue());
if (c1.equals(c.getId()) || c2.equals(c.getId())) { if (c1.equals(c.getId()) || c2.equals(c.getId())) {
IntroducerProtocolState state = IntroducerProtocolState IntroducerProtocolState state = IntroducerProtocolState
@@ -198,7 +198,13 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
// remove the group (all messages will be removed with it) // remove the group (all messages will be removed with it)
// this contact won't get our abort message, but the other will // this contact won't get our abort message, but the other will
db.removeGroup(txn, introductionGroupFactory.createIntroductionGroup(c)); db.removeGroup(txn,
introductionGroupFactory.createIntroductionGroup(c));
}
@Override
protected Group getContactGroup(Contact c) {
return introductionGroupFactory.createIntroductionGroup(c);
} }
/** /**
@@ -207,8 +213,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
* in the introduction protocol and which engine we need to start. * in the introduction protocol and which engine we need to start.
*/ */
@Override @Override
protected void incomingMessage(Transaction txn, Message m, BdfList body, protected boolean incomingReadableMessage(Transaction txn, Message m, BdfList body,
BdfDictionary message) throws DbException { BdfDictionary message) throws DbException, FormatException {
// Get message data and type // Get message data and type
GroupId groupId = m.getGroupId(); GroupId groupId = m.getGroupId();
@@ -218,7 +224,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
if (type == TYPE_REQUEST) { if (type == TYPE_REQUEST) {
boolean stateExists = true; boolean stateExists = true;
try { try {
getSessionState(txn, groupId, message.getRaw(SESSION_ID), false); getSessionState(txn, groupId, message.getRaw(SESSION_ID),
false);
} catch (FormatException e) { } catch (FormatException e) {
stateExists = false; stateExists = false;
} }
@@ -233,7 +240,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} }
deleteMessage(txn, m.getId()); deleteMessage(txn, m.getId());
return; return false;
} }
try { try {
introduceeManager.incomingMessage(txn, state, message); introduceeManager.incomingMessage(txn, state, message);
@@ -246,7 +253,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
} }
} }
// our role can be anything // our role can be anything
else if (type == TYPE_RESPONSE || type == TYPE_ACK || type == TYPE_ABORT) { else if (type == TYPE_RESPONSE || type == TYPE_ACK ||
type == TYPE_ABORT) {
BdfDictionary state; BdfDictionary state;
try { try {
state = getSessionState(txn, groupId, state = getSessionState(txn, groupId,
@@ -254,7 +262,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
} catch (FormatException e) { } catch (FormatException e) {
LOG.warning("Could not find state for message, deleting..."); LOG.warning("Could not find state for message, deleting...");
deleteMessage(txn, m.getId()); deleteMessage(txn, m.getId());
return; return false;
} }
long role = state.getLong(ROLE, -1L); long role = state.getLong(ROLE, -1L);
@@ -264,27 +272,35 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
} else if (role == ROLE_INTRODUCEE) { } else if (role == ROLE_INTRODUCEE) {
introduceeManager.incomingMessage(txn, state, message); introduceeManager.incomingMessage(txn, state, message);
} else { } else {
if(LOG.isLoggable(WARNING)) { if (LOG.isLoggable(WARNING)) {
LOG.warning("Unknown role '" + role + LOG.warning("Unknown role '" + role +
"'. Deleting message..."); "'. Deleting message...");
deleteMessage(txn, m.getId());
} }
deleteMessage(txn, m.getId());
return false;
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state); if (role == ROLE_INTRODUCER)
introducerManager.abort(txn, state);
else introduceeManager.abort(txn, state); else introduceeManager.abort(txn, state);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state); if (role == ROLE_INTRODUCER)
introducerManager.abort(txn, state);
else introduceeManager.abort(txn, state); else introduceeManager.abort(txn, state);
} }
} else { } else {
// the message has been validated, so this should not happen // the message has been validated, so this should not happen
if(LOG.isLoggable(WARNING)) { if (LOG.isLoggable(WARNING)) {
LOG.warning("Unknown message type '" + type + "', deleting..."); LOG.warning("Unknown message type '" + type + "', deleting...");
} }
deleteMessage(txn, m.getId());
return false;
} }
// The message is valid
return true;
} }
@Override @Override
@@ -374,14 +390,15 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
int role = state.getLong(ROLE).intValue(); int role = state.getLong(ROLE).intValue();
boolean local; boolean local;
long time = msg.getLong(MESSAGE_TIME); long time = msg.getLong(TIMESTAMP);
boolean accepted = msg.getBoolean(ACCEPT, false); boolean accepted = msg.getBoolean(ACCEPT, false);
boolean read = msg.getBoolean(READ, false); boolean read = msg.getBoolean(READ, false);
AuthorId authorId; AuthorId authorId;
String name; String name;
if (type == TYPE_RESPONSE) { if (type == TYPE_RESPONSE) {
if (role == ROLE_INTRODUCER) { if (role == ROLE_INTRODUCER) {
if (!concernsThisContact(contactId, messageId, state)) { if (!concernsThisContact(contactId, messageId,
state)) {
// this response is not from contactId // this response is not from contactId
continue; continue;
} }
@@ -445,7 +462,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
list.add(ir); list.add(ir);
} }
} catch (FormatException e) { } catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
} }
} }
txn.setComplete(); txn.setComplete();
@@ -457,17 +475,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
return list; return list;
} }
@Override
public void setReadFlag(MessageId m, boolean read) throws DbException {
try {
BdfDictionary meta = new BdfDictionary();
meta.put(READ, read);
clientHelper.mergeMessageMetadata(m, meta);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
private String getNameForIntroducer(ContactId contactId, private String getNameForIntroducer(ContactId contactId,
BdfDictionary state) throws FormatException { BdfDictionary state) throws FormatException {
@@ -475,7 +482,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
return state.getString(CONTACT_2); return state.getString(CONTACT_2);
if (contactId.getInt() == state.getLong(CONTACT_ID_2).intValue()) if (contactId.getInt() == state.getLong(CONTACT_ID_2).intValue())
return state.getString(CONTACT_1); return state.getString(CONTACT_1);
throw new RuntimeException("Contact not part of this introduction session"); throw new RuntimeException(
"Contact not part of this introduction session");
} }
private AuthorId getAuthorIdForIntroducer(ContactId contactId, private AuthorId getAuthorIdForIntroducer(ContactId contactId,
@@ -485,10 +493,12 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
return new AuthorId(state.getRaw(AUTHOR_ID_2)); return new AuthorId(state.getRaw(AUTHOR_ID_2));
if (contactId.getInt() == state.getLong(CONTACT_ID_2).intValue()) if (contactId.getInt() == state.getLong(CONTACT_ID_2).intValue())
return new AuthorId(state.getRaw(AUTHOR_ID_1)); return new AuthorId(state.getRaw(AUTHOR_ID_1));
throw new RuntimeException("Contact not part of this introduction session"); throw new RuntimeException(
"Contact not part of this introduction session");
} }
private boolean concernsThisContact(ContactId contactId, MessageId messageId, private boolean concernsThisContact(ContactId contactId,
MessageId messageId,
BdfDictionary state) throws FormatException { BdfDictionary state) throws FormatException {
if (contactId.getInt() == state.getLong(CONTACT_ID_1).intValue()) { if (contactId.getInt() == state.getLong(CONTACT_ID_1).intValue()) {
@@ -520,7 +530,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
// to find state for introducee // to find state for introducee
Map<MessageId, BdfDictionary> map = clientHelper Map<MessageId, BdfDictionary> map = clientHelper
.getMessageMetadataAsDictionary(txn, .getMessageMetadataAsDictionary(txn,
introductionGroupFactory.createLocalGroup().getId()); introductionGroupFactory.createLocalGroup()
.getId());
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
if (Arrays.equals(m.getValue().getRaw(SESSION_ID), sessionId)) { if (Arrays.equals(m.getValue().getRaw(SESSION_ID), sessionId)) {
BdfDictionary state = m.getValue(); BdfDictionary state = m.getValue();

View File

@@ -1,9 +1,9 @@
package org.briarproject.introduction; package org.briarproject.introduction;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.SessionId; import org.briarproject.api.clients.SessionId;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList; import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.data.MetadataEncoder;
@@ -13,13 +13,15 @@ import org.briarproject.api.system.Clock;
import org.briarproject.clients.BdfMessageValidator; import org.briarproject.clients.BdfMessageValidator;
import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH; import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID; import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG; import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
@@ -67,7 +69,9 @@ class IntroductionValidator extends BdfMessageValidator {
d.put(SESSION_ID, id); d.put(SESSION_ID, id);
d.put(GROUP_ID, m.getGroupId()); d.put(GROUP_ID, m.getGroupId());
d.put(MESSAGE_ID, m.getId()); d.put(MESSAGE_ID, m.getId());
d.put(MESSAGE_TIME, m.getTimestamp()); d.put(TIMESTAMP, m.getTimestamp());
d.put(LOCAL, false);
d.put(READ, false);
return new BdfMessageContext(d); return new BdfMessageContext(d);
} }

View File

@@ -16,10 +16,10 @@ import org.briarproject.api.system.Clock;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG; import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
@@ -61,7 +61,7 @@ public class MessageSender {
Group group = db.getGroup(txn, groupId); Group group = db.getGroup(txn, groupId);
long timestamp = clock.currentTimeMillis(); long timestamp = clock.currentTimeMillis();
message.put(MESSAGE_TIME, timestamp); message.put(TIMESTAMP, timestamp);
Metadata metadata = metadataEncoder.encode(message); Metadata metadata = metadataEncoder.encode(message);
messageQueueManager messageQueueManager

View File

@@ -24,7 +24,7 @@ import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus; import org.briarproject.api.sync.MessageStatus;
import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.clients.ReadableMessageManagerImpl;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -33,23 +33,25 @@ import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
class MessagingManagerImpl extends BdfIncomingMessageHook import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
class MessagingManagerImpl extends ReadableMessageManagerImpl
implements MessagingManager, Client, AddContactHook, RemoveContactHook { implements MessagingManager, Client, AddContactHook, RemoveContactHook {
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
"6bcdc006c0910b0f44e40644c3b31f1a" "6bcdc006c0910b0f44e40644c3b31f1a"
+ "8bf9a6d6021d40d219c86b731b903070")); + "8bf9a6d6021d40d219c86b731b903070"));
private final DatabaseComponent db;
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
@Inject @Inject
MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
MetadataParser metadataParser, MetadataParser metadataParser,
PrivateGroupFactory privateGroupFactory) { PrivateGroupFactory privateGroupFactory) {
super(clientHelper, metadataParser); super(clientHelper, db, metadataParser);
this.db = db;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
} }
@@ -78,7 +80,8 @@ class MessagingManagerImpl extends BdfIncomingMessageHook
} }
} }
private Group getContactGroup(Contact c) { @Override
protected Group getContactGroup(Contact c) {
return privateGroupFactory.createPrivateGroup(CLIENT_ID, c); return privateGroupFactory.createPrivateGroup(CLIENT_ID, c);
} }
@@ -93,30 +96,33 @@ class MessagingManagerImpl extends BdfIncomingMessageHook
} }
@Override @Override
protected void incomingMessage(Transaction txn, Message m, BdfList body, protected boolean incomingReadableMessage(Transaction txn, Message m, BdfList body,
BdfDictionary meta) throws DbException, FormatException { BdfDictionary meta) throws DbException, FormatException {
// Broadcast event
GroupId groupId = m.getGroupId(); GroupId groupId = m.getGroupId();
long timestamp = meta.getLong("timestamp"); long timestamp = meta.getLong(TIMESTAMP);
String contentType = meta.getString("contentType"); String contentType = meta.getString("contentType");
boolean local = meta.getBoolean("local"); boolean local = meta.getBoolean(LOCAL);
boolean read = meta.getBoolean("read"); boolean read = meta.getBoolean(READ);
PrivateMessageHeader header = new PrivateMessageHeader( PrivateMessageHeader header = new PrivateMessageHeader(
m.getId(), timestamp, contentType, local, read, false, false); m.getId(), timestamp, contentType, local, read, false, false);
PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent( PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent(
header, groupId); header, groupId);
txn.attach(event); txn.attach(event);
return true;
} }
@Override @Override
public void addLocalMessage(PrivateMessage m) throws DbException { public void addLocalMessage(PrivateMessage m) throws DbException {
try { try {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put("timestamp", m.getMessage().getTimestamp()); meta.put(TIMESTAMP, m.getMessage().getTimestamp());
if (m.getParent() != null) meta.put("parent", m.getParent()); if (m.getParent() != null) meta.put("parent", m.getParent());
meta.put("contentType", m.getContentType()); meta.put("contentType", m.getContentType());
meta.put("local", true); meta.put(LOCAL, true);
meta.put("read", true); meta.put(READ, true);
clientHelper.addLocalMessage(m.getMessage(), CLIENT_ID, meta, true); clientHelper.addLocalMessage(m.getMessage(), CLIENT_ID, meta, true);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -169,10 +175,10 @@ class MessagingManagerImpl extends BdfIncomingMessageHook
BdfDictionary meta = metadata.get(id); BdfDictionary meta = metadata.get(id);
if (meta == null) continue; if (meta == null) continue;
try { try {
long timestamp = meta.getLong("timestamp"); long timestamp = meta.getLong(TIMESTAMP);
String contentType = meta.getString("contentType"); String contentType = meta.getString("contentType");
boolean local = meta.getBoolean("local"); boolean local = meta.getBoolean(LOCAL);
boolean read = meta.getBoolean("read"); boolean read = meta.getBoolean(READ);
headers.add(new PrivateMessageHeader(id, timestamp, contentType, headers.add(new PrivateMessageHeader(id, timestamp, contentType,
local, read, s.isSent(), s.isSeen())); local, read, s.isSent(), s.isSeen()));
} catch (FormatException e) { } catch (FormatException e) {
@@ -192,15 +198,4 @@ class MessagingManagerImpl extends BdfIncomingMessageHook
throw new DbException(e); throw new DbException(e);
} }
} }
@Override
public void setReadFlag(MessageId m, boolean read) throws DbException {
try {
BdfDictionary meta = new BdfDictionary();
meta.put("read", read);
clientHelper.mergeMessageMetadata(m, meta);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -12,6 +12,9 @@ import org.briarproject.api.sync.Message;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
import org.briarproject.clients.BdfMessageValidator; import org.briarproject.clients.BdfMessageValidator;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH; import static org.briarproject.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
@@ -38,11 +41,11 @@ class PrivateMessageValidator extends BdfMessageValidator {
checkLength(privateMessageBody, 0, MAX_PRIVATE_MESSAGE_BODY_LENGTH); checkLength(privateMessageBody, 0, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
// Return the metadata // Return the metadata
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put("timestamp", m.getTimestamp()); meta.put(TIMESTAMP, m.getTimestamp());
if (parentId != null) meta.put("parent", parentId); if (parentId != null) meta.put("parent", parentId);
meta.put("contentType", contentType); meta.put("contentType", contentType);
meta.put("local", false); meta.put(LOCAL, false);
meta.put("read", false); meta.put(READ, false);
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
} }

View File

@@ -16,21 +16,21 @@ import javax.inject.Inject;
import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME;
import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC;
import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE;
import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY;
import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE;
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_DESC_LENGTH; import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_DESC_LENGTH;
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_TITLE_LENGTH; import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_TITLE_LENGTH;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG; import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
import static org.briarproject.api.sharing.SharingConstants.LOCAL;
import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE; 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; import static org.briarproject.api.sharing.SharingConstants.TYPE;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
@@ -92,7 +92,7 @@ class BlogSharingValidator extends BdfMessageValidator {
d.put(TYPE, type); d.put(TYPE, type);
d.put(SESSION_ID, id); d.put(SESSION_ID, id);
d.put(LOCAL, false); d.put(LOCAL, false);
d.put(TIME, m.getTimestamp()); d.put(TIMESTAMP, m.getTimestamp());
return new BdfMessageContext(d); return new BdfMessageContext(d);
} }
} }

View File

@@ -14,19 +14,20 @@ import org.briarproject.clients.BdfMessageValidator;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.forum.ForumConstants.FORUM_NAME; import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT; import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG; import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG;
import static org.briarproject.api.sharing.SharingConstants.LOCAL;
import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE; 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; import static org.briarproject.api.sharing.SharingConstants.TYPE;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
@@ -77,7 +78,8 @@ class ForumSharingValidator extends BdfMessageValidator {
d.put(TYPE, type); d.put(TYPE, type);
d.put(SESSION_ID, id); d.put(SESSION_ID, id);
d.put(LOCAL, false); d.put(LOCAL, false);
d.put(TIME, m.getTimestamp()); d.put(TIMESTAMP, m.getTimestamp());
d.put(READ, false);
return new BdfMessageContext(d); return new BdfMessageContext(d);
} }
} }

View File

@@ -35,7 +35,7 @@ import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus; import org.briarproject.api.sync.MessageStatus;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.clients.ReadableMessageManagerImpl;
import org.briarproject.util.StringUtils; import org.briarproject.util.StringUtils;
import java.io.IOException; import java.io.IOException;
@@ -53,10 +53,11 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
import static org.briarproject.api.clients.ReadableMessageConstants.LOCAL;
import static org.briarproject.api.clients.ReadableMessageConstants.READ;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.sharing.SharingConstants.CONTACT_ID; import static org.briarproject.api.sharing.SharingConstants.CONTACT_ID;
import static org.briarproject.api.sharing.SharingConstants.IS_SHARER; import static org.briarproject.api.sharing.SharingConstants.IS_SHARER;
import static org.briarproject.api.sharing.SharingConstants.LOCAL;
import static org.briarproject.api.sharing.SharingConstants.READ;
import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; import static org.briarproject.api.sharing.SharingConstants.SESSION_ID;
import static org.briarproject.api.sharing.SharingConstants.SHAREABLE_ID; import static org.briarproject.api.sharing.SharingConstants.SHAREABLE_ID;
import static org.briarproject.api.sharing.SharingConstants.SHARED_BY_US; import static org.briarproject.api.sharing.SharingConstants.SHARED_BY_US;
@@ -76,7 +77,6 @@ import static org.briarproject.api.sharing.SharingConstants.TASK_REMOVE_SHAREABL
import static org.briarproject.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE; import static org.briarproject.api.sharing.SharingConstants.TASK_SHARE_SHAREABLE;
import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US; import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_BY_US;
import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US; import static org.briarproject.api.sharing.SharingConstants.TASK_UNSHARE_SHAREABLE_SHARED_WITH_US;
import static org.briarproject.api.sharing.SharingConstants.TIME;
import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US; import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US;
import static org.briarproject.api.sharing.SharingConstants.TYPE; import static org.briarproject.api.sharing.SharingConstants.TYPE;
import static org.briarproject.api.sharing.SharingMessage.BaseMessage; import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
@@ -84,14 +84,13 @@ import static org.briarproject.api.sharing.SharingMessage.Invitation;
import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE; import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM extends InvitationMessage, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationReceivedEvent, IRR extends InvitationResponseReceivedEvent> abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM extends InvitationMessage, IS extends InviteeSessionState, SS extends SharerSessionState, IR extends InvitationReceivedEvent, IRR extends InvitationResponseReceivedEvent>
extends BdfIncomingMessageHook extends ReadableMessageManagerImpl
implements SharingManager<S, IM>, Client, AddContactHook, implements SharingManager<S, IM>, Client, AddContactHook,
RemoveContactHook { RemoveContactHook {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SharingManagerImpl.class.getName()); Logger.getLogger(SharingManagerImpl.class.getName());
private final DatabaseComponent db;
private final MessageQueueManager messageQueueManager; private final MessageQueueManager messageQueueManager;
private final MetadataEncoder metadataEncoder; private final MetadataEncoder metadataEncoder;
private final SecureRandom random; private final SecureRandom random;
@@ -105,8 +104,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
SecureRandom random, PrivateGroupFactory privateGroupFactory, SecureRandom random, PrivateGroupFactory privateGroupFactory,
Clock clock) { Clock clock) {
super(clientHelper, metadataParser); super(clientHelper, db, metadataParser);
this.db = db;
this.messageQueueManager = messageQueueManager; this.messageQueueManager = messageQueueManager;
this.metadataEncoder = metadataEncoder; this.metadataEncoder = metadataEncoder;
this.random = random; this.random = random;
@@ -186,8 +184,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
} }
@Override @Override
protected void incomingMessage(Transaction txn, Message m, BdfList body, protected boolean incomingReadableMessage(Transaction txn, Message m,
BdfDictionary d) throws DbException, FormatException { BdfList body, BdfDictionary d) throws DbException, FormatException {
BaseMessage msg = BaseMessage.from(getIFactory(), m.getGroupId(), d); BaseMessage msg = BaseMessage.from(getIFactory(), m.getGroupId(), d);
SessionId sessionId = msg.getSessionId(); SessionId sessionId = msg.getSessionId();
@@ -223,6 +221,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
} catch (FormatException e) { } catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
deleteMessage(txn, m.getId()); deleteMessage(txn, m.getId());
return false;
} }
} else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT || } else if (msg.getType() == SHARE_MSG_TYPE_ACCEPT ||
msg.getType() == SHARE_MSG_TYPE_DECLINE) { msg.getType() == SHARE_MSG_TYPE_DECLINE) {
@@ -257,6 +256,9 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
// message has passed validator, so that should never happen // message has passed validator, so that should never happen
throw new RuntimeException("Illegal Sharing Message"); throw new RuntimeException("Illegal Sharing Message");
} }
// The message is valid
return true;
} }
@Override @Override
@@ -344,7 +346,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
I msg = getIFactory().build(group.getId(), d); I msg = getIFactory().build(group.getId(), d);
MessageStatus status = MessageStatus status =
db.getMessageStatus(txn, contactId, m.getKey()); db.getMessageStatus(txn, contactId, m.getKey());
long time = d.getLong(TIME); long time = d.getLong(TIMESTAMP);
boolean local = d.getBoolean(LOCAL); boolean local = d.getBoolean(LOCAL);
boolean read = d.getBoolean(READ, false); boolean read = d.getBoolean(READ, false);
boolean available = false; boolean available = false;
@@ -492,17 +494,6 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
} }
} }
@Override
public void setReadFlag(MessageId m, boolean read) throws DbException {
try {
BdfDictionary meta = new BdfDictionary();
meta.put(READ, read);
clientHelper.mergeMessageMetadata(m, meta);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
void removingShareable(Transaction txn, S f) throws DbException { void removingShareable(Transaction txn, S f) throws DbException {
try { try {
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
@@ -851,14 +842,14 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
// add message itself as metadata // add message itself as metadata
BdfDictionary d = m.toBdfDictionary(); BdfDictionary d = m.toBdfDictionary();
d.put(LOCAL, true); d.put(LOCAL, true);
d.put(TIME, timestamp); d.put(TIMESTAMP, timestamp);
Metadata meta = metadataEncoder.encode(d); Metadata meta = metadataEncoder.encode(d);
messageQueueManager messageQueueManager
.sendMessage(txn, group, timestamp, body, meta); .sendMessage(txn, group, timestamp, body, meta);
} }
private Group getContactGroup(Contact c) { protected Group getContactGroup(Contact c) {
return privateGroupFactory.createPrivateGroup(getClientId(), c); return privateGroupFactory.createPrivateGroup(getClientId(), c);
} }
@@ -933,8 +924,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
} }
private void storeShareableList(Transaction txn, GroupId groupId, private void storeShareableList(Transaction txn, GroupId groupId,
String key, String key, List<S> shareables)
List<S> shareables) throws DbException, FormatException { throws DbException, FormatException {
BdfList list = encodeShareableList(shareables); BdfList list = encodeShareableList(shareables);
BdfDictionary metadata = BdfDictionary.of( BdfDictionary metadata = BdfDictionary.of(

View File

@@ -5,6 +5,7 @@ import org.briarproject.TestUtils;
import org.briarproject.api.Bytes; import org.briarproject.api.Bytes;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
@@ -19,7 +20,6 @@ import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.introduction.IntroduceeProtocolState; import org.briarproject.api.introduction.IntroduceeProtocolState;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.properties.TransportPropertyManager;
import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
@@ -34,6 +34,7 @@ import org.junit.Test;
import java.security.SecureRandom; import java.security.SecureRandom;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST; import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
@@ -46,7 +47,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER; import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID; import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID; import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
@@ -63,7 +63,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
public class IntroduceeManagerTest extends BriarTestCase { public class IntroduceeManagerTest extends BriarTestCase {
@@ -164,7 +163,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
msg.put(GROUP_ID, introductionGroup1.getId()); msg.put(GROUP_ID, introductionGroup1.getId());
msg.put(SESSION_ID, sessionId); msg.put(SESSION_ID, sessionId);
msg.put(MESSAGE_ID, message1.getId()); msg.put(MESSAGE_ID, message1.getId());
msg.put(MESSAGE_TIME, time); msg.put(TIMESTAMP, time);
msg.put(NAME, introducee2.getAuthor().getName()); msg.put(NAME, introducee2.getAuthor().getName());
msg.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey()); msg.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey());
@@ -192,7 +191,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
msg.put(GROUP_ID, introductionGroup1.getId()); msg.put(GROUP_ID, introductionGroup1.getId());
msg.put(SESSION_ID, sessionId); msg.put(SESSION_ID, sessionId);
msg.put(MESSAGE_ID, message1.getId()); msg.put(MESSAGE_ID, message1.getId());
msg.put(MESSAGE_TIME, time); msg.put(TIMESTAMP, time);
msg.put(NAME, introducee2.getAuthor().getName()); msg.put(NAME, introducee2.getAuthor().getName());
msg.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey()); msg.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey());

View File

@@ -27,6 +27,7 @@ import org.junit.Test;
import java.security.SecureRandom; import java.security.SecureRandom;
import static org.briarproject.api.clients.ReadableMessageConstants.TIMESTAMP;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES; import static org.briarproject.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
import static org.briarproject.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS; import static org.briarproject.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
@@ -39,7 +40,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2; import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY; import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.ROLE; import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
@@ -136,7 +136,7 @@ public class IntroducerManagerTest extends BriarTestCase {
msg1.put(NAME, state.getString(CONTACT_2)); msg1.put(NAME, state.getString(CONTACT_2));
msg1.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey()); msg1.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey());
final BdfDictionary msg1send = (BdfDictionary) msg1.clone(); final BdfDictionary msg1send = (BdfDictionary) msg1.clone();
msg1send.put(MESSAGE_TIME, time); msg1send.put(TIMESTAMP, time);
final BdfDictionary msg2 = new BdfDictionary(); final BdfDictionary msg2 = new BdfDictionary();
msg2.put(TYPE, TYPE_REQUEST); msg2.put(TYPE, TYPE_REQUEST);
@@ -145,7 +145,7 @@ public class IntroducerManagerTest extends BriarTestCase {
msg2.put(NAME, state.getString(CONTACT_1)); msg2.put(NAME, state.getString(CONTACT_1));
msg2.put(PUBLIC_KEY, introducee1.getAuthor().getPublicKey()); msg2.put(PUBLIC_KEY, introducee1.getAuthor().getPublicKey());
final BdfDictionary msg2send = (BdfDictionary) msg2.clone(); final BdfDictionary msg2send = (BdfDictionary) msg2.clone();
msg2send.put(MESSAGE_TIME, time); msg2send.put(TIMESTAMP, time);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// initialize and store session state // initialize and store session state

View File

@@ -248,7 +248,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
}}); }});
introductionManager introductionManager
.incomingMessage(txn, message1, new BdfList(), msg); .incomingReadableMessage(txn, message1, new BdfList(), msg);
context.assertIsSatisfied(); context.assertIsSatisfied();
assertFalse(txn.isComplete()); assertFalse(txn.isComplete());
@@ -277,7 +277,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
}}); }});
introductionManager introductionManager
.incomingMessage(txn, message1, new BdfList(), msg); .incomingReadableMessage(txn, message1, new BdfList(), msg);
context.assertIsSatisfied(); context.assertIsSatisfied();
assertFalse(txn.isComplete()); assertFalse(txn.isComplete());