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 5f27522d83073625084fe43f188c2f9193219cf8..ca7c10d7bd3292216e3bfb9812314263ec814f59 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 @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.net.ProtocolException; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; @@ -135,16 +136,20 @@ abstract class AbstractMailboxSession { while (!terminated.get()) { try { MailboxRequest req = mailboxProtocol.getNextRequest(); - if (req.getType() == END) { - synchronized (remoteSessionFinished) { - remoteSessionFinished.set(true); - } + if (req.getType() == END) return; - } ioExecutor.execute(() -> handleRequest(req)); } catch (InterruptedException e) { - logException(LOG, INFO, e); - return; + if (LOG.isLoggable(INFO)) + LOG.info(e.toString()); + } catch (ProtocolException e) { + if (LOG.isLoggable(INFO)) + LOG.info(e.toString()); + handleProtocolException(); + } finally { + synchronized (remoteSessionFinished){ + remoteSessionFinished.set(true); + } } } } @@ -277,6 +282,8 @@ abstract class AbstractMailboxSession { public abstract void run() throws IOException; + protected abstract void handleProtocolException(); + protected class MailboxSessionHandleException extends Exception { public MailboxSessionHandleException(String error) { super(error); 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 caed520d4d85298b3803d04b87290fff1cb99f54..c794731a9eddb17bb319218b99b7102917bfb5dd 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 @@ -13,15 +13,13 @@ import java.io.IOException; import java.util.concurrent.Executor; import java.util.logging.Logger; -import static java.util.logging.Level.INFO; - class MailboxOwnerSession extends AbstractMailboxSession { private static final Logger LOG = Logger.getLogger(MailboxOwnerSession.class.getName()); private final Executor ioExecutor; private final MailboxProtocol mailboxProtocol; - private SyncSession syncSession; + private SyncSession duplexOutgoingSession; public MailboxOwnerSession(ContactId contactId, Executor ioExecutor, KeyManager keyManager, @@ -42,8 +40,19 @@ class MailboxOwnerSession extends AbstractMailboxSession { @Override public void run() throws IOException { ioExecutor.execute(() -> readRequests()); - syncSession = createDuplexOutgoingSession(); - syncSession.run(); + duplexOutgoingSession = createDuplexOutgoingSession(); + duplexOutgoingSession.run(); + try { + endSession(); + } catch (InterruptedException e) { + throw new IOException("Interrupted while ending session"); + } + } + + @Override + protected void handleProtocolException() { + if (duplexOutgoingSession != null) + duplexOutgoingSession.interrupt(); } @Override 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 cef10a8b62ee6a87417878ab5009b9cc1c9936d7..9085b834b89af45e0990361f98c821173d97dc0a 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 @@ -25,6 +25,7 @@ class PrivateMailboxSession extends AbstractMailboxSession { private static final Logger LOG = Logger.getLogger(PrivateMailboxSession.class.getName()); private MailboxProtocol mailboxProtocol; + private SyncSession duplexOutgoingSession; public PrivateMailboxSession(ContactId contactId, Executor ioExecutor, KeyManager keyManager, @@ -71,7 +72,8 @@ class PrivateMailboxSession extends AbstractMailboxSession { @Override public void run() throws IOException { ioExecutor.execute(() -> super.readRequests()); - createDuplexOutgoingSession().run(); + duplexOutgoingSession = createDuplexOutgoingSession(); + duplexOutgoingSession.run(); try { endSession(); } catch (InterruptedException e) { @@ -79,6 +81,12 @@ class PrivateMailboxSession extends AbstractMailboxSession { } } + @Override + protected void handleProtocolException() { + if (duplexOutgoingSession != null) + duplexOutgoingSession.interrupt(); + } + @Override public void handleStore(MailboxRequestStore req) throws MailboxSessionHandleException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocol.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocol.java index 7df043a439d28f4ed5273c8b829b5aab4ca928d9..e5db5b2f1e94b0a479772591a59df7cbe8885945 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocol.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocol.java @@ -53,6 +53,8 @@ public class MailboxProtocol implements Runnable { public void sendKeepAlive() throws IOException { // flush the writer without pending data to send a keepalive + if (stopped.get()) + throw new ProtocolException("Mailbox protocol has stopped"); synchronized (mailboxBdfWriter) { mailboxBdfWriter.flush(); } @@ -93,8 +95,12 @@ public class MailboxProtocol implements Runnable { } public MailboxRequest getNextRequest() - throws InterruptedException { - return inQueue.take(); + throws InterruptedException, ProtocolException { + MailboxRequest req = inQueue.take(); + if (stopped.get()) + throw new ProtocolException("Protocol has stopped"); + + return req; } @Override diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocolIntegrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocolIntegrationTest.java index 7a5420289f917dc25da8d6467a5d1182e156adfb..d1e02bbbb2c846a391431f5355ee847855ac6da7 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocolIntegrationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/protocol/MailboxProtocolIntegrationTest.java @@ -13,6 +13,7 @@ import org.junit.Test; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; +import java.net.ProtocolException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionHandler; @@ -73,7 +74,7 @@ public class MailboxProtocolIntegrationTest extends BrambleTestCase { mailboxProtocol = new MailboxProtocol(ioExecutor, bdfWriter, bdfReader); } - @Test + @Test(expected = ProtocolException.class) public void testProtocolTerminationOnClosedConnection() throws IOException, InterruptedException { ioExecutor.execute(mailboxProtocol); @@ -88,12 +89,13 @@ public class MailboxProtocolIntegrationTest extends BrambleTestCase { pipedOS.close(); // And "End" request should be the next read request - MailboxRequest recvReq = mailboxProtocol.getNextRequest(); - assertEquals(END, recvReq.getType()); - - // pending request should be marked as failed - assertEquals(false, req.awaitAndGetResponse()); - assertEquals("Connection closed", req.getError()); + try { + MailboxRequest recvReq = mailboxProtocol.getNextRequest(); + }finally { + // pending request should be marked as failed + assertEquals(false, req.awaitAndGetResponse()); + assertEquals("Connection closed", req.getError()); + } }