diff --git a/briar-core/src/org/briarproject/privategroup/Constants.java b/briar-core/src/org/briarproject/privategroup/Constants.java index b67d715d4841bb6e3a451e802455c3a794c792f8..3c83d232618f074ac612e095eba4772aebf9bd95 100644 --- a/briar-core/src/org/briarproject/privategroup/Constants.java +++ b/briar-core/src/org/briarproject/privategroup/Constants.java @@ -8,11 +8,11 @@ interface Constants { String KEY_TYPE = "type"; String KEY_TIMESTAMP = "timestamp"; String KEY_READ = MSG_KEY_READ; - String KEY_PARENT_ID = "parentId"; + String KEY_PARENT_MSG_ID = "parentMsgId"; + String KEY_NEW_MEMBER_MSG_ID = "newMemberMsgId"; + String KEY_PREVIOUS_MSG_ID = "previousMsgId"; String KEY_AUTHOR_ID = "authorId"; String KEY_AUTHOR_NAME = "authorName"; String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey"; - // Messaging Group Metadata - String KEY_PREVIOUS_MSG_ID = "previousMsgId"; } diff --git a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java index 1fcaec82d3bb6fb4bb4178072c36652347b760af..01385793966e2ad89f6321c4a84edb67909c237b 100644 --- a/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java +++ b/briar-core/src/org/briarproject/privategroup/GroupMessageValidator.java @@ -29,7 +29,9 @@ import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_ import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY; -import static org.briarproject.privategroup.Constants.KEY_PARENT_ID; +import static org.briarproject.privategroup.Constants.KEY_NEW_MEMBER_MSG_ID; +import static org.briarproject.privategroup.Constants.KEY_PARENT_MSG_ID; +import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.privategroup.Constants.KEY_READ; import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP; import static org.briarproject.privategroup.Constants.KEY_TYPE; @@ -80,6 +82,8 @@ class GroupMessageValidator extends BdfMessageValidator { break; case POST: c = validatePost(m, g, body, member_name, member_public_key); + addMessageMetadata(c, member_name, member_public_key, + m.getTimestamp()); break; default: throw new InvalidMessageException("Unknown Message Type"); @@ -141,6 +145,7 @@ class GroupMessageValidator extends BdfMessageValidator { // Return the metadata and dependencies BdfDictionary meta = new BdfDictionary(); + meta.put(KEY_NEW_MEMBER_MSG_ID, new_member_id); return new BdfMessageContext(meta, dependencies); } @@ -185,7 +190,8 @@ class GroupMessageValidator extends BdfMessageValidator { // Return the metadata and dependencies BdfDictionary meta = new BdfDictionary(); - if (parent_id != null) meta.put(KEY_PARENT_ID, parent_id); + if (parent_id != null) meta.put(KEY_PARENT_MSG_ID, parent_id); + meta.put(KEY_PREVIOUS_MSG_ID, previous_message_id); return new BdfMessageContext(meta, dependencies); } diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java index caf8b81ae4a0614cf53129525e9e13faaadae2c4..eb3a888f0406ddd475772b8efafd74946911d4b6 100644 --- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java @@ -16,6 +16,7 @@ import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.privategroup.GroupMessage; import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.JoinMessageHeader; +import org.briarproject.api.privategroup.MessageType; import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupManager; @@ -28,6 +29,7 @@ import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.util.StringUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -45,7 +47,8 @@ import static org.briarproject.api.privategroup.MessageType.POST; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME; import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY; -import static org.briarproject.privategroup.Constants.KEY_PARENT_ID; +import static org.briarproject.privategroup.Constants.KEY_NEW_MEMBER_MSG_ID; +import static org.briarproject.privategroup.Constants.KEY_PARENT_MSG_ID; import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.privategroup.Constants.KEY_READ; import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP; @@ -100,6 +103,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements throws DbException, FormatException { BdfDictionary meta = new BdfDictionary(); meta.put(KEY_TYPE, NEW_MEMBER.getInt()); + addMessageMetadata(meta, m, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); } @@ -166,9 +170,11 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements try { BdfDictionary meta = new BdfDictionary(); meta.put(KEY_TYPE, POST.getInt()); - if (m.getParent() != null) meta.put(KEY_PARENT_ID, m.getParent()); + if (m.getParent() != null) meta.put(KEY_PARENT_MSG_ID, m.getParent()); addMessageMetadata(meta, m, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); + setPreviousMsgId(txn, m.getMessage().getGroupId(), + m.getMessage().getId()); trackOutgoingMessage(txn, m.getMessage()); txn.setComplete(); } catch (FormatException e) { @@ -181,6 +187,15 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true); } + private void addMessageMetadata(BdfDictionary meta, GroupMessage m, + boolean read) { + meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp()); + meta.put(KEY_READ, read); + meta.put(KEY_AUTHOR_ID, m.getMember().getId()); + meta.put(KEY_AUTHOR_NAME, m.getMember().getName()); + meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey()); + } + @Override public PrivateGroup getPrivateGroup(GroupId g) throws DbException { PrivateGroup privateGroup; @@ -288,8 +303,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements throws DbException, FormatException { MessageId parentId = null; - if (meta.containsKey(KEY_PARENT_ID)) { - parentId = new MessageId(meta.getRaw(KEY_PARENT_ID)); + if (meta.containsKey(KEY_PARENT_MSG_ID)) { + parentId = new MessageId(meta.getRaw(KEY_PARENT_MSG_ID)); } long timestamp = meta.getLong(KEY_TIMESTAMP); @@ -318,23 +333,86 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements protected boolean incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, FormatException { - trackIncomingMessage(txn, m); - - // TODO POST timestamp must be greater than the timestamps of the parent post, if any, and the member's previous message - - // TODO JOIN timestamp must be equal to the timestamp of the new member message. - // TODO JOIN new_member_id must be the identifier of a NEW_MEMBER message with the same member_name and member_public_key - - return true; - } - - private void addMessageMetadata(BdfDictionary meta, GroupMessage m, - boolean read) { - meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp()); - meta.put(KEY_READ, read); - meta.put(KEY_AUTHOR_ID, m.getMember().getId()); - meta.put(KEY_AUTHOR_NAME, m.getMember().getName()); - meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey()); + long timestamp = meta.getLong(KEY_TIMESTAMP); + MessageType type = + MessageType.valueOf(meta.getLong(KEY_TYPE).intValue()); + switch (type) { + case NEW_MEMBER: + // don't track incoming message, because it won't show in the UI + return true; + case JOIN: + // new_member_id must be the identifier of a NEW_MEMBER message + byte[] newMemberIdBytes = + meta.getOptionalRaw(KEY_NEW_MEMBER_MSG_ID); + MessageId newMemberId = new MessageId(newMemberIdBytes); + BdfDictionary newMemberMeta = clientHelper + .getMessageMetadataAsDictionary(txn, newMemberId); + MessageType newMemberType = MessageType + .valueOf(newMemberMeta.getLong(KEY_TYPE).intValue()); + if (newMemberType != NEW_MEMBER) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + // timestamp must be equal to timestamp of NEW_MEMBER message + if (timestamp != newMemberMeta.getLong(KEY_TIMESTAMP)) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + // NEW_MEMBER must have same member_name and member_public_key + if (!Arrays.equals(meta.getRaw(KEY_AUTHOR_ID), + newMemberMeta.getRaw(KEY_AUTHOR_ID))) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + // TODO add to member list + trackIncomingMessage(txn, m); + return true; + case POST: + // timestamp must be greater than the timestamps of parent post + byte[] parentIdBytes = meta.getOptionalRaw(KEY_PARENT_MSG_ID); + if (parentIdBytes != null) { + MessageId parentId = new MessageId(parentIdBytes); + BdfDictionary parentMeta = clientHelper + .getMessageMetadataAsDictionary(txn, parentId); + if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP)) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + MessageType parentType = MessageType + .valueOf(parentMeta.getLong(KEY_TYPE).intValue()); + if (parentType != POST) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + } + // and the member's previous message + byte[] previousMsgIdBytes = meta.getRaw(KEY_PREVIOUS_MSG_ID); + MessageId previousMsgId = new MessageId(previousMsgIdBytes); + BdfDictionary previousMeta = clientHelper + .getMessageMetadataAsDictionary(txn, previousMsgId); + if (timestamp <= previousMeta.getLong(KEY_TIMESTAMP)) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + // previous message must be from same member + if (!Arrays.equals(meta.getRaw(KEY_AUTHOR_ID), + previousMeta.getRaw(KEY_AUTHOR_ID))) { + // FIXME throw new InvalidMessageException() (#643) + db.deleteMessage(txn, m.getId()); + return false; + } + trackIncomingMessage(txn, m); + return true; + default: + // the validator should only let valid types pass + throw new RuntimeException("Unknown MessageType"); + } } }