Use client versioning for private groups.

This commit is contained in:
akwizgran
2018-04-16 14:55:02 +01:00
parent be309057cd
commit f4c5855dd8
20 changed files with 251 additions and 44 deletions

View File

@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -28,6 +29,8 @@ import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_VERSION;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
@@ -45,6 +48,7 @@ abstract class AbstractProtocolEngine<S extends Session>
protected final PrivateGroupFactory privateGroupFactory; protected final PrivateGroupFactory privateGroupFactory;
protected final MessageTracker messageTracker; protected final MessageTracker messageTracker;
private final ClientVersioningManager clientVersioningManager;
private final GroupMessageFactory groupMessageFactory; private final GroupMessageFactory groupMessageFactory;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final MessageParser messageParser; private final MessageParser messageParser;
@@ -52,6 +56,7 @@ abstract class AbstractProtocolEngine<S extends Session>
private final Clock clock; private final Clock clock;
AbstractProtocolEngine(DatabaseComponent db, ClientHelper clientHelper, AbstractProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, GroupMessageFactory groupMessageFactory,
@@ -60,6 +65,7 @@ abstract class AbstractProtocolEngine<S extends Session>
Clock clock) { Clock clock) {
this.db = db; this.db = db;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.clientVersioningManager = clientVersioningManager;
this.privateGroupManager = privateGroupManager; this.privateGroupManager = privateGroupManager;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.groupMessageFactory = groupMessageFactory; this.groupMessageFactory = groupMessageFactory;
@@ -90,10 +96,14 @@ abstract class AbstractProtocolEngine<S extends Session>
return expected != null && dependency.equals(expected); return expected != null && dependency.equals(expected);
} }
void setPrivateGroupVisibility(Transaction txn, S session, Visibility v) void setPrivateGroupVisibility(Transaction txn, S session,
throws DbException, FormatException { Visibility preferred) throws DbException, FormatException {
// Apply min of preferred visibility and client's visibility
ContactId contactId = getContactId(txn, session.getContactGroupId()); ContactId contactId = getContactId(txn, session.getContactGroupId());
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), v); Visibility client = clientVersioningManager.getClientVisibility(txn,
contactId, CLIENT_ID, CLIENT_VERSION);
Visibility min = Visibility.min(preferred, client);
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), min);
} }
Message sendInviteMessage(Transaction txn, S session, Message sendInviteMessage(Transaction txn, S session,

View File

@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
@@ -36,15 +37,16 @@ import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> { class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
CreatorProtocolEngine(DatabaseComponent db, ClientHelper clientHelper, CreatorProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, GroupMessageFactory groupMessageFactory,
IdentityManager identityManager, MessageParser messageParser, IdentityManager identityManager, MessageParser messageParser,
MessageEncoder messageEncoder, MessageTracker messageTracker, MessageEncoder messageEncoder, MessageTracker messageTracker,
Clock clock) { Clock clock) {
super(db, clientHelper, privateGroupManager, privateGroupFactory, super(db, clientHelper, clientVersioningManager, privateGroupManager,
groupMessageFactory, identityManager, messageParser, privateGroupFactory, groupMessageFactory, identityManager,
messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }
@Override @Override

View File

@@ -2,19 +2,30 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group.Visibility;
import javax.annotation.concurrent.Immutable; 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;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
enum CreatorState implements State { enum CreatorState implements State {
START(0), INVITED(1), JOINED(2), LEFT(3), DISSOLVED(4), ERROR(5); START(0, INVISIBLE),
INVITED(1, INVISIBLE),
JOINED(2, SHARED),
LEFT(3, INVISIBLE),
DISSOLVED(4, INVISIBLE),
ERROR(5, INVISIBLE);
private final int value; private final int value;
private final Visibility visibility;
CreatorState(int value) { CreatorState(int value, Visibility visibility) {
this.value = value; this.value = value;
this.visibility = visibility;
} }
@Override @Override
@@ -22,6 +33,11 @@ enum CreatorState implements State {
return value; return value;
} }
@Override
public Visibility getVisibility() {
return visibility;
}
static CreatorState fromValue(int value) throws FormatException { static CreatorState fromValue(int value) throws FormatException {
for (CreatorState s : values()) if (s.value == value) return s; for (CreatorState s : values()) if (s.value == value) return s;
throw new FormatException(); throw new FormatException();

View File

@@ -15,6 +15,7 @@ interface GroupInvitationConstants {
String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted"; String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted";
// Session keys // Session keys
String SESSION_KEY_IS_SESSION = "isSession";
String SESSION_KEY_SESSION_ID = "sessionId"; String SESSION_KEY_SESSION_ID = "sessionId";
String SESSION_KEY_PRIVATE_GROUP_ID = "privateGroupId"; String SESSION_KEY_PRIVATE_GROUP_ID = "privateGroupId";
String SESSION_KEY_LAST_LOCAL_MESSAGE_ID = "lastLocalMessageId"; String SESSION_KEY_LAST_LOCAL_MESSAGE_ID = "lastLocalMessageId";

View File

@@ -16,7 +16,10 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client; import org.briarproject.bramble.api.sync.Client;
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;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
@@ -36,15 +39,17 @@ import org.briarproject.briar.client.ConversationClientImpl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static java.util.logging.Level.INFO;
import static org.briarproject.briar.privategroup.invitation.CreatorState.START; import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
@@ -59,8 +64,12 @@ import static org.briarproject.briar.privategroup.invitation.Role.PEER;
@NotNullByDefault @NotNullByDefault
class GroupInvitationManagerImpl extends ConversationClientImpl class GroupInvitationManagerImpl extends ConversationClientImpl
implements GroupInvitationManager, Client, ContactHook, implements GroupInvitationManager, Client, ContactHook,
PrivateGroupHook { PrivateGroupHook, ClientVersioningHook {
private static final Logger LOG =
Logger.getLogger(GroupInvitationManagerImpl.class.getName());
private final ClientVersioningManager clientVersioningManager;
private final ContactGroupFactory contactGroupFactory; private final ContactGroupFactory contactGroupFactory;
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final PrivateGroupManager privateGroupManager; private final PrivateGroupManager privateGroupManager;
@@ -73,8 +82,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
@Inject @Inject
GroupInvitationManagerImpl(DatabaseComponent db, GroupInvitationManagerImpl(DatabaseComponent db,
ClientHelper clientHelper, MetadataParser metadataParser, ClientHelper clientHelper,
MessageTracker messageTracker, ClientVersioningManager clientVersioningManager,
MetadataParser metadataParser, MessageTracker messageTracker,
ContactGroupFactory contactGroupFactory, ContactGroupFactory contactGroupFactory,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
@@ -82,6 +92,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
SessionEncoder sessionEncoder, SessionEncoder sessionEncoder,
ProtocolEngineFactory engineFactory) { ProtocolEngineFactory engineFactory) {
super(db, clientHelper, metadataParser, messageTracker); super(db, clientHelper, metadataParser, messageTracker);
this.clientVersioningManager = clientVersioningManager;
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.privateGroupManager = privateGroupManager; this.privateGroupManager = privateGroupManager;
@@ -110,7 +121,11 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
Group g = getContactGroup(c); Group g = getContactGroup(c);
// Store the group and share it with the contact // Store the group and share it with the contact
db.addGroup(txn, g); db.addGroup(txn, g);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED); Visibility client = clientVersioningManager.getClientVisibility(txn,
c.getId(), CLIENT_ID, CLIENT_VERSION);
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 // Attach the contact ID to the group
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt()); meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
@@ -565,6 +580,72 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
} }
} }
@Override
public void onClientVisibilityChanging(Transaction txn, Contact c,
Visibility v) throws DbException {
// Apply the client's visibility to the contact group
if (LOG.isLoggable(INFO))
LOG.info("Applying visibility " + v + " to contact group");
Group g = getContactGroup(c);
db.setGroupVisibility(txn, c.getId(), g.getId(), v);
}
ClientVersioningHook getPrivateGroupClientVersioningHook() {
return this::onPrivateGroupClientVisibilityChanging;
}
private void onPrivateGroupClientVisibilityChanging(Transaction txn,
Contact c, Visibility client) throws DbException {
try {
Collection<Group> shareables =
db.getGroups(txn, PrivateGroupManager.CLIENT_ID,
PrivateGroupManager.CLIENT_VERSION);
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 private group, 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()) {
Role role = sessionParser.getRole(d);
if (role == CREATOR) {
CreatorSession s =
sessionParser.parseCreatorSession(contactGroupId, d);
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
} else if (role == INVITEE) {
InviteeSession s =
sessionParser.parseInviteeSession(contactGroupId, d);
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
} else if (role == PEER) {
PeerSession s =
sessionParser.parsePeerSession(contactGroupId, d);
m.put(s.getPrivateGroupId(), s.getState().getVisibility());
} else {
throw new AssertionError();
}
}
return m;
}
private static class StoredSession { private static class StoredSession {
private final MessageId storageId; private final MessageId storageId;

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; 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.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.messaging.ConversationManager; import org.briarproject.briar.api.messaging.ConversationManager;
@@ -38,13 +39,25 @@ public class GroupInvitationModule {
LifecycleManager lifecycleManager, LifecycleManager lifecycleManager,
ValidationManager validationManager, ContactManager contactManager, ValidationManager validationManager, ContactManager contactManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
ConversationManager conversationManager) { ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager) {
lifecycleManager.registerClient(groupInvitationManager); lifecycleManager.registerClient(groupInvitationManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, CLIENT_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, CLIENT_VERSION,
groupInvitationManager); groupInvitationManager);
contactManager.registerContactHook(groupInvitationManager); contactManager.registerContactHook(groupInvitationManager);
privateGroupManager.registerPrivateGroupHook(groupInvitationManager); privateGroupManager.registerPrivateGroupHook(groupInvitationManager);
conversationManager.registerConversationClient(groupInvitationManager); conversationManager.registerConversationClient(groupInvitationManager);
clientVersioningManager.registerClient(CLIENT_ID, CLIENT_VERSION);
clientVersioningManager.registerClientVersioningHook(CLIENT_ID,
CLIENT_VERSION, groupInvitationManager);
// The group invitation manager handles client visibility changes for
// the private group manager
clientVersioningManager.registerClient(PrivateGroupManager.CLIENT_ID,
PrivateGroupManager.CLIENT_VERSION);
clientVersioningManager.registerClientVersioningHook(
PrivateGroupManager.CLIENT_ID,
PrivateGroupManager.CLIENT_VERSION,
groupInvitationManager.getPrivateGroupClientVersioningHook());
return groupInvitationManager; return groupInvitationManager;
} }

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -41,15 +42,16 @@ import static org.briarproject.briar.privategroup.invitation.InviteeState.START;
class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> { class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
InviteeProtocolEngine(DatabaseComponent db, ClientHelper clientHelper, InviteeProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, GroupMessageFactory groupMessageFactory,
IdentityManager identityManager, MessageParser messageParser, IdentityManager identityManager, MessageParser messageParser,
MessageEncoder messageEncoder, MessageTracker messageTracker, MessageEncoder messageEncoder, MessageTracker messageTracker,
Clock clock) { Clock clock) {
super(db, clientHelper, privateGroupManager, privateGroupFactory, super(db, clientHelper, clientVersioningManager, privateGroupManager,
groupMessageFactory, identityManager, messageParser, privateGroupFactory, groupMessageFactory, identityManager,
messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }
@Override @Override
@@ -212,6 +214,12 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
throws DbException { throws DbException {
// Send a LEAVE message // Send a LEAVE message
Message sent = sendLeaveMessage(txn, s, false); Message sent = sendLeaveMessage(txn, s, false);
try {
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
// Move to the LEFT state // Move to the LEFT state
return new InviteeSession(s.getContactGroupId(), s.getPrivateGroupId(), return new InviteeSession(s.getContactGroupId(), s.getPrivateGroupId(),
sent.getId(), s.getLastRemoteMessageId(), sent.getTimestamp(), sent.getId(), s.getLastRemoteMessageId(), sent.getTimestamp(),

View File

@@ -2,20 +2,32 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group.Visibility;
import javax.annotation.concurrent.Immutable; 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 @Immutable
@NotNullByDefault @NotNullByDefault
enum InviteeState implements State { enum InviteeState implements State {
START(0), INVITED(1), ACCEPTED(2), JOINED(3), LEFT(4), DISSOLVED(5), START(0, INVISIBLE),
ERROR(6); INVITED(1, INVISIBLE),
ACCEPTED(2, VISIBLE),
JOINED(3, SHARED),
LEFT(4, INVISIBLE),
DISSOLVED(5, INVISIBLE),
ERROR(6, INVISIBLE);
private final int value; private final int value;
private final Visibility visibility;
InviteeState(int value) { InviteeState(int value, Visibility visibility) {
this.value = value; this.value = value;
this.visibility = visibility;
} }
@Override @Override
@@ -23,6 +35,11 @@ enum InviteeState implements State {
return value; return value;
} }
@Override
public Visibility getVisibility() {
return visibility;
}
static InviteeState fromValue(int value) throws FormatException { static InviteeState fromValue(int value) throws FormatException {
for (InviteeState s : values()) if (s.value == value) return s; for (InviteeState s : values()) if (s.value == value) return s;
throw new FormatException(); throw new FormatException();

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
@@ -36,15 +37,16 @@ import static org.briarproject.briar.privategroup.invitation.PeerState.START;
class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> { class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
PeerProtocolEngine(DatabaseComponent db, ClientHelper clientHelper, PeerProtocolEngine(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, GroupMessageFactory groupMessageFactory,
IdentityManager identityManager, MessageParser messageParser, IdentityManager identityManager, MessageParser messageParser,
MessageEncoder messageEncoder, MessageTracker messageTracker, MessageEncoder messageEncoder, MessageTracker messageTracker,
Clock clock) { Clock clock) {
super(db, clientHelper, privateGroupManager, privateGroupFactory, super(db, clientHelper, clientVersioningManager, privateGroupManager,
groupMessageFactory, identityManager, messageParser, privateGroupFactory, groupMessageFactory, identityManager,
messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }
@Override @Override

View File

@@ -2,20 +2,32 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group.Visibility;
import javax.annotation.concurrent.Immutable; 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 @Immutable
@NotNullByDefault @NotNullByDefault
enum PeerState implements State { enum PeerState implements State {
START(0), AWAIT_MEMBER(1), NEITHER_JOINED(2), LOCAL_JOINED(3), START(0, INVISIBLE),
BOTH_JOINED(4), LOCAL_LEFT(5), ERROR(6); AWAIT_MEMBER(1, INVISIBLE),
NEITHER_JOINED(2, INVISIBLE),
LOCAL_JOINED(3, VISIBLE),
BOTH_JOINED(4, SHARED),
LOCAL_LEFT(5, INVISIBLE),
ERROR(6, INVISIBLE);
private final int value; private final int value;
private final Visibility visibility;
PeerState(int value) { PeerState(int value, Visibility visibility) {
this.value = value; this.value = value;
this.visibility = visibility;
} }
@Override @Override
@@ -23,6 +35,11 @@ enum PeerState implements State {
return value; return value;
} }
@Override
public Visibility getVisibility() {
return visibility;
}
static PeerState fromValue(int value) throws FormatException { static PeerState fromValue(int value) throws FormatException {
for (PeerState s : values()) if (s.value == value) return s; for (PeerState s : values()) if (s.value == value) return s;
throw new FormatException(); throw new FormatException();

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.privategroup.GroupMessageFactory; import org.briarproject.briar.api.privategroup.GroupMessageFactory;
@@ -19,6 +20,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final ClientVersioningManager clientVersioningManager;
private final PrivateGroupManager privateGroupManager; private final PrivateGroupManager privateGroupManager;
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final GroupMessageFactory groupMessageFactory; private final GroupMessageFactory groupMessageFactory;
@@ -30,6 +32,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
@Inject @Inject
ProtocolEngineFactoryImpl(DatabaseComponent db, ClientHelper clientHelper, ProtocolEngineFactoryImpl(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager,
PrivateGroupManager privateGroupManager, PrivateGroupManager privateGroupManager,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
GroupMessageFactory groupMessageFactory, GroupMessageFactory groupMessageFactory,
@@ -38,6 +41,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
Clock clock) { Clock clock) {
this.db = db; this.db = db;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.clientVersioningManager = clientVersioningManager;
this.privateGroupManager = privateGroupManager; this.privateGroupManager = privateGroupManager;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.groupMessageFactory = groupMessageFactory; this.groupMessageFactory = groupMessageFactory;
@@ -50,21 +54,24 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
@Override @Override
public ProtocolEngine<CreatorSession> createCreatorEngine() { public ProtocolEngine<CreatorSession> createCreatorEngine() {
return new CreatorProtocolEngine(db, clientHelper, privateGroupManager, return new CreatorProtocolEngine(db, clientHelper,
clientVersioningManager, privateGroupManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupFactory, groupMessageFactory, identityManager,
messageParser, messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }
@Override @Override
public ProtocolEngine<InviteeSession> createInviteeEngine() { public ProtocolEngine<InviteeSession> createInviteeEngine() {
return new InviteeProtocolEngine(db, clientHelper, privateGroupManager, return new InviteeProtocolEngine(db, clientHelper,
clientVersioningManager, privateGroupManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupFactory, groupMessageFactory, identityManager,
messageParser, messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }
@Override @Override
public ProtocolEngine<PeerSession> createPeerEngine() { public ProtocolEngine<PeerSession> createPeerEngine() {
return new PeerProtocolEngine(db, clientHelper, privateGroupManager, return new PeerProtocolEngine(db, clientHelper,
clientVersioningManager, privateGroupManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupFactory, groupMessageFactory, identityManager,
messageParser, messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
} }

View File

@@ -9,6 +9,7 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_IS_SESSION;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
@@ -28,6 +29,7 @@ class SessionEncoderImpl implements SessionEncoder {
@Override @Override
public BdfDictionary encodeSession(Session s) { public BdfDictionary encodeSession(Session s) {
BdfDictionary d = new BdfDictionary(); BdfDictionary d = new BdfDictionary();
d.put(SESSION_KEY_IS_SESSION, true);
d.put(SESSION_KEY_SESSION_ID, s.getPrivateGroupId()); d.put(SESSION_KEY_SESSION_ID, s.getPrivateGroupId());
d.put(SESSION_KEY_PRIVATE_GROUP_ID, s.getPrivateGroupId()); d.put(SESSION_KEY_PRIVATE_GROUP_ID, s.getPrivateGroupId());
MessageId lastLocalMessageId = s.getLastLocalMessageId(); MessageId lastLocalMessageId = s.getLastLocalMessageId();

View File

@@ -11,6 +11,8 @@ interface SessionParser {
BdfDictionary getSessionQuery(SessionId s); BdfDictionary getSessionQuery(SessionId s);
BdfDictionary getAllSessionsQuery();
Role getRole(BdfDictionary d) throws FormatException; Role getRole(BdfDictionary d) throws FormatException;
CreatorSession parseCreatorSession(GroupId contactGroupId, BdfDictionary d) CreatorSession parseCreatorSession(GroupId contactGroupId, BdfDictionary d)

View File

@@ -13,6 +13,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_INVITE_TIMESTAMP;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_IS_SESSION;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.SESSION_KEY_LOCAL_TIMESTAMP;
@@ -37,6 +38,11 @@ class SessionParserImpl implements SessionParser {
return BdfDictionary.of(new BdfEntry(SESSION_KEY_SESSION_ID, s)); 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 @Override
public Role getRole(BdfDictionary d) throws FormatException { public Role getRole(BdfDictionary d) throws FormatException {
return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue()); return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue());

View File

@@ -1,6 +1,10 @@
package org.briarproject.briar.privategroup.invitation; package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.sync.Group.Visibility;
interface State { interface State {
int getValue(); int getValue();
Visibility getVisibility();
} }

View File

@@ -10,7 +10,9 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Group; 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.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
@@ -24,6 +26,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.jmock.Expectations; import org.jmock.Expectations;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
@@ -47,6 +50,8 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
context.mock(DatabaseComponent.class); context.mock(DatabaseComponent.class);
protected final ClientHelper clientHelper = protected final ClientHelper clientHelper =
context.mock(ClientHelper.class); context.mock(ClientHelper.class);
protected final ClientVersioningManager clientVersioningManager =
context.mock(ClientVersioningManager.class);
protected final PrivateGroupFactory privateGroupFactory = protected final PrivateGroupFactory privateGroupFactory =
context.mock(PrivateGroupFactory.class); context.mock(PrivateGroupFactory.class);
protected final PrivateGroupManager privateGroupManager = protected final PrivateGroupManager privateGroupManager =
@@ -181,10 +186,13 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
}}); }});
} }
protected void expectSetPrivateGroupVisibility(Group.Visibility v) protected void expectSetPrivateGroupVisibility(Visibility v)
throws Exception { throws Exception {
expectGetContactId(); expectGetContactId();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientVersioningManager).getClientVisibility(txn, contactId,
CLIENT_ID, CLIENT_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contactId, privateGroupId, v); oneOf(db).setGroupVisibility(txn, contactId, privateGroupId, v);
}}); }});
} }

View File

@@ -19,9 +19,10 @@ import static org.junit.Assert.assertEquals;
public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
private final CreatorProtocolEngine engine = private final CreatorProtocolEngine engine =
new CreatorProtocolEngine(db, clientHelper, privateGroupManager, new CreatorProtocolEngine(db, clientHelper, clientVersioningManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupManager, privateGroupFactory,
messageParser, messageEncoder, messageTracker, clock); groupMessageFactory, identityManager, messageParser,
messageEncoder, messageTracker, clock);
private CreatorSession getDefaultSession(CreatorState state) { private CreatorSession getDefaultSession(CreatorState state) {
return new CreatorSession(contactGroupId, privateGroupId, return new CreatorSession(contactGroupId, privateGroupId,

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.ClientVersioningManager;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
@@ -69,6 +70,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final ClientVersioningManager clientVersioningManager =
context.mock(ClientVersioningManager.class);
private final ContactGroupFactory contactGroupFactory = private final ContactGroupFactory contactGroupFactory =
context.mock(ContactGroupFactory.class); context.mock(ContactGroupFactory.class);
private final PrivateGroupFactory privateGroupFactory = private final PrivateGroupFactory privateGroupFactory =
@@ -140,11 +143,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
}}); }});
MetadataParser metadataParser = context.mock(MetadataParser.class); MetadataParser metadataParser = context.mock(MetadataParser.class);
MessageTracker messageTracker = context.mock(MessageTracker.class); MessageTracker messageTracker = context.mock(MessageTracker.class);
groupInvitationManager = groupInvitationManager = new GroupInvitationManagerImpl(db,
new GroupInvitationManagerImpl(db, clientHelper, metadataParser, clientHelper, clientVersioningManager, metadataParser,
messageTracker, contactGroupFactory, messageTracker, contactGroupFactory, privateGroupFactory,
privateGroupFactory, privateGroupManager, messageParser, privateGroupManager, messageParser, sessionParser,
sessionParser, sessionEncoder, engineFactory); sessionEncoder, engineFactory);
} }
@Test @Test
@@ -184,6 +187,9 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
CLIENT_VERSION, c); CLIENT_VERSION, c);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup); oneOf(db).addGroup(txn, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn, contactId,
CLIENT_ID, CLIENT_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, c.getId(), contactGroup.getId(), oneOf(db).setGroupVisibility(txn, c.getId(), contactGroup.getId(),
SHARED); SHARED);
oneOf(clientHelper) oneOf(clientHelper)

View File

@@ -38,9 +38,10 @@ import static org.junit.Assert.assertTrue;
public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
private final InviteeProtocolEngine engine = private final InviteeProtocolEngine engine =
new InviteeProtocolEngine(db, clientHelper, privateGroupManager, new InviteeProtocolEngine(db, clientHelper, clientVersioningManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupManager, privateGroupFactory,
messageParser, messageEncoder, messageTracker, clock); groupMessageFactory, identityManager, messageParser,
messageEncoder, messageTracker, clock);
private final LocalAuthor localAuthor = getLocalAuthor(); private final LocalAuthor localAuthor = getLocalAuthor();
private InviteeSession getDefaultSession(InviteeState state) { private InviteeSession getDefaultSession(InviteeState state) {
@@ -238,6 +239,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
@Test @Test
public void testOnLeaveActionFromAccepted() throws Exception { public void testOnLeaveActionFromAccepted() throws Exception {
expectSendLeaveMessage(false); expectSendLeaveMessage(false);
expectSetPrivateGroupVisibility(INVISIBLE);
InviteeSession session = getDefaultSession(ACCEPTED); InviteeSession session = getDefaultSession(ACCEPTED);
InviteeSession newSession = engine.onLeaveAction(txn, session); InviteeSession newSession = engine.onLeaveAction(txn, session);
@@ -249,6 +251,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
@Test @Test
public void testOnLeaveActionFromJoined() throws Exception { public void testOnLeaveActionFromJoined() throws Exception {
expectSendLeaveMessage(false); expectSendLeaveMessage(false);
expectSetPrivateGroupVisibility(INVISIBLE);
InviteeSession session = getDefaultSession(JOINED); InviteeSession session = getDefaultSession(JOINED);
InviteeSession newSession = engine.onLeaveAction(txn, session); InviteeSession newSession = engine.onLeaveAction(txn, session);

View File

@@ -24,9 +24,10 @@ import static org.junit.Assert.assertTrue;
public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { public class PeerProtocolEngineTest extends AbstractProtocolEngineTest {
private final PeerProtocolEngine engine = private final PeerProtocolEngine engine =
new PeerProtocolEngine(db, clientHelper, privateGroupManager, new PeerProtocolEngine(db, clientHelper, clientVersioningManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupManager, privateGroupFactory,
messageParser, messageEncoder, messageTracker, clock); groupMessageFactory, identityManager, messageParser,
messageEncoder, messageTracker, clock);
private PeerSession getDefaultSession(PeerState state) { private PeerSession getDefaultSession(PeerState state) {
return new PeerSession(contactGroupId, privateGroupId, return new PeerSession(contactGroupId, privateGroupId,