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 9461e2c91bf96321a99b6942b7521453f9111c46..5f27522d83073625084fe43f188c2f9193219cf8 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 @@ -3,6 +3,7 @@ package org.briarproject.bramble.mailbox; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.mailbox.MailboxConstants; +import org.briarproject.bramble.api.sync.SyncSession; import org.briarproject.bramble.api.sync.SyncSessionFactory; import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.api.transport.StreamContext; @@ -28,9 +29,10 @@ import java.util.logging.Logger; 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.END; import static org.briarproject.bramble.util.LogUtils.logException; -abstract class AbstractMailboxSession implements Runnable { +abstract class AbstractMailboxSession { private static final Logger LOG = Logger.getLogger(AbstractMailboxSession.class.getName()); protected final Executor ioExecutor; @@ -45,7 +47,7 @@ abstract class AbstractMailboxSession implements Runnable { // Used to handle graceful session termination with END request private AtomicBoolean remoteSessionFinished = new AtomicBoolean(false); - protected boolean running; + protected AtomicBoolean terminated = new AtomicBoolean(false); public AbstractMailboxSession(Executor ioExecutor, KeyManager keyManager, @@ -71,8 +73,8 @@ abstract class AbstractMailboxSession implements Runnable { /** * @return True if the session is running */ - public boolean isRunning() { - return running; + public boolean isTerminated() { + return terminated.get(); } @@ -86,16 +88,13 @@ abstract class AbstractMailboxSession implements Runnable { * Note: The stream is not encrypted, since the MailboxProtocol is responsible * for encrypting/decrypting requests */ - protected void runDuplexOutgoingSession() { + protected SyncSession createDuplexOutgoingSession() { MailboxSyncRequestWriter mbWriter = new MailboxSyncRequestWriter(mailboxProtocol); - try { - syncSessionFactory - .createDuplexOutgoingSession(contactId, transportMaxLatency, - transportMaxIdleTime, mbWriter).run(); - } catch (IOException e) { - logException(LOG, WARNING, e); - } + + return syncSessionFactory + .createDuplexOutgoingSession(contactId, transportMaxLatency, + transportMaxIdleTime, mbWriter); } /** @@ -133,12 +132,17 @@ abstract class AbstractMailboxSession implements Runnable { * Must be called if the session wants to receive and handle requests */ public void readRequests() { - while (!remoteSessionFinished.get()) { + while (!terminated.get()) { try { MailboxRequest req = mailboxProtocol.getNextRequest(); + if (req.getType() == END) { + synchronized (remoteSessionFinished) { + remoteSessionFinished.set(true); + } + return; + } ioExecutor.execute(() -> handleRequest(req)); - } catch (IOException | InterruptedException e) { - // TODO: Handle interruptedException differently ? + } catch (InterruptedException e) { logException(LOG, INFO, e); return; } @@ -147,10 +151,11 @@ abstract class AbstractMailboxSession implements Runnable { /** * Calls the appropriate handler for an incoming request - * + * <p> * NOTE: If a session does not support a specific request the appropriate * handler needs to be overwritten. This handler should throw a * {@link MailboxSessionHandleException}. + * * @param req */ private void handleRequest(MailboxRequest req) { @@ -167,9 +172,6 @@ abstract class AbstractMailboxSession implements Runnable { case SYNC: handleSync((MailboxRequestSync) req); break; - case END: - handleEnd((MailboxRequestEnd) req); - break; default: throw new MailboxSessionHandleException( "Unsupported request type"); @@ -194,17 +196,6 @@ abstract class AbstractMailboxSession implements Runnable { } } - /** - * Marks the remote side of the session as finished. The session is active - * until this side of the session calls {@link #endSession()} - * @param req - */ - private void handleEnd(MailboxRequestEnd req) { - synchronized (remoteSessionFinished) { - remoteSessionFinished.set(true); - } - } - /** * Must be called once at the end of a AbstractMailboxSession to signal the end of * the session to the peer. This call blocks until the remote session @@ -215,10 +206,13 @@ abstract class AbstractMailboxSession implements Runnable { mailboxProtocol.writeRequest(new MailboxRequestEnd()); - while (!remoteSessionFinished.get()) { - remoteSessionFinished.wait(); + synchronized (remoteSessionFinished) { + while (!remoteSessionFinished.get()) { + remoteSessionFinished.wait(); + } } - running = false; + + terminated.set(true); } @@ -262,10 +256,12 @@ abstract class AbstractMailboxSession implements Runnable { keyManager.getStreamContext(MailboxConstants.ID, tag); if (ctx == null) { - throw new IOException("Received stream with unrecognisable tag"); + throw new IOException( + "Received stream with unrecognisable tag"); } - InputStream reader = streamReaderFactory.createStreamReader(in, ctx); + InputStream reader = + streamReaderFactory.createStreamReader(in, ctx); syncSessionFactory.createIncomingSession(ctx.getContactId(), reader) .run(); @@ -274,15 +270,16 @@ abstract class AbstractMailboxSession implements Runnable { } } + public void handleStore(MailboxRequestStore req) + throws MailboxSessionHandleException { + // TODO: mailbox storage for Mailbox implementation + } + + public abstract void run() throws IOException; + protected class MailboxSessionHandleException extends Exception { public MailboxSessionHandleException(String error) { super(error); } } - - public void handleStore(MailboxRequestStore req) - throws MailboxSessionHandleException{ - // TODO: mailbox storage for Mailbox implementation - } - }