You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by jo...@apache.org on 2021/09/14 17:58:00 UTC

[mina] branch 2.2.X updated (3726e4a -> 6675179)

This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a change to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git.


    from 3726e4a  Fix DIRMINA-1035
     add 498588d  formatted mina.filter.ssl
     add e60463a  adds IoSession#isServer()
     add f75a710  Adds unique identifier to toString() result
     add d9b3528  Adds initial ssl2
     add 95e59dd  Fixes possible incorrect assertion of handshaking during write
     add b817f02  Fixes bug in TailFilter which triggers the connect future on created instead of opened.
     add 81272b9  Fix for ssl2 request backlog
     add d64c8c7  Adds SSL2 flow control
     add f711c2a  Adds support for IoEvent.SECURED and IoSession#isSecured()
     add 2bd87b6  Improves loop encode/decode functions
     add 040b77c  certs cleanup
     add 89dc050  simplifies #isSecured() checking; adds null checks
     add 94a43f8  Adds hard ceiling for the number of queued cleartext messages in SSL2Handler
     add 2f59eed  Adds filter extend handler for engine creation allowing users to implement components like DIRMINA-1122 by themselves without having to patch the project.  Simply override onEngineCreated()
     add 4aa4729  Adds missing null check for enabled ciphersuites/protocols
     add d53d1f8  ensures that receive() is not executed in recursion in order to prevent corruption of the decode buffer.  qreceive() may be executed in recursion because it does not modify the decode buffer.
     add 5fe18b2  ensures that qreceive() loops when possible
     add 8d076dc  Fixes Issue with SSLEngine emit FINISHED twice in conjunction with needing to loop the receive buffer to consume more data. Prevents accidently freeing of the ZERO buffer. Enables receive() recursion from within a receive -> write -> finish -> receive loop.
     add 86119e3  improves engine customization
     add 4c11155  SSL improvements
     new 6564261  Merge branch 'bugfix/DIRMINA1132' into 2.2.X
     new 93a1428  Corrects HTTP decode for pipeline requests
     new 8b61c5b  Updates SSL & unit tests for the main SSL package changes
     new a7ceb08  Fix size == 0 check; removes unused tests
     new 6675179  applies null check

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/mina/core/buffer/AbstractIoBuffer.java  |   2 +
 .../core/filterchain/DefaultIoFilterChain.java     |  34 +-
 .../mina/core/session/AbstractIoSession.java       |   8 +-
 .../org/apache/mina/core/session/IoSession.java    |   5 +
 .../mina/core/write/WriteRejectedException.java    |  44 +
 .../mina/filter/codec/textline/LineDelimiter.java  |   2 +-
 .../mina/filter/ssl/BogusTrustManagerFactory.java  | 113 +--
 ...e-info.java => DisableEncryptWriteRequest.java} |  11 +-
 .../{SslEvent.java => EncryptedWriteRequest.java}  |  30 +-
 .../apache/mina/filter/ssl/KeyStoreFactory.java    | 292 +++----
 .../apache/mina/filter/ssl/SSLContextFactory.java  | 443 ++++++++++
 .../filter/ssl/{SslEvent.java => SSLEvent.java}    |   8 +-
 .../java/org/apache/mina/filter/ssl/SSLFilter.java | 320 ++++++++
 .../org/apache/mina/filter/ssl/SSLHandler.java     | 284 +++++++
 .../org/apache/mina/filter/ssl/SSLHandlerG0.java   | 606 ++++++++++++++
 .../apache/mina/filter/ssl/SslContextFactory.java  | 437 ----------
 .../java/org/apache/mina/filter/ssl/SslFilter.java | 909 ---------------------
 .../org/apache/mina/filter/ssl/SslHandler.java     | 871 --------------------
 .../org/apache/mina/filter/ssl/package-info.java   |   3 +-
 .../proxy/handlers/socks/Socks4LogicHandler.java   |   5 +-
 .../transport/socket/nio/NioSocketSession.java     | 614 +++++++-------
 ...dentityHashSet.java => BasicThreadFactory.java} |  68 +-
 .../java/org/apache/mina/util/StackInspector.java  |  78 ++
 .../SslTestHandshakeExceptionDIRMINA1077Test.java  |  35 +-
 .../org/apache/mina/filter/ssl/SSLFilterMain.java  | 126 +++
 .../apache/mina/filter/ssl/SslDIRMINA937Test.java  | 168 ----
 .../org/apache/mina/filter/ssl/SslEngineTest.java  | 486 -----------
 .../org/apache/mina/filter/ssl/SslFilterTest.java  | 142 ----
 .../java/org/apache/mina/filter/ssl/SslTest.java   | 266 ------
 .../apache/mina/filter/ssl/emptykeystore.sslTest   | Bin 32 -> 0 bytes
 .../filter/ssl/{keystore.sslTest => keystore.jks}  | Bin
 .../ssl/{truststore.sslTest => truststore.jks}     | Bin
 .../java/org/apache/mina/example/chat/Main.java    |   4 +-
 .../example/chat/client/ChatClientSupport.java     |   5 +-
 .../org/apache/mina/example/echoserver/Main.java   |   4 +-
 .../apache/mina/example/tcp/perf/TcpSslClient.java |   5 +-
 .../apache/mina/example/tcp/perf/TcpSslServer.java |   4 +-
 .../mina/example/echoserver/AbstractTest.java      |   9 +-
 .../mina/example/echoserver/ConnectorTest.java     |  13 +-
 .../mina/example/echoserver/ssl/SslFilterTest.java |   6 +-
 .../org/apache/mina/http/HttpServerDecoder.java    |   2 +-
 41 files changed, 2546 insertions(+), 3916 deletions(-)
 create mode 100644 mina-core/src/main/java/org/apache/mina/core/write/WriteRejectedException.java
 copy mina-core/src/main/java/org/apache/mina/filter/ssl/{package-info.java => DisableEncryptWriteRequest.java} (81%)
 copy mina-core/src/main/java/org/apache/mina/filter/ssl/{SslEvent.java => EncryptedWriteRequest.java} (51%)
 create mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SSLContextFactory.java
 rename mina-core/src/main/java/org/apache/mina/filter/ssl/{SslEvent.java => SSLEvent.java} (91%)
 create mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SSLFilter.java
 create mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandler.java
 create mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
 delete mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SslContextFactory.java
 delete mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SslFilter.java
 delete mode 100644 mina-core/src/main/java/org/apache/mina/filter/ssl/SslHandler.java
 copy mina-core/src/main/java/org/apache/mina/util/{IdentityHashSet.java => BasicThreadFactory.java} (50%)
 create mode 100644 mina-core/src/main/java/org/apache/mina/util/StackInspector.java
 create mode 100644 mina-core/src/test/java/org/apache/mina/filter/ssl/SSLFilterMain.java
 delete mode 100644 mina-core/src/test/java/org/apache/mina/filter/ssl/SslDIRMINA937Test.java
 delete mode 100644 mina-core/src/test/java/org/apache/mina/filter/ssl/SslEngineTest.java
 delete mode 100644 mina-core/src/test/java/org/apache/mina/filter/ssl/SslFilterTest.java
 delete mode 100644 mina-core/src/test/java/org/apache/mina/filter/ssl/SslTest.java
 delete mode 100644 mina-core/src/test/resources/org/apache/mina/filter/ssl/emptykeystore.sslTest
 rename mina-core/src/test/resources/org/apache/mina/filter/ssl/{keystore.sslTest => keystore.jks} (100%)
 rename mina-core/src/test/resources/org/apache/mina/filter/ssl/{truststore.sslTest => truststore.jks} (100%)

[mina] 04/05: Fix size == 0 check; removes unused tests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a commit to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit a7ceb0817ce1c2b1f12cfdb30ecfc37e130be180
Author: Jonathan Valliere <jo...@apache.org>
AuthorDate: Thu Sep 9 14:01:35 2021 -0400

    Fix size == 0 check; removes unused tests
---
 .../org/apache/mina/filter/ssl/SSLHandlerG0.java   |   6 +-
 .../apache/mina/filter/ssl/SSLDIRMINA937Test.java  | 167 --------
 .../org/apache/mina/filter/ssl/SSLEngineTest.java  | 465 ---------------------
 .../apache/mina/filter/ssl/emptykeystore.sslTest   | Bin 32 -> 0 bytes
 .../apache/mina/filter/{ssl2 => ssl}/keystore.jks  | Bin
 .../org/apache/mina/filter/ssl/keystore.sslTest    | Bin 1368 -> 0 bytes
 .../mina/filter/{ssl2 => ssl}/truststore.jks       | Bin
 .../org/apache/mina/filter/ssl/truststore.sslTest  | Bin 654 -> 0 bytes
 8 files changed, 3 insertions(+), 635 deletions(-)

diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
index de99b7f..4cf3e17 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
@@ -257,7 +257,7 @@ public class SSLHandlerG0 extends SSLHandler {
 		}
 
 		if (this.mEncodeQueue.isEmpty()) {
-			if (qwrite(next, request) == false) {
+			if (this.qwrite(next, request) == false) {
 				if (LOGGER.isDebugEnabled()) {
 					LOGGER.debug("{} write() - unable to write right now, saving request for later", toString(),
 							request);
@@ -511,7 +511,7 @@ public class SSLHandlerG0 extends SSLHandler {
 			return;
 		}
 
-		if (this.mEncodeQueue.size() != 0) {
+		if (this.mEncodeQueue.size() == 0) {
 			if (LOGGER.isDebugEnabled()) {
 				LOGGER.debug("{} flush() - no saved messages", toString());
 			}
@@ -523,7 +523,7 @@ public class SSLHandlerG0 extends SSLHandler {
 			if (LOGGER.isDebugEnabled()) {
 				LOGGER.debug("{} flush() - {}", toString(), current);
 			}
-			if (qwrite(next, current) == false) {
+			if (this.qwrite(next, current) == false) {
 				this.mEncodeQueue.addFirst(current);
 				break;
 			}
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java
deleted file mode 100644
index da3f66e..0000000
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.mina.filter.ssl;
-
-import static org.junit.Assert.*;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Security;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
-import org.apache.mina.core.service.IoHandlerAdapter;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.FilterEvent;
-import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
-import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
-import org.apache.mina.transport.socket.nio.NioSocketConnector;
-import org.apache.mina.util.AvailablePortFinder;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * Test an SSL session where the connection cannot be established with the server due to 
- * incompatible protocols (Test for DIRMINA-937)
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class SSLDIRMINA937Test {
-    /** A static port used for his test, chosen to avoid collisions */
-    private static final int port = AvailablePortFinder.getNextAvailable(5555);
-
-    /** A JVM independant KEY_MANAGER_FACTORY algorithm */
-    private static final String KEY_MANAGER_FACTORY_ALGORITHM;
-
-    static {
-        String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
-        if (algorithm == null) {
-            algorithm = KeyManagerFactory.getDefaultAlgorithm();
-        }
-
-        KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
-    }
-
-    private static class TestHandler extends IoHandlerAdapter {
-        public void messageReceived(IoSession session, Object message) throws Exception {
-            String line = (String) message;
-
-            if (line.startsWith("hello")) {
-                //System.out.println("Server got: 'hello', waiting for 'send'");
-                Thread.sleep(1500);
-            } else if (line.startsWith("send")) {
-                //System.out.println("Server got: 'send', sending 'data'");
-                session.write("data");
-            }
-        }
-    }
-
-    /**
-     * Starts a Server with the SSL Filter and a simple text line 
-     * protocol codec filter
-     */
-    private static void startServer() throws Exception {
-        NioSocketAcceptor acceptor = new NioSocketAcceptor();
-
-        acceptor.setReuseAddress(true);
-        DefaultIoFilterChainBuilder filters = acceptor.getFilterChain();
-
-        // Inject the SSL filter
-        SSLContext context = createSSLContext("TLSv1");
-        SSLFilter sslFilter = new SSLFilter(context);
-        sslFilter.setEnabledProtocols(new String[] { "TLSv1" });
-        //sslFilter.setEnabledCipherSuites(getServerCipherSuites(context.getDefaultSSLParameters().getCipherSuites()));
-        filters.addLast("sslFilter", sslFilter);
-
-        // Inject the TestLine codec filter
-        filters.addLast("text", new ProtocolCodecFilter(new TextLineCodecFactory()));
-
-        acceptor.setHandler(new TestHandler());
-        acceptor.bind(new InetSocketAddress(port));
-    }
-
-    /**
-     * Starts a client which will connect twice using SSL
-     */
-    private static void startClient(final CountDownLatch counter) throws Exception {
-        NioSocketConnector connector = new NioSocketConnector();
-        
-        DefaultIoFilterChainBuilder filters = connector.getFilterChain();
-        SSLFilter sslFilter = new SSLFilter(createSSLContext("TLSv1.1"));
-        sslFilter.setEnabledProtocols(new String[] { "TLSv1.1" });
-        //sslFilter.setEnabledCipherSuites(getClientCipherSuites());
-        filters.addLast("sslFilter", sslFilter);
-        connector.setHandler(new IoHandlerAdapter() {
-            @Override
-            public void messageReceived(IoSession session, Object message) throws Exception {
-            }
-
-            @Override
-            public void event(IoSession session, FilterEvent event) throws Exception {
-                if (event == SSLEvent.UNSECURED ) {
-                    counter.countDown();
-                }
-            }
-        });
-        connector.connect(new InetSocketAddress("localhost", port));
-    }
-
-    private static SSLContext createSSLContext(String protocol) throws IOException, GeneralSecurityException {
-        char[] passphrase = "password".toCharArray();
-
-        SSLContext ctx = SSLContext.getInstance(protocol);
-        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-        TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-
-        KeyStore ks = KeyStore.getInstance("JKS");
-        KeyStore ts = KeyStore.getInstance("JKS");
-
-        ks.load(SSLDIRMINA937Test.class.getResourceAsStream("keystore.sslTest"), passphrase);
-        ts.load(SSLDIRMINA937Test.class.getResourceAsStream("truststore.sslTest"), passphrase);
-
-        kmf.init(ks, passphrase);
-        tmf.init(ts);
-        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
-
-        return ctx;
-    }
-
-    /**
-     * Test is ignore as it will cause the build to fail
-     * 
-     * @throws Exception If the test failed
-     */
-    @Test
-    @Ignore("This test is not yet fully functionnal, it servers as the basis for validating DIRMINA-937")
-    public void testDIRMINA937() throws Exception {
-        startServer();
-
-        final CountDownLatch counter = new CountDownLatch(1);
-        startClient(counter);
-        assertTrue(counter.await(10, TimeUnit.SECONDS));
-    }
-}
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java
deleted file mode 100644
index 54937d8..0000000
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java
+++ /dev/null
@@ -1,465 +0,0 @@
-package org.apache.mina.filter.ssl;
-
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Security;
-import java.util.Deque;
-import java.util.concurrent.BlockingDeque;
-import java.util.concurrent.LinkedBlockingDeque;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.mina.core.buffer.IoBuffer;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class SSLEngineTest {
-	private BlockingDeque<ByteBuffer> clientQueue = new LinkedBlockingDeque<>();
-	private BlockingDeque<ByteBuffer> serverQueue = new LinkedBlockingDeque<>();
-
-	private class Handshaker implements Runnable {
-		private SSLEngine sslEngine;
-		private ByteBuffer workBuffer;
-		private ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
-
-		private void push(Deque<ByteBuffer> queue, ByteBuffer buffer) {
-			ByteBuffer result = ByteBuffer.allocate(buffer.capacity());
-			result.put(buffer);
-			queue.addFirst(result);
-		}
-
-		public void run() {
-			HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
-			SSLEngineResult result;
-
-			try {
-				while (handshakeStatus != HandshakeStatus.FINISHED) {
-					switch (handshakeStatus) {
-						case NEED_TASK:
-							break;
-
-						case NEED_UNWRAP:
-							// The SSLEngine waits for some input.
-							// We may have received too few data (TCP fragmentation)
-							//
-							ByteBuffer data = serverQueue.takeLast();
-							result = sslEngine.unwrap(data, workBuffer);
-
-							while (result.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
-								// We need more data, until then, wait.
-								// ByteBuffer data = serverQueue.takeLast();
-								result = sslEngine.unwrap(data, workBuffer);
-							}
-
-							handshakeStatus = sslEngine.getHandshakeStatus();
-							break;
-
-						case NEED_WRAP:
-						case NOT_HANDSHAKING:
-							result = sslEngine.wrap(emptyBuffer, workBuffer);
-
-							workBuffer.flip();
-
-							if (workBuffer.hasRemaining()) {
-								push(clientQueue, workBuffer);
-								workBuffer.clear();
-							}
-
-							handshakeStatus = result.getHandshakeStatus();
-
-							break;
-
-						case FINISHED:
-
-					}
-				}
-			} catch (SSLException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			} catch (InterruptedException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-		}
-
-		public Handshaker(SSLEngine sslEngine) {
-			this.sslEngine = sslEngine;
-			int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
-			workBuffer = ByteBuffer.allocate(packetBufferSize);
-		}
-	}
-
-	/** A JVM independant KEY_MANAGER_FACTORY algorithm */
-	private static final String KEY_MANAGER_FACTORY_ALGORITHM;
-
-	static {
-		String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
-		if (algorithm == null) {
-			algorithm = KeyManagerFactory.getDefaultAlgorithm();
-		}
-
-		KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
-	}
-
-	/** App data buffer for the client SSLEngine */
-	private IoBuffer inNetBufferClient;
-
-	/** Net data buffer for the client SSLEngine */
-	private IoBuffer outNetBufferClient;
-
-	/** App data buffer for the server SSLEngine */
-	private IoBuffer inNetBufferServer;
-
-	/** Net data buffer for the server SSLEngine */
-	private IoBuffer outNetBufferServer;
-
-	private final IoBuffer emptyBuffer = IoBuffer.allocate(0);
-
-	private static SSLContext createSSLContext() throws IOException, GeneralSecurityException {
-		char[] passphrase = "password".toCharArray();
-
-		SSLContext ctx = SSLContext.getInstance("TLS");
-		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-		TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-
-		KeyStore ks = KeyStore.getInstance("JKS");
-		KeyStore ts = KeyStore.getInstance("JKS");
-
-		ks.load(SSLEngineTest.class.getResourceAsStream("keystore.jks"), passphrase);
-		ts.load(SSLEngineTest.class.getResourceAsStream("truststore.jks"), passphrase);
-
-		kmf.init(ks, passphrase);
-		tmf.init(ts);
-		ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
-
-		return ctx;
-	}
-
-	/**
-	 * Decrypt the incoming buffer and move the decrypted data to an application
-	 * buffer.
-	 */
-	private SSLEngineResult unwrap(SSLEngine sslEngine, IoBuffer inBuffer, IoBuffer outBuffer) throws SSLException {
-		// We first have to create the application buffer if it does not exist
-		if (outBuffer == null) {
-			outBuffer = IoBuffer.allocate(inBuffer.remaining());
-		} else {
-			// We already have one, just add the new data into it
-			outBuffer.expand(inBuffer.remaining());
-		}
-
-		SSLEngineResult res;
-		Status status;
-		HandshakeStatus localHandshakeStatus;
-
-		do {
-			// Decode the incoming data
-			res = sslEngine.unwrap(inBuffer.buf(), outBuffer.buf());
-			status = res.getStatus();
-
-			// We can be processing the Handshake
-			localHandshakeStatus = res.getHandshakeStatus();
-
-			if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-				// We have to grow the target buffer, it's too small.
-				// Then we can call the unwrap method again
-				int newCapacity = sslEngine.getSession().getApplicationBufferSize();
-
-				if (inBuffer.remaining() >= newCapacity) {
-					// The buffer is already larger than the max buffer size suggested by the SSL
-					// engine.
-					// Raising it any more will not make sense and it will end up in an endless
-					// loop. Throwing an error is safer
-					throw new SSLException("SSL buffer overflow");
-				}
-
-				inBuffer.expand(newCapacity);
-				continue;
-			}
-		} while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW))
-				&& ((localHandshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
-						|| (localHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)));
-
-		return res;
-	}
-
-	private SSLEngineResult.Status unwrapHandshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer)
-			throws SSLException {
-		// Prepare the net data for reading.
-		if ((appBuffer == null) || !appBuffer.hasRemaining()) {
-			// Need more data.
-			return SSLEngineResult.Status.BUFFER_UNDERFLOW;
-		}
-
-		SSLEngineResult res = unwrap(sslEngine, appBuffer, netBuffer);
-		HandshakeStatus handshakeStatus = res.getHandshakeStatus();
-
-		// checkStatus(res);
-
-		// If handshake finished, no data was produced, and the status is still
-		// ok, try to unwrap more
-		if ((handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED)
-				&& (res.getStatus() == SSLEngineResult.Status.OK) && appBuffer.hasRemaining()) {
-			res = unwrap(sslEngine, appBuffer, netBuffer);
-
-			// prepare to be written again
-			if (appBuffer.hasRemaining()) {
-				appBuffer.compact();
-			} else {
-				appBuffer.free();
-				appBuffer = null;
-			}
-		} else {
-			// prepare to be written again
-			if (appBuffer.hasRemaining()) {
-				appBuffer.compact();
-			} else {
-				appBuffer.free();
-				appBuffer = null;
-			}
-		}
-
-		return res.getStatus();
-	}
-
-	/* no qualifier */boolean isInboundDone(SSLEngine sslEngine) {
-		return sslEngine == null || sslEngine.isInboundDone();
-	}
-
-	/* no qualifier */boolean isOutboundDone(SSLEngine sslEngine) {
-		return sslEngine == null || sslEngine.isOutboundDone();
-	}
-
-	/**
-	 * Perform any handshaking processing.
-	 */
-	/* no qualifier */HandshakeStatus handshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer)
-			throws SSLException {
-		SSLEngineResult result;
-		HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
-
-		for (;;) {
-			switch (handshakeStatus) {
-				case FINISHED:
-					// handshakeComplete = true;
-					return handshakeStatus;
-
-				case NEED_TASK:
-					// handshakeStatus = doTasks();
-					break;
-
-				case NEED_UNWRAP:
-					// we need more data read
-					SSLEngineResult.Status status = unwrapHandshake(sslEngine, appBuffer, netBuffer);
-					handshakeStatus = sslEngine.getHandshakeStatus();
-
-					return handshakeStatus;
-
-				case NEED_WRAP:
-					result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-
-					while (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-						netBuffer.capacity(netBuffer.capacity() << 1);
-						netBuffer.limit(netBuffer.capacity());
-
-						result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-					}
-
-					netBuffer.flip();
-					return result.getHandshakeStatus();
-
-				case NOT_HANDSHAKING:
-					result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-
-					while (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-						netBuffer.capacity(netBuffer.capacity() << 1);
-						netBuffer.limit(netBuffer.capacity());
-
-						result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-					}
-
-					netBuffer.flip();
-					handshakeStatus = result.getHandshakeStatus();
-					return handshakeStatus;
-
-				default:
-					throw new IllegalStateException("error");
-			}
-		}
-	}
-
-	/**
-	 * Do all the outstanding handshake tasks in the current Thread.
-	 */
-	private SSLEngineResult.HandshakeStatus doTasks(SSLEngine sslEngine) {
-		/*
-		 * We could run this in a separate thread, but I don't see the need for this
-		 * when used from SSLFilter. Use thread filters in MINA instead?
-		 */
-		Runnable runnable;
-		while ((runnable = sslEngine.getDelegatedTask()) != null) {
-			// Thread thread = new Thread(runnable);
-			// thread.start();
-			runnable.run();
-		}
-		return sslEngine.getHandshakeStatus();
-	}
-
-	private HandshakeStatus handshake(SSLEngine sslEngine, HandshakeStatus expected, IoBuffer inBuffer,
-			IoBuffer outBuffer, boolean dumpBuffer) throws SSLException {
-		HandshakeStatus handshakeStatus = handshake(sslEngine, inBuffer, outBuffer);
-
-		if (handshakeStatus != expected) {
-			fail();
-		}
-
-		if (dumpBuffer) {
-			System.out.println("Message:" + outBuffer);
-		}
-
-		return handshakeStatus;
-	}
-
-	@Test
-	@Ignore
-	public void testSSL() throws Exception {
-		// Initialise the client SSLEngine
-		SSLContext sslContextClient = createSSLContext();
-		SSLEngine sslEngineClient = sslContextClient.createSSLEngine();
-		int packetBufferSize = sslEngineClient.getSession().getPacketBufferSize();
-		inNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-		outNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-
-		sslEngineClient.setUseClientMode(true);
-
-		// Initialise the Server SSLEngine
-		SSLContext sslContextServer = createSSLContext();
-		SSLEngine sslEngineServer = sslContextServer.createSSLEngine();
-		packetBufferSize = sslEngineServer.getSession().getPacketBufferSize();
-		inNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-		outNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-
-		sslEngineServer.setUseClientMode(false);
-
-		Handshaker handshakerClient = new Handshaker(sslEngineClient);
-		Handshaker handshakerServer = new Handshaker(sslEngineServer);
-
-		handshakerServer.run();
-
-		HandshakeStatus handshakeStatusClient = sslEngineClient.getHandshakeStatus();
-		HandshakeStatus handshakeStatusServer = sslEngineServer.getHandshakeStatus();
-
-		// <<< Server
-		// Start the server
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, null, outNetBufferServer,
-				false);
-
-		// >>> Client
-		// Now start the client, which will generate a CLIENT_HELLO,
-		// stored into the outNetBufferClient
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, null, outNetBufferClient, true);
-
-		// <<< Server
-		// Process the CLIENT_HELLO on the server
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, outNetBufferClient,
-				outNetBufferServer, false);
-
-		// Process the tasks on the server, prepare the SERVER_HELLO message
-		handshakeStatusServer = doTasks(sslEngineServer);
-
-		// We should be ready to generate the SERVER_HELLO message
-		if (handshakeStatusServer != HandshakeStatus.NEED_WRAP) {
-			fail();
-		}
-
-		// Get the SERVER_HELLO message, with all the associated messages
-		// ([Certificate], [ServerKeyExchange], [CertificateRequest], ServerHelloDone)
-		outNetBufferServer.clear();
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, null, outNetBufferServer, true);
-
-		// >>> Client
-		// Process the SERVER_HELLO message on the client
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_TASK, outNetBufferServer,
-				inNetBufferClient, false);
-
-		// Prepare the client response
-		handshakeStatusClient = doTasks(sslEngineClient);
-
-		// We should get back the Client messages ([Certificate],
-		// ClientKeyExchange, [CertificateVerify])
-		if (handshakeStatusClient != HandshakeStatus.NEED_WRAP) {
-			fail();
-		}
-
-		// Generate the [Certificate], ClientKeyExchange, [CertificateVerify] messages
-		outNetBufferClient.clear();
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, null, outNetBufferClient, true);
-
-		// <<< Server
-		// Process the CLIENT_KEY_EXCHANGE on the server
-		outNetBufferServer.clear();
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, outNetBufferClient,
-				outNetBufferServer, false);
-
-		// Do the controls
-		handshakeStatusServer = doTasks(sslEngineServer);
-
-		// The server is waiting for more
-		if (handshakeStatusServer != HandshakeStatus.NEED_UNWRAP) {
-			fail();
-		}
-
-		// >>> Client
-		// The CHANGE_CIPHER_SPEC message generation
-		outNetBufferClient.clear();
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, null, outNetBufferClient, true);
-
-		// <<< Server
-		// Process the CHANGE_CIPHER_SPEC on the server
-		outNetBufferServer.clear();
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, outNetBufferClient,
-				outNetBufferServer, false);
-
-		// >>> Client
-		// Generate the FINISHED message on thee client
-		outNetBufferClient.clear();
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, null, outNetBufferClient, true);
-
-		// <<< Server
-		// Process the client FINISHED message
-		outNetBufferServer.clear();
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, outNetBufferClient,
-				outNetBufferServer, false);
-
-		// Generate the CHANGE_CIPHER_SPEC message on the server
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, null, outNetBufferServer, true);
-
-		// >>> Client
-		// Process the server CHANGE_SCIPHER_SPEC message on the client
-		outNetBufferClient.clear();
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, outNetBufferServer,
-				outNetBufferClient, false);
-
-		// <<< Server
-		// Generate the server FINISHED message
-		outNetBufferServer.clear();
-		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.FINISHED, null, outNetBufferServer, true);
-
-		// >>> Client
-		// Process the server FINISHED message on the client
-		outNetBufferClient.clear();
-		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NOT_HANDSHAKING, outNetBufferServer,
-				outNetBufferClient, false);
-	}
-}
diff --git a/mina-core/src/test/resources/org/apache/mina/filter/ssl/emptykeystore.sslTest b/mina-core/src/test/resources/org/apache/mina/filter/ssl/emptykeystore.sslTest
deleted file mode 100644
index 65d4b65..0000000
Binary files a/mina-core/src/test/resources/org/apache/mina/filter/ssl/emptykeystore.sslTest and /dev/null differ
diff --git a/mina-core/src/test/resources/org/apache/mina/filter/ssl2/keystore.jks b/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.jks
similarity index 100%
rename from mina-core/src/test/resources/org/apache/mina/filter/ssl2/keystore.jks
rename to mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.jks
diff --git a/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.sslTest b/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.sslTest
deleted file mode 100644
index 36190ba..0000000
Binary files a/mina-core/src/test/resources/org/apache/mina/filter/ssl/keystore.sslTest and /dev/null differ
diff --git a/mina-core/src/test/resources/org/apache/mina/filter/ssl2/truststore.jks b/mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.jks
similarity index 100%
rename from mina-core/src/test/resources/org/apache/mina/filter/ssl2/truststore.jks
rename to mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.jks
diff --git a/mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.sslTest b/mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.sslTest
deleted file mode 100644
index 48c5963..0000000
Binary files a/mina-core/src/test/resources/org/apache/mina/filter/ssl/truststore.sslTest and /dev/null differ

[mina] 01/05: Merge branch 'bugfix/DIRMINA1132' into 2.2.X

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a commit to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit 656426159477b4c1e6c64c80b16c7bea16bde3d6
Merge: 3726e4a 4c11155
Author: Jonathan Valliere <jo...@emoten.com>
AuthorDate: Thu Aug 19 13:59:30 2021 -0400

    Merge branch 'bugfix/DIRMINA1132' into 2.2.X

 .../apache/mina/core/buffer/AbstractIoBuffer.java  |   2 +
 .../core/filterchain/DefaultIoFilterChain.java     |  34 +-
 .../mina/core/session/AbstractIoSession.java       |   5 +
 .../org/apache/mina/core/session/IoSession.java    |   5 +
 .../mina/core/write/WriteRejectedException.java    |  44 ++
 .../mina/filter/ssl/BogusTrustManagerFactory.java  | 112 +--
 .../apache/mina/filter/ssl/KeyStoreFactory.java    | 292 ++++----
 .../apache/mina/filter/ssl/SslContextFactory.java  | 782 +++++++++++----------
 .../java/org/apache/mina/filter/ssl/SslEvent.java  |   6 +-
 .../org/apache/mina/filter/ssl/SslHandler.java     |   3 +-
 .../org/apache/mina/filter/ssl/package-info.java   |   3 +-
 .../mina/filter/ssl2/EncryptedWriteRequest.java    |  19 +
 .../org/apache/mina/filter/ssl2/SSL2Filter.java    | 319 +++++++++
 .../org/apache/mina/filter/ssl2/SSL2Handler.java   | 259 +++++++
 .../org/apache/mina/filter/ssl2/SSL2HandlerG0.java | 574 +++++++++++++++
 .../transport/socket/nio/NioSocketSession.java     | 612 ++++++++--------
 .../org/apache/mina/util/BasicThreadFactory.java   |  62 ++
 .../java/org/apache/mina/util/StackInspector.java  |  78 ++
 .../apache/mina/filter/ssl2/SSL2SimpleTest.java    | 127 ++++
 .../org/apache/mina/filter/ssl2/keystore.jks       | Bin 0 -> 1368 bytes
 .../org/apache/mina/filter/ssl2/truststore.jks     | Bin 0 -> 654 bytes
 21 files changed, 2416 insertions(+), 922 deletions(-)

[mina] 03/05: Updates SSL & unit tests for the main SSL package changes

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a commit to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit 8b61c5b33448cdf1c88f72bc506b517258829b8d
Author: Jonathan Valliere <jo...@apache.org>
AuthorDate: Thu Sep 9 12:46:58 2021 -0400

    Updates SSL & unit tests for the main SSL package changes
---
 .../mina/core/session/AbstractIoSession.java       |   3 +-
 .../mina/filter/codec/textline/LineDelimiter.java  |   2 +-
 .../mina/filter/ssl/BogusTrustManagerFactory.java  |   1 +
 ...lEvent.java => DisableEncryptWriteRequest.java} |  13 +-
 .../{SslEvent.java => EncryptedWriteRequest.java}  |  30 +-
 ...lContextFactory.java => SSLContextFactory.java} |   2 +-
 .../filter/ssl/{SslEvent.java => SSLEvent.java}    |   2 +-
 .../{ssl2/SSL2Filter.java => ssl/SSLFilter.java}   |  35 +-
 .../{ssl2/SSL2Handler.java => ssl/SSLHandler.java} |  33 +-
 .../SSL2HandlerG0.java => ssl/SSLHandlerG0.java}   |  46 +-
 .../java/org/apache/mina/filter/ssl/SslFilter.java | 909 ---------------------
 .../org/apache/mina/filter/ssl/SslHandler.java     | 872 --------------------
 .../mina/filter/ssl2/EncryptedWriteRequest.java    |  19 -
 .../transport/socket/nio/NioSocketSession.java     |   8 +-
 .../SslTestHandshakeExceptionDIRMINA1077Test.java  |  35 +-
 ...lDIRMINA937Test.java => SSLDIRMINA937Test.java} |  13 +-
 .../org/apache/mina/filter/ssl/SSLEngineTest.java  | 465 +++++++++++
 .../SSL2SimpleTest.java => ssl/SSLFilterMain.java} |  11 +-
 .../org/apache/mina/filter/ssl/SslEngineTest.java  | 486 -----------
 .../org/apache/mina/filter/ssl/SslFilterTest.java  | 142 ----
 .../java/org/apache/mina/filter/ssl/SslTest.java   | 266 ------
 .../java/org/apache/mina/example/chat/Main.java    |   4 +-
 .../example/chat/client/ChatClientSupport.java     |   5 +-
 .../org/apache/mina/example/echoserver/Main.java   |   4 +-
 .../apache/mina/example/tcp/perf/TcpSslClient.java |   5 +-
 .../apache/mina/example/tcp/perf/TcpSslServer.java |   4 +-
 .../mina/example/echoserver/AbstractTest.java      |   9 +-
 .../mina/example/echoserver/ConnectorTest.java     |  13 +-
 .../mina/example/echoserver/ssl/SslFilterTest.java |   6 +-
 29 files changed, 633 insertions(+), 2810 deletions(-)

diff --git a/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java b/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java
index 1bd9786..3da42dc 100644
--- a/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java
+++ b/mina-core/src/main/java/org/apache/mina/core/session/AbstractIoSession.java
@@ -575,8 +575,7 @@ public abstract class AbstractIoSession implements IoSession {
         filterChain.fireFilterWrite(writeRequest);
 
         // TODO : This is not our business ! The caller has created a
-        // FileChannel,
-        // he has to close it !
+        // FileChannel and has to close it !
         if (openedFileChannel != null) {
             // If we opened a FileChannel, it needs to be closed when the write
             // has completed
diff --git a/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.java b/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
index 9910f99..8fd1a5a 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
@@ -38,7 +38,7 @@ public class LineDelimiter {
     /** the line delimiter constant of the current O/S. */
     public static final LineDelimiter DEFAULT;
 
-    /** Compute the default delimiter on he current OS */
+    /** Compute the default delimiter on the current OS */
     static {
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
         PrintWriter out = new PrintWriter(bout, true);
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.java
index e0402c2..36be305 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/BogusTrustManagerFactory.java
@@ -70,6 +70,7 @@ public class BogusTrustManagerFactory extends TrustManagerFactory {
 	/**
 	 * Creates a new BogusTrustManagerFactory instance
 	 */
+	@SuppressWarnings("deprecation")
 	public BogusTrustManagerFactory() {
 		super(new BogusTrustManagerFactorySpi(), new Provider("MinaBogus", 1.0, "") {
 			private static final long serialVersionUID = -4024169055312053827L;
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/DisableEncryptWriteRequest.java
similarity index 76%
copy from mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
copy to mina-core/src/main/java/org/apache/mina/filter/ssl/DisableEncryptWriteRequest.java
index e1c497d..5f92555 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/DisableEncryptWriteRequest.java
@@ -19,14 +19,11 @@
  */
 package org.apache.mina.filter.ssl;
 
-import org.apache.mina.filter.FilterEvent;
+import org.apache.mina.core.write.WriteRequest;
 
 /**
- * A SSL event sent by {@link SslFilter} when the session is secured or not
- * secured.
- * 
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ * Interface used to designate WriteRequest objects which should not be encrypted.
  */
-public enum SslEvent implements FilterEvent {
-	SECURED, UNSECURED
-}
+public interface DisableEncryptWriteRequest extends WriteRequest {
+
+}
\ No newline at end of file
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/EncryptedWriteRequest.java
similarity index 51%
copy from mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
copy to mina-core/src/main/java/org/apache/mina/filter/ssl/EncryptedWriteRequest.java
index e1c497d..8279dc7 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/EncryptedWriteRequest.java
@@ -19,14 +19,28 @@
  */
 package org.apache.mina.filter.ssl;
 
-import org.apache.mina.filter.FilterEvent;
+import org.apache.mina.core.write.DefaultWriteRequest;
+import org.apache.mina.core.write.WriteRequest;
 
 /**
- * A SSL event sent by {@link SslFilter} when the session is secured or not
- * secured.
- * 
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ * Specialty WriteRequest which indicates that the contents has been encrypted.
+ * <p>
+ * This prevents a WriteRequest from being encrypted twice and allows unwrapping
+ * of these WriteRequets when dispatching the messageSent events.
+ * <p>
+ * Users should not create their own EncryptedWriteRequest objects.
  */
-public enum SslEvent implements FilterEvent {
-	SECURED, UNSECURED
-}
+public class EncryptedWriteRequest extends DefaultWriteRequest {
+
+	// The original message
+	private WriteRequest originalRequest;
+
+	public EncryptedWriteRequest(Object encodedMessage, WriteRequest parent) {
+		super(encodedMessage, parent != null ? parent.getFuture() : null);
+		this.originalRequest = parent != null ? parent : this;
+	}
+
+	public WriteRequest getOriginalRequest() {
+		return this.originalRequest;
+	}
+}
\ No newline at end of file
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslContextFactory.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLContextFactory.java
similarity index 99%
rename from mina-core/src/main/java/org/apache/mina/filter/ssl/SslContextFactory.java
rename to mina-core/src/main/java/org/apache/mina/filter/ssl/SSLContextFactory.java
index 255eeb5..f942091 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslContextFactory.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLContextFactory.java
@@ -49,7 +49,7 @@ import javax.net.ssl.TrustManagerFactory;
  *
  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
  */
-public class SslContextFactory {
+public class SSLContextFactory {
 
 	private String provider = null;
 
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLEvent.java
similarity index 95%
rename from mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
rename to mina-core/src/main/java/org/apache/mina/filter/ssl/SSLEvent.java
index e1c497d..ff60a71 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslEvent.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLEvent.java
@@ -27,6 +27,6 @@ import org.apache.mina.filter.FilterEvent;
  * 
  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
  */
-public enum SslEvent implements FilterEvent {
+public enum SSLEvent implements FilterEvent {
 	SECURED, UNSECURED
 }
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Filter.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLFilter.java
similarity index 90%
rename from mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Filter.java
rename to mina-core/src/main/java/org/apache/mina/filter/ssl/SSLFilter.java
index 00554db..ab32b75 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Filter.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLFilter.java
@@ -17,7 +17,7 @@
  *  under the License.
  *
  */
-package org.apache.mina.filter.ssl2;
+package org.apache.mina.filter.ssl;
 
 import java.net.InetSocketAddress;
 import java.util.Objects;
@@ -40,30 +40,31 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * An simple SSL processor which performs flow control of encrypted information
+ * A SSL processor which performs flow control of encrypted information
  * on the filter-chain.
  * <p>
  * The initial handshake is automatically enabled for "client" sessions once the
  * filter is added to the filter-chain and the session is connected.
  *
+ * @author Jonathan Valliere
  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
  */
-public class SSL2Filter extends IoFilterAdapter {
+public class SSLFilter extends IoFilterAdapter {
 	/**
 	 * The presence of this attribute in a session indicates that the session is
 	 * secured.
 	 */
-	static public final AttributeKey SSL_SECURED = new AttributeKey(SSL2Filter.class, "status");
+	static public final AttributeKey SSL_SECURED = new AttributeKey(SSLFilter.class, "status");
 
 	/**
 	 * Returns the SSL2Handler object
 	 */
-	static protected final AttributeKey SSL_HANDLER = new AttributeKey(SSL2Filter.class, "handler");
+	static protected final AttributeKey SSL_HANDLER = new AttributeKey(SSLFilter.class, "handler");
 
 	/**
 	 * The logger
 	 */
-	static protected final Logger LOGGER = LoggerFactory.getLogger(SSL2Filter.class);
+	static protected final Logger LOGGER = LoggerFactory.getLogger(SSLFilter.class);
 
 	/**
 	 * Task executor for processing handshakes
@@ -82,7 +83,7 @@ public class SSL2Filter extends IoFilterAdapter {
 	 * 
 	 * @param context The SSLContext to use
 	 */
-	public SSL2Filter(SSLContext context) {
+	public SSLFilter(SSLContext context) {
 		Objects.requireNonNull(context, "ssl must not be null");
 
 		this.mContext = context;
@@ -166,7 +167,7 @@ public class SSL2Filter extends IoFilterAdapter {
 	@Override
 	public void onPreAdd(IoFilterChain parent, String name, NextFilter next) throws Exception {
 		// Check that we don't have a SSL filter already present in the chain
-		if (parent.contains(SSL2Filter.class)) {
+		if (parent.contains(SSLFilter.class)) {
 			throw new IllegalStateException("Only one SSL filter is permitted in a chain");
 		}
 
@@ -193,7 +194,7 @@ public class SSL2Filter extends IoFilterAdapter {
 	@Override
 	public void onPreRemove(IoFilterChain parent, String name, NextFilter next) throws Exception {
 		IoSession session = parent.getSession();
-		onClose(next, session, false);
+		this.onClose(next, session, false);
 	}
 
 	/**
@@ -205,12 +206,12 @@ public class SSL2Filter extends IoFilterAdapter {
 	 * @throws Exception
 	 */
 	synchronized protected void onConnected(NextFilter next, IoSession session) throws Exception {
-		SSL2Handler x = SSL2Handler.class.cast(session.getAttribute(SSL_HANDLER));
+		SSLHandler x = SSLHandler.class.cast(session.getAttribute(SSL_HANDLER));
 
 		if (x == null) {
 			final InetSocketAddress s = InetSocketAddress.class.cast(session.getRemoteAddress());
 			final SSLEngine e = this.createEngine(session, s);
-			x = new SSL2HandlerG0(e, EXECUTOR, session);
+			x = new SSLHandlerG0(e, EXECUTOR, session);
 			session.setAttribute(SSL_HANDLER, x);
 		}
 
@@ -219,12 +220,12 @@ public class SSL2Filter extends IoFilterAdapter {
 
 	synchronized protected void onClose(NextFilter next, IoSession session, boolean linger) throws Exception {
 		session.removeAttribute(SSL_SECURED);
-		SSL2Handler x = SSL2Handler.class.cast(session.removeAttribute(SSL_HANDLER));
+		SSLHandler x = SSLHandler.class.cast(session.removeAttribute(SSL_HANDLER));
 		if (x != null) {
 			x.close(next, linger);
 		}
 	}
-	
+
 	/**
 	 * Customization handler for creating the engine
 	 * 
@@ -277,7 +278,7 @@ public class SSL2Filter extends IoFilterAdapter {
 	public void messageReceived(NextFilter next, IoSession session, Object message) throws Exception {
 		if (LOGGER.isDebugEnabled())
 			LOGGER.debug("session {} received {}", session, message);
-		SSL2Handler x = SSL2Handler.class.cast(session.getAttribute(SSL_HANDLER));
+		SSLHandler x = SSLHandler.class.cast(session.getAttribute(SSL_HANDLER));
 		x.receive(next, IoBuffer.class.cast(message));
 	}
 
@@ -291,7 +292,7 @@ public class SSL2Filter extends IoFilterAdapter {
 
 		if (request instanceof EncryptedWriteRequest) {
 			EncryptedWriteRequest e = EncryptedWriteRequest.class.cast(request);
-			SSL2Handler x = SSL2Handler.class.cast(session.getAttribute(SSL_HANDLER));
+			SSLHandler x = SSLHandler.class.cast(session.getAttribute(SSL_HANDLER));
 			x.ack(next, request);
 			if (e.getOriginalRequest() != e) {
 				next.messageSent(session, e.getOriginalRequest());
@@ -309,10 +310,10 @@ public class SSL2Filter extends IoFilterAdapter {
 		if (LOGGER.isDebugEnabled())
 			LOGGER.debug("session {} write {}", session, request);
 
-		if (request instanceof EncryptedWriteRequest) {
+		if (request instanceof EncryptedWriteRequest || request instanceof DisableEncryptWriteRequest) {
 			super.filterWrite(next, session, request);
 		} else {
-			SSL2Handler x = SSL2Handler.class.cast(session.getAttribute(SSL_HANDLER));
+			SSLHandler x = SSLHandler.class.cast(session.getAttribute(SSL_HANDLER));
 			x.write(next, request);
 		}
 	}
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Handler.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandler.java
similarity index 84%
rename from mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Handler.java
rename to mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandler.java
index b5e522b..029d7be 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2Handler.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandler.java
@@ -1,4 +1,23 @@
-package org.apache.mina.filter.ssl2;
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.filter.ssl;
 
 import java.util.Deque;
 import java.util.concurrent.ConcurrentLinkedDeque;
@@ -16,7 +35,13 @@ import org.apache.mina.core.write.WriteRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class SSL2Handler {
+/**
+ * Default interface for SSL exposed to the {@link SSLFilter}
+ * 
+ * @author Jonathan Valliere
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public abstract class SSLHandler {
 
 	/**
 	 * Minimum size of encoder buffer in packets
@@ -36,7 +61,7 @@ public abstract class SSL2Handler {
 	/**
 	 * Static logger
 	 */
-	static protected final Logger LOGGER = LoggerFactory.getLogger(SSL2Handler.class);
+	static protected final Logger LOGGER = LoggerFactory.getLogger(SSLHandler.class);
 
 	/**
 	 * Write Requests which are enqueued prior to the completion of the handshaking
@@ -75,7 +100,7 @@ public abstract class SSL2Handler {
 	 * @param e executor
 	 * @param s session
 	 */
-	public SSL2Handler(SSLEngine p, Executor e, IoSession s) {
+	public SSLHandler(SSLEngine p, Executor e, IoSession s) {
 		this.mEngine = p;
 		this.mExecutor = e;
 		this.mSession = s;
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2HandlerG0.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
similarity index 91%
rename from mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2HandlerG0.java
rename to mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
index fd2ecd1..de99b7f 100644
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl2/SSL2HandlerG0.java
+++ b/mina-core/src/main/java/org/apache/mina/filter/ssl/SSLHandlerG0.java
@@ -1,4 +1,23 @@
-package org.apache.mina.filter.ssl2;
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.mina.filter.ssl;
 
 import java.nio.BufferOverflowException;
 import java.util.ArrayList;
@@ -13,9 +32,17 @@ import org.apache.mina.core.filterchain.IoFilter.NextFilter;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.core.write.WriteRejectedException;
 import org.apache.mina.core.write.WriteRequest;
-import org.apache.mina.filter.ssl.SslEvent;
 
-public class SSL2HandlerG0 extends SSL2Handler {
+/**
+ * Default implementation of SSLHandler
+ * <p>
+ * The concurrency model is enforced using a simple mutex to ensure that the
+ * state of the decode buffer and closure is concurrent with the SSLEngine.
+ * 
+ * @author Jonathan Valliere
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class SSLHandlerG0 extends SSLHandler {
 
 	/**
 	 * Maximum number of queued messages waiting for encoding
@@ -69,7 +96,7 @@ public class SSL2HandlerG0 extends SSL2Handler {
 	 * @param e executor
 	 * @param s session
 	 */
-	public SSL2HandlerG0(SSLEngine p, Executor e, IoSession s) {
+	public SSLHandlerG0(SSLEngine p, Executor e, IoSession s) {
 		super(p, e, s);
 	}
 
@@ -462,8 +489,8 @@ public class SSL2HandlerG0 extends SSL2Handler {
 	synchronized protected void lfinish(final NextFilter next) throws SSLException {
 		if (this.mHandshakeComplete == false) {
 			this.mHandshakeComplete = true;
-			this.mSession.setAttribute(SSL2Filter.SSL_SECURED, this.mEngine.getSession());
-			next.event(this.mSession, SslEvent.SECURED);
+			this.mSession.setAttribute(SSLFilter.SSL_SECURED, this.mEngine.getSession());
+			next.event(this.mSession, SSLEvent.SECURED);
 		}
 		/**
 		 * There exists a bug in the JDK which emits FINISHED twice instead of once.
@@ -518,9 +545,14 @@ public class SSL2HandlerG0 extends SSL2Handler {
 		if (LOGGER.isDebugEnabled()) {
 			LOGGER.debug("{} close() - closing session", toString());
 		}
+		
+		if (this.mHandshakeComplete) {
+			next.event(this.mSession, SSLEvent.UNSECURED);
+		}
 
 		this.mOutboundLinger = linger;
 		this.mOutboundClosing = true;
+
 		if (linger == false) {
 			if (this.mEncodeQueue.size() != 0) {
 				next.exceptionCaught(this.mSession,
@@ -542,7 +574,7 @@ public class SSL2HandlerG0 extends SSL2Handler {
 				this.mExecutor.execute(new Runnable() {
 					@Override
 					public void run() {
-						SSL2HandlerG0.this.execute_task(next);
+						SSLHandlerG0.this.execute_task(next);
 					}
 				});
 			}
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslFilter.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SslFilter.java
deleted file mode 100644
index 1c4a532..0000000
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslFilter.java
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.mina.filter.ssl;
-
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLSession;
-
-import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.mina.core.filterchain.IoFilter;
-import org.apache.mina.core.filterchain.IoFilterAdapter;
-import org.apache.mina.core.filterchain.IoFilterChain;
-import org.apache.mina.core.future.DefaultWriteFuture;
-import org.apache.mina.core.future.IoFuture;
-import org.apache.mina.core.future.IoFutureListener;
-import org.apache.mina.core.future.WriteFuture;
-import org.apache.mina.core.service.IoAcceptor;
-import org.apache.mina.core.service.IoHandler;
-import org.apache.mina.core.session.AttributeKey;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.core.write.DefaultWriteRequest;
-import org.apache.mina.core.write.WriteRequest;
-import org.apache.mina.core.write.WriteToClosedSessionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * An SSL filter that encrypts and decrypts the data exchanged in the session.
- * Adding this filter triggers SSL handshake procedure immediately by sending
- * a SSL 'hello' message, so you don't need to call
- * {@link #startSsl(IoSession)} manually unless you are implementing StartTLS
- * (see below).  If you don't want the handshake procedure to start
- * immediately, please specify {@code false} as {@code autoStart} parameter in
- * the constructor.
- * <p>
- * This filter uses an {@link SSLEngine} which was introduced in Java 5, so
- * Java version 5 or above is mandatory to use this filter. And please note that
- * this filter only works for TCP/IP connections.
- *
- * <h2>Implementing StartTLS</h2>
- * <p>
- * You can use {@link #DISABLE_ENCRYPTION_ONCE} attribute to implement StartTLS:
- * <pre>
- * public void messageReceived(IoSession session, Object message) {
- *    if (message instanceof MyStartTLSRequest) {
- *        // Insert SSLFilter to get ready for handshaking
- *        session.getFilterChain().addFirst(sslFilter);
- *
- *        // Disable encryption temporarily.
- *        // This attribute will be removed by SSLFilter
- *        // inside the Session.write() call below.
- *        session.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
- *
- *        // Write StartTLSResponse which won't be encrypted.
- *        session.write(new MyStartTLSResponse(OK));
- *
- *        // Now DISABLE_ENCRYPTION_ONCE attribute is cleared.
- *        assert session.getAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE) == null;
- *    }
- * }
- * </pre>
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- * @org.apache.xbean.XBean
- */
-public class SslFilter extends IoFilterAdapter {
-    /** The logger */
-    private static final Logger LOGGER = LoggerFactory.getLogger(SslFilter.class);
-
-    /**
-     * A session attribute key that stores underlying {@link SSLSession}
-     * for each session.
-     */
-    public static final AttributeKey SSL_SESSION = new AttributeKey(SslFilter.class, "session");
-
-    /**
-     * A session attribute key that makes next one write request bypass
-     * this filter (not encrypting the data).  This is a marker attribute,
-     * which means that you can put whatever as its value. ({@link Boolean#TRUE}
-     * is preferred.)  The attribute is automatically removed from the session
-     * attribute map as soon as {@link IoSession#write(Object)} is invoked,
-     * and therefore should be put again if you want to make more messages
-     * bypass this filter.  This is especially useful when you implement
-     * StartTLS.
-     */
-    public static final AttributeKey DISABLE_ENCRYPTION_ONCE = new AttributeKey(SslFilter.class, "disableOnce");
-
-    /**
-     * A session attribute key that makes this filter to emit a
-     * {@link IoHandler#messageReceived(IoSession, Object)} event with a
-     * special message ({@link SslEvent#SECURED} or {@link SslEvent#UNSECURED}).
-     * This is a marker attribute, which means that you can put whatever as its
-     * value. ({@link Boolean#TRUE} is preferred.)  By default, this filter
-     * doesn't emit any events related with SSL session flow control.
-     */
-    public static final AttributeKey USE_NOTIFICATION = new AttributeKey(SslFilter.class, "useNotification");
-
-    /**
-     * A session attribute key that should be set to an {@link InetSocketAddress}.
-     * Setting this attribute causes
-     * {@link SSLContext#createSSLEngine(String, int)} to be called passing the
-     * hostname and port of the {@link InetSocketAddress} to get an
-     * {@link SSLEngine} instance. If not set {@link SSLContext#createSSLEngine()}
-     * will be called.
-     * <br>
-     * Using this feature {@link SSLSession} objects may be cached and reused
-     * when in client mode.
-     *
-     * @see SSLContext#createSSLEngine(String, int)
-     */
-    public static final AttributeKey PEER_ADDRESS = new AttributeKey(SslFilter.class, "peerAddress");
-
-    /** An attribute containing the next filter */
-    private static final AttributeKey NEXT_FILTER = new AttributeKey(SslFilter.class, "nextFilter");
-
-    private static final AttributeKey SSL_HANDLER = new AttributeKey(SslFilter.class, "handler");
-
-    /** The SslContext used */
-    /* No qualifier */final SSLContext sslContext;
-
-    /** A flag used to tell the filter to start the handshake immediately */
-    private final boolean autoStart;
-
-    /** A flag used to determinate if the handshake should start immediately */
-    public static final boolean START_HANDSHAKE = true;
-
-    /** A flag used to determinate if the handshake should wait for the client to initiate the handshake */
-    public static final boolean CLIENT_HANDSHAKE = false;
-
-    private boolean client;
-
-    private boolean needClientAuth;
-
-    private boolean wantClientAuth;
-
-    private String[] enabledCipherSuites;
-
-    private String[] enabledProtocols;
-
-    /**
-     * Creates a new SSL filter using the specified {@link SSLContext}.
-     * The handshake will start immediately after the filter has been added
-     * to the chain.
-     * 
-     * @param sslContext The SSLContext to use
-     */
-    public SslFilter(SSLContext sslContext) {
-        this(sslContext, START_HANDSHAKE);
-    }
-
-    /**
-     * Creates a new SSL filter using the specified {@link SSLContext}.
-     * If the <tt>autostart</tt> flag is set to <tt>true</tt>, the
-     * handshake will start immediately after the filter has been added
-     * to the chain.
-     * 
-     * @param sslContext The SSLContext to use
-     * @param autoStart The flag used to tell the filter to start the handshake immediately
-     */
-    public SslFilter(SSLContext sslContext, boolean autoStart) {
-        if (sslContext == null) {
-            throw new IllegalArgumentException("sslContext");
-        }
-
-        this.sslContext = sslContext;
-        this.autoStart = autoStart;
-    }
-
-    /**
-     * Returns the underlying {@link SSLSession} for the specified session.
-     *
-     * @param session The current session 
-     * @return <tt>null</tt> if no {@link SSLSession} is initialized yet.
-     */
-    public SSLSession getSslSession(IoSession session) {
-        return (SSLSession) session.getAttribute(SSL_SESSION);
-    }
-
-    /**
-     * (Re)starts SSL session for the specified <tt>session</tt> if not started yet.
-     * Please note that SSL session is automatically started by default, and therefore
-     * you don't need to call this method unless you've used TLS closure.
-     *
-     * @param session The session that will be switched to SSL mode
-     * @return <tt>true</tt> if the SSL session has been started, <tt>false</tt> if already started.
-     * @throws SSLException if failed to start the SSL session
-     */
-    public boolean startSsl(IoSession session) throws SSLException {
-        SslHandler sslHandler = getSslSessionHandler(session);
-        boolean started;
-
-        try {
-            synchronized (sslHandler) {
-                if (sslHandler.isOutboundDone()) {
-                    NextFilter nextFilter = (NextFilter) session.getAttribute(NEXT_FILTER);
-                    sslHandler.destroy();
-                    sslHandler.init();
-                    sslHandler.handshake(nextFilter);
-                    started = true;
-                } else {
-                    started = false;
-                }
-                sslHandler.flushFilterWrite();
-            }
-            sslHandler.flushMessageReceived();
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        }
-
-        return started;
-    }
-
-    /**
-     * An extended toString() method for sessions. If the SSL handshake
-     * is not yet completed, we will print (ssl) in small caps. Once it's
-     * completed, we will use SSL capitalized.
-     */
-    /* no qualifier */String getSessionInfo(IoSession session) {
-        StringBuilder sb = new StringBuilder();
-
-        if (session.getService() instanceof IoAcceptor) {
-            sb.append("Session Server");
-
-        } else {
-            sb.append("Session Client");
-        }
-
-        sb.append('[').append(session.getId()).append(']');
-
-        SslHandler sslHandler = (SslHandler) session.getAttribute(SSL_HANDLER);
-
-        if (sslHandler == null) {
-            sb.append("(no sslEngine)");
-        } else if (isSslStarted(session)) {
-            if (sslHandler.isHandshakeComplete()) {
-                sb.append("(SSL)");
-            } else {
-                sb.append("(ssl...)");
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * @return <tt>true</tt> if and only if the specified <tt>session</tt> is
-     * encrypted/decrypted over SSL/TLS currently. This method will start
-     * to return <tt>false</tt> after TLS <tt>close_notify</tt> message
-     * is sent and any messages written after then is not going to get encrypted.
-     * 
-     * @param session the session we want to check
-     */
-    public boolean isSslStarted(IoSession session) {
-        SslHandler sslHandler = (SslHandler) session.getAttribute(SSL_HANDLER);
-
-        if (sslHandler == null) {
-            return false;
-        }
-
-        synchronized (sslHandler) {
-            return !sslHandler.isOutboundDone();
-        }
-    }
-
-    /**
-     * @return <tt>true</tt> if and only if the conditions for
-     * {@link #isSslStarted(IoSession)} are met, and the handhake has
-     * completed.
-     *
-     * @param session the session we want to check
-     */
-    public boolean isSecured(IoSession session) {
-        SslHandler sslHandler = (SslHandler) session.getAttribute(SSL_HANDLER);
-
-        if (sslHandler == null) {
-            return false;
-        }
-
-        synchronized (sslHandler) {
-            return !sslHandler.isOutboundDone() && sslHandler.isHandshakeComplete();
-        }
-    }
-
-
-    /**
-     * Stops the SSL session by sending TLS <tt>close_notify</tt> message to
-     * initiate TLS closure.
-     *
-     * @param session the {@link IoSession} to initiate TLS closure
-     * @return The Future for the initiated closure
-     * @throws SSLException if failed to initiate TLS closure
-     */
-    public WriteFuture stopSsl(IoSession session) throws SSLException {
-        SslHandler sslHandler = getSslSessionHandler(session);
-        NextFilter nextFilter = (NextFilter) session.getAttribute(NEXT_FILTER);
-        WriteFuture future;
-
-        try {
-            synchronized (sslHandler) {
-                future = initiateClosure(nextFilter, session);
-                sslHandler.flushFilterWrite();
-            }
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        }
-
-        return future;
-    }
-
-    /**
-     * @return <tt>true</tt> if the engine is set to use client mode
-     * when handshaking.
-     */
-    public boolean isUseClientMode() {
-        return client;
-    }
-
-    /**
-     * Configures the engine to use client (or server) mode when handshaking.
-     * 
-     * @param clientMode <tt>true</tt> when we are in client mode, <tt>false</tt> when in server mode
-     */
-    public void setUseClientMode(boolean clientMode) {
-        this.client = clientMode;
-    }
-
-    /**
-     * @return <tt>true</tt> if the engine will <em>require</em> client authentication.
-     * This option is only useful to engines in the server mode.
-     */
-    public boolean isNeedClientAuth() {
-        return needClientAuth;
-    }
-
-    /**
-     * Configures the engine to <em>require</em> client authentication.
-     * This option is only useful for engines in the server mode.
-     * 
-     * @param needClientAuth A flag set when we need to authenticate the client
-     */
-    public void setNeedClientAuth(boolean needClientAuth) {
-        this.needClientAuth = needClientAuth;
-    }
-
-    /**
-     * @return <tt>true</tt> if the engine will <em>request</em> client authentication.
-     * This option is only useful to engines in the server mode.
-     */
-    public boolean isWantClientAuth() {
-        return wantClientAuth;
-    }
-
-    /**
-     * Configures the engine to <em>request</em> client authentication.
-     * This option is only useful for engines in the server mode.
-     * 
-     * @param wantClientAuth A flag set when we want to check the client authentication
-     */
-    public void setWantClientAuth(boolean wantClientAuth) {
-        this.wantClientAuth = wantClientAuth;
-    }
-
-    /**
-     * @return the list of cipher suites to be enabled when {@link SSLEngine}
-     * is initialized. <tt>null</tt> means 'use {@link SSLEngine}'s default.'
-     */
-    public String[] getEnabledCipherSuites() {
-        return enabledCipherSuites;
-    }
-
-    /**
-     * Sets the list of cipher suites to be enabled when {@link SSLEngine}
-     * is initialized.
-     *
-     * @param cipherSuites <tt>null</tt> means 'use {@link SSLEngine}'s default.'
-     */
-    public void setEnabledCipherSuites(String[] cipherSuites) {
-        this.enabledCipherSuites = cipherSuites;
-    }
-
-    /**
-     * @return the list of protocols to be enabled when {@link SSLEngine}
-     * is initialized. <tt>null</tt> means 'use {@link SSLEngine}'s default.'
-     */
-    public String[] getEnabledProtocols() {
-        return enabledProtocols;
-    }
-
-    /**
-     * Sets the list of protocols to be enabled when {@link SSLEngine}
-     * is initialized.
-     *
-     * @param protocols <tt>null</tt> means 'use {@link SSLEngine}'s default.'
-     */
-    public void setEnabledProtocols(String[] protocols) {
-        this.enabledProtocols = protocols;
-    }
-
-    /**
-     * Executed just before the filter is added into the chain, we do :
-     * <ul>
-     * <li>check that we don't have a SSL filter already present
-     * <li>we update the next filter
-     * <li>we create the SSL handler helper class
-     * <li>and we store it into the session's Attributes
-     * </ul>
-     */
-    @Override
-    public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException {
-        // Check that we don't have a SSL filter already present in the chain
-        if (parent.contains(SslFilter.class)) {
-            String msg = "Only one SSL filter is permitted in a chain.";
-            LOGGER.error(msg);
-            throw new IllegalStateException(msg);
-        }
-
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("Adding the SSL Filter {} to the chain", name);
-        }
-
-        IoSession session = parent.getSession();
-        session.setAttribute(NEXT_FILTER, nextFilter);
-
-        // Create a SSL handler and start handshake.
-        SslHandler sslHandler = new SslHandler(this, session);
-        
-        // Adding the supported ciphers in the SSLHandler
-        if ((enabledCipherSuites == null) || (enabledCipherSuites.length == 0)) {
-            enabledCipherSuites = sslContext.getServerSocketFactory().getSupportedCipherSuites();
-        }
-
-        sslHandler.init();
-
-        session.setAttribute(SSL_HANDLER, sslHandler);
-    }
-
-    @Override
-    public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException {
-        if (autoStart == START_HANDSHAKE) {
-            initiateHandshake(nextFilter, parent.getSession());
-        }
-    }
-
-    @Override
-    public void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws SSLException {
-        IoSession session = parent.getSession();
-        stopSsl(session);
-        session.removeAttribute(NEXT_FILTER);
-        session.removeAttribute(SSL_HANDLER);
-    }
-
-    // IoFilter impl.
-    @Override
-    public void sessionClosed(NextFilter nextFilter, IoSession session) throws SSLException {
-        SslHandler sslHandler = getSslSessionHandler(session);
-
-        try {
-            synchronized (sslHandler) {
-                // release resources
-                sslHandler.destroy();
-            }
-        } finally {
-            // notify closed session
-            nextFilter.sessionClosed(session);
-        }
-    }
-
-    @Override
-    public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws SSLException {
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{}: Message received : {}", getSessionInfo(session), message);
-        }
-
-        SslHandler sslHandler = getSslSessionHandler(session);
-        AtomicBoolean canPushMessage = new AtomicBoolean( false );
-        
-        // The SslHandler instance is *guaranteed* to nit be null here
-
-        synchronized (sslHandler) {
-            if (sslHandler.isOutboundDone() && sslHandler.isInboundDone()) {
-                // We aren't handshaking here. Let's push the message to the next filter
-                
-                // Note: we can push the message to the queue immediately, 
-                // but don't do so in the synchronized block. We use a protected
-                // flag to do so.
-                canPushMessage.set( true );
-            } else {
-                canPushMessage.set( false );
-                IoBuffer buf = (IoBuffer) message;
-                
-                try {
-                    if (sslHandler.isOutboundDone()) {
-                        sslHandler.destroy();
-                        throw new SSLException("Outbound done");
-                    }
-                
-                    // forward read encrypted data to SSL handler
-                    sslHandler.messageReceived(nextFilter, buf.buf());
-                    
-                    // Handle data to be forwarded to application or written to net
-                    handleSslData(nextFilter, sslHandler);
-                    
-                    if (sslHandler.isInboundDone()) {
-                        if (sslHandler.isOutboundDone()) {
-                            sslHandler.destroy();
-                        } else {
-                            initiateClosure(nextFilter, session);
-                        }
-                    
-                        if (buf.hasRemaining()) {
-                            // Forward the data received after closure.
-                            sslHandler.scheduleMessageReceived(nextFilter, buf);
-                        }
-                    }
-                } catch (SSLException ssle) {
-                    if (!sslHandler.isHandshakeComplete()) {
-                        SSLException newSsle = new SSLHandshakeException("SSL handshake failed.");
-                        newSsle.initCause(ssle);
-                        ssle = newSsle;
-            
-                        // Close the session immediately, the handshake has failed
-                        session.closeNow();
-                    } else {
-                        // Free the SSL Handler buffers
-                        sslHandler.release();
-                    }
-                
-                    throw ssle;
-                }
-            }
-        }
-    
-        if (canPushMessage.get()) {
-            nextFilter.messageReceived(session, message);
-        } else {
-            sslHandler.flushMessageReceived();
-        }
-    }
-
-    @Override
-    public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) {
-        if (writeRequest instanceof EncryptedWriteRequest) {
-            EncryptedWriteRequest wrappedRequest = (EncryptedWriteRequest) writeRequest;
-            nextFilter.messageSent(session, wrappedRequest.getParentRequest());
-        } else {
-            // ignore extra buffers used for handshaking
-        }
-    }
-
-    @Override
-    public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
-
-        if (cause instanceof WriteToClosedSessionException) {
-            // Filter out SSL close notify, which is likely to fail to flush
-            // due to disconnection.
-            WriteToClosedSessionException e = (WriteToClosedSessionException) cause;
-            List<WriteRequest> failedRequests = e.getRequests();
-            boolean containsCloseNotify = false;
-
-            for (WriteRequest r : failedRequests) {
-                if (isCloseNotify(r.getMessage())) {
-                    containsCloseNotify = true;
-                    break;
-                }
-            }
-
-            if (containsCloseNotify) {
-                if (failedRequests.size() == 1) {
-                    // close notify is the only failed request; bail out.
-                    return;
-                }
-
-                List<WriteRequest> newFailedRequests = new ArrayList<>(failedRequests.size() - 1);
-
-                for (WriteRequest r : failedRequests) {
-                    if (!isCloseNotify(r.getMessage())) {
-                        newFailedRequests.add(r);
-                    }
-                }
-
-                if (newFailedRequests.isEmpty()) {
-                    // the failedRequests were full with close notify; bail out.
-                    return;
-                }
-
-                cause = new WriteToClosedSessionException(newFailedRequests, cause.getMessage(), cause.getCause());
-            }
-        }
-
-        nextFilter.exceptionCaught(session, cause);
-    }
-
-    private boolean isCloseNotify(Object message) {
-        if (!(message instanceof IoBuffer)) {
-            return false;
-        }
-
-        IoBuffer buf = (IoBuffer) message;
-        int offset = buf.position();
-
-        return (buf.get(offset + 0) == 0x15) /* Alert */
-                && (buf.get(offset + 1) == 0x03) /* TLS/SSL */
-                && ((buf.get(offset + 2) == 0x00) /* SSL 3.0 */
-                        || (buf.get(offset + 2) == 0x01) /* TLS 1.0 */
-                        || (buf.get(offset + 2) == 0x02) /* TLS 1.1 */
-                        || (buf.get(offset + 2) == 0x03)) /* TLS 1.2 */
-                        && (buf.get(offset + 3) == 0x00); /* close_notify */
-    }
-
-    @Override
-    public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws SSLException {
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{}: Writing Message : {}", getSessionInfo(session), writeRequest);
-        }
-
-        boolean needsFlush = true;
-        SslHandler sslHandler = getSslSessionHandler(session);
-
-        try {
-            synchronized (sslHandler) {
-                if (!isSslStarted(session)) {
-                    sslHandler.scheduleFilterWrite(nextFilter, writeRequest);
-                }
-                // Don't encrypt the data if encryption is disabled.
-                else if (session.containsAttribute(DISABLE_ENCRYPTION_ONCE)) {
-                    // Remove the marker attribute because it is temporary.
-                    session.removeAttribute(DISABLE_ENCRYPTION_ONCE);
-                    sslHandler.scheduleFilterWrite(nextFilter, writeRequest);
-                } else {
-                    // Otherwise, encrypt the buffer.
-                    IoBuffer buf = (IoBuffer) writeRequest.getMessage();
-
-                    if (sslHandler.isWritingEncryptedData()) {
-                        // data already encrypted; simply return buffer
-                        sslHandler.scheduleFilterWrite(nextFilter, writeRequest);
-                    } else if (sslHandler.isHandshakeComplete()) {
-                        // SSL encrypt
-                        sslHandler.encrypt(buf.buf());
-                        IoBuffer encryptedBuffer = sslHandler.fetchOutNetBuffer();
-                        writeRequest.setMessage( encryptedBuffer );
-                        sslHandler.scheduleFilterWrite(nextFilter, new EncryptedWriteRequest(writeRequest,
-                            encryptedBuffer));
-                    } else {
-                        if (session.isConnected()) {
-                            // Handshake not complete yet.
-                            sslHandler.schedulePreHandshakeWriteRequest(nextFilter, writeRequest);
-                        }
-
-                        needsFlush = false;
-                    }
-                }
-                if (needsFlush) {
-                    sslHandler.flushFilterWrite();
-                }
-            }
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        }
-    }
-
-    @Override
-    public void filterClose(final NextFilter nextFilter, final IoSession session) throws SSLException {
-        SslHandler sslHandler = (SslHandler) session.getAttribute(SSL_HANDLER);
-
-        if (sslHandler == null) {
-            // The connection might already have closed, or
-            // SSL might have not started yet.
-            nextFilter.filterClose(session);
-            return;
-        }
-
-        WriteFuture future = null;
-
-        try {
-            synchronized (sslHandler) {
-                if (isSslStarted(session)) {
-                    future = initiateClosure(nextFilter, session);
-                    future.addListener(new IoFutureListener<IoFuture>() {
-                        @Override
-                        public void operationComplete(IoFuture future) {
-                            nextFilter.filterClose(session);
-                        }
-                    });
-                }
-                sslHandler.flushFilterWrite();
-            }
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        } finally {
-            if (future == null) {
-                nextFilter.filterClose(session);
-            }
-        }
-    }
-
-    /**
-     * Initiate the SSL handshake. This can be invoked if you have set the 'autoStart' to
-     * false when creating the SslFilter instance.
-     * 
-     * @param session The session for which the SSL handshake should be done
-     * @throws SSLException If the handshake failed
-     */
-    public void initiateHandshake(IoSession session) throws SSLException {
-        IoFilterChain filterChain = session.getFilterChain();
-        
-        if (filterChain == null) {
-            throw new SSLException("No filter chain");
-        }
-        
-        IoFilter.NextFilter nextFilter = filterChain.getNextFilter(SslFilter.class);
-        
-        if (nextFilter == null) {
-            throw new SSLException("No SSL next filter in the chain");
-        }
-        
-        initiateHandshake(nextFilter, session);
-    }
-
-    private void initiateHandshake(NextFilter nextFilter, IoSession session) throws SSLException {
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{} : Starting the first handshake", getSessionInfo(session));
-        }
-        
-        SslHandler sslHandler = getSslSessionHandler(session);
-
-        try {
-            synchronized (sslHandler) {
-                sslHandler.handshake(nextFilter);
-                sslHandler.flushFilterWrite();
-            }
-            sslHandler.flushMessageReceived();
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        }
-    }
-
-    private WriteFuture initiateClosure(NextFilter nextFilter, IoSession session) throws SSLException {
-        SslHandler sslHandler = getSslSessionHandler(session);
-        WriteFuture future = null;
-
-        // if already shut down
-        try {
-            synchronized(sslHandler) {
-                if (!sslHandler.closeOutbound()) {
-                    return DefaultWriteFuture.newNotWrittenFuture(session, new IllegalStateException(
-                            "SSL session is shut down already."));
-                }
-    
-                // there might be data to write out here?
-                future = sslHandler.writeNetBuffer(nextFilter);
-    
-                if (future == null) {
-                    future = DefaultWriteFuture.newWrittenFuture(session);
-                }
-    
-                if (sslHandler.isInboundDone()) {
-                    sslHandler.destroy();
-                }
-            }
-
-            // Inform that the session is not any more secured
-            session.getFilterChain().fireEvent(SslEvent.UNSECURED);
-        } catch (SSLException se) {
-            sslHandler.release();
-            throw se;
-        }
-
-        return future;
-    }
-
-    // Utilities
-    private void handleSslData(NextFilter nextFilter, SslHandler sslHandler) throws SSLException {
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{}: Processing the SSL Data ", getSessionInfo(sslHandler.getSession()));
-        }
-
-        // Flush any buffered write requests occurred before handshaking.
-        if (sslHandler.isHandshakeComplete()) {
-            sslHandler.flushPreHandshakeEvents();
-        }
-
-        // Write encrypted data to be written (if any)
-        sslHandler.writeNetBuffer(nextFilter);
-
-        // handle app. data read (if any)
-        handleAppDataRead(nextFilter, sslHandler);
-    }
-
-    private void handleAppDataRead(NextFilter nextFilter, SslHandler sslHandler) {
-        // forward read app data
-        IoBuffer readBuffer = sslHandler.fetchAppBuffer();
-
-        if (readBuffer.hasRemaining()) {
-            sslHandler.scheduleMessageReceived(nextFilter, readBuffer);
-        }
-    }
-
-    private SslHandler getSslSessionHandler(IoSession session) {
-        SslHandler sslHandler = (SslHandler) session.getAttribute(SSL_HANDLER);
-
-        if (sslHandler == null) {
-            throw new IllegalStateException();
-        }
-
-        synchronized(sslHandler) {
-            if (sslHandler.getSslFilter() != this) {
-                throw new IllegalArgumentException("Not managed by this filter.");
-            }
-        }
-
-        return sslHandler;
-    }
-
-    /**
-     * A message that is sent from {@link SslFilter} when the connection became
-     * secure or is not secure anymore.
-     *
-     * @author <a href="http://mina.apache.org">Apache MINA Project</a>
-     */
-    public static class SslFilterMessage {
-        private final String name;
-
-        private SslFilterMessage(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-    
-    /**
-     * A private class used to store encrypted messages. This is necessary
-     * to be able to emit the messageSent event with the proper original
-     * message, but not for handshake messages, which will be swallowed.
-     *
-     */
-    /* package protected */ static class EncryptedWriteRequest extends DefaultWriteRequest {
-        // Thee encrypted messagee
-        private final IoBuffer encryptedMessage;
-        
-        // The original message
-        private WriteRequest parentRequest;
-
-        /**
-         * Create a new instance of an EncryptedWriteRequest
-         * @param writeRequest The parent request
-         * @param encryptedMessage The encrypted message
-         */
-        private EncryptedWriteRequest(WriteRequest writeRequest, IoBuffer encryptedMessage) {
-            super(encryptedMessage);
-            parentRequest = writeRequest;
-            this.encryptedMessage = encryptedMessage;
-        }
-
-        /**
-         * @return teh encrypted message
-         */
-        @Override
-        public Object getMessage() {
-            return encryptedMessage;
-        }
-
-        /**
-         * @return The parent WriteRequest
-         */
-        public WriteRequest getParentRequest() {
-            return parentRequest;
-        }
-        
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public WriteFuture getFuture() {
-            return parentRequest.getFuture();
-        }
-    }
-}
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslHandler.java b/mina-core/src/main/java/org/apache/mina/filter/ssl/SslHandler.java
deleted file mode 100644
index 6198100..0000000
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl/SslHandler.java
+++ /dev/null
@@ -1,872 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-package org.apache.mina.filter.ssl;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.mina.core.RuntimeIoException;
-import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.mina.core.filterchain.IoFilter.NextFilter;
-import org.apache.mina.core.filterchain.IoFilterEvent;
-import org.apache.mina.core.future.DefaultWriteFuture;
-import org.apache.mina.core.future.WriteFuture;
-import org.apache.mina.core.session.IoEventType;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.core.write.DefaultWriteRequest;
-import org.apache.mina.core.write.WriteRequest;
-import org.apache.mina.core.write.WriteRequestQueue;
-import org.apache.mina.filter.ssl.SslFilter.EncryptedWriteRequest;
-import org.apache.mina.filter.ssl2.SSL2Filter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A helper class using the SSLEngine API to decrypt/encrypt data.
- * <p/>
- * Each connection has a SSLEngine that is used through the lifetime of the connection.
- * We allocate buffers for use as the outbound and inbound network buffers.
- * These buffers handle all of the intermediary data for the SSL connection. To make things easy,
- * we'll require outNetBuffer be completely flushed before trying to wrap any more data.
- * <p/>
- * This class is not to be used by any client, it's closely associated with the SSL Filter.
- * None of its methods are public as they should not be used by any other class but from
- * the SslFilter class, in the same package
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-/** No qualifier*/
-class SslHandler {
-    /** A logger for this class */
-    private static final Logger LOGGER = LoggerFactory.getLogger(SslHandler.class);
-
-    /** The SSL Filter which has created this handler */
-    private final SslFilter sslFilter;
-
-    /** The current session */
-    private final IoSession session;
-
-    private final Queue<IoFilterEvent> preHandshakeEventQueue = new ConcurrentLinkedQueue<>();
-
-    private final Queue<IoFilterEvent> filterWriteEventQueue = new ConcurrentLinkedQueue<>();
-
-    /** A queue used to stack all the incoming data until the SSL session is established */
-    private final Queue<IoFilterEvent> messageReceivedEventQueue = new ConcurrentLinkedQueue<>();
-
-    private SSLEngine sslEngine;
-
-    /**
-     * Encrypted data from the net
-     */
-    private IoBuffer inNetBuffer;
-
-    /**
-     * Encrypted data to be written to the net
-     */
-    private IoBuffer outNetBuffer;
-
-    /**
-     * Application cleartext data to be read by application
-     */
-    private IoBuffer appBuffer;
-
-    /**
-     * Empty buffer used during initial handshake and close operations
-     */
-    private final IoBuffer emptyBuffer = IoBuffer.allocate(0);
-
-    private SSLEngineResult.HandshakeStatus handshakeStatus;
-
-    /**
-     * A flag set to true when the first SSL handshake has been completed
-     * This is used to avoid sending a notification to the application handler
-     * when we switch to a SECURE or UNSECURE session.
-     */
-    private boolean firstSSLNegociation;
-
-    /** A flag set to true when a SSL Handshake has been completed */
-    private boolean handshakeComplete;
-
-    /** A flag used to indicate to the SslFilter that the buffer
-     * it will write is already encrypted (this will be the case
-     * for data being produced during the handshake). */
-    private boolean writingEncryptedData;
-
-    /**
-     * Create a new SSL Handler, and initialize it.
-     *
-     * @param sslContext
-     * @throws SSLException
-     */
-    /* no qualifier */SslHandler(SslFilter sslFilter, IoSession session) {
-        this.sslFilter = sslFilter;
-        this.session = session;
-    }
-
-    /**
-     * Initialize the SSL handshake.
-     *
-     * @throws SSLException If the underlying SSLEngine handshake initialization failed
-     */
-    /* no qualifier */void init() throws SSLException {
-        if (sslEngine != null) {
-            // We already have a SSL engine created, no need to create a new one
-            return;
-        }
-
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{} Initializing the SSL Handler", sslFilter.getSessionInfo(session));
-        }
-
-        InetSocketAddress peer = (InetSocketAddress) session.getAttribute(SslFilter.PEER_ADDRESS);
-
-        // Create the SSL engine here
-        if (peer == null) {
-            sslEngine = sslFilter.sslContext.createSSLEngine();
-        } else {
-            sslEngine = sslFilter.sslContext.createSSLEngine(peer.getHostName(), peer.getPort());
-        }
-
-        // Initialize the engine in client mode if necessary
-        sslEngine.setUseClientMode(sslFilter.isUseClientMode());
-
-        // Initialize the different SslEngine modes
-        if (!sslEngine.getUseClientMode()) {
-            // Those parameters are only valid when in server mode
-            if (sslFilter.isWantClientAuth()) {
-                sslEngine.setWantClientAuth(true);
-            }
-
-            if (sslFilter.isNeedClientAuth()) {
-                sslEngine.setNeedClientAuth(true);
-            }
-        }
-
-        // Set the cipher suite to use by this SslEngine instance
-        if (sslFilter.getEnabledCipherSuites() != null) {
-            sslEngine.setEnabledCipherSuites(sslFilter.getEnabledCipherSuites());
-        }
-
-        // Set the list of enabled protocols
-        if (sslFilter.getEnabledProtocols() != null) {
-            sslEngine.setEnabledProtocols(sslFilter.getEnabledProtocols());
-        }
-
-        // TODO : we may not need to call this method...
-        // However, if we don't call it here, the tests are failing. Why?
-        handshakeStatus = sslEngine.getHandshakeStatus();
-
-        // Default value
-        writingEncryptedData = false;
-
-        // We haven't yet started a SSL negotiation
-        // set the flags accordingly
-        firstSSLNegociation = true;
-        handshakeComplete = false;
-
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{} SSL Handler Initialization done.", sslFilter.getSessionInfo(session));
-        }
-    }
-    
-
-    /**
-     * Release allocated buffers.
-     */
-    /* no qualifier */void destroy() {
-        if (sslEngine == null) {
-            return;
-        }
-
-        // Close inbound and flush all remaining data if available.
-        try {
-            sslEngine.closeInbound();
-        } catch (SSLException e) {
-            if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Unexpected exception from SSLEngine.closeInbound().", e);
-            }
-        }
-
-        if (outNetBuffer != null) {
-            outNetBuffer.capacity(sslEngine.getSession().getPacketBufferSize());
-        } else {
-            createOutNetBuffer(0);
-        }
-        try {
-            do {
-                outNetBuffer.clear();
-            } while (sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()).bytesProduced() > 0);
-        } catch (SSLException e) {
-            // Ignore.
-        } finally {
-            outNetBuffer.free();
-            outNetBuffer = null;
-        }
-
-        sslEngine.closeOutbound();
-        sslEngine = null;
-
-        preHandshakeEventQueue.clear();
-    }
-
-    /**
-     * @return The SSL filter which has created this handler
-     */
-    /* no qualifier */SslFilter getSslFilter() {
-        return sslFilter;
-    }
-
-    /* no qualifier */IoSession getSession() {
-        return session;
-    }
-
-    /**
-     * Check if we are writing encrypted data.
-     */
-    /* no qualifier */boolean isWritingEncryptedData() {
-        return writingEncryptedData;
-    }
-
-    /**
-     * Check if handshake is completed.
-     */
-    /* no qualifier */boolean isHandshakeComplete() {
-        return handshakeComplete;
-    }
-
-    /**
-     * Check if handshake is on going.
-     */
-    /* no qualifier */boolean notHandshaking() {
-        return handshakeStatus == HandshakeStatus.FINISHED || handshakeStatus == HandshakeStatus.NOT_HANDSHAKING;
-    }
-
-    /* no qualifier */boolean isInboundDone() {
-        return sslEngine == null || sslEngine.isInboundDone();
-    }
-
-    /* no qualifier */boolean isOutboundDone() {
-        return sslEngine == null || sslEngine.isOutboundDone();
-    }
-
-    /**
-     * Check if there is any need to complete handshake.
-     */
-    /* no qualifier */boolean needToCompleteHandshake() {
-        return handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone();
-    }
-
-    /* no qualifier */void schedulePreHandshakeWriteRequest(NextFilter nextFilter, WriteRequest writeRequest) {
-        preHandshakeEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest));
-    }
-
-    /* no qualifier */void flushPreHandshakeEvents() throws SSLException {
-        IoFilterEvent scheduledWrite;
-
-        while ((scheduledWrite = preHandshakeEventQueue.poll()) != null) {
-            sslFilter
-            .filterWrite(scheduledWrite.getNextFilter(), session, (WriteRequest) scheduledWrite.getParameter());
-        }
-    }
-
-    /* no qualifier */void scheduleFilterWrite(NextFilter nextFilter, WriteRequest writeRequest) {
-        filterWriteEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest));
-    }
-
-    /* no qualifier */void flushFilterWrite() {
-        // Fire events only when the lock is available for this handler.
-        IoFilterEvent event;
-    
-        // We need synchronization here inevitably because filterWrite can be
-        // called simultaneously and cause 'bad record MAC' integrity error.
-        while ((event = filterWriteEventQueue.poll()) != null) {
-            NextFilter nextFilter = event.getNextFilter();
-            nextFilter.filterWrite(session, (WriteRequest) event.getParameter());
-        }
-    }
-
-    /**
-     * Push the newly received data into a queue, waiting for the SSL session
-     * to be fully established
-     *
-     * @param nextFilter The next filter to call
-     * @param message The incoming data
-     */
-    /* no qualifier */void scheduleMessageReceived(NextFilter nextFilter, Object message) {
-        messageReceivedEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message));
-    }
-    
-    /* no qualifier */void flushMessageReceived() {
-        IoFilterEvent event;
-    
-        while ((event = messageReceivedEventQueue.poll()) != null) {
-            NextFilter nextFilter = event.getNextFilter();
-            nextFilter.messageReceived(session, event.getParameter());
-        }
-    }
-
-    /**
-     * Call when data are read from net. It will perform the initial hanshake or decrypt
-     * the data if SSL has been initialiaed.
-     * 
-     * @param buf buffer to decrypt
-     * @param nextFilter Next filter in chain
-     * @throws SSLException on errors
-     */
-    /* no qualifier */void messageReceived(NextFilter nextFilter, ByteBuffer buf) throws SSLException {
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("{} Processing the received message", sslFilter.getSessionInfo(session));
-        }
-
-        // append buf to inNetBuffer
-        if (inNetBuffer == null) {
-            inNetBuffer = IoBuffer.allocate(buf.remaining()).setAutoExpand(true);
-        }
-
-        inNetBuffer.put(buf);
-
-        if (!handshakeComplete) {
-            handshake(nextFilter);
-        } else {
-            // Prepare the net data for reading.
-            inNetBuffer.flip();
-
-            if (!inNetBuffer.hasRemaining()) {
-                return;
-            }
-
-            SSLEngineResult res = unwrap();
-
-            // prepare to be written again
-            if (inNetBuffer.hasRemaining()) {
-                inNetBuffer.compact();
-            } else {
-                inNetBuffer.free();
-                inNetBuffer = null;
-            }
-
-            checkStatus(res);
-
-            renegotiateIfNeeded(nextFilter, res);
-        }
-
-        if (isInboundDone()) {
-            // Rewind the MINA buffer if not all data is processed and inbound
-            // is finished.
-            int inNetBufferPosition = inNetBuffer == null ? 0 : inNetBuffer.position();
-            buf.position(buf.position() - inNetBufferPosition);
-
-            if (inNetBuffer != null) {
-                inNetBuffer.free();
-                inNetBuffer = null;
-            }
-        }
-    }
-
-    /**
-     * Get decrypted application data.
-     * 
-     * @return buffer with data
-     */
-    /* no qualifier */IoBuffer fetchAppBuffer() {
-        if (appBuffer == null) {
-            return IoBuffer.allocate(0);
-        } else {
-            IoBuffer newAppBuffer = appBuffer.flip();
-            appBuffer = null;
-
-            return newAppBuffer.shrink();
-        }
-    }
-
-    /**
-     * Get encrypted data to be sent.
-     * 
-     * @return buffer with data
-     */
-    /* no qualifier */IoBuffer fetchOutNetBuffer() {
-        IoBuffer answer = outNetBuffer;
-        
-        if (answer == null) {
-            return emptyBuffer;
-        }
-
-        outNetBuffer = null;
-        
-        return answer.shrink();
-    }
-
-    /**
-     * Encrypt provided buffer. Encrypted data returned by getOutNetBuffer().
-     * 
-     * @param src
-     *            data to encrypt
-     * @throws SSLException
-     *             on errors
-     */
-    /* no qualifier */void encrypt(ByteBuffer src) throws SSLException {
-        if (!handshakeComplete) {
-            throw new IllegalStateException();
-        }
-
-        if (!src.hasRemaining()) {
-            if (outNetBuffer == null) {
-                outNetBuffer = emptyBuffer;
-            }
-            return;
-        }
-
-        createOutNetBuffer(src.remaining());
-
-        // Loop until there is no more data in src
-        while (src.hasRemaining()) {
-
-            SSLEngineResult result = sslEngine.wrap(src, outNetBuffer.buf());
-            
-            if (result.getStatus() == SSLEngineResult.Status.OK) {
-                if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
-                    doTasks();
-                }
-            } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-                outNetBuffer.capacity(outNetBuffer.capacity() << 1);
-                outNetBuffer.limit(outNetBuffer.capacity());
-            } else {
-                throw new SSLException("SSLEngine error during encrypt: " + result.getStatus() + " src: " + src
-                        + "outNetBuffer: " + outNetBuffer);
-            }
-        }
-
-        outNetBuffer.flip();
-    }
-
-    /**
-     * Start SSL shutdown process.
-     * 
-     * @return <tt>true</tt> if shutdown process is started. <tt>false</tt> if
-     *         shutdown process is already finished.
-     * @throws SSLException
-     *             on errors
-     */
-    /* no qualifier */boolean closeOutbound() throws SSLException {
-        if (sslEngine == null || sslEngine.isOutboundDone()) {
-            return false;
-        }
-
-        sslEngine.closeOutbound();
-
-        createOutNetBuffer(0);
-        SSLEngineResult result;
-
-        for (;;) {
-            result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf());
-            if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-                outNetBuffer.capacity(outNetBuffer.capacity() << 1);
-                outNetBuffer.limit(outNetBuffer.capacity());
-            } else {
-                break;
-            }
-        }
-
-        if (result.getStatus() != SSLEngineResult.Status.CLOSED) {
-            throw new SSLException("Improper close state: " + result);
-        }
-
-        outNetBuffer.flip();
-
-        return true;
-    }
-
-    /**
-     * @param res
-     * @throws SSLException
-     */
-    private void checkStatus(SSLEngineResult res) throws SSLException {
-
-        SSLEngineResult.Status status = res.getStatus();
-
-        /*
-         * The status may be:
-         * OK - Normal operation
-         * OVERFLOW - Should never happen since the application buffer is sized to hold the maximum
-         * packet size.
-         * UNDERFLOW - Need to read more data from the socket. It's normal.
-         * CLOSED - The other peer closed the socket. Also normal.
-         */
-        switch (status) {
-            case BUFFER_OVERFLOW:
-                throw new SSLException("SSLEngine error during decrypt: " + status + " inNetBuffer: " + inNetBuffer
-                    + "appBuffer: " + appBuffer);
-            case CLOSED:
-                Exception exception =new RuntimeIoException("SSL/TLS close_notify received");
-                
-                // Empty the Ssl queue
-                for (IoFilterEvent event:filterWriteEventQueue) {
-                    EncryptedWriteRequest writeRequest = (EncryptedWriteRequest)event.getParameter();
-                    WriteFuture writeFuture = writeRequest.getParentRequest().getFuture();
-                    writeFuture.setException(exception);
-                    writeFuture.notifyAll();
-                }
-                
-                // Empty the session queue
-                WriteRequestQueue queue = session.getWriteRequestQueue();
-                WriteRequest request = null;
-               
-    	    	while ((request = queue.poll(session)) != null) {
-    	    	    WriteFuture writeFuture = request.getFuture();
-    	    	    writeFuture.setException(exception);
-    	    	    writeFuture.notifyAll();
-        	}
-                    
-                // We *must* shutdown session
-                session.closeNow();
-                break;
-            default: 
-                break;
-        }
-    }
-
-    /**
-     * Perform any handshaking processing.
-     */
-    /* no qualifier */void handshake(NextFilter nextFilter) throws SSLException {
-        for (;;) {
-            switch (handshakeStatus) {
-            case FINISHED:
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("{} processing the FINISHED state", sslFilter.getSessionInfo(session));
-                }
-
-                session.setAttribute(SslFilter.SSL_SESSION, sslEngine.getSession());
-                handshakeComplete = true;
-
-                // Send the SECURE message only if it's the first SSL handshake
-                if (firstSSLNegociation) {
-                    firstSSLNegociation = false;
-                    this.session.setAttribute(SSL2Filter.SSL_SECURED, this);
-                    nextFilter.event(session, SslEvent.SECURED);
-                }
-
-                if (LOGGER.isDebugEnabled()) {
-                    if (!isOutboundDone()) {
-                        LOGGER.debug("{} is now secured", sslFilter.getSessionInfo(session));
-                    } else {
-                        LOGGER.debug("{} is not secured yet", sslFilter.getSessionInfo(session));
-                    }
-                }
-
-                return;
-
-            case NEED_TASK:
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("{} processing the NEED_TASK state", sslFilter.getSessionInfo(session));
-                }
-
-                handshakeStatus = doTasks();
-                break;
-
-            case NEED_UNWRAP:
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("{} processing the NEED_UNWRAP state", sslFilter.getSessionInfo(session));
-                }
-                // we need more data read
-                SSLEngineResult.Status status = unwrapHandshake(nextFilter);
-
-                if (status == SSLEngineResult.Status.BUFFER_UNDERFLOW
-                        && handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED || isInboundDone()) {
-                    // We need more data or the session is closed
-                    return;
-                }
-
-                break;
-
-            case NEED_WRAP:
-            case NOT_HANDSHAKING:
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("{} processing the NEED_WRAP state", sslFilter.getSessionInfo(session));
-                }
-
-                // First make sure that the out buffer is completely empty.
-                // Since we cannot call wrap with data left on the buffer
-                if (outNetBuffer != null && outNetBuffer.hasRemaining()) {
-                    return;
-                }
-
-                SSLEngineResult result;
-                createOutNetBuffer(0);
-
-                result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf());
-
-                while ( result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW ) {
-                    outNetBuffer.capacity(outNetBuffer.capacity() << 1);
-                    outNetBuffer.limit(outNetBuffer.capacity());
-
-                    result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf());
-                }
-
-                outNetBuffer.flip();
-                handshakeStatus = result.getHandshakeStatus();
-                writeNetBuffer(nextFilter);
-                break;
-
-            default:
-                String msg = "Invalid Handshaking State" + handshakeStatus
-                + " while processing the Handshake for session " + session.getId();
-                LOGGER.error(msg);
-                throw new IllegalStateException(msg);
-            }
-        }
-    }
-
-    private void createOutNetBuffer(int expectedRemaining) {
-        // SSLEngine requires us to allocate unnecessarily big buffer
-        // even for small data. *Shrug*
-        int capacity = Math.max(expectedRemaining, sslEngine.getSession().getPacketBufferSize());
-
-        if (outNetBuffer != null) {
-            outNetBuffer.capacity(capacity);
-        } else {
-            outNetBuffer = IoBuffer.allocate(capacity).minimumCapacity(0);
-        }
-    }
-
-    /* no qualifier */WriteFuture writeNetBuffer(NextFilter nextFilter) throws SSLException {
-        // Check if any net data needed to be writen
-        if (outNetBuffer == null || !outNetBuffer.hasRemaining()) {
-            // no; bail out
-            return null;
-        }
-
-        // set flag that we are writing encrypted data
-        // (used in SSLFilter.filterWrite())
-        writingEncryptedData = true;
-
-        // write net data
-        WriteFuture writeFuture = null;
-
-        try {
-            IoBuffer writeBuffer = fetchOutNetBuffer();
-            writeFuture = new DefaultWriteFuture(session);
-            sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(writeBuffer, writeFuture));
-
-            // loop while more writes required to complete handshake
-            while (needToCompleteHandshake()) {
-                try {
-                    handshake(nextFilter);
-                } catch (SSLException ssle) {
-                    SSLException newSsle = new SSLHandshakeException("SSL handshake failed.");
-                    newSsle.initCause(ssle);
-                    throw newSsle;
-                }
-
-                IoBuffer currentOutNetBuffer = fetchOutNetBuffer();
-                
-                if (currentOutNetBuffer != null && currentOutNetBuffer.hasRemaining()) {
-                    writeFuture = new DefaultWriteFuture(session);
-                    sslFilter.filterWrite(nextFilter, session, new DefaultWriteRequest(currentOutNetBuffer, writeFuture));
-                }
-            }
-        } finally {
-            writingEncryptedData = false;
-        }
-
-        return writeFuture;
-    }
-
-    private SSLEngineResult.Status unwrapHandshake(NextFilter nextFilter) throws SSLException {
-        // Prepare the net data for reading.
-        if (inNetBuffer != null) {
-            inNetBuffer.flip();
-        }
-
-        if ((inNetBuffer == null) || !inNetBuffer.hasRemaining()) {
-            // Need more data.
-            return SSLEngineResult.Status.BUFFER_UNDERFLOW;
-        }
-
-        SSLEngineResult res = unwrap();
-        handshakeStatus = res.getHandshakeStatus();
-
-        checkStatus(res);
-
-        // If handshake finished, no data was produced, and the status is still
-        // ok, try to unwrap more
-        if ((handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED)
-                && (res.getStatus() == SSLEngineResult.Status.OK)
-                && inNetBuffer.hasRemaining()) {
-            res = unwrap();
-
-            // prepare to be written again
-            if (inNetBuffer.hasRemaining()) {
-                inNetBuffer.compact();
-            } else {
-                inNetBuffer.free();
-                inNetBuffer = null;
-            }
-
-            renegotiateIfNeeded(nextFilter, res);
-        } else {
-            // prepare to be written again
-            if (inNetBuffer.hasRemaining()) {
-                inNetBuffer.compact();
-            } else {
-                inNetBuffer.free();
-                inNetBuffer = null;
-            }
-        }
-
-        return res.getStatus();
-    }
-
-    private void renegotiateIfNeeded(NextFilter nextFilter, SSLEngineResult res) throws SSLException {
-        if ((res.getStatus() != SSLEngineResult.Status.CLOSED)
-                && (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW)
-                && (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) {
-            // Renegotiation required.
-            handshakeComplete = false;
-            handshakeStatus = res.getHandshakeStatus();
-            handshake(nextFilter);
-        }
-    }
-
-    /**
-     * Decrypt the incoming buffer and move the decrypted data to an
-     * application buffer.
-     */
-    private SSLEngineResult unwrap() throws SSLException {
-        // We first have to create the application buffer if it does not exist
-        if (appBuffer == null) {
-            appBuffer = IoBuffer.allocate(inNetBuffer.remaining());
-        } else {
-            // We already have one, just add the new data into it
-            appBuffer.expand(inNetBuffer.remaining());
-        }
-
-        SSLEngineResult res;
-        Status status;
-        HandshakeStatus localHandshakeStatus;
-
-        do {
-            // Decode the incoming data
-            res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf());
-            status = res.getStatus();
-
-            // We can be processing the Handshake
-            localHandshakeStatus = res.getHandshakeStatus();
-
-            if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-                // We have to grow the target buffer, it's too small.
-                // Then we can call the unwrap method again
-                int newCapacity = sslEngine.getSession().getApplicationBufferSize();
-                
-                if (appBuffer.remaining() >= newCapacity) {
-                    // The buffer is already larger than the max buffer size suggested by the SSL engine.
-                    // Raising it any more will not make sense and it will end up in an endless loop. Throwing an error is safer
-                    throw new SSLException("SSL buffer overflow");
-                }
-
-                appBuffer.expand(newCapacity);
-                continue;
-            }
-        } while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW))
-                && ((localHandshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) || 
-                        (localHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)));
-
-        return res;
-    }
-
-    /**
-     * Do all the outstanding handshake tasks in the current Thread.
-     */
-    private SSLEngineResult.HandshakeStatus doTasks() {
-        /*
-         * We could run this in a separate thread, but I don't see the need for
-         * this when used from SSLFilter. Use thread filters in MINA instead?
-         */
-        Runnable runnable;
-        while ((runnable = sslEngine.getDelegatedTask()) != null) {
-            // TODO : we may have to use a thread pool here to improve the
-            // performances
-            runnable.run();
-        }
-        return sslEngine.getHandshakeStatus();
-    }
-
-    /**
-     * Creates a new MINA buffer that is a deep copy of the remaining bytes in
-     * the given buffer (between index buf.position() and buf.limit())
-     * 
-     * @param src
-     *            the buffer to copy
-     * @return the new buffer, ready to read from
-     */
-    /* no qualifier */static IoBuffer copy(ByteBuffer src) {
-        IoBuffer copy = IoBuffer.allocate(src.remaining());
-        copy.put(src);
-        copy.flip();
-        return copy;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("SSLStatus <");
-
-        if (handshakeComplete) {
-            sb.append("SSL established");
-        } else {
-            sb.append("Processing Handshake").append("; ");
-            sb.append("Status : ").append(handshakeStatus).append("; ");
-        }
-
-        sb.append(", ");
-        sb.append("HandshakeComplete :").append(handshakeComplete).append(", ");
-        sb.append(">");
-
-        return sb.toString();
-    }
-
-    /**
-     * Free the allocated buffers
-     */
-    /* no qualifier */void release() {
-        if (inNetBuffer != null) {
-            inNetBuffer.free();
-            inNetBuffer = null;
-        }
-
-        if (outNetBuffer != null) {
-            outNetBuffer.free();
-            outNetBuffer = null;
-        }
-    }
-}
diff --git a/mina-core/src/main/java/org/apache/mina/filter/ssl2/EncryptedWriteRequest.java b/mina-core/src/main/java/org/apache/mina/filter/ssl2/EncryptedWriteRequest.java
deleted file mode 100644
index caf32d7..0000000
--- a/mina-core/src/main/java/org/apache/mina/filter/ssl2/EncryptedWriteRequest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.apache.mina.filter.ssl2;
-
-import org.apache.mina.core.write.DefaultWriteRequest;
-import org.apache.mina.core.write.WriteRequest;
-
-public class EncryptedWriteRequest extends DefaultWriteRequest {
-
-	// The original message
-	private WriteRequest originalRequest;
-
-	public EncryptedWriteRequest(Object encodedMessage, WriteRequest parent) {
-		super(encodedMessage, parent != null ? parent.getFuture() : null);
-		this.originalRequest = parent != null ? parent : this;
-	}
-
-	public WriteRequest getOriginalRequest() {
-		return this.originalRequest;
-	}
-}
\ No newline at end of file
diff --git a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.java b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.java
index 34064a3..4fb1b5f 100644
--- a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.java
+++ b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioSocketSession.java
@@ -27,16 +27,12 @@ import java.nio.channels.SocketChannel;
 import org.apache.mina.core.RuntimeIoException;
 import org.apache.mina.core.buffer.IoBuffer;
 import org.apache.mina.core.file.FileRegion;
-import org.apache.mina.core.filterchain.IoFilter;
-import org.apache.mina.core.filterchain.IoFilterChain;
 import org.apache.mina.core.service.DefaultTransportMetadata;
 import org.apache.mina.core.service.IoProcessor;
 import org.apache.mina.core.service.IoService;
 import org.apache.mina.core.service.TransportMetadata;
 import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.ssl.SslFilter;
-import org.apache.mina.filter.ssl2.SSL2Filter;
-import org.apache.mina.filter.ssl2.SSL2Handler;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
 import org.apache.mina.transport.socket.SocketSessionConfig;
 
@@ -344,6 +340,6 @@ class NioSocketSession extends NioSession {
 	 */
 	@Override
 	public final boolean isSecured() {
-		return (this.getAttribute(SSL2Filter.SSL_SECURED) != null);
+		return (this.getAttribute(SSLFilter.SSL_SECURED) != null);
 	}
 }
diff --git a/mina-core/src/test/java/org/apache/mina/core/service/SslTestHandshakeExceptionDIRMINA1077Test.java b/mina-core/src/test/java/org/apache/mina/core/service/SslTestHandshakeExceptionDIRMINA1077Test.java
index a44c9c7..9561f7e 100644
--- a/mina-core/src/test/java/org/apache/mina/core/service/SslTestHandshakeExceptionDIRMINA1077Test.java
+++ b/mina-core/src/test/java/org/apache/mina/core/service/SslTestHandshakeExceptionDIRMINA1077Test.java
@@ -22,33 +22,31 @@ package org.apache.mina.core.service;
 
 import static org.junit.Assert.fail;
 
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.Security;
+import java.util.concurrent.CountDownLatch;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
 import org.apache.mina.core.future.ConnectFuture;
-import org.apache.mina.core.service.AbstractIoService;
-import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.mina.util.AvailablePortFinder;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManagerFactory;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Security;
-import java.util.concurrent.CountDownLatch;
-
 /**
  * Test a SSL session and provoke HandshakeException.
  * This test should not hang or timeout when DIRMINA-1076/1077 is fixed.
@@ -92,7 +90,7 @@ public class SslTestHandshakeExceptionDIRMINA1077Test {
         DefaultIoFilterChainBuilder filters = acceptor.getFilterChain();
 
         // Inject the SSL filter
-        SslFilter sslFilter = new SslFilter(createSSLContext(true));
+        SSLFilter sslFilter = new SSLFilter(createSSLContext(true));
         filters.addLast("sslFilter", sslFilter);
         sslFilter.setNeedClientAuth(true);
 
@@ -113,8 +111,7 @@ public class SslTestHandshakeExceptionDIRMINA1077Test {
         DefaultIoFilterChainBuilder filters = nioSocketConnector.getFilterChain();
 
         // Inject the SSL filter
-        SslFilter sslFilter = new SslFilter(createSSLContext(false));
-        sslFilter.setUseClientMode( true );
+        SSLFilter sslFilter = new SSLFilter(createSSLContext(false));
         filters.addLast("sslFilter", sslFilter);
 
         address = InetAddress.getByName("localhost");
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslDIRMINA937Test.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java
similarity index 94%
rename from mina-core/src/test/java/org/apache/mina/filter/ssl/SslDIRMINA937Test.java
rename to mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java
index 3fe5c45..da3f66e 100644
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslDIRMINA937Test.java
+++ b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLDIRMINA937Test.java
@@ -50,7 +50,7 @@ import org.junit.Test;
  *
  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
  */
-public class SslDIRMINA937Test {
+public class SSLDIRMINA937Test {
     /** A static port used for his test, chosen to avoid collisions */
     private static final int port = AvailablePortFinder.getNextAvailable(5555);
 
@@ -92,7 +92,7 @@ public class SslDIRMINA937Test {
 
         // Inject the SSL filter
         SSLContext context = createSSLContext("TLSv1");
-        SslFilter sslFilter = new SslFilter(context);
+        SSLFilter sslFilter = new SSLFilter(context);
         sslFilter.setEnabledProtocols(new String[] { "TLSv1" });
         //sslFilter.setEnabledCipherSuites(getServerCipherSuites(context.getDefaultSSLParameters().getCipherSuites()));
         filters.addLast("sslFilter", sslFilter);
@@ -111,9 +111,8 @@ public class SslDIRMINA937Test {
         NioSocketConnector connector = new NioSocketConnector();
         
         DefaultIoFilterChainBuilder filters = connector.getFilterChain();
-        SslFilter sslFilter = new SslFilter(createSSLContext("TLSv1.1"));
+        SSLFilter sslFilter = new SSLFilter(createSSLContext("TLSv1.1"));
         sslFilter.setEnabledProtocols(new String[] { "TLSv1.1" });
-        sslFilter.setUseClientMode(true);
         //sslFilter.setEnabledCipherSuites(getClientCipherSuites());
         filters.addLast("sslFilter", sslFilter);
         connector.setHandler(new IoHandlerAdapter() {
@@ -123,7 +122,7 @@ public class SslDIRMINA937Test {
 
             @Override
             public void event(IoSession session, FilterEvent event) throws Exception {
-                if (event == SslEvent.UNSECURED ) {
+                if (event == SSLEvent.UNSECURED ) {
                     counter.countDown();
                 }
             }
@@ -141,8 +140,8 @@ public class SslDIRMINA937Test {
         KeyStore ks = KeyStore.getInstance("JKS");
         KeyStore ts = KeyStore.getInstance("JKS");
 
-        ks.load(SslDIRMINA937Test.class.getResourceAsStream("keystore.sslTest"), passphrase);
-        ts.load(SslDIRMINA937Test.class.getResourceAsStream("truststore.sslTest"), passphrase);
+        ks.load(SSLDIRMINA937Test.class.getResourceAsStream("keystore.sslTest"), passphrase);
+        ts.load(SSLDIRMINA937Test.class.getResourceAsStream("truststore.sslTest"), passphrase);
 
         kmf.init(ks, passphrase);
         tmf.init(ts);
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java
new file mode 100644
index 0000000..54937d8
--- /dev/null
+++ b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLEngineTest.java
@@ -0,0 +1,465 @@
+package org.apache.mina.filter.ssl;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.Security;
+import java.util.Deque;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLEngineResult.Status;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.mina.core.buffer.IoBuffer;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class SSLEngineTest {
+	private BlockingDeque<ByteBuffer> clientQueue = new LinkedBlockingDeque<>();
+	private BlockingDeque<ByteBuffer> serverQueue = new LinkedBlockingDeque<>();
+
+	private class Handshaker implements Runnable {
+		private SSLEngine sslEngine;
+		private ByteBuffer workBuffer;
+		private ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
+
+		private void push(Deque<ByteBuffer> queue, ByteBuffer buffer) {
+			ByteBuffer result = ByteBuffer.allocate(buffer.capacity());
+			result.put(buffer);
+			queue.addFirst(result);
+		}
+
+		public void run() {
+			HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
+			SSLEngineResult result;
+
+			try {
+				while (handshakeStatus != HandshakeStatus.FINISHED) {
+					switch (handshakeStatus) {
+						case NEED_TASK:
+							break;
+
+						case NEED_UNWRAP:
+							// The SSLEngine waits for some input.
+							// We may have received too few data (TCP fragmentation)
+							//
+							ByteBuffer data = serverQueue.takeLast();
+							result = sslEngine.unwrap(data, workBuffer);
+
+							while (result.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
+								// We need more data, until then, wait.
+								// ByteBuffer data = serverQueue.takeLast();
+								result = sslEngine.unwrap(data, workBuffer);
+							}
+
+							handshakeStatus = sslEngine.getHandshakeStatus();
+							break;
+
+						case NEED_WRAP:
+						case NOT_HANDSHAKING:
+							result = sslEngine.wrap(emptyBuffer, workBuffer);
+
+							workBuffer.flip();
+
+							if (workBuffer.hasRemaining()) {
+								push(clientQueue, workBuffer);
+								workBuffer.clear();
+							}
+
+							handshakeStatus = result.getHandshakeStatus();
+
+							break;
+
+						case FINISHED:
+
+					}
+				}
+			} catch (SSLException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (InterruptedException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+
+		public Handshaker(SSLEngine sslEngine) {
+			this.sslEngine = sslEngine;
+			int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
+			workBuffer = ByteBuffer.allocate(packetBufferSize);
+		}
+	}
+
+	/** A JVM independant KEY_MANAGER_FACTORY algorithm */
+	private static final String KEY_MANAGER_FACTORY_ALGORITHM;
+
+	static {
+		String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
+		if (algorithm == null) {
+			algorithm = KeyManagerFactory.getDefaultAlgorithm();
+		}
+
+		KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
+	}
+
+	/** App data buffer for the client SSLEngine */
+	private IoBuffer inNetBufferClient;
+
+	/** Net data buffer for the client SSLEngine */
+	private IoBuffer outNetBufferClient;
+
+	/** App data buffer for the server SSLEngine */
+	private IoBuffer inNetBufferServer;
+
+	/** Net data buffer for the server SSLEngine */
+	private IoBuffer outNetBufferServer;
+
+	private final IoBuffer emptyBuffer = IoBuffer.allocate(0);
+
+	private static SSLContext createSSLContext() throws IOException, GeneralSecurityException {
+		char[] passphrase = "password".toCharArray();
+
+		SSLContext ctx = SSLContext.getInstance("TLS");
+		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
+		TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
+
+		KeyStore ks = KeyStore.getInstance("JKS");
+		KeyStore ts = KeyStore.getInstance("JKS");
+
+		ks.load(SSLEngineTest.class.getResourceAsStream("keystore.jks"), passphrase);
+		ts.load(SSLEngineTest.class.getResourceAsStream("truststore.jks"), passphrase);
+
+		kmf.init(ks, passphrase);
+		tmf.init(ts);
+		ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+		return ctx;
+	}
+
+	/**
+	 * Decrypt the incoming buffer and move the decrypted data to an application
+	 * buffer.
+	 */
+	private SSLEngineResult unwrap(SSLEngine sslEngine, IoBuffer inBuffer, IoBuffer outBuffer) throws SSLException {
+		// We first have to create the application buffer if it does not exist
+		if (outBuffer == null) {
+			outBuffer = IoBuffer.allocate(inBuffer.remaining());
+		} else {
+			// We already have one, just add the new data into it
+			outBuffer.expand(inBuffer.remaining());
+		}
+
+		SSLEngineResult res;
+		Status status;
+		HandshakeStatus localHandshakeStatus;
+
+		do {
+			// Decode the incoming data
+			res = sslEngine.unwrap(inBuffer.buf(), outBuffer.buf());
+			status = res.getStatus();
+
+			// We can be processing the Handshake
+			localHandshakeStatus = res.getHandshakeStatus();
+
+			if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
+				// We have to grow the target buffer, it's too small.
+				// Then we can call the unwrap method again
+				int newCapacity = sslEngine.getSession().getApplicationBufferSize();
+
+				if (inBuffer.remaining() >= newCapacity) {
+					// The buffer is already larger than the max buffer size suggested by the SSL
+					// engine.
+					// Raising it any more will not make sense and it will end up in an endless
+					// loop. Throwing an error is safer
+					throw new SSLException("SSL buffer overflow");
+				}
+
+				inBuffer.expand(newCapacity);
+				continue;
+			}
+		} while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW))
+				&& ((localHandshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
+						|| (localHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)));
+
+		return res;
+	}
+
+	private SSLEngineResult.Status unwrapHandshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer)
+			throws SSLException {
+		// Prepare the net data for reading.
+		if ((appBuffer == null) || !appBuffer.hasRemaining()) {
+			// Need more data.
+			return SSLEngineResult.Status.BUFFER_UNDERFLOW;
+		}
+
+		SSLEngineResult res = unwrap(sslEngine, appBuffer, netBuffer);
+		HandshakeStatus handshakeStatus = res.getHandshakeStatus();
+
+		// checkStatus(res);
+
+		// If handshake finished, no data was produced, and the status is still
+		// ok, try to unwrap more
+		if ((handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED)
+				&& (res.getStatus() == SSLEngineResult.Status.OK) && appBuffer.hasRemaining()) {
+			res = unwrap(sslEngine, appBuffer, netBuffer);
+
+			// prepare to be written again
+			if (appBuffer.hasRemaining()) {
+				appBuffer.compact();
+			} else {
+				appBuffer.free();
+				appBuffer = null;
+			}
+		} else {
+			// prepare to be written again
+			if (appBuffer.hasRemaining()) {
+				appBuffer.compact();
+			} else {
+				appBuffer.free();
+				appBuffer = null;
+			}
+		}
+
+		return res.getStatus();
+	}
+
+	/* no qualifier */boolean isInboundDone(SSLEngine sslEngine) {
+		return sslEngine == null || sslEngine.isInboundDone();
+	}
+
+	/* no qualifier */boolean isOutboundDone(SSLEngine sslEngine) {
+		return sslEngine == null || sslEngine.isOutboundDone();
+	}
+
+	/**
+	 * Perform any handshaking processing.
+	 */
+	/* no qualifier */HandshakeStatus handshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer)
+			throws SSLException {
+		SSLEngineResult result;
+		HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
+
+		for (;;) {
+			switch (handshakeStatus) {
+				case FINISHED:
+					// handshakeComplete = true;
+					return handshakeStatus;
+
+				case NEED_TASK:
+					// handshakeStatus = doTasks();
+					break;
+
+				case NEED_UNWRAP:
+					// we need more data read
+					SSLEngineResult.Status status = unwrapHandshake(sslEngine, appBuffer, netBuffer);
+					handshakeStatus = sslEngine.getHandshakeStatus();
+
+					return handshakeStatus;
+
+				case NEED_WRAP:
+					result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
+
+					while (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
+						netBuffer.capacity(netBuffer.capacity() << 1);
+						netBuffer.limit(netBuffer.capacity());
+
+						result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
+					}
+
+					netBuffer.flip();
+					return result.getHandshakeStatus();
+
+				case NOT_HANDSHAKING:
+					result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
+
+					while (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
+						netBuffer.capacity(netBuffer.capacity() << 1);
+						netBuffer.limit(netBuffer.capacity());
+
+						result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
+					}
+
+					netBuffer.flip();
+					handshakeStatus = result.getHandshakeStatus();
+					return handshakeStatus;
+
+				default:
+					throw new IllegalStateException("error");
+			}
+		}
+	}
+
+	/**
+	 * Do all the outstanding handshake tasks in the current Thread.
+	 */
+	private SSLEngineResult.HandshakeStatus doTasks(SSLEngine sslEngine) {
+		/*
+		 * We could run this in a separate thread, but I don't see the need for this
+		 * when used from SSLFilter. Use thread filters in MINA instead?
+		 */
+		Runnable runnable;
+		while ((runnable = sslEngine.getDelegatedTask()) != null) {
+			// Thread thread = new Thread(runnable);
+			// thread.start();
+			runnable.run();
+		}
+		return sslEngine.getHandshakeStatus();
+	}
+
+	private HandshakeStatus handshake(SSLEngine sslEngine, HandshakeStatus expected, IoBuffer inBuffer,
+			IoBuffer outBuffer, boolean dumpBuffer) throws SSLException {
+		HandshakeStatus handshakeStatus = handshake(sslEngine, inBuffer, outBuffer);
+
+		if (handshakeStatus != expected) {
+			fail();
+		}
+
+		if (dumpBuffer) {
+			System.out.println("Message:" + outBuffer);
+		}
+
+		return handshakeStatus;
+	}
+
+	@Test
+	@Ignore
+	public void testSSL() throws Exception {
+		// Initialise the client SSLEngine
+		SSLContext sslContextClient = createSSLContext();
+		SSLEngine sslEngineClient = sslContextClient.createSSLEngine();
+		int packetBufferSize = sslEngineClient.getSession().getPacketBufferSize();
+		inNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
+		outNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
+
+		sslEngineClient.setUseClientMode(true);
+
+		// Initialise the Server SSLEngine
+		SSLContext sslContextServer = createSSLContext();
+		SSLEngine sslEngineServer = sslContextServer.createSSLEngine();
+		packetBufferSize = sslEngineServer.getSession().getPacketBufferSize();
+		inNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
+		outNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
+
+		sslEngineServer.setUseClientMode(false);
+
+		Handshaker handshakerClient = new Handshaker(sslEngineClient);
+		Handshaker handshakerServer = new Handshaker(sslEngineServer);
+
+		handshakerServer.run();
+
+		HandshakeStatus handshakeStatusClient = sslEngineClient.getHandshakeStatus();
+		HandshakeStatus handshakeStatusServer = sslEngineServer.getHandshakeStatus();
+
+		// <<< Server
+		// Start the server
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, null, outNetBufferServer,
+				false);
+
+		// >>> Client
+		// Now start the client, which will generate a CLIENT_HELLO,
+		// stored into the outNetBufferClient
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, null, outNetBufferClient, true);
+
+		// <<< Server
+		// Process the CLIENT_HELLO on the server
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, outNetBufferClient,
+				outNetBufferServer, false);
+
+		// Process the tasks on the server, prepare the SERVER_HELLO message
+		handshakeStatusServer = doTasks(sslEngineServer);
+
+		// We should be ready to generate the SERVER_HELLO message
+		if (handshakeStatusServer != HandshakeStatus.NEED_WRAP) {
+			fail();
+		}
+
+		// Get the SERVER_HELLO message, with all the associated messages
+		// ([Certificate], [ServerKeyExchange], [CertificateRequest], ServerHelloDone)
+		outNetBufferServer.clear();
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, null, outNetBufferServer, true);
+
+		// >>> Client
+		// Process the SERVER_HELLO message on the client
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_TASK, outNetBufferServer,
+				inNetBufferClient, false);
+
+		// Prepare the client response
+		handshakeStatusClient = doTasks(sslEngineClient);
+
+		// We should get back the Client messages ([Certificate],
+		// ClientKeyExchange, [CertificateVerify])
+		if (handshakeStatusClient != HandshakeStatus.NEED_WRAP) {
+			fail();
+		}
+
+		// Generate the [Certificate], ClientKeyExchange, [CertificateVerify] messages
+		outNetBufferClient.clear();
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, null, outNetBufferClient, true);
+
+		// <<< Server
+		// Process the CLIENT_KEY_EXCHANGE on the server
+		outNetBufferServer.clear();
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, outNetBufferClient,
+				outNetBufferServer, false);
+
+		// Do the controls
+		handshakeStatusServer = doTasks(sslEngineServer);
+
+		// The server is waiting for more
+		if (handshakeStatusServer != HandshakeStatus.NEED_UNWRAP) {
+			fail();
+		}
+
+		// >>> Client
+		// The CHANGE_CIPHER_SPEC message generation
+		outNetBufferClient.clear();
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, null, outNetBufferClient, true);
+
+		// <<< Server
+		// Process the CHANGE_CIPHER_SPEC on the server
+		outNetBufferServer.clear();
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, outNetBufferClient,
+				outNetBufferServer, false);
+
+		// >>> Client
+		// Generate the FINISHED message on thee client
+		outNetBufferClient.clear();
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, null, outNetBufferClient, true);
+
+		// <<< Server
+		// Process the client FINISHED message
+		outNetBufferServer.clear();
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, outNetBufferClient,
+				outNetBufferServer, false);
+
+		// Generate the CHANGE_CIPHER_SPEC message on the server
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, null, outNetBufferServer, true);
+
+		// >>> Client
+		// Process the server CHANGE_SCIPHER_SPEC message on the client
+		outNetBufferClient.clear();
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, outNetBufferServer,
+				outNetBufferClient, false);
+
+		// <<< Server
+		// Generate the server FINISHED message
+		outNetBufferServer.clear();
+		handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.FINISHED, null, outNetBufferServer, true);
+
+		// >>> Client
+		// Process the server FINISHED message on the client
+		outNetBufferClient.clear();
+		handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NOT_HANDSHAKING, outNetBufferServer,
+				outNetBufferClient, false);
+	}
+}
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl2/SSL2SimpleTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLFilterMain.java
similarity index 91%
rename from mina-core/src/test/java/org/apache/mina/filter/ssl2/SSL2SimpleTest.java
rename to mina-core/src/test/java/org/apache/mina/filter/ssl/SSLFilterMain.java
index ce1a310..841e777 100644
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl2/SSL2SimpleTest.java
+++ b/mina-core/src/test/java/org/apache/mina/filter/ssl/SSLFilterMain.java
@@ -1,4 +1,4 @@
-package org.apache.mina.filter.ssl2;
+package org.apache.mina.filter.ssl;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -21,13 +21,12 @@ import org.apache.mina.core.service.IoAcceptor;
 import org.apache.mina.core.service.IoConnector;
 import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.ssl.SslDIRMINA937Test;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class SSL2SimpleTest {
+public class SSLFilterMain {
 
 	public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException,
 			UnrecoverableKeyException, CertificateException, IOException {
@@ -41,8 +40,8 @@ public class SSL2SimpleTest {
 
 		final char[] password = "password".toCharArray();
 
-		ks.load(SSL2SimpleTest.class.getResourceAsStream("keystore.jks"), password);
-		ts.load(SSL2SimpleTest.class.getResourceAsStream("truststore.jks"), password);
+		ks.load(SSLFilterMain.class.getResourceAsStream("keystore.jks"), password);
+		ts.load(SSLFilterMain.class.getResourceAsStream("truststore.jks"), password);
 
 		kmf.init(ks, password);
 		tmf.init(ts);
@@ -50,7 +49,7 @@ public class SSL2SimpleTest {
 		final SSLContext context = SSLContext.getInstance("TLSv1.3");
 		context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
 
-		final SSL2Filter filter = new SSL2Filter(context);
+		final SSLFilter filter = new SSLFilter(context);
 		filter.setEnabledCipherSuites(new String[] { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" });
 		filter.setEnabledProtocols(new String[] { "TLSv1.3" });
 
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslEngineTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SslEngineTest.java
deleted file mode 100644
index 28b1122..0000000
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslEngineTest.java
+++ /dev/null
@@ -1,486 +0,0 @@
-package org.apache.mina.filter.ssl;
-
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Security;
-import java.util.Deque;
-import java.util.concurrent.BlockingDeque;
-import java.util.concurrent.LinkedBlockingDeque;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.mina.core.buffer.IoBuffer;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class SslEngineTest
-{
-    private BlockingDeque<ByteBuffer> clientQueue = new LinkedBlockingDeque<>(); 
-    private BlockingDeque<ByteBuffer> serverQueue = new LinkedBlockingDeque<>(); 
-
-    private class Handshaker implements Runnable {
-        private SSLEngine sslEngine;
-        private ByteBuffer workBuffer;
-        private ByteBuffer emptyBuffer= ByteBuffer.allocate(0);
-        
-        private void push(Deque<ByteBuffer> queue, ByteBuffer buffer) {
-            ByteBuffer result = ByteBuffer.allocate(buffer.capacity());
-            result.put(buffer);
-            queue.addFirst(result);
-        }
-        
-        public void run()
-        {
-            HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
-            SSLEngineResult result;
-
-            try
-            {
-                while (handshakeStatus != HandshakeStatus.FINISHED) {
-                    switch (handshakeStatus)
-                    {
-                        case NEED_TASK:
-                            break;
-                            
-                        case NEED_UNWRAP:
-                            // The SSLEngine waits for some input.
-                            // We may have received too few data (TCP fragmentation)
-                            // 
-                            ByteBuffer data = serverQueue.takeLast();
-                            result = sslEngine.unwrap(data, workBuffer);
-                            
-                            while (result.getStatus()  == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
-                                // We need more data, until then, wait.
-                                //ByteBuffer data = serverQueue.takeLast();
-                                result = sslEngine.unwrap(data, workBuffer);
-                            }
-                            
-                            handshakeStatus = sslEngine.getHandshakeStatus();
-                            break;
-
-                        case NEED_WRAP:
-                        case NOT_HANDSHAKING:
-                            result = sslEngine.wrap(emptyBuffer, workBuffer);
-    
-                            workBuffer.flip();
-                            
-                            if (workBuffer.hasRemaining()) {
-                                push(clientQueue, workBuffer);
-                                workBuffer.clear();
-                            }
-                            
-                            handshakeStatus = result.getHandshakeStatus();
-                            
-                            break;
-    
-                        case FINISHED:
-                        
-                    }
-                }
-            }
-            catch ( SSLException e )
-            {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-            catch ( InterruptedException e )
-            {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-        
-        public Handshaker(SSLEngine sslEngine) {
-            this.sslEngine = sslEngine;
-            int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
-            workBuffer = ByteBuffer.allocate(packetBufferSize);
-        }
-    }
-    
-    /** A JVM independant KEY_MANAGER_FACTORY algorithm */
-    private static final String KEY_MANAGER_FACTORY_ALGORITHM;
-
-    static {
-        String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
-        if (algorithm == null) {
-            algorithm = KeyManagerFactory.getDefaultAlgorithm();
-        }
-
-        KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
-    }
-
-    /** App data buffer for the client SSLEngine*/
-    private IoBuffer inNetBufferClient;
-
-    /** Net data buffer for the client SSLEngine */
-    private IoBuffer outNetBufferClient;
-
-    /** App data buffer for the server SSLEngine */
-    private IoBuffer inNetBufferServer;
-
-    /** Net data buffer for the server SSLEngine */
-    private IoBuffer outNetBufferServer;
-    
-    private final IoBuffer emptyBuffer = IoBuffer.allocate(0);
-
-
-    private static SSLContext createSSLContext() throws IOException, GeneralSecurityException {
-        char[] passphrase = "password".toCharArray();
-
-        SSLContext ctx = SSLContext.getInstance("TLS");
-        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-        TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-
-        KeyStore ks = KeyStore.getInstance("JKS");
-        KeyStore ts = KeyStore.getInstance("JKS");
-
-        ks.load(SslTest.class.getResourceAsStream("keystore.sslTest"), passphrase);
-        ts.load(SslTest.class.getResourceAsStream("truststore.sslTest"), passphrase);
-
-        kmf.init(ks, passphrase);
-        tmf.init(ts);
-        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
-
-        return ctx;
-    }
-
-    
-    /**
-     * Decrypt the incoming buffer and move the decrypted data to an
-     * application buffer.
-     */
-    private SSLEngineResult unwrap(SSLEngine sslEngine, IoBuffer inBuffer, IoBuffer outBuffer) throws SSLException {
-        // We first have to create the application buffer if it does not exist
-        if (outBuffer == null) {
-            outBuffer = IoBuffer.allocate(inBuffer.remaining());
-        } else {
-            // We already have one, just add the new data into it
-            outBuffer.expand(inBuffer.remaining());
-        }
-
-        SSLEngineResult res;
-        Status status;
-        HandshakeStatus localHandshakeStatus;
-
-        do {
-            // Decode the incoming data
-            res = sslEngine.unwrap(inBuffer.buf(), outBuffer.buf());
-            status = res.getStatus();
-
-            // We can be processing the Handshake
-            localHandshakeStatus = res.getHandshakeStatus();
-
-            if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
-                // We have to grow the target buffer, it's too small.
-                // Then we can call the unwrap method again
-                int newCapacity = sslEngine.getSession().getApplicationBufferSize();
-                
-                if (inBuffer.remaining() >= newCapacity) {
-                    // The buffer is already larger than the max buffer size suggested by the SSL engine.
-                    // Raising it any more will not make sense and it will end up in an endless loop. Throwing an error is safer
-                    throw new SSLException("SSL buffer overflow");
-                }
-
-                inBuffer.expand(newCapacity);
-                continue;
-            }
-        } while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW))
-                && ((localHandshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) || 
-                        (localHandshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)));
-
-        return res;
-    }
-
-    
-    private SSLEngineResult.Status unwrapHandshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer) throws SSLException {
-        // Prepare the net data for reading.
-        if ((appBuffer == null) || !appBuffer.hasRemaining()) {
-            // Need more data.
-            return SSLEngineResult.Status.BUFFER_UNDERFLOW;
-        }
-
-        SSLEngineResult res = unwrap(sslEngine, appBuffer, netBuffer);
-        HandshakeStatus handshakeStatus = res.getHandshakeStatus();
-
-        //checkStatus(res);
-
-        // If handshake finished, no data was produced, and the status is still
-        // ok, try to unwrap more
-        if ((handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED)
-                && (res.getStatus() == SSLEngineResult.Status.OK)
-                && appBuffer.hasRemaining()) {
-            res = unwrap(sslEngine, appBuffer, netBuffer);
-
-            // prepare to be written again
-            if (appBuffer.hasRemaining()) {
-                appBuffer.compact();
-            } else {
-                appBuffer.free();
-                appBuffer = null;
-            }
-        } else {
-            // prepare to be written again
-            if (appBuffer.hasRemaining()) {
-                appBuffer.compact();
-            } else {
-                appBuffer.free();
-                appBuffer = null;
-            }
-        }
-
-        return res.getStatus();
-    }
-
-    
-    /* no qualifier */boolean isInboundDone(SSLEngine sslEngine) {
-        return sslEngine == null || sslEngine.isInboundDone();
-    }
-
-    
-    /* no qualifier */boolean isOutboundDone(SSLEngine sslEngine) {
-        return sslEngine == null || sslEngine.isOutboundDone();
-    }
-
-    
-    /**
-     * Perform any handshaking processing.
-     */
-    /* no qualifier */HandshakeStatus handshake(SSLEngine sslEngine, IoBuffer appBuffer, IoBuffer netBuffer ) throws SSLException {
-        SSLEngineResult result;
-        HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
-
-        for (;;) {
-            switch (handshakeStatus) {
-            case FINISHED:
-                //handshakeComplete = true;
-                return handshakeStatus;
-
-            case NEED_TASK:
-                //handshakeStatus = doTasks();
-                break;
-
-            case NEED_UNWRAP:
-                // we need more data read
-                SSLEngineResult.Status status = unwrapHandshake(sslEngine, appBuffer, netBuffer);
-                handshakeStatus = sslEngine.getHandshakeStatus();
-
-                return handshakeStatus;
-
-            case NEED_WRAP:
-                result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-
-                while ( result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW ) {
-                    netBuffer.capacity(netBuffer.capacity() << 1);
-                    netBuffer.limit(netBuffer.capacity());
-
-                    result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-                }
-
-                netBuffer.flip();
-                return result.getHandshakeStatus();
-
-            case NOT_HANDSHAKING:
-                result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-
-                while ( result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW ) {
-                    netBuffer.capacity(netBuffer.capacity() << 1);
-                    netBuffer.limit(netBuffer.capacity());
-
-                    result = sslEngine.wrap(emptyBuffer.buf(), netBuffer.buf());
-                }
-
-                netBuffer.flip();
-                handshakeStatus = result.getHandshakeStatus();
-                return handshakeStatus;
-
-            default:
-                throw new IllegalStateException("error");
-            }
-        }
-    }
-
-    
-    /**
-     * Do all the outstanding handshake tasks in the current Thread.
-     */
-    private SSLEngineResult.HandshakeStatus doTasks(SSLEngine sslEngine) {
-        /*
-         * We could run this in a separate thread, but I don't see the need for
-         * this when used from SSLFilter. Use thread filters in MINA instead?
-         */
-        Runnable runnable;
-        while ((runnable = sslEngine.getDelegatedTask()) != null) {
-            //Thread thread = new Thread(runnable);
-            //thread.start();
-            runnable.run();
-        }
-        return sslEngine.getHandshakeStatus();
-    }
-    
-    
-    private HandshakeStatus handshake(SSLEngine sslEngine, HandshakeStatus expected, 
-        IoBuffer inBuffer, IoBuffer outBuffer, boolean dumpBuffer) throws SSLException {
-        HandshakeStatus handshakeStatus = handshake(sslEngine, inBuffer, outBuffer);
-
-        if ( handshakeStatus != expected) {
-            fail();
-        }
-        
-        if (dumpBuffer) {
-            System.out.println("Message:" + outBuffer);
-        }
-        
-        return handshakeStatus;
-    }
-
-    
-    @Test
-    @Ignore
-    public void testSSL() throws Exception {
-        // Initialise the client SSLEngine
-        SSLContext sslContextClient = createSSLContext();
-        SSLEngine sslEngineClient = sslContextClient.createSSLEngine();
-        int packetBufferSize = sslEngineClient.getSession().getPacketBufferSize();
-        inNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-        outNetBufferClient = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-        
-        sslEngineClient.setUseClientMode(true);
-
-        // Initialise the Server SSLEngine
-        SSLContext sslContextServer = createSSLContext();
-        SSLEngine sslEngineServer = sslContextServer.createSSLEngine();
-        packetBufferSize = sslEngineServer.getSession().getPacketBufferSize();
-        inNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-        outNetBufferServer = IoBuffer.allocate(packetBufferSize).setAutoExpand(true);
-        
-        sslEngineServer.setUseClientMode(false);
-        
-        Handshaker handshakerClient = new Handshaker( sslEngineClient );
-        Handshaker handshakerServer = new Handshaker( sslEngineServer );
-        
-        handshakerServer.run();
-
-        HandshakeStatus handshakeStatusClient = sslEngineClient.getHandshakeStatus();
-        HandshakeStatus handshakeStatusServer = sslEngineServer.getHandshakeStatus();
-
-    // <<< Server
-        // Start the server
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, 
-            null, outNetBufferServer, false);
-        
-    // >>> Client
-        // Now start the client, which will generate a CLIENT_HELLO,
-        // stored into the outNetBufferClient
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, 
-            null, outNetBufferClient, true);
-        
-    // <<< Server
-        // Process the CLIENT_HELLO on the server
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, 
-            outNetBufferClient, outNetBufferServer, false);
-
-        // Process the tasks on the server, prepare the SERVER_HELLO message
-        handshakeStatusServer = doTasks(sslEngineServer);
-        
-        // We should be ready to generate the SERVER_HELLO message
-        if ( handshakeStatusServer != HandshakeStatus.NEED_WRAP) {
-            fail();
-        }
-        
-        // Get the SERVER_HELLO message, with all the associated messages
-        // ([Certificate], [ServerKeyExchange], [CertificateRequest], ServerHelloDone)
-        outNetBufferServer.clear();
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, 
-            null, outNetBufferServer, true);
-        
-    // >>> Client
-        // Process the SERVER_HELLO message on the client
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_TASK, 
-            outNetBufferServer, inNetBufferClient, false);
-    
-        // Prepare the client response
-        handshakeStatusClient = doTasks(sslEngineClient);
-    
-        // We should get back the Client messages ([Certificate],
-        // ClientKeyExchange, [CertificateVerify])
-        if ( handshakeStatusClient != HandshakeStatus.NEED_WRAP) {
-            fail();
-        }
-    
-        // Generate the [Certificate], ClientKeyExchange, [CertificateVerify] messages
-        outNetBufferClient.clear();
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, 
-            null, outNetBufferClient, true);
-        
-    // <<< Server
-        // Process the CLIENT_KEY_EXCHANGE on the server
-        outNetBufferServer.clear();
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_TASK, 
-            outNetBufferClient, outNetBufferServer, false);
-
-        // Do the controls
-        handshakeStatusServer = doTasks(sslEngineServer);
-        
-        // The server is waiting for more
-        if ( handshakeStatusServer != HandshakeStatus.NEED_UNWRAP) {
-            fail();
-        }
-
-    // >>> Client
-        // The CHANGE_CIPHER_SPEC message generation
-        outNetBufferClient.clear();
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_WRAP, 
-            null, outNetBufferClient, true);
-
-    // <<< Server
-        // Process the CHANGE_CIPHER_SPEC on the server
-        outNetBufferServer.clear();
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_UNWRAP, 
-            outNetBufferClient, outNetBufferServer, false);
-
-    // >>> Client
-        // Generate the FINISHED message on thee client
-        outNetBufferClient.clear();
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, 
-            null, outNetBufferClient, true);
-
-    // <<< Server
-        // Process the client FINISHED message
-        outNetBufferServer.clear();
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, 
-            outNetBufferClient, outNetBufferServer, false);
-
-        // Generate the CHANGE_CIPHER_SPEC message on the server
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.NEED_WRAP, 
-            null, outNetBufferServer, true);
-        
-    // >>> Client
-        // Process the server CHANGE_SCIPHER_SPEC message on the client
-        outNetBufferClient.clear();
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NEED_UNWRAP, 
-            outNetBufferServer, outNetBufferClient, false);
-
-    // <<< Server
-        // Generate the server FINISHED message
-        outNetBufferServer.clear();
-        handshakeStatusServer = handshake(sslEngineServer, HandshakeStatus.FINISHED, 
-            null, outNetBufferServer, true);
-
-    // >>> Client
-        // Process the server FINISHED message on the client
-        outNetBufferClient.clear();
-        handshakeStatusClient = handshake(sslEngineClient, HandshakeStatus.NOT_HANDSHAKING, 
-            outNetBufferServer, outNetBufferClient, false);
-    }
-}
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslFilterTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SslFilterTest.java
deleted file mode 100644
index 5838e3c..0000000
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslFilterTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */
-
-package org.apache.mina.filter.ssl;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import javax.net.ssl.SSLException;
-
-import org.apache.mina.core.filterchain.IoFilter.NextFilter;
-import org.apache.mina.core.session.DummySession;
-import org.apache.mina.core.session.IdleStatus;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.core.write.DefaultWriteRequest;
-import org.apache.mina.core.write.WriteRequest;
-import org.apache.mina.filter.FilterEvent;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * A test for DIRMINA-1019
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-abstract class AbstractNextFilter implements NextFilter {
-    public abstract void messageReceived(IoSession session, Object message);
-    
-    public abstract void filterWrite(IoSession session, WriteRequest writeRequest);
-    
-    // Following are unimplemented as they aren't used in test
-    public void sessionCreated(IoSession session) { }
-
-    public void sessionOpened(IoSession session) { }
-
-    public void sessionClosed(IoSession session) { }
-
-    public void sessionIdle(IoSession session, IdleStatus status) { }
-
-    public void exceptionCaught(IoSession session, Throwable cause) { }
-
-    public void inputClosed(IoSession session) { }
-
-    public void messageSent(IoSession session, WriteRequest writeRequest) { }
-
-    public void filterClose(IoSession session) { }
-
-    public void event(IoSession session, FilterEvent event) { }
-
-    public String toString() {
-        return null;
-    }
-};
-
-/**
- * A test for DIRMINA-1019
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class SslFilterTest {
-    SslHandler test_class;
-    
-    @Before
-    public void init() throws SSLException {
-        test_class = new SslHandler(null, new DummySession());
-    }
-    
-    @Test
-    public void testFlushRaceCondition() {
-        final ExecutorService executor = Executors.newFixedThreadPool(1);
-        final List<Object> message_received_messages = new ArrayList<Object>();
-        final List<WriteRequest> filter_write_requests = new ArrayList<WriteRequest>();
-        
-        final AbstractNextFilter write_filter = new AbstractNextFilter()
-        {
-            @Override
-            public void messageReceived(IoSession session, Object message) { }
-
-            @Override
-            public void filterWrite(IoSession session, WriteRequest writeRequest) {
-                filter_write_requests.add(writeRequest);
-            }
-        };
-        
-        AbstractNextFilter receive_filter = new AbstractNextFilter()
-        {
-            @Override
-            public void messageReceived(IoSession session, Object message) {
-                message_received_messages.add(message);
-                
-                // This is where the race condition occurs. If a thread calls SslHandler.scheduleFilterWrite(),
-                // followed by SslHandler.flushScheduledEvents(), the queued event will not be processed as
-                // the current thread owns the SslHandler.sslLock and has already "dequeued" all the queued
-                // filterWriteEventQueue.
-                Future<?> write_scheduler = executor.submit(new Runnable() {
-                    public void run() {
-                	synchronized(test_class) {
-                	    test_class.scheduleFilterWrite(write_filter, new DefaultWriteRequest(new byte[] {}));
-                	    test_class.flushFilterWrite();
-                	}
-                    }
-                });
-                
-                try {
-                    write_scheduler.get();
-                } catch (Exception e) { }
-            }
-
-            @Override
-            public void filterWrite(IoSession session, WriteRequest writeRequest) { }
-        };
-        
-        synchronized(test_class) {
-            test_class.scheduleMessageReceived(receive_filter, new byte[] {});
-        }
-        
-        test_class.flushMessageReceived();
-        
-        assertEquals(1, message_received_messages.size());
-        assertEquals(1, filter_write_requests.size());
-    }
-}
diff --git a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslTest.java b/mina-core/src/test/java/org/apache/mina/filter/ssl/SslTest.java
deleted file mode 100644
index e61bad6..0000000
--- a/mina-core/src/test/java/org/apache/mina/filter/ssl/SslTest.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- *
- */package org.apache.mina.filter.ssl;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.Security;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
-import org.apache.mina.core.service.IoHandlerAdapter;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
-import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
-import org.apache.mina.util.AvailablePortFinder;
-import org.junit.Test;
-
-/**
- * Test a SSL session where the connection is established and closed twice. It should be
- * processed correctly (Test for DIRMINA-650)
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class SslTest {
-    /** A static port used for his test, chosen to avoid collisions */
-    private static final int port = AvailablePortFinder.getNextAvailable(5555);
-
-    private static Exception clientError = null;
-
-    private static InetAddress address;
-
-    private static SSLSocketFactory factory;
-    
-    private static NioSocketAcceptor acceptor;
-
-    /** A JVM independant KEY_MANAGER_FACTORY algorithm */
-    private static final String KEY_MANAGER_FACTORY_ALGORITHM;
-
-    static {
-        String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
-        if (algorithm == null) {
-            algorithm = KeyManagerFactory.getDefaultAlgorithm();
-        }
-
-        KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
-    }
-
-    private static class TestHandler extends IoHandlerAdapter {
-        public void messageReceived(IoSession session, Object message) throws Exception {
-            String line = (String) message;
-
-            if (line.startsWith("hello")) {
-                //System.out.println("Server got: 'hello', waiting for 'send'");
-                Thread.sleep(1500);
-            } else if (line.startsWith("send")) {
-                //System.out.println("Server got: 'send', sending 'data'");
-                StringBuilder sb = new StringBuilder();
-                
-                for ( int i = 0; i < 10000; i++) {
-                    sb.append('A');
-                }
-                    
-                session.write(sb.toString());
-                session.closeOnFlush();
-            }
-        }
-    }
-
-    /**
-     * Starts a Server with the SSL Filter and a simple text line 
-     * protocol codec filter
-     */
-    private static void startServer() throws Exception {
-        acceptor = new NioSocketAcceptor();
-
-        acceptor.setReuseAddress(true);
-        DefaultIoFilterChainBuilder filters = acceptor.getFilterChain();
-
-        // Inject the SSL filter
-        SslFilter sslFilter = new SslFilter(createSSLContext());
-        filters.addLast("sslFilter", sslFilter);
-        sslFilter.setNeedClientAuth(true);
-
-        // Inject the TestLine codec filter
-        filters.addLast("text", new ProtocolCodecFilter(new TextLineCodecFactory()));
-
-        acceptor.setHandler(new TestHandler());
-        acceptor.bind(new InetSocketAddress(port));
-    }
-    
-    private static void stopServer() {
-        acceptor.dispose();
-    }
-
-    /**
-     * Starts a client which will connect twice using SSL
-     */
-    private static void startClient() throws Exception {
-        address = InetAddress.getByName("localhost");
-
-        SSLContext context = createSSLContext();
-        factory = context.getSocketFactory();
-
-        connectAndSend();
-
-        // This one will throw a SocketTimeoutException if DIRMINA-650 is not fixed
-        connectAndSend();
-    }
-
-    private static void connectAndSend() throws Exception {
-        Socket parent = new Socket(address, port);
-        Socket socket = factory.createSocket(parent, address.getCanonicalHostName(), port, false);
-
-        //System.out.println("Client sending: hello");
-        socket.getOutputStream().write("hello                      \n".getBytes());
-        socket.getOutputStream().flush();
-        socket.setSoTimeout(1000000);
-
-        //System.out.println("Client sending: send");
-        socket.getOutputStream().write("send\n".getBytes());
-        socket.getOutputStream().flush();
-
-        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-        String line = in.readLine();
-        //System.out.println("Client got: " + line);
-        socket.close();
-    }
-
-    private static SSLContext createSSLContext() throws IOException, GeneralSecurityException {
-        char[] passphrase = "password".toCharArray();
-
-        SSLContext ctx = SSLContext.getInstance("TLS");
-        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-        TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
-
-        KeyStore ks = KeyStore.getInstance("JKS");
-        KeyStore ts = KeyStore.getInstance("JKS");
-
-        ks.load(SslTest.class.getResourceAsStream("keystore.sslTest"), passphrase);
-        ts.load(SslTest.class.getResourceAsStream("truststore.sslTest"), passphrase);
-
-        kmf.init(ks, passphrase);
-        tmf.init(ts);
-        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
-
-        return ctx;
-    }
-
-    @Test
-    public void testSSL() throws Exception {
-        try {
-            startServer();
-    
-            Thread t = new Thread() {
-                public void run() {
-                    try {
-                        startClient();
-                    } catch (Exception e) {
-                        clientError = e;
-                    }
-                }
-            };
-            t.start();
-            t.join();
-            
-            if (clientError != null) {
-                throw clientError;
-            }
-        } finally {
-            stopServer();
-        }
-    }
-    
-    
-    @Test
-    public void unsecureClientTryToConnectoToSecureServer() throws Exception {
-        try {
-            startServer(); // Start Server with SSLFilter
-    
-            //Now start a client without any SSL
-            Thread t = new Thread() {
-                @Override
-                public void run() {
-                    try {
-                        address = InetAddress.getByName("localhost");
-    
-                        Socket socket = new Socket(address, port);
-                        socket.setSoTimeout(10000);
-    
-                        String response = null;
-    
-                        while (response == null) {
-                            try {
-                                System.out.println(socket.isConnected());
-                                // System.out.println("Client sending: hello");
-                                socket.getOutputStream().write("hello                      \n".getBytes());
-                                socket.getOutputStream().flush();
-                                socket.setSoTimeout(1000);
-    
-                                // System.out.println("Client sending: send");
-                                socket.getOutputStream().write("send\n".getBytes());
-                                socket.getOutputStream().flush();
-    
-                                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-                                String line = "";
-                                
-                                while ((line = in.readLine()) != null) {
-                                    response = response + line;
-                                }
-                            } catch (SocketTimeoutException timeout) {
-                                // donothing
-                                timeout.printStackTrace();
-                            }
-                        }
-                        
-                        if (response.contains("AAAAAAA")){
-                            throw new IllegalStateException("getting response:" + response);
-                        }
-                        
-                        // System.out.println("Client got: " + line);
-                        socket.close();
-                    } catch (Exception e) {
-                        clientError = e;
-                    }
-                }
-            };
-            
-            t.start();
-            t.join();
-            
-            if (clientError != null) {
-                throw clientError;
-            }
-        } finally {
-            stopServer();
-        }
-    }
-}
diff --git a/mina-example/src/main/java/org/apache/mina/example/chat/Main.java b/mina-example/src/main/java/org/apache/mina/example/chat/Main.java
index 1e76ad6..a2b847c 100644
--- a/mina-example/src/main/java/org/apache/mina/example/chat/Main.java
+++ b/mina-example/src/main/java/org/apache/mina/example/chat/Main.java
@@ -28,7 +28,7 @@ import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
 import org.apache.mina.filter.compression.CompressionFilter;
 import org.apache.mina.filter.logging.LoggingFilter;
 import org.apache.mina.filter.logging.MdcInjectionFilter;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
 /**
@@ -72,7 +72,7 @@ public class Main {
 
     private static void addSSLSupport(DefaultIoFilterChainBuilder chain)
             throws Exception {
-        SslFilter sslFilter = new SslFilter(BogusSslContextFactory
+    	SSLFilter sslFilter = new SSLFilter(BogusSslContextFactory
                 .getInstance(true));
         chain.addLast("sslFilter", sslFilter);
         System.out.println("SSL ON");
diff --git a/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSupport.java b/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSupport.java
index f099ff6..dea4122 100644
--- a/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSupport.java
+++ b/mina-example/src/main/java/org/apache/mina/example/chat/client/ChatClientSupport.java
@@ -28,12 +28,12 @@ import org.apache.mina.core.future.ConnectFuture;
 import org.apache.mina.core.service.IoHandler;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
-import org.apache.mina.filter.ssl.SslFilter;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
 import org.apache.mina.filter.compression.CompressionFilter;
 import org.apache.mina.filter.logging.LoggingFilter;
 import org.apache.mina.filter.logging.MdcInjectionFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 
 /**
@@ -79,8 +79,7 @@ public class ChatClientSupport {
             if (useSsl) {
                 SSLContext sslContext = BogusSslContextFactory
                         .getInstance(false);
-                SslFilter sslFilter = new SslFilter(sslContext);
-                sslFilter.setUseClientMode(true);
+                SSLFilter sslFilter = new SSLFilter(sslContext);
                 connector.getFilterChain().addFirst("sslFilter", sslFilter);
             }
 
diff --git a/mina-example/src/main/java/org/apache/mina/example/echoserver/Main.java b/mina-example/src/main/java/org/apache/mina/example/echoserver/Main.java
index 6501e78..72b820a 100644
--- a/mina-example/src/main/java/org/apache/mina/example/echoserver/Main.java
+++ b/mina-example/src/main/java/org/apache/mina/example/echoserver/Main.java
@@ -24,7 +24,7 @@ import java.net.InetSocketAddress;
 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
 import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
 import org.apache.mina.filter.compression.CompressionFilter;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.SocketAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
@@ -68,7 +68,7 @@ public class Main {
 
     private static void addSSLSupport(DefaultIoFilterChainBuilder chain)
             throws Exception {
-        SslFilter sslFilter = new SslFilter(BogusSslContextFactory
+    	SSLFilter sslFilter = new SSLFilter(BogusSslContextFactory
                 .getInstance(true));
         chain.addLast("sslFilter", sslFilter);
         System.out.println("SSL ON");
diff --git a/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslClient.java b/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslClient.java
index 7588c54..3b12175 100644
--- a/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslClient.java
+++ b/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslClient.java
@@ -32,7 +32,7 @@ import org.apache.mina.core.service.IoConnector;
 import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IdleStatus;
 import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 
 /**
@@ -70,8 +70,7 @@ public class TcpSslClient extends IoHandlerAdapter {
         // Inject teh SSL filter
         SSLContext sslContext = BogusSslContextFactory
             .getInstance(false);
-        SslFilter sslFilter = new SslFilter(sslContext);
-        sslFilter.setUseClientMode(true);
+        SSLFilter sslFilter = new SSLFilter(sslContext);
         connector.getFilterChain().addFirst("sslFilter", sslFilter);
 
         connector.setHandler(this);
diff --git a/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslServer.java b/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslServer.java
index 13aaf07..0e88963 100644
--- a/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslServer.java
+++ b/mina-example/src/main/java/org/apache/mina/example/tcp/perf/TcpSslServer.java
@@ -29,7 +29,7 @@ import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IdleStatus;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
 /**
@@ -136,7 +136,7 @@ public class TcpSslServer extends IoHandlerAdapter {
         
         // Inject the SSL filter
         DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
-        SslFilter sslFilter = new SslFilter(BogusSslContextFactory
+        SSLFilter sslFilter = new SSLFilter(BogusSslContextFactory
             .getInstance(true));
         chain.addLast("sslFilter", sslFilter);
 
diff --git a/mina-example/src/test/java/org/apache/mina/example/echoserver/AbstractTest.java b/mina-example/src/test/java/org/apache/mina/example/echoserver/AbstractTest.java
index 508f331..8116099 100644
--- a/mina-example/src/test/java/org/apache/mina/example/echoserver/AbstractTest.java
+++ b/mina-example/src/test/java/org/apache/mina/example/echoserver/AbstractTest.java
@@ -30,7 +30,7 @@ import org.apache.mina.core.service.IoAcceptor;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
 import org.apache.mina.filter.FilterEvent;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.DatagramSessionConfig;
 import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
@@ -122,7 +122,7 @@ public abstract class AbstractTest {
                         try {
                             session.getFilterChain().addFirst(
                                     "SSL",
-                                    new SslFilter(BogusSslContextFactory
+                                    new SSLFilter(BogusSslContextFactory
                                             .getInstance(true)));
                         } catch (GeneralSecurityException e) {
                             LOGGER.error("", e);
@@ -143,16 +143,13 @@ public abstract class AbstractTest {
                     
                     buf.mark();
 
-                    if (session.getFilterChain().contains("SSL")
+                    if (session.isSecured()
                             && buf.remaining() == 1 && buf.get() == (byte) '.') {
                         LOGGER.info("TLS Reentrance");
-                        ((SslFilter) session.getFilterChain().get("SSL"))
-                                .startSsl(session);
 
                         // Send a response
                         buf.capacity(1);
                         buf.flip();
-                        session.setAttribute(SslFilter.DISABLE_ENCRYPTION_ONCE);
                         session.write(buf);
                     } else {
                         buf.reset();
diff --git a/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.java b/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.java
index 8f3163f..76a66a6 100644
--- a/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.java
+++ b/mina-example/src/test/java/org/apache/mina/example/echoserver/ConnectorTest.java
@@ -20,7 +20,6 @@
 package org.apache.mina.example.echoserver;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.net.InetAddress;
@@ -34,7 +33,7 @@ import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.core.write.WriteException;
 import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.nio.NioDatagramConnector;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.mina.util.AvailablePortFinder;
@@ -59,7 +58,7 @@ public class ConnectorTest extends AbstractTest {
     private final int DATA_SIZE = 16;
 
     private EchoConnectorHandler handler;
-    private SslFilter connectorSSLFilter;
+    private SSLFilter connectorSSLFilter;
 
     public ConnectorTest() {
         // Do nothing
@@ -69,9 +68,8 @@ public class ConnectorTest extends AbstractTest {
     public void setUp() throws Exception {
         super.setUp();
         handler = new EchoConnectorHandler();
-        connectorSSLFilter = new SslFilter(BogusSslContextFactory
+        connectorSSLFilter = new SSLFilter(BogusSslContextFactory
                 .getInstance(false));
-        connectorSSLFilter.setUseClientMode(true); // set client mode
     }
 
     @Test
@@ -81,7 +79,6 @@ public class ConnectorTest extends AbstractTest {
     }
 
     @Test
-    @Ignore
     public void testTCPWithSSL() throws Exception {
         useSSL = true;
         // Create a connector
@@ -135,7 +132,7 @@ public class ConnectorTest extends AbstractTest {
 
         // Send closeNotify to test TLS closure if it is TLS connection.
         if (useSSL) {
-            connectorSSLFilter.stopSsl(session).awaitUninterruptibly();
+            session.getFilterChain().remove("SSL");
 
             System.out
                     .println("-------------------------------------------------------------------------------");
@@ -161,7 +158,7 @@ public class ConnectorTest extends AbstractTest {
             assertEquals((byte) '.', handler.readBuf.get());
 
             // Now start TLS connection
-            assertTrue(connectorSSLFilter.startSsl(session));
+            session.getFilterChain().addFirst("SSL", connectorSSLFilter);
             testConnector0(session);
         }
 
diff --git a/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest.java b/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest.java
index c5ac40e..7a999aa 100644
--- a/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest.java
+++ b/mina-example/src/test/java/org/apache/mina/example/echoserver/ssl/SslFilterTest.java
@@ -38,7 +38,7 @@ import org.apache.mina.core.service.IoHandlerAdapter;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
-import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.filter.ssl.SSLFilter;
 import org.apache.mina.transport.socket.SocketAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import org.junit.After;
@@ -80,9 +80,9 @@ public class SslFilterTest {
         // Workaround to fix TLS issue : http://java.sun.com/javase/javaseforbusiness/docs/TLSReadme.html
         java.lang.System.setProperty( "sun.security.ssl.allowUnsafeRenegotiation", "true" );
 
-        SslFilter sslFilter = null;
+        SSLFilter sslFilter = null;
         if (useSSL) {
-            sslFilter = new SslFilter(BogusSslContextFactory.getInstance(true));
+            sslFilter = new SSLFilter(BogusSslContextFactory.getInstance(true));
             acceptor.getFilterChain().addLast("sslFilter", sslFilter);
         }
         acceptor.getFilterChain().addLast(

[mina] 02/05: Corrects HTTP decode for pipeline requests

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a commit to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit 93a1428f2e7a393f074ff8c7a07c192c95458af0
Author: Jonathan Valliere <jo...@apache.org>
AuthorDate: Thu Sep 9 12:45:54 2021 -0400

    Corrects HTTP decode for pipeline requests
---
 mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java b/mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java
index 850d9f1..fa7d35d 100644
--- a/mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java
+++ b/mina-http/src/main/java/org/apache/mina/http/HttpServerDecoder.java
@@ -194,7 +194,7 @@ public class HttpServerDecoder implements ProtocolDecoder {
     }
 
     private HttpRequestImpl parseHttpRequestHead(ByteBuffer buffer) {
-        String raw = new String(buffer.array(), 0, buffer.limit());
+        String raw = new String(buffer.array(), buffer.position(), buffer.remaining());
         String[] headersAndBody = RAW_VALUE_PATTERN.split(raw, -1);
 
         if (headersAndBody.length <= 1) {

[mina] 05/05: applies null check

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

johnnyv pushed a commit to branch 2.2.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit 667517901d27ff9f342917bf1966aba150a427af
Author: Jonathan Valliere <jo...@apache.org>
AuthorDate: Tue Sep 14 13:57:24 2021 -0400

    applies null check
---
 .../org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.java     | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.java b/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.java
index bb1354b..a03bf53 100644
--- a/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.java
+++ b/mina-core/src/main/java/org/apache/mina/proxy/handlers/socks/Socks4LogicHandler.java
@@ -72,9 +72,8 @@ public class Socks4LogicHandler extends AbstractSocksLogicHandler {
     protected void writeRequest(final NextFilter nextFilter, final SocksProxyRequest request) {
         try {
             boolean isV4ARequest = Arrays.equals(request.getIpAddress(), SocksProxyConstants.FAKE_IP);
-            byte[] userID = request.getUserName().getBytes("ASCII");
-            byte[] host = isV4ARequest ? request.getHost().getBytes("ASCII") : null;
-
+            byte[] userID = request.getUserName() != null ? request.getUserName().getBytes("ASCII") : null;
+            byte[] host = request.getHost() != null ? request.getHost().getBytes("ASCII") : null;           
             int len = 9 + userID.length;
 
             if (isV4ARequest) {