mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 03:39:05 +01:00
Merge branch '2352-do-not-create-files-for-upload-while-connected' into 'master'
Don't create files for upload while directly connected to contact Closes #2352 See merge request briar/briar!1697
This commit is contained in:
@@ -320,6 +320,13 @@ interface Database<T> {
|
||||
*/
|
||||
Group getGroup(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the ID of the group containing the given message.
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
GroupId getGroupId(T txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the metadata for the given group.
|
||||
* <p/>
|
||||
@@ -345,8 +352,11 @@ interface Database<T> {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of all contacts to which the given group's visibility is
|
||||
* either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||
* Returns the IDs of all contacts for which the given group's visibility
|
||||
* is either {@link Visibility#SHARED shared} or
|
||||
* {@link Visibility#VISIBLE visible}. The value in the map is true if the
|
||||
* group is {@link Visibility#SHARED shared} or false if the group is
|
||||
* {@link Visibility#VISIBLE visible}.
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
|
||||
@@ -287,7 +287,12 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
transaction.attach(new MessageAddedEvent(m, null));
|
||||
transaction.attach(new MessageStateChangedEvent(m.getId(), true,
|
||||
DELIVERED));
|
||||
if (shared) transaction.attach(new MessageSharedEvent(m.getId()));
|
||||
if (shared) {
|
||||
Map<ContactId, Boolean> visibility =
|
||||
db.getGroupVisibility(txn, m.getGroupId());
|
||||
transaction.attach(new MessageSharedEvent(m.getId(),
|
||||
m.getGroupId(), visibility));
|
||||
}
|
||||
}
|
||||
db.mergeMessageMetadata(txn, m.getId(), meta);
|
||||
}
|
||||
@@ -550,6 +555,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
return db.getGroup(txn, g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupId getGroupId(Transaction transaction, MessageId m)
|
||||
throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, m))
|
||||
throw new NoSuchMessageException();
|
||||
return db.getGroupId(txn, m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata getGroupMetadata(Transaction transaction, GroupId g)
|
||||
throws DbException {
|
||||
@@ -1182,7 +1196,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
if (db.getMessageState(txn, m) != DELIVERED)
|
||||
throw new IllegalArgumentException("Shared undelivered message");
|
||||
db.setMessageShared(txn, m, true);
|
||||
transaction.attach(new MessageSharedEvent(m));
|
||||
GroupId g = db.getGroupId(txn, m);
|
||||
Map<ContactId, Boolean> visibility = db.getGroupVisibility(txn, g);
|
||||
transaction.attach(new MessageSharedEvent(m, g, visibility));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1683,6 +1683,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupId getGroupId(Connection txn, MessageId m) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT groupId FROM messages WHERE messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
if (!rs.next()) throw new DbStateException();
|
||||
GroupId g = new GroupId(rs.getBytes(1));
|
||||
rs.close();
|
||||
ps.close();
|
||||
return g;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Group> getGroups(Connection txn, ClientId c,
|
||||
int majorVersion) throws DbException {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.Cancellable;
|
||||
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -12,6 +13,8 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
|
||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
|
||||
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.OutgoingSessionRecord;
|
||||
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
|
||||
@@ -32,6 +35,7 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.logging.Level.INFO;
|
||||
@@ -58,9 +62,16 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
* <p>
|
||||
* If there's no data to send, the worker listens for events indicating
|
||||
* that new data may be ready to send.
|
||||
* <p>
|
||||
* Whenever we're directly connected to the contact, the worker doesn't
|
||||
* check for data to send or start connectivity checks until the contact
|
||||
* disconnects. However, if the worker has already started writing and
|
||||
* uploading a file when the contact connects, the worker will finish the
|
||||
* upload.
|
||||
*/
|
||||
private enum State {
|
||||
CREATED,
|
||||
CONNECTED_TO_CONTACT,
|
||||
CHECKING_FOR_DATA,
|
||||
WAITING_FOR_DATA,
|
||||
CONNECTIVITY_CHECK,
|
||||
@@ -95,6 +106,7 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
private final Clock clock;
|
||||
private final TaskScheduler taskScheduler;
|
||||
private final EventBus eventBus;
|
||||
private final ConnectionRegistry connectionRegistry;
|
||||
private final ConnectivityChecker connectivityChecker;
|
||||
private final MailboxApiCaller mailboxApiCaller;
|
||||
private final MailboxApi mailboxApi;
|
||||
@@ -121,6 +133,7 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
Clock clock,
|
||||
TaskScheduler taskScheduler,
|
||||
EventBus eventBus,
|
||||
ConnectionRegistry connectionRegistry,
|
||||
ConnectivityChecker connectivityChecker,
|
||||
MailboxApiCaller mailboxApiCaller,
|
||||
MailboxApi mailboxApi,
|
||||
@@ -133,6 +146,7 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
this.clock = clock;
|
||||
this.taskScheduler = taskScheduler;
|
||||
this.eventBus = eventBus;
|
||||
this.connectionRegistry = connectionRegistry;
|
||||
this.connectivityChecker = connectivityChecker;
|
||||
this.mailboxApiCaller = mailboxApiCaller;
|
||||
this.mailboxApi = mailboxApi;
|
||||
@@ -182,6 +196,12 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
synchronized (lock) {
|
||||
checkTask = null;
|
||||
if (state != State.CHECKING_FOR_DATA) return;
|
||||
// Check whether we're directly connected to the contact. Calling
|
||||
// this while holding the lock isn't ideal, but it avoids races
|
||||
if (connectionRegistry.isConnected(contactId)) {
|
||||
state = State.CONNECTED_TO_CONTACT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info("Checking for data to send");
|
||||
try {
|
||||
@@ -364,8 +384,14 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
onDataToSend();
|
||||
}
|
||||
} else if (e instanceof MessageSharedEvent) {
|
||||
LOG.info("Message shared");
|
||||
onDataToSend();
|
||||
MessageSharedEvent m = (MessageSharedEvent) e;
|
||||
// If the contact is present in the map (ie the value is not null)
|
||||
// and the value is true, the message's group is shared with the
|
||||
// contact and therefore the message may now be sendable
|
||||
if (m.getGroupVisibility().get(contactId) == TRUE) {
|
||||
LOG.info("Message shared");
|
||||
onDataToSend();
|
||||
}
|
||||
} else if (e instanceof GroupVisibilityUpdatedEvent) {
|
||||
GroupVisibilityUpdatedEvent g = (GroupVisibilityUpdatedEvent) e;
|
||||
if (g.getVisibility() == SHARED &&
|
||||
@@ -373,6 +399,18 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
LOG.info("Group shared");
|
||||
onDataToSend();
|
||||
}
|
||||
} else if (e instanceof ContactConnectedEvent) {
|
||||
ContactConnectedEvent c = (ContactConnectedEvent) e;
|
||||
if (c.getContactId().equals(contactId)) {
|
||||
LOG.info("Contact connected");
|
||||
onContactConnected();
|
||||
}
|
||||
} else if (e instanceof ContactDisconnectedEvent) {
|
||||
ContactDisconnectedEvent c = (ContactDisconnectedEvent) e;
|
||||
if (c.getContactId().equals(contactId)) {
|
||||
LOG.info("Contact disconnected");
|
||||
onContactDisconnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,4 +429,36 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
|
||||
// If we had scheduled a wakeup when data was due to be sent, cancel it
|
||||
if (wakeupTask != null) wakeupTask.cancel();
|
||||
}
|
||||
|
||||
@EventExecutor
|
||||
private void onContactConnected() {
|
||||
Cancellable wakeupTask = null, checkTask = null;
|
||||
synchronized (lock) {
|
||||
if (state == State.DESTROYED) return;
|
||||
// If we're checking for data to send, waiting for data to send,
|
||||
// or checking connectivity then wait until we disconnect from
|
||||
// the contact before proceeding. If we're writing or uploading
|
||||
// a file then continue
|
||||
if (state == State.CHECKING_FOR_DATA ||
|
||||
state == State.WAITING_FOR_DATA ||
|
||||
state == State.CONNECTIVITY_CHECK) {
|
||||
state = State.CONNECTED_TO_CONTACT;
|
||||
wakeupTask = this.wakeupTask;
|
||||
this.wakeupTask = null;
|
||||
checkTask = this.checkTask;
|
||||
this.checkTask = null;
|
||||
}
|
||||
}
|
||||
if (wakeupTask != null) wakeupTask.cancel();
|
||||
if (checkTask != null) checkTask.cancel();
|
||||
}
|
||||
|
||||
@EventExecutor
|
||||
private void onContactDisconnected() {
|
||||
synchronized (lock) {
|
||||
if (state != State.CONNECTED_TO_CONTACT) return;
|
||||
state = State.CHECKING_FOR_DATA;
|
||||
}
|
||||
ioExecutor.execute(this::checkForDataToSend);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.mailbox;
|
||||
|
||||
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
@@ -25,6 +26,7 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
|
||||
private final Clock clock;
|
||||
private final TaskScheduler taskScheduler;
|
||||
private final EventBus eventBus;
|
||||
private final ConnectionRegistry connectionRegistry;
|
||||
private final MailboxApiCaller mailboxApiCaller;
|
||||
private final MailboxApi mailboxApi;
|
||||
private final MailboxFileManager mailboxFileManager;
|
||||
@@ -36,6 +38,7 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
|
||||
Clock clock,
|
||||
TaskScheduler taskScheduler,
|
||||
EventBus eventBus,
|
||||
ConnectionRegistry connectionRegistry,
|
||||
MailboxApiCaller mailboxApiCaller,
|
||||
MailboxApi mailboxApi,
|
||||
MailboxFileManager mailboxFileManager,
|
||||
@@ -45,6 +48,7 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
|
||||
this.clock = clock;
|
||||
this.taskScheduler = taskScheduler;
|
||||
this.eventBus = eventBus;
|
||||
this.connectionRegistry = connectionRegistry;
|
||||
this.mailboxApiCaller = mailboxApiCaller;
|
||||
this.mailboxApi = mailboxApi;
|
||||
this.mailboxFileManager = mailboxFileManager;
|
||||
@@ -57,9 +61,9 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
|
||||
MailboxProperties properties, MailboxFolderId folderId,
|
||||
ContactId contactId) {
|
||||
MailboxUploadWorker worker = new MailboxUploadWorker(ioExecutor, db,
|
||||
clock, taskScheduler, eventBus, connectivityChecker,
|
||||
mailboxApiCaller, mailboxApi, mailboxFileManager,
|
||||
properties, folderId, contactId);
|
||||
clock, taskScheduler, eventBus, connectionRegistry,
|
||||
connectivityChecker, mailboxApiCaller, mailboxApi,
|
||||
mailboxFileManager, properties, folderId, contactId);
|
||||
eventBus.addListener(worker);
|
||||
return worker;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
@@ -233,7 +234,13 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
ContactRemovedEvent c = (ContactRemovedEvent) e;
|
||||
if (c.getContactId().equals(contactId)) interrupt();
|
||||
} else if (e instanceof MessageSharedEvent) {
|
||||
generateOffer();
|
||||
MessageSharedEvent m = (MessageSharedEvent) e;
|
||||
// If the contact is present in the map (ie the value is not null)
|
||||
// and the value is true, the message's group is shared with the
|
||||
// contact and therefore the message may now be sendable
|
||||
if (m.getGroupVisibility().get(contactId) == TRUE) {
|
||||
generateOffer();
|
||||
}
|
||||
} else if (e instanceof GroupVisibilityUpdatedEvent) {
|
||||
GroupVisibilityUpdatedEvent g = (GroupVisibilityUpdatedEvent) e;
|
||||
if (g.getVisibility() == SHARED &&
|
||||
|
||||
Reference in New Issue
Block a user