From 369fb2e527e6ab06ae42cc9efe741832600a74a1 Mon Sep 17 00:00:00 2001 From: bontric <benjohnwie@gmail.com> Date: Thu, 6 Sep 2018 15:58:12 +0200 Subject: [PATCH] Reformat/update MailboxSession implementation --- .../bramble/mailbox/MailboxSession.java | 141 +++++++++++------- 1 file changed, 86 insertions(+), 55 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSession.java index c8c2f1bb0..8aac031fb 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSession.java @@ -9,6 +9,8 @@ import org.briarproject.bramble.api.transport.StreamContext; import org.briarproject.bramble.api.transport.StreamReaderFactory; import org.briarproject.bramble.api.transport.StreamWriter; import org.briarproject.bramble.api.transport.StreamWriterFactory; +import org.briarproject.bramble.mailbox.protocol.MailboxMessage; +import org.briarproject.bramble.mailbox.protocol.MailboxMessage.TYPE; import org.briarproject.bramble.mailbox.protocol.MailboxProtocol; import org.briarproject.bramble.mailbox.protocol.MailboxRequest; import org.briarproject.bramble.mailbox.protocol.MailboxRequestEnd; @@ -45,6 +47,7 @@ abstract class MailboxSession implements Runnable { // Used to handle graceful session termination with END request private AtomicBoolean remoteSessionFinished = new AtomicBoolean(false); + protected boolean running; public MailboxSession(Executor ioExecutor, KeyManager keyManager, @@ -67,6 +70,14 @@ abstract class MailboxSession implements Runnable { this.contactId = contactId; } + /** + * @return True if the session is running + */ + public boolean isRunning() { + return running; + } + + /** * Creates and runs a duplex session which is used for sync streams between * mailbox and owner (user) @@ -89,18 +100,6 @@ abstract class MailboxSession implements Runnable { } } - /** - * Handle an incoming sync stream intended for the mailbox/client - * - * @param syncStream (previously decrypted) sync stream - * @throws IOException - */ - protected void handleSyncStream(byte[] syncStream) - throws IOException { - InputStream is = new ByteArrayInputStream(syncStream); - syncSessionFactory.createIncomingSession(contactId, is).run(); - } - /** * Get an encrypted Sync stream which can be stored on the mailbox by * issuing a STORE request @@ -132,40 +131,6 @@ abstract class MailboxSession implements Runnable { } - /** - * Handles an encrypted stream which was stored on the mailbox and received - * with a TAKE request. - * - * @param encryptedStream - * @throws DbException - * @throws IOException - */ - protected void handleEncryptedSyncStream(byte[] encryptedStream) - throws DbException, IOException { - // read tag from input stream - InputStream in = new ByteArrayInputStream(encryptedStream); - byte[] tag = new byte[TAG_LENGTH]; - int offset = 0; - while (offset < tag.length) { - int read = in.read(tag, offset, tag.length - offset); - if (read == -1) throw new EOFException(); - offset += read; - } - - StreamContext ctx = - keyManager.getStreamContext(MailboxConstants.ID, tag); - - if (ctx == null) { - throw new IOException("Received stream with unrecognisable tag"); - } - - InputStream reader = streamReaderFactory.createStreamReader(in, ctx); - - syncSessionFactory.createIncomingSession(ctx.getContactId(), reader) - .run(); - } - - /** * Must be called if the session wants to receive and handle requests */ @@ -182,12 +147,22 @@ abstract class MailboxSession implements Runnable { } } + /** + * Calls the appropriate handler for an incoming request + * + * 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) { + String error = null; try { switch (req.getType()) { case STORE: handleStore((MailboxRequestStore) req); + break; case TAKE: handleTake((MailboxRequestTake) req); break; @@ -196,6 +171,7 @@ abstract class MailboxSession implements Runnable { break; case END: handleEnd((MailboxRequestEnd) req); + break; default: throw new MailboxSessionHandleException( "Unsupported request type"); @@ -220,6 +196,11 @@ abstract class MailboxSession 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); @@ -227,9 +208,9 @@ abstract class MailboxSession implements Runnable { } /** - * Must be called once at the end of a MailboxSession to signal the end to - * the peer. This call blocks until the remote session signals that - * the session has ended. + * Must be called once at the end of a MailboxSession to signal the end of + * the session to the peer. This call blocks until the remote session + * signals that it was ended. */ protected void endSession() throws InterruptedException, IOException { @@ -239,16 +220,61 @@ abstract class MailboxSession implements Runnable { while (!remoteSessionFinished.get()) { remoteSessionFinished.wait(); } + running = false; } - public abstract void handleSync(MailboxRequestSync req) - throws MailboxSessionHandleException; - public abstract void handleStore(MailboxRequestStore req) - throws MailboxSessionHandleException; + /** + * Handles an incoming SYNC request. The request contains an unencrypted + * BSP stream which is passed to a BSP IncomingSession + * + * @param req MailboxRequestTake + */ + public void handleSync(MailboxRequestSync req) { + try { + InputStream is = new ByteArrayInputStream(req.getSyncStream()); + syncSessionFactory.createIncomingSession(contactId, is).run(); + } catch (IOException e) { + logException(LOG, WARNING, e); + } + } - public abstract void handleTake(MailboxRequestTake req) - throws MailboxSessionHandleException; + /** + * Handles an incoming TAKE request. The request contains an encrypted BSP + * stream. From this stream, the tag is read and a StreamReader is created. + * A BSP IncomingSession is created for the stream + * + * @param req MailboxRequestTake + * @throws MailboxSessionHandleException + */ + public void handleTake(MailboxRequestTake req) + throws MailboxSessionHandleException { + InputStream in = new ByteArrayInputStream(req.getEncryptedSyncStream()); + byte[] tag = new byte[TAG_LENGTH]; + try { + // read tag from input stream + int offset = 0; + while (offset < tag.length) { + int read = in.read(tag, offset, tag.length - offset); + if (read == -1) throw new EOFException(); + offset += read; + } + + StreamContext ctx = + keyManager.getStreamContext(MailboxConstants.ID, tag); + + if (ctx == null) { + throw new IOException("Received stream with unrecognisable tag"); + } + + InputStream reader = streamReaderFactory.createStreamReader(in, ctx); + + syncSessionFactory.createIncomingSession(ctx.getContactId(), reader) + .run(); + } catch (DbException | IOException e) { + throw new MailboxSessionHandleException(e.toString()); + } + } protected class MailboxSessionHandleException extends Exception { public MailboxSessionHandleException(String error) { @@ -256,4 +282,9 @@ abstract class MailboxSession implements Runnable { } } + public void handleStore(MailboxRequestStore req) + throws MailboxSessionHandleException{ + // TODO: mailbox storage for Mailbox implementation + } + } -- GitLab