diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java index 3083387b6bf1f76f393b6dc6d2066c67f32e8e77..3ab61521d8342c044b48a83c56438ca1a42afd87 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.blog.Blog; @@ -22,6 +23,9 @@ import org.briarproject.briar.api.sharing.InvitationRequest; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; +import static org.briarproject.briar.api.blog.BlogManager.CLIENT_VERSION; + @Immutable @NotNullByDefault class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> { @@ -31,13 +35,14 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> { invitationFactory; @Inject - BlogProtocolEngineImpl(DatabaseComponent db, - ClientHelper clientHelper, MessageEncoder messageEncoder, - MessageParser<Blog> messageParser, MessageTracker messageTracker, - Clock clock, BlogManager blogManager, + BlogProtocolEngineImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, + MessageEncoder messageEncoder, MessageParser<Blog> messageParser, + MessageTracker messageTracker, Clock clock, BlogManager blogManager, InvitationFactory<Blog, BlogInvitationResponse> invitationFactory) { - super(db, clientHelper, messageEncoder, messageParser, messageTracker, - clock); + super(db, clientHelper, clientVersioningManager, messageEncoder, + messageParser, messageTracker, clock, CLIENT_ID, + CLIENT_VERSION); this.blogManager = blogManager; this.invitationFactory = invitationFactory; } @@ -46,8 +51,8 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> { Event getInvitationRequestReceivedEvent(InviteMessage<Blog> m, ContactId contactId, boolean available, boolean canBeOpened) { InvitationRequest<Blog> request = invitationFactory - .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + .createInvitationRequest(false, false, true, false, m, + contactId, available, canBeOpened); return new BlogInvitationRequestReceivedEvent(m.getShareable(), contactId, request); } @@ -74,7 +79,7 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> { @Override protected ClientId getShareableClientId() { - return BlogManager.CLIENT_ID; + return CLIENT_ID; } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java index 7a92f1c5f1fcc15bb7c12fd8d6f5fa0303813103..41554bcf4999fa601014b011663b39d814da9ffe 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogSharingManagerImpl.java @@ -12,6 +12,7 @@ import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.BlogInvitationResponse; import org.briarproject.briar.api.blog.BlogManager; @@ -32,6 +33,7 @@ class BlogSharingManagerImpl extends SharingManagerImpl<Blog> @Inject BlogSharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser<Blog> messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, @@ -39,9 +41,9 @@ class BlogSharingManagerImpl extends SharingManagerImpl<Blog> ProtocolEngine<Blog> engine, InvitationFactory<Blog, BlogInvitationResponse> invitationFactory, IdentityManager identityManager, BlogManager blogManager) { - super(db, clientHelper, metadataParser, messageParser, sessionEncoder, - sessionParser, messageTracker, contactGroupFactory, engine, - invitationFactory); + super(db, clientHelper, clientVersioningManager, metadataParser, + messageParser, sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory); this.identityManager = identityManager; this.blogManager = blogManager; } @@ -56,6 +58,16 @@ class BlogSharingManagerImpl extends SharingManagerImpl<Blog> return CLIENT_VERSION; } + @Override + protected ClientId getShareableClientId() { + return BlogManager.CLIENT_ID; + } + + @Override + protected int getShareableClientVersion() { + return BlogManager.CLIENT_VERSION; + } + @Override public void addingContact(Transaction txn, Contact c) throws DbException { // Create a group to share with the contact diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java index 9fb695e50718ca5686841a8a133184bdd0a0d7a2..90ad6888d9bedebc2ddc12ee3c1101479b29d08c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.client.MessageTracker; @@ -22,6 +23,9 @@ import org.briarproject.briar.api.sharing.InvitationRequest; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID; +import static org.briarproject.briar.api.forum.ForumManager.CLIENT_VERSION; + @Immutable @NotNullByDefault class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> { @@ -32,12 +36,15 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> { @Inject ForumProtocolEngineImpl(DatabaseComponent db, - ClientHelper clientHelper, MessageEncoder messageEncoder, - MessageParser<Forum> messageParser, MessageTracker messageTracker, - Clock clock, ForumManager forumManager, + ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, + MessageEncoder messageEncoder, MessageParser<Forum> messageParser, + MessageTracker messageTracker, Clock clock, + ForumManager forumManager, InvitationFactory<Forum, ForumInvitationResponse> invitationFactory) { - super(db, clientHelper, messageEncoder, messageParser, messageTracker, - clock); + super(db, clientHelper, clientVersioningManager, messageEncoder, + messageParser, messageTracker, clock, CLIENT_ID, + CLIENT_VERSION); this.forumManager = forumManager; this.invitationFactory = invitationFactory; } @@ -46,8 +53,8 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> { Event getInvitationRequestReceivedEvent(InviteMessage<Forum> m, ContactId contactId, boolean available, boolean canBeOpened) { InvitationRequest<Forum> request = invitationFactory - .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + .createInvitationRequest(false, false, true, false, m, + contactId, available, canBeOpened); return new ForumInvitationRequestReceivedEvent(m.getShareable(), contactId, request); } @@ -74,7 +81,7 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> { @Override protected ClientId getShareableClientId() { - return ForumManager.CLIENT_ID; + return CLIENT_ID; } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java index 528743b9cc6ba65d939f8db3c27ab7014d8e3b36..2f1ac5efbd403b5c16f5feb3b003962348f9d155 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumSharingManagerImpl.java @@ -8,9 +8,11 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumInvitationResponse; +import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumManager.RemoveForumHook; import org.briarproject.briar.api.forum.ForumSharingManager; @@ -22,15 +24,16 @@ class ForumSharingManagerImpl extends SharingManagerImpl<Forum> @Inject ForumSharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser<Forum> messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, ContactGroupFactory contactGroupFactory, ProtocolEngine<Forum> engine, InvitationFactory<Forum, ForumInvitationResponse> invitationFactory) { - super(db, clientHelper, metadataParser, messageParser, sessionEncoder, - sessionParser, messageTracker, contactGroupFactory, engine, - invitationFactory); + super(db, clientHelper, clientVersioningManager, metadataParser, + messageParser, sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory); } @Override @@ -43,6 +46,16 @@ class ForumSharingManagerImpl extends SharingManagerImpl<Forum> return CLIENT_VERSION; } + @Override + protected ClientId getShareableClientId() { + return ForumManager.CLIENT_ID; + } + + @Override + protected int getShareableClientVersion() { + return ForumManager.CLIENT_VERSION; + } + @Override public void removingForum(Transaction txn, Forum f) throws DbException { removingShareable(txn, f); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java index e6a7976d5829b21478ae15dbb11d476cb740b7bf..6097c61aaa605737878c223ddae671e0bd3f9a67 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java @@ -11,6 +11,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.GroupId; @@ -52,19 +53,27 @@ abstract class ProtocolEngineImpl<S extends Shareable> protected final ClientHelper clientHelper; protected final MessageParser<S> messageParser; + private final ClientVersioningManager clientVersioningManager; private final MessageEncoder messageEncoder; private final MessageTracker messageTracker; private final Clock clock; + private final ClientId shareableClientId; + private final int shareableClientVersion; ProtocolEngineImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MessageEncoder messageEncoder, MessageParser<S> messageParser, - MessageTracker messageTracker, Clock clock) { + MessageTracker messageTracker, Clock clock, + ClientId shareableClientId, int shareableClientVersion) { this.db = db; this.clientHelper = clientHelper; + this.clientVersioningManager = clientVersioningManager; this.messageEncoder = messageEncoder; this.messageParser = messageParser; this.messageTracker = messageTracker; this.clock = clock; + this.shareableClientId = shareableClientId; + this.shareableClientVersion = shareableClientVersion; } @Override @@ -598,9 +607,13 @@ abstract class ProtocolEngineImpl<S extends Shareable> } private void setShareableVisibility(Transaction txn, Session session, - Visibility v) throws DbException, FormatException { + Visibility preferred) throws DbException, FormatException { + // Apply min of preferred visibility and client's visibility ContactId contactId = getContactId(txn, session.getContactGroupId()); - db.setGroupVisibility(txn, contactId, session.getShareableId(), v); + Visibility client = clientVersioningManager.getClientVisibility(txn, + contactId, shareableClientId, shareableClientVersion); + Visibility min = Visibility.min(preferred, client); + db.setGroupVisibility(txn, contactId, session.getShareableId(), min); } private ContactId getContactId(Transaction txn, GroupId contactGroupId) diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java index 7cf2bf139d67495092dec01dc158674aec217a63..641731a4aa9180cbb7dcb62545866ddce137b014 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionEncoderImpl.java @@ -9,6 +9,7 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_INVITE_TIMESTAMP; +import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_IS_SESSION; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LOCAL_TIMESTAMP; @@ -27,6 +28,7 @@ class SessionEncoderImpl implements SessionEncoder { @Override public BdfDictionary encodeSession(Session s) { BdfDictionary d = new BdfDictionary(); + d.put(SESSION_KEY_IS_SESSION, true); d.put(SESSION_KEY_SESSION_ID, s.getShareableId()); d.put(SESSION_KEY_SHAREABLE_ID, s.getShareableId()); MessageId lastLocalMessageId = s.getLastLocalMessageId(); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java index a82aed3eca199a2eb8eb2924375595a88ba42a0e..eec97355f4db745ea8fb54712cd73717698de051 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java @@ -11,6 +11,8 @@ interface SessionParser { BdfDictionary getSessionQuery(SessionId s); + BdfDictionary getAllSessionsQuery(); + Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java index 62d9c44b12b276ea27655471b916451597ceedcb..ee0c06f61f32d6acb9149d6664b927cde30eb14f 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java @@ -13,6 +13,7 @@ import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_INVITE_TIMESTAMP; +import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_IS_SESSION; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.sharing.SharingConstants.SESSION_KEY_LOCAL_TIMESTAMP; @@ -33,6 +34,11 @@ class SessionParserImpl implements SessionParser { return BdfDictionary.of(new BdfEntry(SESSION_KEY_SESSION_ID, s)); } + @Override + public BdfDictionary getAllSessionsQuery() { + return BdfDictionary.of(new BdfEntry(SESSION_KEY_IS_SESSION, true)); + } + @Override public Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java index d98099e27b2ff30a024ce7a2efbe4b72c01c26e1..f2522d1a9bb05a51a2d68d2a7f29db9153d832a4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java @@ -18,6 +18,7 @@ interface SharingConstants { String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted"; // Session keys + String SESSION_KEY_IS_SESSION = "isSession"; String SESSION_KEY_STATE = "state"; String SESSION_KEY_SESSION_ID = "sessionId"; String SESSION_KEY_SHAREABLE_ID = "shareableId"; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 711e3875e5081687e2689044e9e9c5eeaa51a7f1..d249fc1f6051571898b7d16fcc4fcd3c274e3fc9 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -16,7 +16,10 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.ClientId; +import org.briarproject.bramble.api.sync.ClientVersioningManager; +import org.briarproject.bramble.api.sync.ClientVersioningManager.ClientVersioningHook; import org.briarproject.bramble.api.sync.Group; +import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; @@ -37,9 +40,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Logger; import javax.annotation.Nullable; +import static java.util.logging.Level.INFO; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.briar.sharing.MessageType.ABORT; import static org.briarproject.briar.sharing.MessageType.ACCEPT; @@ -52,8 +57,13 @@ import static org.briarproject.briar.sharing.State.SHARING; @NotNullByDefault abstract class SharingManagerImpl<S extends Shareable> extends ConversationClientImpl - implements SharingManager<S>, Client, ContactHook { + implements SharingManager<S>, Client, ContactHook, + ClientVersioningHook { + private static final Logger LOG = + Logger.getLogger(SharingManagerImpl.class.getName()); + + private final ClientVersioningManager clientVersioningManager; private final MessageParser<S> messageParser; private final SessionEncoder sessionEncoder; private final SessionParser sessionParser; @@ -62,12 +72,14 @@ abstract class SharingManagerImpl<S extends Shareable> private final InvitationFactory<S, ?> invitationFactory; SharingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ClientVersioningManager clientVersioningManager, MetadataParser metadataParser, MessageParser<S> messageParser, SessionEncoder sessionEncoder, SessionParser sessionParser, MessageTracker messageTracker, ContactGroupFactory contactGroupFactory, ProtocolEngine<S> engine, InvitationFactory<S, ?> invitationFactory) { super(db, clientHelper, metadataParser, messageTracker); + this.clientVersioningManager = clientVersioningManager; this.messageParser = messageParser; this.sessionEncoder = sessionEncoder; this.sessionParser = sessionParser; @@ -80,6 +92,10 @@ abstract class SharingManagerImpl<S extends Shareable> protected abstract int getClientVersion(); + protected abstract ClientId getShareableClientId(); + + protected abstract int getShareableClientVersion(); + @Override public void createLocalState(Transaction txn) throws DbException { // Create a local group to indicate that we've set this client up @@ -93,18 +109,22 @@ abstract class SharingManagerImpl<S extends Shareable> @Override public void addingContact(Transaction txn, Contact c) throws DbException { + // Create a group to share with the contact + Group g = getContactGroup(c); + // Store the group and share it with the contact + db.addGroup(txn, g); + Visibility client = clientVersioningManager.getClientVisibility(txn, + c.getId(), getClientId(), getClientVersion()); + if (LOG.isLoggable(INFO)) + LOG.info("Applying visibility " + client + " to new contact group"); + db.setGroupVisibility(txn, c.getId(), g.getId(), client); + // Attach the contact ID to the group + BdfDictionary meta = new BdfDictionary(); + meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt()); try { - // Create a group to share with the contact - Group g = getContactGroup(c); - // Store the group and share it with the contact - db.addGroup(txn, g); - db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED); - // Attach the contact ID to the group - BdfDictionary meta = new BdfDictionary(); - meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt()); clientHelper.mergeGroupMetadata(txn, g.getId(), meta); } catch (FormatException e) { - throw new DbException(e); + throw new AssertionError(e); } } @@ -156,9 +176,13 @@ abstract class SharingManagerImpl<S extends Shareable> getSessionId(shareable.getId())); if (existingSession != null) return; - // Add and share the shareable with the contact + // Add the shareable db.addGroup(txn, shareable.getGroup()); - db.setGroupVisibility(txn, c.getId(), shareable.getId(), SHARED); + + // Apply the client's visibility + Visibility client = clientVersioningManager.getClientVisibility(txn, + c.getId(), getShareableClientId(), getShareableClientVersion()); + db.setGroupVisibility(txn, c.getId(), shareable.getId(), client); // Initialize session in sharing state Session session = new Session(SHARING, contactGroupId, @@ -420,6 +444,7 @@ abstract class SharingManagerImpl<S extends Shareable> Transaction txn = db.startTransaction(true); try { for (Contact c : db.getContacts(txn)) { + // FIXME: Check the session for the preferred visibility? if (db.getGroupVisibility(txn, c.getId(), g) == SHARED) contacts.add(c); } @@ -480,6 +505,58 @@ abstract class SharingManagerImpl<S extends Shareable> } } + @Override + public void onClientVisibilityChanging(Transaction txn, Contact c, + Visibility v) throws DbException { + // Apply the client's visibility to the contact group + Group g = getContactGroup(c); + if (LOG.isLoggable(INFO)) + LOG.info("Applying visibility " + v + " to contact group"); + db.setGroupVisibility(txn, c.getId(), g.getId(), v); + } + + ClientVersioningHook getShareableClientVersioningHook() { + return this::onShareableClientVisibilityChanging; + } + + // Versioning hook for the shareable client + private void onShareableClientVisibilityChanging(Transaction txn, Contact c, + Visibility client) throws DbException { + try { + Collection<Group> shareables = db.getGroups(txn, + getShareableClientId(), getShareableClientVersion()); + Map<GroupId, Visibility> m = getPreferredVisibilities(txn, c); + for (Group g : shareables) { + Visibility preferred = m.get(g.getId()); + if (preferred == null) continue; // No session for this group + // Apply min of preferred visibility and client's visibility + Visibility min = Visibility.min(preferred, client); + if (LOG.isLoggable(INFO)) { + LOG.info("Applying visibility " + min + + " to shareable, preferred " + preferred + + ", client" + client); + } + db.setGroupVisibility(txn, c.getId(), g.getId(), min); + } + } catch (FormatException e) { + throw new DbException(e); + } + } + + private Map<GroupId, Visibility> getPreferredVisibilities(Transaction txn, + Contact c) throws DbException, FormatException { + GroupId contactGroupId = getContactGroup(c).getId(); + BdfDictionary query = sessionParser.getAllSessionsQuery(); + Map<MessageId, BdfDictionary> results = clientHelper + .getMessageMetadataAsDictionary(txn, contactGroupId, query); + Map<GroupId, Visibility> m = new HashMap<>(); + for (BdfDictionary d : results.values()) { + Session s = sessionParser.parseSession(contactGroupId, d); + m.put(s.getShareableId(), s.getState().getVisibility()); + } + return m; + } + private static class StoredSession { private final MessageId storageId; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java index 4dfe78d8d33b8528cc38f9de660122fae04f3ca4..b31bfe68c7ca19bcdc56fab97ab3337dbd4ce10e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java @@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.blog.Blog; @@ -73,6 +74,7 @@ public class SharingModule { LifecycleManager lifecycleManager, ContactManager contactManager, ValidationManager validationManager, ConversationManager conversationManager, BlogManager blogManager, + ClientVersioningManager clientVersioningManager, BlogSharingManagerImpl blogSharingManager) { lifecycleManager.registerClient(blogSharingManager); contactManager.registerContactHook(blogSharingManager); @@ -81,6 +83,18 @@ public class SharingModule { blogSharingManager); conversationManager.registerConversationClient(blogSharingManager); blogManager.registerRemoveBlogHook(blogSharingManager); + clientVersioningManager.registerClient(BlogSharingManager.CLIENT_ID, + BlogSharingManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + BlogSharingManager.CLIENT_ID, BlogSharingManager.CLIENT_VERSION, + blogSharingManager); + // The blog sharing manager handles client visibility changes for the + // blog manager + clientVersioningManager.registerClient(BlogManager.CLIENT_ID, + BlogManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + BlogManager.CLIENT_ID, BlogManager.CLIENT_VERSION, + blogSharingManager.getShareableClientVersioningHook()); return blogSharingManager; } @@ -123,6 +137,7 @@ public class SharingModule { LifecycleManager lifecycleManager, ContactManager contactManager, ValidationManager validationManager, ConversationManager conversationManager, ForumManager forumManager, + ClientVersioningManager clientVersioningManager, ForumSharingManagerImpl forumSharingManager) { lifecycleManager.registerClient(forumSharingManager); contactManager.registerContactHook(forumSharingManager); @@ -131,6 +146,18 @@ public class SharingModule { ForumSharingManager.CLIENT_VERSION, forumSharingManager); conversationManager.registerConversationClient(forumSharingManager); forumManager.registerRemoveForumHook(forumSharingManager); + clientVersioningManager.registerClient(ForumSharingManager.CLIENT_ID, + ForumSharingManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + ForumSharingManager.CLIENT_ID, + ForumSharingManager.CLIENT_VERSION, forumSharingManager); + // The forum sharing manager handles client visibility changes for the + // forum manager + clientVersioningManager.registerClient(ForumManager.CLIENT_ID, + ForumManager.CLIENT_VERSION); + clientVersioningManager.registerClientVersioningHook( + ForumManager.CLIENT_ID, ForumManager.CLIENT_VERSION, + forumSharingManager.getShareableClientVersioningHook()); return forumSharingManager; } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java index ade7d7a248787123e6a10bd8cfcc43cc4ba51210..2d0ed97660d9af2cbb2c79b4e47cde5e2537b01c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/State.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/State.java @@ -2,26 +2,41 @@ package org.briarproject.briar.sharing; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.sync.Group.Visibility; import javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; +import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; +import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; + @Immutable @NotNullByDefault enum State { - START(0), LOCAL_INVITED(1), REMOTE_INVITED(2), SHARING(3), LOCAL_LEFT(4), - REMOTE_HANGING(5); + START(0, INVISIBLE), + LOCAL_INVITED(1, INVISIBLE), + REMOTE_INVITED(2, VISIBLE), + SHARING(3, SHARED), + LOCAL_LEFT(4, INVISIBLE), + REMOTE_HANGING(5, INVISIBLE); private final int value; + private final Visibility visibility; - State(int value) { + State(int value, Visibility visibility) { this.value = value; + this.visibility = visibility; } public int getValue() { return value; } + public Visibility getVisibility() { + return visibility; + } + public boolean canInvite() { return this == START; } diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java index 8a7a3775f05d90ec1db2d1b1dc56671708a2c3af..5b109533c9545aff783accf1e242dc52146c3a65 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java @@ -14,6 +14,7 @@ import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.sync.ClientVersioningManager; import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; @@ -24,7 +25,6 @@ import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.SessionId; import org.jmock.Expectations; -import org.jmock.Mockery; import org.junit.Test; import java.util.Collection; @@ -44,12 +44,13 @@ import static org.briarproject.briar.sharing.SharingConstants.GROUP_KEY_CONTACT_ public class BlogSharingManagerImplTest extends BrambleMockTestCase { - private final Mockery context = new Mockery(); private final BlogSharingManagerImpl blogSharingManager; private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final IdentityManager identityManager = context.mock(IdentityManager.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class); + private final ClientVersioningManager clientVersioningManager = + context.mock(ClientVersioningManager.class); private final SessionEncoder sessionEncoder = context.mock(SessionEncoder.class); private final SessionParser sessionParser = @@ -80,14 +81,15 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { @SuppressWarnings("unchecked") public BlogSharingManagerImplTest() { MetadataParser metadataParser = context.mock(MetadataParser.class); - MessageTracker messageTracker = context.mock(MessageTracker.class); MessageParser<Blog> messageParser = context.mock(MessageParser.class); + MessageTracker messageTracker = context.mock(MessageTracker.class); InvitationFactory<Blog, BlogInvitationResponse> invitationFactory = context.mock(InvitationFactory.class); blogSharingManager = new BlogSharingManagerImpl(db, clientHelper, - metadataParser, messageParser, sessionEncoder, sessionParser, - messageTracker, contactGroupFactory, engine, invitationFactory, - identityManager, blogManager); + clientVersioningManager, metadataParser, messageParser, + sessionEncoder, sessionParser, messageTracker, + contactGroupFactory, engine, invitationFactory, identityManager, + blogManager); } @Test @@ -124,6 +126,9 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { CLIENT_VERSION, contact); will(returnValue(contactGroup)); oneOf(db).addGroup(txn, contactGroup); + oneOf(clientVersioningManager).getClientVisibility(txn, contactId, + CLIENT_ID, CLIENT_VERSION); + will(returnValue(SHARED)); oneOf(db).setGroupVisibility(txn, contactId, contactGroup.getId(), SHARED); // Attach the contact ID to the group @@ -207,6 +212,10 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase { will(returnValue(sessions)); if (sessions.size() == 0) { oneOf(db).addGroup(txn, blog.getGroup()); + oneOf(clientVersioningManager).getClientVisibility(txn, + contactId, BlogManager.CLIENT_ID, + BlogManager.CLIENT_VERSION); + will(returnValue(SHARED)); oneOf(db).setGroupVisibility(txn, contact.getId(), blog.getGroup().getId(), SHARED); oneOf(clientHelper) diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index ebd3f2238336d10729680d58936c661cb4b9f184..bb955313b508c3dd9ff1ca283c4a2a8af418c417 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -256,6 +256,8 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone sync0To2(1, true); sync1To0(1, true); sync2To0(1, true); + sync0To1(1, true); + sync0To2(1, true); } protected void addContacts1And2() throws Exception { @@ -269,6 +271,7 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone // Sync initial client versioning updates sync1To2(1, true); sync2To1(1, true); + sync1To2(1, true); } @After