diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java index cbeb56d60f2ecf2c14000f897ef145c849bea0c8..99cdce517842fcceb6ff98bc6b22b82921713388 100644 --- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java @@ -55,6 +55,7 @@ import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; import static org.briarproject.api.forum.ForumConstants.CONTACT_ID; +import static org.briarproject.api.forum.ForumConstants.FORUM_ID; import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.api.forum.ForumConstants.IS_SHARER; import static org.briarproject.api.forum.ForumConstants.LOCAL; @@ -67,6 +68,7 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION; import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE; +import static org.briarproject.api.forum.ForumConstants.STATE; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US; import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM; @@ -155,16 +157,18 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook @Override public void removingContact(Transaction txn, Contact c) throws DbException { + // query for this contact c + BdfDictionary query = BdfDictionary.of( + new BdfEntry(CONTACT_ID, c.getId().getInt()) + ); + // clean up session states with that contact from localGroup - Long id = (long) c.getId().getInt(); try { Map<MessageId, BdfDictionary> map = clientHelper - .getMessageMetadataAsDictionary(txn, localGroup.getId()); + .getMessageMetadataAsDictionary(txn, localGroup.getId(), + query); for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) { - BdfDictionary d = entry.getValue(); - if (id.equals(d.getLong(CONTACT_ID))) { - deleteMessage(txn, entry.getKey()); - } + deleteMessage(txn, entry.getKey()); } } catch (FormatException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -312,6 +316,11 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook public Collection<ForumInvitationMessage> getForumInvitationMessages( ContactId contactId) throws DbException { + // query for all invitations + BdfDictionary query = BdfDictionary.of( + new BdfEntry(TYPE, SHARE_MSG_TYPE_INVITATION) + ); + Transaction txn = db.startTransaction(false); try { Contact contact = db.getContact(txn, contactId); @@ -320,13 +329,10 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook Collection<ForumInvitationMessage> list = new ArrayList<ForumInvitationMessage>(); Map<MessageId, BdfDictionary> map = clientHelper - .getMessageMetadataAsDictionary(txn, group.getId()); + .getMessageMetadataAsDictionary(txn, group.getId(), query); for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { BdfDictionary d = m.getValue(); try { - if (d.getLong(TYPE) != SHARE_MSG_TYPE_INVITATION) - continue; - Invitation msg = Invitation.from(group.getId(), d); MessageStatus status = db.getMessageStatus(txn, contactId, m.getKey()); @@ -542,17 +548,25 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook try { return getSessionStateForSharer(txn, sessionId); } catch (NoSuchMessageException e) { - // State not found directly, so iterate over all states - // to find state for invitee + // State not found directly, so query for state for invitee + BdfDictionary query = BdfDictionary.of( + new BdfEntry(SESSION_ID, sessionId) + ); + Map<MessageId, BdfDictionary> map = clientHelper - .getMessageMetadataAsDictionary(txn, localGroup.getId()); + .getMessageMetadataAsDictionary(txn, localGroup.getId(), + query); + + if (map.size() > 1 && LOG.isLoggable(WARNING)) { + LOG.warning( + "More than one session state found for message with session ID " + + Arrays.hashCode(sessionId.getBytes())); + } + for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { - BdfDictionary state = m.getValue(); - if (Arrays.equals(state.getRaw(SESSION_ID), - sessionId.getBytes())) { - return fromBdfDictionary(state); - } + return fromBdfDictionary(m.getValue()); } + if (warn && LOG.isLoggable(WARNING)) { LOG.warning( "No session state found for message with session ID " + @@ -578,25 +592,36 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook private InviteeSessionState getSessionStateForResponse(Transaction txn, Forum f) throws DbException, FormatException { + // query for invitee states for that forum in state await response + BdfDictionary query = BdfDictionary.of( + new BdfEntry(IS_SHARER, false), + new BdfEntry(FORUM_ID, f.getId()), + new BdfEntry(STATE, + InviteeSessionState.State.AWAIT_LOCAL_RESPONSE + .getValue()) + ); + Map<MessageId, BdfDictionary> map = clientHelper - .getMessageMetadataAsDictionary(txn, localGroup.getId()); + .getMessageMetadataAsDictionary(txn, localGroup.getId(), query); + + // TODO we might have been invited to the same forum from several people + // in different sessions, so we need to handle this (#391) + if (map.size() > 1 && LOG.isLoggable(WARNING)) { + LOG.warning( + "More than one session state found for forum with ID " + + Arrays.hashCode(f.getId().getBytes()) + + " in state AWAIT_LOCAL_RESPONSE"); + } + for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { - BdfDictionary d = m.getValue(); - try { - ForumSharingSessionState s = fromBdfDictionary(d); - if (!(s instanceof InviteeSessionState)) continue; - if (!f.getId().equals(s.getForumId())) continue; + return (InviteeSessionState) fromBdfDictionary(m.getValue()); + } - InviteeSessionState state = (InviteeSessionState) s; - if (state.getState() == - InviteeSessionState.State.AWAIT_LOCAL_RESPONSE) { - // Note that there should always be only one session - // in this state for the same forum - return state; - } - } catch (FormatException e) { - if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - } + if (LOG.isLoggable(WARNING)) { + LOG.warning( + "No session state found for forum with ID " + + Arrays.hashCode(f.getId().getBytes()) + + " in state AWAIT_LOCAL_RESPONSE"); } throw new DbException(); } @@ -604,22 +629,17 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook private ForumSharingSessionState getSessionStateForLeaving(Transaction txn, Forum f, ContactId c) throws DbException, FormatException { + BdfDictionary query = BdfDictionary.of( + new BdfEntry(CONTACT_ID, c.getInt()), + new BdfEntry(FORUM_ID, f.getId()) + ); Map<MessageId, BdfDictionary> map = clientHelper - .getMessageMetadataAsDictionary(txn, localGroup.getId()); + .getMessageMetadataAsDictionary(txn, localGroup.getId(), query); for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) { BdfDictionary d = m.getValue(); try { ForumSharingSessionState s = fromBdfDictionary(d); - // check that this session is with the right contact - if (!c.equals(s.getContactId())) continue; - - // check that this state actually concerns this forum - if (!s.getForumName().equals(f.getName()) || - !Arrays.equals(s.getForumSalt(), f.getSalt())) { - continue; - } - // check that a forum get be left in current session if (s instanceof SharerSessionState) { SharerSessionState state = (SharerSessionState) s;