From 65ef48938a458221325a1481f15459b0ed9d8044 Mon Sep 17 00:00:00 2001
From: bontric <benjohnwie@gmail.com>
Date: Mon, 24 Sep 2018 18:27:11 +0200
Subject: [PATCH] Add check to AbstractMailboxSession#getSyncStreamsToStore to
 ensure that no empty streams are sent to the mailbox and update session
 Constructors

---
 .../mailbox/AbstractMailboxSession.java       | 38 ++++++++++---
 .../mailbox/ContactMailboxSession.java        | 53 +++++++++----------
 .../mailbox/MailboxContactSession.java        |  5 +-
 .../bramble/mailbox/MailboxOwnerSession.java  |  4 ++
 .../mailbox/MailboxSessionFactoryImpl.java    | 14 +++--
 .../mailbox/PrivateMailboxSession.java        | 10 ++--
 6 files changed, 76 insertions(+), 48 deletions(-)

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/AbstractMailboxSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/AbstractMailboxSession.java
index b1adf5248..013fd0e17 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/AbstractMailboxSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/AbstractMailboxSession.java
@@ -1,7 +1,9 @@
 package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.mailbox.MailboxConstants;
 import org.briarproject.bramble.api.sync.SyncSession;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
@@ -38,6 +40,7 @@ public abstract class AbstractMailboxSession implements Runnable {
 			Logger.getLogger(AbstractMailboxSession.class.getName());
 	private final Executor ioExecutor;
 	private final ContactId contactId;
+	private DatabaseComponent db;
 	private KeyManager keyManager;
 	private SyncSessionFactory syncSessionFactory;
 	private final StreamWriterFactory streamWriterFactory;
@@ -54,6 +57,7 @@ public abstract class AbstractMailboxSession implements Runnable {
 
 
 	public AbstractMailboxSession(Executor ioExecutor,
+			DatabaseComponent db,
 			KeyManager keyManager,
 			SyncSessionFactory syncSessionFactory,
 			StreamWriterFactory streamWriterFactory,
@@ -64,6 +68,7 @@ public abstract class AbstractMailboxSession implements Runnable {
 			ContactId contactId) {
 
 		this.ioExecutor = ioExecutor;
+		this.db = db;
 		this.keyManager = keyManager;
 		this.syncSessionFactory = syncSessionFactory;
 		this.streamWriterFactory = streamWriterFactory;
@@ -221,14 +226,30 @@ public abstract class AbstractMailboxSession implements Runnable {
 	 * Get an encrypted Sync stream which can be stored on the mailbox by
 	 * issuing a STORE request
 	 *
-	 * @param targetContactId The encrypted sync stream is generated for the given
+	 * @param c The encrypted sync stream is generated for the given
 	 * contactId
-	 * @return Encrypted Sync stream
+	 * @return Encrypted Sync stream or Null if no data is available to send
 	 * @throws DbException
 	 * @throws IOException
 	 */
-	protected byte[] getSyncStreamToStore(ContactId targetContactId)
+	@Nullable
+	protected byte[] getSyncStreamToStore(ContactId c)
 			throws DbException, IOException {
+		Transaction txn = null;
+		boolean hasMessages;
+
+		try {
+			txn  = db.startTransaction(true);
+			hasMessages = db.hasMessagesOrAcksToSend(txn, c);
+			db.commitTransaction(txn);
+		} finally {
+			if (txn != null)
+				db.endTransaction(txn);
+		}
+
+		if (!hasMessages)
+			return null;
+
 		StreamContext ctx =
 				keyManager
 						.getStreamContext(targetContactId, MailboxConstants.ID);
@@ -241,12 +262,15 @@ public abstract class AbstractMailboxSession implements Runnable {
 		StreamWriter streamWriter = streamWriterFactory
 				.createStreamWriter(os, ctx);
 
-		syncSessionFactory.createSimplexOutgoingSession(targetContactId,
-				MailboxConstants.MAX_LATENCY, streamWriter);
+		syncSessionFactory.createSimplexOutgoingSession(c,
+				MailboxConstants.MAX_LATENCY, streamWriter).run();
+		byte [] buf = os.toByteArray();
 
-		return os.toByteArray();
-	}
+		if (buf.length <= 0)
+			return null;
 
+		return buf;
+	}
 
 	/**
 	 * Reads a Tag from the given InputStream and returns the matching StreamContext
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ContactMailboxSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ContactMailboxSession.java
index 60785ad44..78b5da37e 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ContactMailboxSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ContactMailboxSession.java
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.api.transport.KeyManager;
@@ -33,7 +34,6 @@ import static org.briarproject.bramble.util.LogUtils.logException;
 public class ContactMailboxSession extends AbstractMailboxSession {
 	private static final Logger LOG =
 			Logger.getLogger(ContactMailboxSession.class.getName());
-	private final KeyManager keyManager;
 	private final SyncSessionFactory syncSessionFactory;
 	private final StreamReaderFactory streamReaderFactory;
 	private final MailboxProtocol mailboxProtocol;
@@ -45,11 +45,12 @@ public class ContactMailboxSession extends AbstractMailboxSession {
 			StreamWriterFactory streamWriterFactory,
 			StreamReaderFactory streamReaderFactory,
 			MailboxProtocol mailboxProtocol,
-			int transportMaxLatency, int transportMaxIdleTime) {
-		super(ioExecutor, keyManager, syncSessionFactory, streamWriterFactory,
+			int transportMaxLatency, int transportMaxIdleTime,
+			DatabaseComponent db) {
+		super(ioExecutor, db, keyManager, syncSessionFactory,
+				streamWriterFactory,
 				streamReaderFactory, mailboxProtocol, transportMaxLatency,
 				transportMaxIdleTime, contactId);
-		this.keyManager = keyManager;
 		this.syncSessionFactory = syncSessionFactory;
 		this.streamReaderFactory = streamReaderFactory;
 		this.mailboxProtocol = mailboxProtocol;
@@ -62,13 +63,29 @@ public class ContactMailboxSession extends AbstractMailboxSession {
 	@Override
 	public void run() {
 		// Get messages to send and formulate a STORE request
+		byte[] encryptedStream;
 		try {
-			sendStreamsToStore();
-		} catch (IOException e) {
-			if (LOG.isLoggable(WARNING))
-				LOG.warning(e.toString());
-		} catch (DbException | InterruptedException e) {
+			// Get sync stream if available
+			 encryptedStream = getSyncStreamToStore(contactId);
+		} catch (IOException | DbException e) {
 			logException(LOG, WARNING, e);
+			return;
+		}
+
+		if (encryptedStream == null)
+				return;
+
+		// Send a STORE request and wait for a response
+		MailboxRequestStore req = new MailboxRequestStore(encryptedStream);
+		try {
+			mailboxProtocol.writeRequest(req);
+			if (!req.awaitAndGetResponse())
+				throw new ProtocolException(req.getError());
+		} catch (InterruptedException  | IOException e) {
+			// TODO: Handle STORE request error!
+			if (LOG.isLoggable(WARNING))
+				LOG.info(e.toString());
+			return;
 		}
 
 		// End the session by issuing and END request and wait for peer
@@ -81,24 +98,6 @@ public class ContactMailboxSession extends AbstractMailboxSession {
 		}
 	}
 
-	void sendStreamsToStore()
-			throws IOException, DbException, InterruptedException {
-
-		// Get sync stream if available
-		byte[] encryptedStream = getSyncStreamToStore(contactId);
-
-		while (encryptedStream != null || encryptedStream.length > 0) {
-			// Send a STORE request and wait for a response
-			MailboxRequestStore req = new MailboxRequestStore(encryptedStream);
-			mailboxProtocol.writeRequest(req);
-			if (!req.awaitAndGetResponse())
-				// TODO: Handle STORE request error!
-				throw new ProtocolException(req.getError());
-
-			// Get next sync stream if available
-			encryptedStream = getSyncStreamToStore(contactId);
-		}
-	}
 
 	/**
 	 * Handles an incoming TAKE request. The request contains an encrypted BSP
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxContactSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxContactSession.java
index 447496fa4..4d8d3a358 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxContactSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxContactSession.java
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.api.transport.KeyManager;
 import org.briarproject.bramble.api.transport.StreamReaderFactory;
@@ -39,8 +40,8 @@ public class MailboxContactSession extends AbstractMailboxSession {
 			StreamWriterFactory streamWriterFactory,
 			StreamReaderFactory streamReaderFactory,
 			MailboxProtocol mailboxProtocol, int transportMaxLatency,
-			int transportMaxIdleTime, MailboxStorage mailboxStorage) {
-		super(ioExecutor, keyManager, syncSessionFactory, streamWriterFactory,
+			int transportMaxIdleTime, MailboxStorage mailboxStorage, DatabaseComponent db) {
+		super(ioExecutor, db, keyManager, syncSessionFactory, streamWriterFactory,
 				streamReaderFactory, mailboxProtocol, transportMaxLatency,
 				transportMaxIdleTime, contactId);
 		this.mailboxProtocol = mailboxProtocol;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxOwnerSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxOwnerSession.java
index 8101f4c0c..257eb884d 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxOwnerSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxOwnerSession.java
@@ -1,6 +1,8 @@
 package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.mailbox.MailboxConstants;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.api.transport.KeyManager;
 import org.briarproject.bramble.api.transport.StreamReaderFactory;
@@ -10,7 +12,9 @@ import org.briarproject.bramble.mailbox.protocol.MailboxProtocol;
 import org.briarproject.bramble.mailbox.protocol.MailboxRequest;
 import org.briarproject.bramble.mailbox.protocol.MailboxRequestHandler;
 import org.briarproject.bramble.mailbox.protocol.MailboxRequestStore;
+import org.briarproject.bramble.mailbox.protocol.MailboxRequestTake;
 
+import java.io.IOException;
 import java.net.ProtocolException;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSessionFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSessionFactoryImpl.java
index b5a93bff5..65e39e385 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSessionFactoryImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSessionFactoryImpl.java
@@ -2,6 +2,7 @@ package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactType;
+import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.lifecycle.IoExecutor;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.api.transport.KeyManager;
@@ -21,17 +22,20 @@ public class MailboxSessionFactoryImpl implements MailboxSessionFactory {
 	private final SyncSessionFactory syncSessionFactory;
 	private final StreamWriterFactory streamWriterFactory;
 	private final StreamReaderFactory streamReaderFactory;
+	private DatabaseComponent db;
+
 	@Inject
 	public MailboxSessionFactoryImpl(@IoExecutor Executor ioExecutor,
 			KeyManager keyManager,
 			SyncSessionFactory syncSessionFactory,
 			StreamWriterFactory streamWriterFactory,
-			StreamReaderFactory streamReaderFactory) {
+			StreamReaderFactory streamReaderFactory, DatabaseComponent db) {
 		this.ioExecutor = ioExecutor;
 		this.keyManager = keyManager;
 		this.syncSessionFactory = syncSessionFactory;
 		this.streamWriterFactory = streamWriterFactory;
 		this.streamReaderFactory = streamReaderFactory;
+		this.db = db;
 
 		// FIXME: using temporary storage for now
 		this.mailboxStorage = new MailboxStorage();
@@ -51,22 +55,22 @@ public class MailboxSessionFactoryImpl implements MailboxSessionFactory {
 				return new PrivateMailboxSession(contactId, ioExecutor,
 						keyManager, syncSessionFactory, streamWriterFactory,
 						streamReaderFactory, mailboxProtocol,
-						transportMaxLatency, transportMaxIdleTime);
+						transportMaxLatency, transportMaxIdleTime, db);
 			case CONTACT_MAILBOX:
 				return new ContactMailboxSession(contactId, ioExecutor,
 						keyManager, syncSessionFactory, streamWriterFactory,
 						streamReaderFactory, mailboxProtocol,
-						transportMaxLatency, transportMaxIdleTime);
+						transportMaxLatency, transportMaxIdleTime, db);
 			case MAILBOX_OWNER:
 				return new MailboxOwnerSession(contactId, ioExecutor,
 						keyManager, syncSessionFactory, streamWriterFactory,
 						streamReaderFactory, mailboxProtocol,
-						transportMaxLatency, transportMaxIdleTime, mailboxStorage);
+						transportMaxLatency, transportMaxIdleTime, mailboxStorage, db);
 			case MAILBOX_CONTACT:
 				return new MailboxContactSession(contactId, ioExecutor,
 						keyManager, syncSessionFactory, streamWriterFactory,
 						streamReaderFactory, mailboxProtocol,
-						transportMaxLatency, transportMaxIdleTime, mailboxStorage);
+						transportMaxLatency, transportMaxIdleTime, mailboxStorage, db);
 		}
 		return null;
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/PrivateMailboxSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/PrivateMailboxSession.java
index 933a686ff..0ef05af61 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/PrivateMailboxSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/PrivateMailboxSession.java
@@ -1,9 +1,8 @@
 package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.mailbox.MailboxConstants;
-import org.briarproject.bramble.api.mailbox.MailboxInfo;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.api.transport.KeyManager;
 import org.briarproject.bramble.api.transport.StreamContext;
@@ -17,17 +16,14 @@ import org.briarproject.bramble.mailbox.protocol.MailboxRequestStore;
 import org.briarproject.bramble.mailbox.protocol.MailboxRequestTake;
 
 import java.io.ByteArrayInputStream;
-import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.ProtocolException;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
-import java.util.stream.Stream;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.briarproject.bramble.mailbox.protocol.MailboxMessage.TYPE.TAKE;
 import static org.briarproject.bramble.util.LogUtils.logException;
 
@@ -49,9 +45,9 @@ public class PrivateMailboxSession extends AbstractMailboxSession {
 			StreamWriterFactory streamWriterFactory,
 			StreamReaderFactory streamReaderFactory,
 			MailboxProtocol mailboxProtocol, int transportMaxLatency,
-			int transportMaxIdleTime) {
+			int transportMaxIdleTime, DatabaseComponent db) {
 
-		super(ioExecutor, keyManager, syncSessionFactory, streamWriterFactory,
+		super(ioExecutor, db, keyManager, syncSessionFactory, streamWriterFactory,
 				streamReaderFactory, mailboxProtocol, transportMaxLatency,
 				transportMaxIdleTime, contactId);
 		this.keyManager = keyManager;
-- 
GitLab