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:03 UTC

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

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(