Added third group visibility state.

This commit is contained in:
akwizgran
2016-11-15 14:08:01 +00:00
parent 007df4288b
commit ec1f4dccdb
19 changed files with 563 additions and 408 deletions

View File

@@ -12,7 +12,6 @@ import org.briarproject.api.blogs.MessageType;
import org.briarproject.api.clients.Client;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
@@ -68,6 +67,7 @@ import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
import static org.briarproject.api.contact.ContactManager.AddContactHook;
import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.blogs.BlogPostValidator.authorToBdfDictionary;
@NotNullByDefault
@@ -96,35 +96,24 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@Override
public void createLocalState(Transaction txn) throws DbException {
// Ensure that the local identity has its own personal blog
LocalAuthor la = identityManager.getLocalAuthor(txn);
Blog b = blogFactory.createBlog(la);
Group g = b.getGroup();
if (!db.containsGroup(txn, g.getId())) {
db.addGroup(txn, g);
for (ContactId c : db.getContacts(txn, la.getId())) {
db.setVisibleToContact(txn, c, g.getId(), true);
}
}
// Ensure that we have the personal blogs of all pre-existing contacts
// Create our personal blog if necessary
LocalAuthor a = identityManager.getLocalAuthor(txn);
Blog b = blogFactory.createBlog(a);
db.addGroup(txn, b.getGroup());
// Ensure that we have the personal blogs of all contacts
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
}
@Override
public void addingContact(Transaction txn, Contact c) throws DbException {
// get personal blog of the contact
// Add the personal blog of the contact and share it with the contact
Blog b = blogFactory.createBlog(c.getAuthor());
Group g = b.getGroup();
if (!db.containsGroup(txn, g.getId())) {
// add the personal blog of the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
// share our personal blog with the new contact
LocalAuthor a = db.getLocalAuthor(txn, c.getLocalAuthorId());
Blog b2 = blogFactory.createBlog(a);
db.setVisibleToContact(txn, c.getId(), b2.getId(), true);
}
db.addGroup(txn, b.getGroup());
db.setGroupVisibility(txn, c.getId(), b.getId(), SHARED);
// Share our personal blog with the contact
LocalAuthor a = identityManager.getLocalAuthor(txn);
Blog b2 = blogFactory.createBlog(a);
db.setGroupVisibility(txn, c.getId(), b2.getId(), SHARED);
}
@Override

View File

@@ -12,6 +12,7 @@ import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Group.Visibility;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
@@ -72,6 +73,13 @@ interface Database<T> {
*/
void addGroup(T txn, Group g) throws DbException;
/**
* Sets the given group's visibility to the given contact to either
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
*/
void addGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
throws DbException;
/**
* Stores a local pseudonym.
*/
@@ -98,7 +106,7 @@ interface Database<T> {
* Initialises the status of the given message with respect to the given
* contact.
*
* @param ack whether the message needs to be acknowledged.
* @param ack whether the message needs to be acknowledged.
* @param seen whether the contact has seen the message.
*/
void addStatus(T txn, ContactId c, MessageId m, boolean ack, boolean seen)
@@ -116,11 +124,6 @@ interface Database<T> {
void addTransportKeys(T txn, ContactId c, TransportKeys k)
throws DbException;
/**
* Makes a group visible to the given contact.
*/
void addVisibility(T txn, ContactId c, GroupId g) throws DbException;
/**
* Returns true if the database contains the given contact for the given
* local pseudonym.
@@ -166,17 +169,9 @@ interface Database<T> {
boolean containsTransport(T txn, TransportId t) throws DbException;
/**
* Returns true if the database contains the given group and the group is
* visible to the given contact.
* <p/>
* Read-only.
*/
boolean containsVisibleGroup(T txn, ContactId c, GroupId g)
throws DbException;
/**
* Returns true if the database contains the given message and the message
* is visible to the given contact.
* Returns true if the database contains the given message, the message is
* shared, and the visibility of the message's group to the given contact
* is either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
* <p/>
* Read-only.
*/
@@ -267,6 +262,24 @@ interface Database<T> {
*/
Collection<Group> getGroups(T txn, ClientId c) throws DbException;
/**
* Returns the given group's visibility to the given contact, or
* {@link Visibility INVISIBLE} if the group is not in the database.
* <p/>
* Read-only.
*/
Visibility getGroupVisibility(T txn, ContactId c, GroupId g)
throws DbException;
/**
* Returns the IDs of all contacts to which the given group's visibility is
* either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
* <p/>
* Read-only.
*/
Collection<ContactId> getGroupVisibility(T txn, GroupId g)
throws DbException;
/**
* Returns the local pseudonym with the given ID.
* <p/>
@@ -477,13 +490,6 @@ interface Database<T> {
Map<ContactId, TransportKeys> getTransportKeys(T txn, TransportId t)
throws DbException;
/**
* Returns the IDs of all contacts to which the given group is visible.
* <p/>
* Read-only.
*/
Collection<ContactId> getVisibility(T txn, GroupId g) throws DbException;
/**
* Increments the outgoing stream counter for the given contact and
* transport in the given rotation period.
@@ -550,6 +556,13 @@ interface Database<T> {
*/
void removeGroup(T txn, GroupId g) throws DbException;
/**
* Sets the given group's visibility to the given contact to
* {@link Visibility INVISIBLE}.
*/
void removeGroupVisibility(T txn, ContactId c, GroupId g)
throws DbException;
/**
* Removes a local pseudonym (and all associated state) from the database.
*/
@@ -585,11 +598,6 @@ interface Database<T> {
*/
void removeTransport(T txn, TransportId t) throws DbException;
/**
* Makes a group invisible to the given contact.
*/
void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
/**
* Resets the transmission count and expiry time of the given message with
* respect to the given contact.
@@ -607,6 +615,13 @@ interface Database<T> {
void setContactActive(T txn, ContactId c, boolean active)
throws DbException;
/**
* Sets the given group's visibility to the given contact to either
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
*/
void setGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
throws DbException;
/**
* Marks the given message as shared.
*/

View File

@@ -42,6 +42,7 @@ import org.briarproject.api.settings.Settings;
import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Group.Visibility;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
@@ -66,6 +67,8 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
@@ -97,6 +100,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public boolean open() throws DbException {
Runnable shutdownHook = new Runnable() {
@Override
public void run() {
try {
close();
@@ -223,7 +227,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
private void addMessage(T txn, Message m, State state, boolean shared,
@Nullable ContactId sender) throws DbException {
db.addMessage(txn, m, state, shared);
for (ContactId c : db.getVisibility(txn, m.getGroupId())) {
for (ContactId c : db.getGroupVisibility(txn, m.getGroupId())) {
boolean offered = db.removeOfferedMessage(txn, c, m.getId());
boolean seen = offered || c.equals(sender);
db.addStatus(txn, c, m.getId(), seen, seen);
@@ -441,6 +445,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getGroups(txn, c);
}
@Override
public Visibility getGroupVisibility(Transaction transaction, ContactId c,
GroupId g) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
return db.getGroupVisibility(txn, c, g);
}
@Override
public LocalAuthor getLocalAuthor(Transaction transaction, AuthorId a)
throws DbException {
@@ -602,17 +615,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
db.incrementStreamCounter(txn, c, t, rotationPeriod);
}
@Override
public boolean isVisibleToContact(Transaction transaction, ContactId c,
GroupId g) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
if (!db.containsGroup(txn, g))
throw new NoSuchGroupException();
return db.containsVisibleGroup(txn, c, g);
}
@Override
public void mergeGroupMetadata(Transaction transaction, GroupId g,
Metadata meta) throws DbException {
@@ -672,7 +674,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
if (db.containsVisibleGroup(txn, c, m.getGroupId())) {
if (db.getGroupVisibility(txn, c, m.getGroupId()) != INVISIBLE) {
if (db.containsMessage(txn, m.getId())) {
db.raiseSeenFlag(txn, c, m.getId());
db.raiseAckFlag(txn, c, m.getId());
@@ -745,7 +747,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
GroupId id = g.getId();
if (!db.containsGroup(txn, id))
throw new NoSuchGroupException();
Collection<ContactId> affected = db.getVisibility(txn, id);
Collection<ContactId> affected = db.getGroupVisibility(txn, id);
db.removeGroup(txn, id);
transaction.attach(new GroupRemovedEvent(g));
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
@@ -794,6 +796,34 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new ContactStatusChangedEvent(c, active));
}
@Override
public void setGroupVisibility(Transaction transaction, ContactId c,
GroupId g, Visibility v) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
if (!db.containsGroup(txn, g))
throw new NoSuchGroupException();
Visibility old = db.getGroupVisibility(txn, c, g);
if (old == v) return;
if (old == INVISIBLE) {
db.addGroupVisibility(txn, c, g, v == SHARED);
for (MessageId m : db.getMessageIds(txn, g)) {
boolean seen = db.removeOfferedMessage(txn, c, m);
db.addStatus(txn, c, m, seen, seen);
}
} else if (v == INVISIBLE) {
db.removeGroupVisibility(txn, c, g);
for (MessageId m : db.getMessageIds(txn, g))
db.removeStatus(txn, c, m);
} else {
db.setGroupVisibility(txn, c, g, v == SHARED);
}
List<ContactId> affected = Collections.singletonList(c);
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
}
@Override
public void setMessageShared(Transaction transaction, MessageId m)
throws DbException {
@@ -845,33 +875,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
db.setReorderingWindow(txn, c, t, rotationPeriod, base, bitmap);
}
@Override
public void setVisibleToContact(Transaction transaction, ContactId c,
GroupId g, boolean visible) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
if (!db.containsGroup(txn, g))
throw new NoSuchGroupException();
boolean wasVisible = db.containsVisibleGroup(txn, c, g);
if (visible && !wasVisible) {
db.addVisibility(txn, c, g);
for (MessageId m : db.getMessageIds(txn, g)) {
boolean seen = db.removeOfferedMessage(txn, c, m);
db.addStatus(txn, c, m, seen, seen);
}
} else if (!visible && wasVisible) {
db.removeVisibility(txn, c, g);
for (MessageId m : db.getMessageIds(txn, g))
db.removeStatus(txn, c, m);
}
if (visible != wasVisible) {
List<ContactId> affected = Collections.singletonList(c);
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
}
}
@Override
public void updateTransportKeys(Transaction transaction,
Map<ContactId, TransportKeys> keys) throws DbException {

View File

@@ -15,6 +15,7 @@ import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Group.Visibility;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
@@ -50,6 +51,9 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.api.sync.Group.Visibility.VISIBLE;
import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.api.sync.ValidationManager.State.PENDING;
@@ -67,8 +71,8 @@ import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
*/
abstract class JdbcDatabase implements Database<Connection> {
private static final int SCHEMA_VERSION = 28;
private static final int MIN_SCHEMA_VERSION = 28;
private static final int SCHEMA_VERSION = 29;
private static final int MIN_SCHEMA_VERSION = 29;
private static final String CREATE_SETTINGS =
"CREATE TABLE settings"
@@ -121,6 +125,7 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE TABLE groupVisibilities"
+ " (contactId INT NOT NULL,"
+ " groupId HASH NOT NULL,"
+ " shared BOOLEAN NOT NULL,"
+ " PRIMARY KEY (contactId, groupId),"
+ " FOREIGN KEY (contactId)"
+ " REFERENCES contacts (contactId)"
@@ -356,6 +361,7 @@ abstract class JdbcDatabase implements Database<Connection> {
return s;
}
@Override
public Connection startTransaction() throws DbException {
Connection txn = null;
connectionsLock.lock();
@@ -384,6 +390,7 @@ abstract class JdbcDatabase implements Database<Connection> {
return txn;
}
@Override
public void abortTransaction(Connection txn) {
try {
txn.rollback();
@@ -414,6 +421,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void commitTransaction(Connection txn) throws DbException {
try {
txn.commit();
@@ -429,7 +437,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
protected void closeAllConnections() throws SQLException {
void closeAllConnections() throws SQLException {
boolean interrupted = false;
connectionsLock.lock();
try {
@@ -455,11 +463,13 @@ abstract class JdbcDatabase implements Database<Connection> {
if (interrupted) Thread.currentThread().interrupt();
}
@Override
public DeviceId getDeviceId(Connection txn) throws DbException {
Settings s = getSettings(txn, DEVICE_SETTINGS_NAMESPACE);
return new DeviceId(StringUtils.fromHexString(s.get(DEVICE_ID_KEY)));
}
@Override
public ContactId addContact(Connection txn, Author remote, AuthorId local,
boolean verified, boolean active) throws DbException {
PreparedStatement ps = null;
@@ -497,6 +507,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addGroup(Connection txn, Group g) throws DbException {
PreparedStatement ps = null;
try {
@@ -515,6 +526,28 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addGroupVisibility(Connection txn, ContactId c, GroupId g,
boolean shared) throws DbException {
PreparedStatement ps = null;
try {
String sql = "INSERT INTO groupVisibilities"
+ " (contactId, groupId, shared)"
+ " VALUES (?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
ps.setBoolean(3, shared);
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public void addLocalAuthor(Connection txn, LocalAuthor a)
throws DbException {
PreparedStatement ps = null;
@@ -537,6 +570,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addMessage(Connection txn, Message m, State state,
boolean shared) throws DbException {
PreparedStatement ps = null;
@@ -562,6 +596,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addOfferedMessage(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -592,6 +627,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addStatus(Connection txn, ContactId c, MessageId m, boolean ack,
boolean seen) throws DbException {
PreparedStatement ps = null;
@@ -613,6 +649,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addMessageDependency(Connection txn, GroupId g,
MessageId dependent, MessageId dependency) throws DbException {
PreparedStatement ps = null;
@@ -633,6 +670,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addTransport(Connection txn, TransportId t, int maxLatency)
throws DbException {
PreparedStatement ps = null;
@@ -651,6 +689,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void addTransportKeys(Connection txn, ContactId c, TransportKeys k)
throws DbException {
PreparedStatement ps = null;
@@ -712,24 +751,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void addVisibility(Connection txn, ContactId c, GroupId g)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "INSERT INTO groupVisibilities (contactId, groupId)"
+ " VALUES (?, ?)";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public boolean containsContact(Connection txn, AuthorId remote,
AuthorId local) throws DbException {
PreparedStatement ps = null;
@@ -753,6 +775,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean containsContact(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
@@ -774,6 +797,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean containsGroup(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
@@ -795,6 +819,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean containsLocalAuthor(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
@@ -816,6 +841,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean containsMessage(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -837,6 +863,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean containsTransport(Connection txn, TransportId t)
throws DbException {
PreparedStatement ps = null;
@@ -858,29 +885,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public boolean containsVisibleGroup(Connection txn, ContactId c, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT NULL FROM groupVisibilities"
+ " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
rs = ps.executeQuery();
boolean found = rs.next();
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return found;
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public boolean containsVisibleMessage(Connection txn, ContactId c,
MessageId m) throws DbException {
PreparedStatement ps = null;
@@ -891,7 +896,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ON m.groupId = gv.groupId"
+ " WHERE messageId = ?"
+ " AND contactId = ?"
+ " AND shared = TRUE";
+ " AND m.shared = TRUE";
ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes());
ps.setInt(2, c.getInt());
@@ -908,6 +913,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public int countOfferedMessages(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
@@ -931,6 +937,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void deleteMessage(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null;
try {
@@ -947,6 +954,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void deleteMessageMetadata(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -963,6 +971,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Contact getContact(Connection txn, ContactId c) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
@@ -992,6 +1001,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<Contact> getContacts(Connection txn)
throws DbException {
PreparedStatement ps = null;
@@ -1025,6 +1035,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<ContactId> getContacts(Connection txn, AuthorId local)
throws DbException {
PreparedStatement ps = null;
@@ -1047,6 +1058,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<Contact> getContactsByAuthorId(Connection txn,
AuthorId remote) throws DbException {
PreparedStatement ps = null;
@@ -1081,6 +1093,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Group getGroup(Connection txn, GroupId g) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
@@ -1103,6 +1116,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<Group> getGroups(Connection txn, ClientId c)
throws DbException {
PreparedStatement ps = null;
@@ -1129,6 +1143,56 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Visibility getGroupVisibility(Connection txn, ContactId c, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT shared FROM groupVisibilities"
+ " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
rs = ps.executeQuery();
Visibility v;
if (rs.next()) v = rs.getBoolean(1) ? SHARED : VISIBLE;
else v = INVISIBLE;
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return v;
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public Collection<ContactId> getGroupVisibility(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId FROM groupVisibilities"
+ " WHERE groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes());
rs = ps.executeQuery();
List<ContactId> visible = new ArrayList<ContactId>();
while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
rs.close();
ps.close();
return Collections.unmodifiableList(visible);
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public LocalAuthor getLocalAuthor(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
@@ -1158,6 +1222,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<LocalAuthor> getLocalAuthors(Connection txn)
throws DbException {
PreparedStatement ps = null;
@@ -1187,6 +1252,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessageIds(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
@@ -1231,6 +1297,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessageIds(Connection txn, GroupId g,
Metadata query) throws DbException {
// If there are no query terms, return all delivered messages
@@ -1271,6 +1338,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Map<MessageId, Metadata> getMessageMetadata(Connection txn,
GroupId g) throws DbException {
PreparedStatement ps = null;
@@ -1308,6 +1376,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Map<MessageId, Metadata> getMessageMetadata(Connection txn,
GroupId g, Metadata query) throws DbException {
// Retrieve the matching message IDs
@@ -1320,6 +1389,7 @@ abstract class JdbcDatabase implements Database<Connection> {
return Collections.unmodifiableMap(all);
}
@Override
public Metadata getGroupMetadata(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
@@ -1342,6 +1412,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Metadata getMessageMetadata(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -1367,6 +1438,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Metadata getMessageMetadataForValidator(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -1394,6 +1466,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageStatus> getMessageStatus(Connection txn,
ContactId c, GroupId g) throws DbException {
PreparedStatement ps = null;
@@ -1426,6 +1499,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public MessageStatus getMessageStatus(Connection txn,
ContactId c, MessageId m) throws DbException {
PreparedStatement ps = null;
@@ -1453,6 +1527,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Map<MessageId, State> getMessageDependencies(Connection txn,
MessageId m) throws DbException {
PreparedStatement ps = null;
@@ -1490,6 +1565,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Map<MessageId, State> getMessageDependents(Connection txn,
MessageId m) throws DbException {
PreparedStatement ps = null;
@@ -1519,6 +1595,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public State getMessageState(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -1541,6 +1618,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToAck(Connection txn, ContactId c,
int maxMessages) throws DbException {
PreparedStatement ps = null;
@@ -1565,6 +1643,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToOffer(Connection txn,
ContactId c, int maxMessages) throws DbException {
long now = clock.currentTimeMillis();
@@ -1572,10 +1651,13 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT m.messageId FROM messages AS m"
+ " JOIN groupVisibilities AS gv"
+ " ON m.groupId = gv.groupId"
+ " JOIN statuses AS s"
+ " ON m.messageId = s.messageId"
+ " WHERE contactId = ?"
+ " AND state = ? AND shared = TRUE AND raw IS NOT NULL"
+ " AND gv.contactId = s.contactId"
+ " WHERE gv.contactId = ? AND gv.shared = TRUE"
+ " AND state = ? AND m.shared = TRUE AND raw IS NOT NULL"
+ " AND seen = FALSE AND requested = FALSE"
+ " AND expiry < ?"
+ " ORDER BY timestamp LIMIT ?";
@@ -1597,6 +1679,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToRequest(Connection txn,
ContactId c, int maxMessages) throws DbException {
PreparedStatement ps = null;
@@ -1621,6 +1704,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToSend(Connection txn, ContactId c,
int maxLength) throws DbException {
long now = clock.currentTimeMillis();
@@ -1628,10 +1712,13 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT length, m.messageId FROM messages AS m"
+ " JOIN groupVisibilities AS gv"
+ " ON m.groupId = gv.groupId"
+ " JOIN statuses AS s"
+ " ON m.messageId = s.messageId"
+ " WHERE contactId = ?"
+ " AND state = ? AND shared = TRUE AND raw IS NOT NULL"
+ " AND gv.contactId = s.contactId"
+ " WHERE gv.contactId = ? AND gv.shared = TRUE"
+ " AND state = ? AND m.shared = TRUE AND raw IS NOT NULL"
+ " AND seen = FALSE"
+ " AND expiry < ?"
+ " ORDER BY timestamp";
@@ -1658,11 +1745,13 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToValidate(Connection txn,
ClientId c) throws DbException {
return getMessagesInState(txn, c, UNKNOWN);
}
@Override
public Collection<MessageId> getPendingMessages(Connection txn,
ClientId c) throws DbException {
return getMessagesInState(txn, c, PENDING);
@@ -1692,6 +1781,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getMessagesToShare(
Connection txn, ClientId c) throws DbException {
PreparedStatement ps = null;
@@ -1721,6 +1811,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
@Nullable
public byte[] getRawMessage(Connection txn, MessageId m)
throws DbException {
@@ -1744,6 +1835,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Collection<MessageId> getRequestedMessagesToSend(Connection txn,
ContactId c, int maxLength) throws DbException {
long now = clock.currentTimeMillis();
@@ -1751,10 +1843,13 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT length, m.messageId FROM messages AS m"
+ " JOIN groupVisibilities AS gv"
+ " ON m.groupId = gv.groupId"
+ " JOIN statuses AS s"
+ " ON m.messageId = s.messageId"
+ " WHERE contactId = ?"
+ " AND state = ? AND shared = TRUE AND raw IS NOT NULL"
+ " AND gv.contactId = s.contactId"
+ " WHERE gv.contactId = ? AND gv.shared = TRUE"
+ " AND state = ? AND m.shared = TRUE AND raw IS NOT NULL"
+ " AND seen = FALSE AND requested = TRUE"
+ " AND expiry < ?"
+ " ORDER BY timestamp";
@@ -1781,6 +1876,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Settings getSettings(Connection txn, String namespace)
throws DbException {
PreparedStatement ps = null;
@@ -1802,6 +1898,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public Map<ContactId, TransportKeys> getTransportKeys(Connection txn,
TransportId t) throws DbException {
PreparedStatement ps = null;
@@ -1863,28 +1960,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public Collection<ContactId> getVisibility(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId FROM groupVisibilities"
+ " WHERE groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes());
rs = ps.executeQuery();
List<ContactId> visible = new ArrayList<ContactId>();
while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
rs.close();
ps.close();
return Collections.unmodifiableList(visible);
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public void incrementStreamCounter(Connection txn, ContactId c,
TransportId t, long rotationPeriod) throws DbException {
PreparedStatement ps = null;
@@ -1904,6 +1980,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void lowerAckFlag(Connection txn, ContactId c,
Collection<MessageId> acked) throws DbException {
PreparedStatement ps = null;
@@ -1930,6 +2007,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void lowerRequestedFlag(Connection txn, ContactId c,
Collection<MessageId> requested) throws DbException {
PreparedStatement ps = null;
@@ -1956,11 +2034,13 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void mergeGroupMetadata(Connection txn, GroupId g, Metadata meta)
throws DbException {
mergeMetadata(txn, g.getBytes(), meta, "groupMetadata", "groupId");
}
@Override
public void mergeMessageMetadata(Connection txn, MessageId m, Metadata meta)
throws DbException {
mergeMetadata(txn, m.getBytes(), meta, "messageMetadata", "messageId");
@@ -2041,6 +2121,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void mergeSettings(Connection txn, Settings s, String namespace)
throws DbException {
PreparedStatement ps = null;
@@ -2087,6 +2168,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void raiseAckFlag(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -2105,6 +2187,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void raiseRequestedFlag(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -2123,6 +2206,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void raiseSeenFlag(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -2141,6 +2225,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeContact(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
@@ -2157,6 +2242,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeGroup(Connection txn, GroupId g) throws DbException {
PreparedStatement ps = null;
try {
@@ -2172,6 +2258,26 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeGroupVisibility(Connection txn, ContactId c, GroupId g)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "DELETE FROM groupVisibilities"
+ " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public void removeLocalAuthor(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
@@ -2188,6 +2294,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeMessage(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null;
try {
@@ -2203,6 +2310,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public boolean removeOfferedMessage(Connection txn, ContactId c,
MessageId m) throws DbException {
PreparedStatement ps = null;
@@ -2222,6 +2330,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeOfferedMessages(Connection txn, ContactId c,
Collection<MessageId> requested) throws DbException {
PreparedStatement ps = null;
@@ -2246,6 +2355,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeStatus(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -2264,6 +2374,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void removeTransport(Connection txn, TransportId t)
throws DbException {
PreparedStatement ps = null;
@@ -2280,24 +2391,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void removeVisibility(Connection txn, ContactId c, GroupId g)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "DELETE FROM groupVisibilities"
+ " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setBytes(2, g.getBytes());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public void resetExpiryTime(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -2316,6 +2410,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setContactVerified(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
@@ -2333,6 +2428,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setContactActive(Connection txn, ContactId c, boolean active)
throws DbException {
PreparedStatement ps = null;
@@ -2350,6 +2446,27 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setGroupVisibility(Connection txn, ContactId c, GroupId g,
boolean shared) throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE groupVisibilities SET shared = ?"
+ " WHERE contactId = ? AND groupId = ?";
ps = txn.prepareStatement(sql);
ps.setBoolean(1, shared);
ps.setInt(2, c.getInt());
ps.setBytes(3, g.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
@Override
public void setMessageShared(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null;
try {
@@ -2366,6 +2483,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setMessageState(Connection txn, MessageId m, State state)
throws DbException {
PreparedStatement ps = null;
@@ -2383,6 +2501,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setReorderingWindow(Connection txn, ContactId c, TransportId t,
long rotationPeriod, long base, byte[] bitmap) throws DbException {
PreparedStatement ps = null;
@@ -2404,6 +2523,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void updateExpiryTime(Connection txn, ContactId c, MessageId m,
int maxLatency) throws DbException {
PreparedStatement ps = null;
@@ -2437,6 +2557,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void updateTransportKeys(Connection txn,
Map<ContactId, TransportKeys> keys) throws DbException {
PreparedStatement ps = null;

View File

@@ -73,6 +73,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
@@ -116,7 +117,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
if (db.containsGroup(txn, g.getId())) return;
// Store the group and share it with the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Attach the contact ID to the group
BdfDictionary gm = new BdfDictionary();
gm.put(CONTACT, c.getId().getInt());

View File

@@ -33,6 +33,7 @@ import java.util.Map;
import javax.inject.Inject;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
@NotNullByDefault
@@ -64,7 +65,7 @@ class MessagingManagerImpl extends ConversationClientImpl
if (db.containsGroup(txn, g.getId())) return;
// Store the group and share it with the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Attach the contact ID to the group
BdfDictionary d = new BdfDictionary();
d.put("contactId", c.getId().getInt());

View File

@@ -18,6 +18,7 @@ import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.privategroup.PrivateGroupManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Group.Visibility;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
@@ -90,11 +91,10 @@ abstract class AbstractProtocolEngine<S extends Session>
return dependency.equals(expected);
}
void syncPrivateGroupWithContact(Transaction txn, S session, boolean sync)
void setPrivateGroupVisibility(Transaction txn, S session, Visibility v)
throws DbException, FormatException {
ContactId contactId = getContactId(txn, session.getContactGroupId());
db.setVisibleToContact(txn, contactId, session.getPrivateGroupId(),
sync);
db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), v);
}
Message sendInviteMessage(Transaction txn, S session,

View File

@@ -22,6 +22,8 @@ import org.briarproject.api.system.Clock;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.privategroup.invitation.CreatorState.DISSOLVED;
import static org.briarproject.privategroup.invitation.CreatorState.ERROR;
import static org.briarproject.privategroup.invitation.CreatorState.INVITED;
@@ -158,8 +160,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
private CreatorSession onLocalLeave(Transaction txn, CreatorSession s)
throws DbException {
try {
// Stop syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, false);
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -183,8 +185,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
// Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false);
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
// Broadcast an event
ContactId contactId = getContactId(txn, m.getContactGroupId());
txn.attach(new GroupInvitationResponseReceivedEvent(contactId,
@@ -224,8 +226,8 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
// The dependency, if any, must be the last remote message
if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s);
// Stop syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, false);
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
// Move to the INVITEE_LEFT state
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
@@ -236,9 +238,9 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
throws DbException, FormatException {
// If the session has already been aborted, do nothing
if (s.getState() == ERROR) return s;
// If we subscribe, stop syncing the private group with the contact
// If we subscribe, make the private group invisible to the contact
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
syncPrivateGroupWithContact(txn, s, false);
setPrivateGroupVisibility(txn, s, INVISIBLE);
// Send an ABORT message
Message sent = sendAbortMessage(txn, s);
// Move to the ERROR state

View File

@@ -45,6 +45,7 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.privategroup.invitation.CreatorState.START;
import static org.briarproject.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.privategroup.invitation.MessageType.ABORT;
@@ -110,7 +111,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
if (db.containsGroup(txn, g.getId())) return;
// Store the group and share it with the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
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());

View File

@@ -25,6 +25,8 @@ import org.briarproject.api.system.Clock;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.privategroup.invitation.InviteeState.DISSOLVED;
import static org.briarproject.privategroup.invitation.InviteeState.ERROR;
import static org.briarproject.privategroup.invitation.InviteeState.INVITED;
@@ -157,8 +159,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
try {
// Subscribe to the private group
subscribeToPrivateGroup(txn, inviteId);
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -228,8 +230,8 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s);
try {
// Stop syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, false);
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -247,9 +249,9 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
if (s.getState() == ERROR) return s;
// Mark any invite messages in the session unavailable to answer
markInvitesUnavailableToAnswer(txn, s);
// Stop syncing the private group with the contact, if we subscribe
// If we subscribe, make the private group invisible to the contact
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
syncPrivateGroupWithContact(txn, s, false);
setPrivateGroupVisibility(txn, s, INVISIBLE);
// Send an ABORT message
Message sent = sendAbortMessage(txn, s);
// Move to the ERROR state

View File

@@ -20,6 +20,8 @@ import org.briarproject.api.system.Clock;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.privategroup.invitation.PeerState.AWAIT_MEMBER;
import static org.briarproject.privategroup.invitation.PeerState.BOTH_JOINED;
import static org.briarproject.privategroup.invitation.PeerState.ERROR;
@@ -178,8 +180,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
// Send a JOIN message
Message sent = sendJoinMessage(txn, s, false);
try {
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -195,8 +197,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
// Send a LEAVE message
Message sent = sendLeaveMessage(txn, s, false);
try {
// Stop syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, false);
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -228,8 +230,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
// Send a JOIN message
Message sent = sendJoinMessage(txn, s, false);
try {
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
@@ -263,8 +265,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
return abort(txn, s);
// Send a JOIN message
Message sent = sendJoinMessage(txn, s, false);
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
// Mark the relationship visible to the group, revealed by contact
relationshipRevealed(txn, s, true);
// Move to the BOTH_JOINED state
@@ -277,8 +279,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
// The dependency, if any, must be the last remote message
if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s);
// Start syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, true);
// Share the private group with the contact
setPrivateGroupVisibility(txn, s, SHARED);
// Mark the relationship visible to the group, revealed by us
relationshipRevealed(txn, s, false);
// Move to the BOTH_JOINED state
@@ -314,8 +316,8 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
// The dependency, if any, must be the last remote message
if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s);
// Stop syncing the private group with the contact
syncPrivateGroupWithContact(txn, s, false);
// Make the private group invisible to the contact
setPrivateGroupVisibility(txn, s, INVISIBLE);
// Move to the LOCAL_JOINED state
return new PeerSession(s.getContactGroupId(), s.getPrivateGroupId(),
s.getLastLocalMessageId(), m.getId(), s.getLocalTimestamp(),
@@ -326,9 +328,9 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
throws DbException, FormatException {
// If the session has already been aborted, do nothing
if (s.getState() == ERROR) return s;
// Stop syncing the private group with the contact, if we subscribe
// If we subscribe, make the private group invisible to the contact
if (isSubscribedPrivateGroup(txn, s.getPrivateGroupId()))
syncPrivateGroupWithContact(txn, s, false);
setPrivateGroupVisibility(txn, s, INVISIBLE);
// Send an ABORT message
Message sent = sendAbortMessage(txn, s);
// Move to the ERROR state

View File

@@ -29,6 +29,8 @@ import java.util.Map.Entry;
import javax.inject.Inject;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
class TransportPropertyManagerImpl implements TransportPropertyManager,
Client, AddContactHook, RemoveContactHook {
@@ -64,7 +66,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (db.containsGroup(txn, g.getId())) return;
// Store the group and share it with the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Copy the latest local properties into the group
Map<TransportId, TransportProperties> local = getLocalProperties(txn);
for (Entry<TransportId, TransportProperties> e : local.entrySet()) {

View File

@@ -87,6 +87,8 @@ import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US;
import static org.briarproject.api.sharing.SharingConstants.TYPE;
import static org.briarproject.api.sharing.SharingMessage.BaseMessage;
import static org.briarproject.api.sharing.SharingMessage.Invitation;
import static org.briarproject.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.api.sync.Group.Visibility.SHARED;
import static org.briarproject.clients.BdfConstants.MSG_KEY_READ;
import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
@@ -159,7 +161,7 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
if (db.containsGroup(txn, g.getId())) return;
// Store the group and share it with the contact
db.addGroup(txn, g);
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Attach the contact ID to the group
BdfDictionary meta = new BdfDictionary();
meta.put(CONTACT_ID, c.getId().getInt());
@@ -908,20 +910,20 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IS
// TODO we might want to call the add() method of the respective
// manager here, because blogs add a description for example
db.addGroup(txn, f.getGroup());
db.setVisibleToContact(txn, contactId, f.getId(), true);
db.setGroupVisibility(txn, contactId, f.getId(), SHARED);
} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
addToList(txn, groupId, TO_BE_SHARED_BY_US, f);
} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_TO_BE_SHARED_BY_US) {
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
} else if (task == TASK_SHARE_SHAREABLE) {
db.setVisibleToContact(txn, contactId, f.getId(), true);
db.setGroupVisibility(txn, contactId, f.getId(), SHARED);
removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
addToList(txn, groupId, SHARED_BY_US, f);
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_BY_US) {
db.setVisibleToContact(txn, contactId, f.getId(), false);
db.setGroupVisibility(txn, contactId, f.getId(), INVISIBLE);
removeFromList(txn, groupId, SHARED_BY_US, f);
} else if (task == TASK_UNSHARE_SHAREABLE_SHARED_WITH_US) {
db.setVisibleToContact(txn, contactId, f.getId(), false);
db.setGroupVisibility(txn, contactId, f.getId(), INVISIBLE);
removeFromList(txn, groupId, SHARED_WITH_US, f);
}
}