You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2018/02/11 13:19:52 UTC

[1/2] httpcomponents-core git commit: Improved locking interface of non-blocking I/O sessions

Repository: httpcomponents-core
Updated Branches:
  refs/heads/master 39eeb3a0f -> 65e51b1a5


Improved locking interface of non-blocking I/O sessions


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/65e51b1a
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/65e51b1a
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/65e51b1a

Branch: refs/heads/master
Commit: 65e51b1a59fef1598c26a9f2603bbe540c89bcfd
Parents: 9188bf4
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Sat Feb 10 12:27:49 2018 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sat Feb 10 15:41:57 2018 +0100

----------------------------------------------------------------------
 .../hc/core5/testing/nio/LoggingIOSession.java  |   6 +
 .../org/apache/hc/core5/reactor/IOSession.java  |   9 +
 .../apache/hc/core5/reactor/IOSessionImpl.java  |  31 +-
 .../hc/core5/reactor/InternalDataChannel.java   |  25 +-
 .../hc/core5/reactor/ssl/SSLIOSession.java      | 386 ++++++++++++-------
 5 files changed, 289 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/65e51b1a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
index feb6fed..ac6c245 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
@@ -32,6 +32,7 @@ import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.SelectionKey;
+import java.util.concurrent.locks.Lock;
 
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
@@ -64,6 +65,11 @@ public class LoggingIOSession implements IOSession {
     }
 
     @Override
+    public Lock lock() {
+        return this.session.lock();
+    }
+
+    @Override
     public void addLast(final Command command) {
         this.session.addLast(command);
         if (this.log.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/65e51b1a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
index 7068d29..19b48e5 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
@@ -29,6 +29,7 @@ package org.apache.hc.core5.reactor;
 
 import java.net.SocketAddress;
 import java.nio.channels.ByteChannel;
+import java.util.concurrent.locks.Lock;
 
 import org.apache.hc.core5.io.GracefullyCloseable;
 import org.apache.hc.core5.util.Identifiable;
@@ -56,6 +57,14 @@ public interface IOSession extends GracefullyCloseable, Identifiable {
     int CLOSED       = Integer.MAX_VALUE;
 
     /**
+     * Returns session lock that should be used by I/O event handlers
+     * to synchronize access to the session.
+     *
+     * @since 5.0
+     */
+    Lock lock();
+
+    /**
      * Inserts {@link Command} at the end of the command queue.
      *
      * @since 5.0

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/65e51b1a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
index c179f25..b486ace 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
@@ -36,6 +36,8 @@ import java.util.Deque;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.util.Args;
@@ -46,9 +48,10 @@ class IOSessionImpl implements IOSession {
 
     private final SelectionKey key;
     private final SocketChannel channel;
+    private final Deque<Command> commandQueue;
+    private final Lock lock;
     private final String id;
     private final AtomicInteger status;
-    private final Deque<Command> commandQueue;
 
     private volatile IOEventHandler eventHandler;
     private volatile int socketTimeout;
@@ -66,6 +69,7 @@ class IOSessionImpl implements IOSession {
         this.key = Args.notNull(key, "Selection key");
         this.channel = Args.notNull(socketChannel, "Socket channel");
         this.commandQueue = new ConcurrentLinkedDeque<>();
+        this.lock = new ReentrantLock();
         this.socketTimeout = 0;
         this.id = String.format("i/o-%08X", COUNT.getAndIncrement());
         this.status = new AtomicInteger(ACTIVE);
@@ -79,6 +83,11 @@ class IOSessionImpl implements IOSession {
     }
 
     @Override
+    public Lock lock() {
+        return lock;
+    }
+
+    @Override
     public void addLast(final Command command) {
         commandQueue.addLast(command);
         setEvent(SelectionKey.OP_WRITE);
@@ -120,10 +129,8 @@ class IOSessionImpl implements IOSession {
         if (this.status.get() == CLOSED) {
             return;
         }
-        synchronized (this.key) {
-            this.key.interestOps(newValue);
-            this.key.selector().wakeup();
-        }
+        this.key.interestOps(newValue);
+        this.key.selector().wakeup();
     }
 
     @Override
@@ -131,10 +138,13 @@ class IOSessionImpl implements IOSession {
         if (this.status.get() == CLOSED) {
             return;
         }
-        synchronized (this.key) {
+        lock.lock();
+        try {
             this.key.interestOps(this.key.interestOps() | op);
-            this.key.selector().wakeup();
+        } finally {
+            lock.unlock();
         }
+        this.key.selector().wakeup();
     }
 
     @Override
@@ -142,10 +152,13 @@ class IOSessionImpl implements IOSession {
         if (this.status.get() == CLOSED) {
             return;
         }
-        synchronized (this.key) {
+        lock.lock();
+        try {
             this.key.interestOps(this.key.interestOps() & ~op);
-            this.key.selector().wakeup();
+        } finally {
+            lock.unlock();
         }
+        this.key.selector().wakeup();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/65e51b1a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
index 5322c90..ab28092 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
@@ -34,6 +34,7 @@ import java.nio.channels.SelectionKey;
 import java.util.Queue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
 
 import javax.net.ssl.SSLContext;
 
@@ -79,6 +80,7 @@ final class InternalDataChannel extends InternalChannel implements ProtocolIOSes
         return ioSession.getId();
     }
 
+
     @Override
     public IOEventHandler getHandler() {
         return handlerRef.get();
@@ -89,15 +91,6 @@ final class InternalDataChannel extends InternalChannel implements ProtocolIOSes
         handlerRef.set(handler);
     }
 
-    private IOSession getSessionImpl() {
-        final SSLIOSession tlsSession = tlsSessionRef.get();
-        if (tlsSession != null) {
-            return tlsSession;
-        } else {
-            return ioSession;
-        }
-    }
-
     private IOEventHandler ensureHandler() {
         final IOEventHandler handler = handlerRef.get();
         Asserts.notNull(handler, "IO event handler");
@@ -259,6 +252,20 @@ final class InternalDataChannel extends InternalChannel implements ProtocolIOSes
     }
 
     @Override
+    public Lock lock() {
+        return ioSession.lock();
+    }
+
+    private IOSession getSessionImpl() {
+        final SSLIOSession tlsSession = tlsSessionRef.get();
+        if (tlsSession != null) {
+            return tlsSession;
+        } else {
+            return ioSession;
+        }
+    }
+
+    @Override
     public void close() {
         if (closed.compareAndSet(false, true)) {
             try {

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/65e51b1a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
index 8325480..47f0bec 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
@@ -35,6 +35,7 @@ import java.nio.channels.CancelledKeyException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.SelectionKey;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
@@ -192,6 +193,11 @@ public class SSLIOSession implements IOSession {
         return session.getId();
     }
 
+    @Override
+    public Lock lock() {
+        return this.session.lock();
+    }
+
     /**
      * Returns {@code true} is the session has been fully initialized,
      * {@code false} otherwise.
@@ -208,32 +214,37 @@ public class SSLIOSession implements IOSession {
      * @throws SSLException in case of a SSL protocol exception.
      * @throws IllegalStateException if the session has already been initialized.
      */
-    public synchronized void initialize() throws SSLException {
+    public void initialize() throws SSLException {
         Asserts.check(!this.initialized, "SSL I/O session already initialized");
-        if (this.status >= IOSession.CLOSING) {
-            return;
-        }
-        switch (this.sslMode) {
-        case CLIENT:
-            this.sslEngine.setUseClientMode(true);
-            break;
-        case SERVER:
-            this.sslEngine.setUseClientMode(false);
-            break;
-        }
-        if (this.initializer != null) {
-            this.initializer.initialize(this.targetEndpoint, this.sslEngine);
-        }
-        this.initialized = true;
-        this.sslEngine.beginHandshake();
+        this.session.lock().lock();
+        try {
+            if (this.status >= IOSession.CLOSING) {
+                return;
+            }
+            switch (this.sslMode) {
+                case CLIENT:
+                    this.sslEngine.setUseClientMode(true);
+                    break;
+                case SERVER:
+                    this.sslEngine.setUseClientMode(false);
+                    break;
+            }
+            if (this.initializer != null) {
+                this.initializer.initialize(this.targetEndpoint, this.sslEngine);
+            }
+            this.initialized = true;
+            this.sslEngine.beginHandshake();
 
-        this.inEncrypted.release();
-        this.outEncrypted.release();
-        this.inPlain.release();
-        doHandshake();
+            this.inEncrypted.release();
+            this.outEncrypted.release();
+            this.inPlain.release();
+            doHandshake();
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
-    public synchronized TlsDetails getTlsDetails() {
+    public TlsDetails getTlsDetails() {
         return tlsDetails;
     }
 
@@ -492,20 +503,25 @@ public class SSLIOSession implements IOSession {
      *
      * @throws IOException in case of an I/O error.
      */
-    public synchronized boolean isAppInputReady() throws IOException {
-        do {
-            final int bytesRead = receiveEncryptedData();
-            if (bytesRead == -1) {
-                this.endOfStream = true;
-            }
-            doHandshake();
-            final HandshakeStatus status = this.sslEngine.getHandshakeStatus();
-            if (status == HandshakeStatus.NOT_HANDSHAKING || status == HandshakeStatus.FINISHED) {
-                decryptData();
-            }
-        } while (this.sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK);
-        // Some decrypted data is available or at the end of stream
-        return this.inPlain.hasData() || (this.endOfStream && this.status == ACTIVE);
+    public boolean isAppInputReady() throws IOException {
+        this.session.lock().lock();
+        try {
+            do {
+                final int bytesRead = receiveEncryptedData();
+                if (bytesRead == -1) {
+                    this.endOfStream = true;
+                }
+                doHandshake();
+                final HandshakeStatus status = this.sslEngine.getHandshakeStatus();
+                if (status == HandshakeStatus.NOT_HANDSHAKING || status == HandshakeStatus.FINISHED) {
+                    decryptData();
+                }
+            } while (this.sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK);
+            // Some decrypted data is available or at the end of stream
+            return this.inPlain.hasData() || (this.endOfStream && this.status == ACTIVE);
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     /**
@@ -514,10 +530,15 @@ public class SSLIOSession implements IOSession {
      *
      * @throws IOException - not thrown currently
      */
-    public synchronized boolean isAppOutputReady() throws IOException {
-        return (this.appEventMask & SelectionKey.OP_WRITE) > 0
-            && this.status == ACTIVE
-            && this.sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING;
+    public boolean isAppOutputReady() throws IOException {
+        this.session.lock().lock();
+        try {
+            return (this.appEventMask & SelectionKey.OP_WRITE) > 0
+                    && this.status == ACTIVE
+                    && this.sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING;
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     /**
@@ -525,8 +546,13 @@ public class SSLIOSession implements IOSession {
      *
      * @throws IOException - not thrown currently
      */
-    public synchronized void inboundTransport() throws IOException {
-        updateEventMask();
+    public void inboundTransport() throws IOException {
+        this.session.lock().lock();
+        try {
+            updateEventMask();
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     /**
@@ -534,67 +560,82 @@ public class SSLIOSession implements IOSession {
      *
      * @throws IOException in case of an I/O error.
      */
-    public synchronized void outboundTransport() throws IOException {
-        if (this.session.isClosed()) {
-            return;
+    public void outboundTransport() throws IOException {
+        this.session.lock().lock();
+        try {
+            if (this.session.isClosed()) {
+                return;
+            }
+            sendEncryptedData();
+            doHandshake();
+            updateEventMask();
+        } finally {
+            this.session.lock().unlock();
         }
-        sendEncryptedData();
-        doHandshake();
-        updateEventMask();
     }
 
     /**
      * Returns whether the session will produce any more inbound data.
      */
-    public synchronized boolean isInboundDone() {
+    public boolean isInboundDone() {
         return this.sslEngine.isInboundDone();
     }
 
     /**
      * Returns whether the session will accept any more outbound data.
      */
-    public synchronized boolean isOutboundDone() {
+    public boolean isOutboundDone() {
         return this.sslEngine.isOutboundDone();
     }
 
-    private synchronized int writePlain(final ByteBuffer src) throws IOException {
+    private int writePlain(final ByteBuffer src) throws IOException {
         Args.notNull(src, "Byte buffer");
-        if (this.status != ACTIVE) {
-            throw new ClosedChannelException();
-        }
-        final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire();
-        final SSLEngineResult result = doWrap(src, outEncryptedBuf);
-        if (result.getStatus() == Status.CLOSED) {
-            this.status = CLOSED;
+        this.session.lock().lock();
+        try {
+            if (this.status != ACTIVE) {
+                throw new ClosedChannelException();
+            }
+            final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire();
+            final SSLEngineResult result = doWrap(src, outEncryptedBuf);
+            if (result.getStatus() == Status.CLOSED) {
+                this.status = CLOSED;
+            }
+            return result.bytesConsumed();
+        } finally {
+            this.session.lock().unlock();
         }
-        return result.bytesConsumed();
     }
 
-    private synchronized int readPlain(final ByteBuffer dst) {
+    private int readPlain(final ByteBuffer dst) {
         Args.notNull(dst, "Byte buffer");
-        if (this.inPlain.hasData()) {
-            // Acquire buffer
-            final ByteBuffer inPlainBuf = this.inPlain.acquire();
+        this.session.lock().lock();
+        try {
+            if (this.inPlain.hasData()) {
+                // Acquire buffer
+                final ByteBuffer inPlainBuf = this.inPlain.acquire();
 
-            // Perform opertaions
-            inPlainBuf.flip();
-            final int n = Math.min(inPlainBuf.remaining(), dst.remaining());
-            for (int i = 0; i < n; i++) {
-                dst.put(inPlainBuf.get());
-            }
-            inPlainBuf.compact();
+                // Perform opertaions
+                inPlainBuf.flip();
+                final int n = Math.min(inPlainBuf.remaining(), dst.remaining());
+                for (int i = 0; i < n; i++) {
+                    dst.put(inPlainBuf.get());
+                }
+                inPlainBuf.compact();
 
-            // Release if empty
-            if (inPlainBuf.position() == 0) {
-                this.inPlain.release();
+                // Release if empty
+                if (inPlainBuf.position() == 0) {
+                    this.inPlain.release();
+                }
+                bytesReadCount.addAndGet(n);
+                return n;
             }
-            bytesReadCount.addAndGet(n);
-            return n;
-        }
-        if (this.endOfStream) {
-            return -1;
+            if (this.endOfStream) {
+                return -1;
+            }
+            return 0;
+        } finally {
+            this.session.lock().unlock();
         }
-        return 0;
     }
 
     public void resetReadCount() {
@@ -606,32 +647,42 @@ public class SSLIOSession implements IOSession {
     }
 
     @Override
-    public synchronized void close() {
-        if (this.status >= CLOSING) {
-            return;
-        }
-        this.status = CLOSING;
-        if (this.session.getSocketTimeout() == 0) {
-            this.session.setSocketTimeout(1000);
-        }
+    public void close() {
+        this.session.lock().lock();
         try {
-            updateEventMask();
-        } catch (final CancelledKeyException ex) {
-            shutdown(ShutdownType.GRACEFUL);
+            if (this.status >= CLOSING) {
+                return;
+            }
+            this.status = CLOSING;
+            if (this.session.getSocketTimeout() == 0) {
+                this.session.setSocketTimeout(1000);
+            }
+            try {
+                updateEventMask();
+            } catch (final CancelledKeyException ex) {
+                shutdown(ShutdownType.GRACEFUL);
+            }
+        } finally {
+            this.session.lock().unlock();
         }
     }
 
     @Override
-    public synchronized void shutdown(final ShutdownType shutdownType) {
-        if (this.status == CLOSED) {
-            return;
-        }
-        this.inEncrypted.release();
-        this.outEncrypted.release();
-        this.inPlain.release();
+    public void shutdown(final ShutdownType shutdownType) {
+        this.session.lock().lock();
+        try {
+            if (this.status == CLOSED) {
+                return;
+            }
+            this.inEncrypted.release();
+            this.outEncrypted.release();
+            this.inPlain.release();
 
-        this.status = CLOSED;
-        this.session.shutdown(shutdownType);
+            this.status = CLOSED;
+            this.session.shutdown(shutdownType);
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
@@ -645,15 +696,25 @@ public class SSLIOSession implements IOSession {
     }
 
     @Override
-    public synchronized void addLast(final Command command) {
-        this.session.addLast(command);
-        setEvent(SelectionKey.OP_WRITE);
+    public void addLast(final Command command) {
+        this.session.lock().lock();
+        try {
+            this.session.addLast(command);
+            setEvent(SelectionKey.OP_WRITE);
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
-    public synchronized void addFirst(final Command command) {
-        this.session.addFirst(command);
-        setEvent(SelectionKey.OP_WRITE);
+    public void addFirst(final Command command) {
+        this.session.lock().lock();
+        try {
+            this.session.addFirst(command);
+            setEvent(SelectionKey.OP_WRITE);
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
@@ -677,26 +738,46 @@ public class SSLIOSession implements IOSession {
     }
 
     @Override
-    public synchronized int getEventMask() {
-        return this.appEventMask;
+    public int getEventMask() {
+        this.session.lock().lock();
+        try {
+            return this.appEventMask;
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
-    public synchronized void setEventMask(final int ops) {
-        this.appEventMask = ops;
-        updateEventMask();
+    public void setEventMask(final int ops) {
+        this.session.lock().lock();
+        try {
+            this.appEventMask = ops;
+            updateEventMask();
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
-    public synchronized void setEvent(final int op) {
-        this.appEventMask = this.appEventMask | op;
-        updateEventMask();
+    public void setEvent(final int op) {
+        this.session.lock().lock();
+        try {
+            this.appEventMask = this.appEventMask | op;
+            updateEventMask();
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
-    public synchronized void clearEvent(final int op) {
-        this.appEventMask = this.appEventMask & ~op;
-        updateEventMask();
+    public void clearEvent(final int op) {
+        this.session.lock().lock();
+        try {
+            this.appEventMask = this.appEventMask & ~op;
+            updateEventMask();
+        } finally {
+            this.session.lock().unlock();
+        }
     }
 
     @Override
@@ -740,41 +821,46 @@ public class SSLIOSession implements IOSession {
 
     @Override
     public String toString() {
-        final StringBuilder buffer = new StringBuilder();
-        buffer.append(this.session);
-        buffer.append("[");
-        switch (this.status) {
-        case ACTIVE:
-            buffer.append("ACTIVE");
-            break;
-        case CLOSING:
-            buffer.append("CLOSING");
-            break;
-        case CLOSED:
-            buffer.append("CLOSED");
-            break;
-        }
-        buffer.append("][");
-        formatOps(buffer, this.appEventMask);
-        buffer.append("][");
-        buffer.append(this.sslEngine.getHandshakeStatus());
-        if (this.sslEngine.isInboundDone()) {
-            buffer.append("][inbound done][");
-        }
-        if (this.sslEngine.isOutboundDone()) {
-            buffer.append("][outbound done][");
+        this.session.lock().lock();
+        try {
+            final StringBuilder buffer = new StringBuilder();
+            buffer.append(this.session);
+            buffer.append("[");
+            switch (this.status) {
+                case ACTIVE:
+                    buffer.append("ACTIVE");
+                    break;
+                case CLOSING:
+                    buffer.append("CLOSING");
+                    break;
+                case CLOSED:
+                    buffer.append("CLOSED");
+                    break;
+            }
+            buffer.append("][");
+            formatOps(buffer, this.appEventMask);
+            buffer.append("][");
+            buffer.append(this.sslEngine.getHandshakeStatus());
+            if (this.sslEngine.isInboundDone()) {
+                buffer.append("][inbound done][");
+            }
+            if (this.sslEngine.isOutboundDone()) {
+                buffer.append("][outbound done][");
+            }
+            if (this.endOfStream) {
+                buffer.append("][EOF][");
+            }
+            buffer.append("][");
+            buffer.append(!this.inEncrypted.hasData() ? 0 : inEncrypted.acquire().position());
+            buffer.append("][");
+            buffer.append(!this.inPlain.hasData() ? 0 : inPlain.acquire().position());
+            buffer.append("][");
+            buffer.append(!this.outEncrypted.hasData() ? 0 : outEncrypted.acquire().position());
+            buffer.append("]");
+            return buffer.toString();
+        } finally {
+            this.session.lock().unlock();
         }
-        if (this.endOfStream) {
-            buffer.append("][EOF][");
-        }
-        buffer.append("][");
-        buffer.append(!this.inEncrypted.hasData() ? 0 : inEncrypted.acquire().position());
-        buffer.append("][");
-        buffer.append(!this.inPlain.hasData() ? 0 : inPlain.acquire().position());
-        buffer.append("][");
-        buffer.append(!this.outEncrypted.hasData() ? 0 : outEncrypted.acquire().position());
-        buffer.append("]");
-        return buffer.toString();
     }
 
 }


[2/2] httpcomponents-core git commit: Redesign of non-blocking application protocol APIs

Posted by ol...@apache.org.
Redesign of non-blocking application protocol APIs


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/9188bf41
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/9188bf41
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/9188bf41

Branch: refs/heads/master
Commit: 9188bf41ab7ba3087db93011662664983c39df59
Parents: 39eeb3a
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Fri Feb 9 20:01:02 2018 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sat Feb 10 15:41:57 2018 +0100

----------------------------------------------------------------------
 .../nio/AbstractHttp2StreamMultiplexer.java     |  6 +--
 .../impl/nio/ClientHttp2StreamMultiplexer.java  |  8 ++--
 .../ClientHttp2StreamMultiplexerFactory.java    |  4 +-
 .../impl/nio/ClientHttpProtocolNegotiator.java  | 10 ++---
 .../ClientHttpProtocolNegotiatorFactory.java    |  4 +-
 .../nio/Http2OnlyClientProtocolNegotiator.java  |  8 ++--
 .../impl/nio/ServerHttp2StreamMultiplexer.java  |  6 +--
 .../ServerHttp2StreamMultiplexerFactory.java    |  4 +-
 .../impl/nio/ServerHttpProtocolNegotiator.java  | 12 ++---
 .../ServerHttpProtocolNegotiatorFactory.java    |  4 +-
 .../Http2MultiplexingRequesterBootstrap.java    |  4 +-
 .../InternalClientHttp1EventHandlerFactory.java |  6 +--
 .../InternalClientHttp2EventHandlerFactory.java |  4 +-
 .../InternalServerHttp1EventHandlerFactory.java |  6 +--
 .../InternalServerHttp2EventHandlerFactory.java |  4 +-
 .../hc/core5/testing/nio/LoggingIOSession.java  | 11 -----
 .../core5/testing/nio/Http1IntegrationTest.java | 23 ++++------
 .../core5/testing/nio/Http2IntegrationTest.java |  7 +--
 .../nio/TestDefaultListeningIOReactor.java      |  4 +-
 .../impl/nio/AbstractHttp1StreamDuplexer.java   | 20 ++++++---
 .../nio/ClientHttp1IOEventHandlerFactory.java   |  4 +-
 .../impl/nio/ClientHttp1StreamDuplexer.java     |  4 +-
 .../nio/ClientHttp1StreamDuplexerFactory.java   |  4 +-
 .../nio/ServerHttp1IOEventHandlerFactory.java   |  4 +-
 .../impl/nio/ServerHttp1StreamDuplexer.java     |  4 +-
 .../nio/ServerHttp1StreamDuplexerFactory.java   |  4 +-
 .../hc/core5/reactor/IOEventHandlerFactory.java |  2 +-
 .../org/apache/hc/core5/reactor/IOSession.java  | 14 ------
 .../apache/hc/core5/reactor/IOSessionImpl.java  | 10 -----
 .../hc/core5/reactor/IOSessionRequest.java      |  2 +-
 .../hc/core5/reactor/InternalDataChannel.java   | 46 ++++++++++----------
 .../hc/core5/reactor/ProtocolIOSession.java     | 39 +++++++++++++++++
 .../apache/hc/core5/reactor/ProtocolLayer.java  | 44 +++++++++++++++++++
 .../hc/core5/reactor/SingleCoreIOReactor.java   |  4 +-
 .../hc/core5/reactor/TlsCapableIOSession.java   | 39 -----------------
 .../hc/core5/reactor/ssl/SSLIOSession.java      | 11 -----
 36 files changed, 196 insertions(+), 194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
index c83274c..d5a9b64 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
@@ -84,7 +84,7 @@ import org.apache.hc.core5.http2.nio.AsyncPingHandler;
 import org.apache.hc.core5.http2.nio.command.PingCommand;
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.ByteArrayBuffer;
@@ -99,7 +99,7 @@ abstract class AbstractHttp2StreamMultiplexer implements Identifiable, HttpConne
     enum SettingsHandshake { READY, TRANSMITTED, ACKED }
 
     private final Mode mode;
-    private final TlsCapableIOSession ioSession;
+    private final ProtocolIOSession ioSession;
     private final FrameFactory frameFactory;
     private final StreamIdGenerator idGenerator;
     private final HttpProcessor httpProcessor;
@@ -134,7 +134,7 @@ abstract class AbstractHttp2StreamMultiplexer implements Identifiable, HttpConne
 
     AbstractHttp2StreamMultiplexer(
             final Mode mode,
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final FrameFactory frameFactory,
             final StreamIdGenerator idGenerator,
             final HttpProcessor httpProcessor,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
index 617c787..d6dcf59 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
@@ -39,7 +39,7 @@ import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
 import org.apache.hc.core5.http2.frame.FrameFactory;
 import org.apache.hc.core5.http2.frame.StreamIdGenerator;
 import org.apache.hc.core5.net.InetAddressUtils;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 
 /**
  * Client side HTTP/2 stream multiplexer.
@@ -51,7 +51,7 @@ public class ClientHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
 
     public ClientHttp2StreamMultiplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final FrameFactory frameFactory,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
@@ -63,7 +63,7 @@ public class ClientHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
     }
 
     public ClientHttp2StreamMultiplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final H2Config h2Config,
@@ -72,7 +72,7 @@ public class ClientHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
     }
 
     public ClientHttp2StreamMultiplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final H2Config h2Config,
             final CharCodingConfig charCodingConfig) {

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
index 1297746..a45d4fa 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
@@ -35,7 +35,7 @@ import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -76,7 +76,7 @@ public final class ClientHttp2StreamMultiplexerFactory {
         this(httpProcessor, null, streamListener);
     }
 
-    public ClientHttp2StreamMultiplexer create(final TlsCapableIOSession ioSession) {
+    public ClientHttp2StreamMultiplexer create(final ProtocolIOSession ioSession) {
         return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
                 pushHandlerFactory, h2Config, charCodingConfig, streamListener);
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
index 67a4803..313222c 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
@@ -52,7 +52,7 @@ import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
 import org.apache.hc.core5.util.Args;
 
@@ -68,7 +68,7 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
             0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d,
             0x0d, 0x0a, 0x0d, 0x0a};
 
-    private final TlsCapableIOSession ioSession;
+    private final ProtocolIOSession ioSession;
     private final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory;
     private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
     private final HttpVersionPolicy versionPolicy;
@@ -76,7 +76,7 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
     private volatile ByteBuffer preface;
 
     public ClientHttpProtocolNegotiator(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory,
             final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
             final HttpVersionPolicy versionPolicy) {
@@ -105,7 +105,7 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
             }
             if (preface == null) {
                 final ClientHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(ioSession);
-                session.setHandler(new ClientHttp1IOEventHandler(http1StreamHandler));
+                ioSession.upgrade(new ClientHttp1IOEventHandler(http1StreamHandler));
                 http1StreamHandler.onConnect(null);
             } else {
                 writePreface(session);
@@ -125,7 +125,7 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
             final ClientHttp2StreamMultiplexer streamMultiplexer = http2StreamHandlerFactory.create(ioSession);
             final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
             newHandler.connected(session);
-            session.setHandler(newHandler);
+            ioSession.upgrade(newHandler);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
index d9c0f67..020f273 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
@@ -32,7 +32,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
 import org.apache.hc.core5.http2.HttpVersionPolicy;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -55,7 +55,7 @@ public class ClientHttpProtocolNegotiatorFactory implements IOEventHandlerFactor
     }
 
     @Override
-    public ClientHttpProtocolNegotiator createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public ClientHttpProtocolNegotiator createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         return new ClientHttpProtocolNegotiator(
                 ioSession,
                 http1StreamHandlerFactory,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2OnlyClientProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2OnlyClientProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2OnlyClientProtocolNegotiator.java
index 7bfaff1..c80d8b3 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2OnlyClientProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2OnlyClientProtocolNegotiator.java
@@ -49,7 +49,7 @@ import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.TextUtils;
@@ -60,14 +60,14 @@ import org.apache.hc.core5.util.TextUtils;
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
 public class Http2OnlyClientProtocolNegotiator implements HttpConnectionEventHandler {
 
-    private final TlsCapableIOSession ioSession;
+    private final ProtocolIOSession ioSession;
     private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
     private final boolean strictALPNHandshake;
 
     private final ByteBuffer preface;
 
     public Http2OnlyClientProtocolNegotiator(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
             final boolean strictALPNHandshake) {
         this.ioSession = Args.notNull(ioSession, "I/O session");
@@ -108,7 +108,7 @@ public class Http2OnlyClientProtocolNegotiator implements HttpConnectionEventHan
             final ClientHttp2StreamMultiplexer streamMultiplexer = http2StreamHandlerFactory.create(ioSession);
             final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
             newHandler.connected(session);
-            session.setHandler(newHandler);
+            ioSession.upgrade(newHandler);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
index 6c1ff01..b2f8139 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
@@ -39,7 +39,7 @@ import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
 import org.apache.hc.core5.http2.frame.FrameFactory;
 import org.apache.hc.core5.http2.frame.StreamIdGenerator;
 import org.apache.hc.core5.net.InetAddressUtils;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -52,7 +52,7 @@ public class ServerHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
     private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
 
     public ServerHttp2StreamMultiplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final FrameFactory frameFactory,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
@@ -64,7 +64,7 @@ public class ServerHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
     }
 
     public ServerHttp2StreamMultiplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final CharCodingConfig charCodingConfig,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
index 7cb03f3..7e349fe 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
@@ -35,7 +35,7 @@ import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -63,7 +63,7 @@ public final class ServerHttp2StreamMultiplexerFactory {
         this.streamListener = streamListener;
     }
 
-    public ServerHttp2StreamMultiplexer create(final TlsCapableIOSession ioSession) {
+    public ServerHttp2StreamMultiplexer create(final ProtocolIOSession ioSession) {
         return new ServerHttp2StreamMultiplexer(
                 ioSession,
                 DefaultFrameFactory.INSTANCE,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
index e90d825..744de4a 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
@@ -49,7 +49,7 @@ import org.apache.hc.core5.http2.HttpVersionPolicy;
 import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.IOSession;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
 import org.apache.hc.core5.util.Args;
 
@@ -61,7 +61,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
 
     final static byte[] PREFACE = ClientHttpProtocolNegotiator.PREFACE;
 
-    private final TlsCapableIOSession ioSession;
+    private final ProtocolIOSession ioSession;
     private final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory;
     private final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
     private final HttpVersionPolicy versionPolicy;
@@ -70,7 +70,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
     private volatile boolean expectValidH2Preface;
 
     public ServerHttpProtocolNegotiator(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory,
             final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
             final HttpVersionPolicy versionPolicy) {
@@ -99,7 +99,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
                     final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(
                             tlsDetails != null ? URIScheme.HTTPS.id : URIScheme.HTTP.id,
                             ioSession);
-                    session.setHandler(new ServerHttp1IOEventHandler(http1StreamHandler));
+                    ioSession.upgrade(new ServerHttp1IOEventHandler(http1StreamHandler));
                     http1StreamHandler.onConnect(null);
                     break;
             }
@@ -133,7 +133,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
                 }
                 if (validH2Preface) {
                     final ServerHttp2StreamMultiplexer http2StreamHandler = http2StreamHandlerFactory.create(ioSession);
-                    session.setHandler(new ServerHttp2IOEventHandler(http2StreamHandler));
+                    ioSession.upgrade(new ServerHttp2IOEventHandler(http2StreamHandler));
                     http2StreamHandler.onConnect(bytebuf.hasRemaining() ? bytebuf : null);
                     http2StreamHandler.onInput();
                 } else {
@@ -141,7 +141,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
                     final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(
                             tlsDetails != null ? URIScheme.HTTPS.id : URIScheme.HTTP.id,
                             ioSession);
-                    session.setHandler(new ServerHttp1IOEventHandler(http1StreamHandler));
+                    ioSession.upgrade(new ServerHttp1IOEventHandler(http1StreamHandler));
                     bytebuf.rewind();
                     http1StreamHandler.onConnect(bytebuf);
                     http1StreamHandler.onInput();

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
index d53a25b..d2a32b2 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
@@ -33,7 +33,7 @@ import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.http2.HttpVersionPolicy;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -59,7 +59,7 @@ public class ServerHttpProtocolNegotiatorFactory implements IOEventHandlerFactor
     }
 
     @Override
-    public ServerHttpProtocolNegotiator createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public ServerHttpProtocolNegotiator createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         if (tlsStrategy != null) {
             tlsStrategy.upgrade(
                     ioSession,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2MultiplexingRequesterBootstrap.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2MultiplexingRequesterBootstrap.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2MultiplexingRequesterBootstrap.java
index 982120d..bca1121 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2MultiplexingRequesterBootstrap.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2MultiplexingRequesterBootstrap.java
@@ -50,7 +50,7 @@ import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.IOSessionListener;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -202,7 +202,7 @@ public class Http2MultiplexingRequesterBootstrap {
                 new IOEventHandlerFactory() {
 
                     @Override
-                    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+                    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
                         return new Http2OnlyClientProtocolNegotiator(ioSession, http2StreamHandlerFactory, strictALPNHandshake);
                     }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
index 1735ee9..d949b02 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
@@ -51,7 +51,7 @@ import org.apache.hc.core5.http.nio.NHttpMessageWriterFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -85,7 +85,7 @@ class InternalClientHttp1EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     protected ClientHttp1StreamDuplexer createClientHttp1StreamDuplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final H1Config h1Config,
             final CharCodingConfig charCodingConfig,
@@ -101,7 +101,7 @@ class InternalClientHttp1EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         if (sslContext != null) {
             ioSession.startTls(sslContext, null ,null, null);
         }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
index 567a85c..87c0ed0 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
@@ -43,7 +43,7 @@ import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexerFactory;
 import org.apache.hc.core5.http2.impl.nio.ClientHttpProtocolNegotiator;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 class InternalClientHttp2EventHandlerFactory implements IOEventHandlerFactory {
@@ -74,7 +74,7 @@ class InternalClientHttp2EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         if (sslContext != null) {
             ioSession.startTls(sslContext, null ,null, null);
         }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
index 50e8b29..4cc9171 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
@@ -54,7 +54,7 @@ import org.apache.hc.core5.http.nio.NHttpMessageWriterFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -91,7 +91,7 @@ class InternalServerHttp1EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     protected ServerHttp1StreamDuplexer createServerHttp1StreamDuplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final H1Config h1Config,
@@ -109,7 +109,7 @@ class InternalServerHttp1EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         if (sslContext != null) {
             ioSession.startTls(sslContext, null ,null, null);
         }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
index 548f1da..0691c33 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
@@ -43,7 +43,7 @@ import org.apache.hc.core5.http2.impl.nio.ServerHttp2StreamMultiplexerFactory;
 import org.apache.hc.core5.http2.impl.nio.ServerHttpProtocolNegotiator;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 class InternalServerHttp2EventHandlerFactory implements IOEventHandlerFactory {
@@ -74,7 +74,7 @@ class InternalServerHttp2EventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         if (sslContext != null) {
             ioSession.startTls(sslContext, null ,null, null);
         }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
index 59ac54b..feb6fed 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
@@ -35,7 +35,6 @@ import java.nio.channels.SelectionKey;
 
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
-import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.testing.classic.Wire;
 import org.slf4j.Logger;
@@ -208,16 +207,6 @@ public class LoggingIOSession implements IOSession {
     }
 
     @Override
-    public IOEventHandler getHandler() {
-        return this.session.getHandler();
-    }
-
-    @Override
-    public void setHandler(final IOEventHandler handler) {
-        this.session.setHandler(handler);
-    }
-
-    @Override
     public String toString() {
         return this.session.toString();
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
index 92b9ef3..2579935 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
@@ -65,7 +65,6 @@ import org.apache.hc.core5.http.ContentLengthStrategy;
 import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpConnection;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpHost;
@@ -122,22 +121,21 @@ import org.apache.hc.core5.http.protocol.RequestConnControl;
 import org.apache.hc.core5.http.protocol.RequestContent;
 import org.apache.hc.core5.http.protocol.RequestValidateHost;
 import org.apache.hc.core5.reactor.ExceptionEvent;
-import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOSession;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.testing.SSLTestContexts;
 import org.apache.hc.core5.util.CharArrayBuffer;
 import org.apache.hc.core5.util.TextUtils;
 import org.apache.hc.core5.util.TimeValue;
-import org.slf4j.LoggerFactory;
-import org.slf4j.Logger;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @RunWith(Parameterized.class)
 public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
@@ -737,11 +735,6 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
         final IOSession ioSession = sessionFuture.get();
         final ClientSessionEndpoint streamEndpoint = new ClientSessionEndpoint(ioSession);
 
-        final IOEventHandler handler = ioSession.getHandler();
-        Assert.assertNotNull(handler);
-        Assert.assertTrue(handler instanceof HttpConnection);
-        final HttpConnection conn = (HttpConnection) handler;
-
         final HttpRequest request1 = new BasicHttpRequest("POST", createRequestURI(serverEndpoint, "/echo"));
         request1.addHeader("password", "secret");
         final Future<Message<HttpResponse, String>> future1 = streamEndpoint.execute(
@@ -754,7 +747,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
         Assert.assertEquals(200, response1.getCode());
         Assert.assertNotNull("All is well", result1.getBody());
 
-        Assert.assertTrue(conn.isOpen());
+        Assert.assertFalse(ioSession.isClosed());
 
         final HttpRequest request2 = new BasicHttpRequest("POST", createRequestURI(serverEndpoint, "/echo"));
         final Future<Message<HttpResponse, String>> future2 = streamEndpoint.execute(
@@ -767,7 +760,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
         Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response2.getCode());
         Assert.assertNotNull("You shall not pass", result2.getBody());
 
-        Assert.assertTrue(conn.isOpen());
+        Assert.assertFalse(ioSession.isClosed());
 
         final HttpRequest request3 = new BasicHttpRequest("POST", createRequestURI(serverEndpoint, "/echo"));
         request3.addHeader("password", "secret");
@@ -781,7 +774,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
         Assert.assertEquals(200, response3.getCode());
         Assert.assertNotNull("All is well", result3.getBody());
 
-        Assert.assertTrue(conn.isOpen());
+        Assert.assertFalse(ioSession.isClosed());
 
         final HttpRequest request4 = new BasicHttpRequest("POST", createRequestURI(serverEndpoint, "/echo"));
         final Future<Message<HttpResponse, String>> future4 = streamEndpoint.execute(
@@ -794,7 +787,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
         Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response4.getCode());
         Assert.assertNotNull("You shall not pass", result4.getBody());
 
-        Assert.assertFalse(conn.isOpen());
+        Assert.assertTrue(ioSession.isClosed());
     }
 
     @Test
@@ -1383,7 +1376,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
 
             @Override
             protected ServerHttp1StreamDuplexer createServerHttp1StreamDuplexer(
-                    final TlsCapableIOSession ioSession,
+                    final ProtocolIOSession ioSession,
                     final HttpProcessor httpProcessor,
                     final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
                     final H1Config h1Config,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
index 429c6d9..892f8c6 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
@@ -113,11 +113,10 @@ import org.apache.hc.core5.http2.nio.support.BasicPingHandler;
 import org.apache.hc.core5.reactor.ExceptionEvent;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.testing.SSLTestContexts;
 import org.apache.hc.core5.util.TextUtils;
 import org.apache.hc.core5.util.TimeValue;
-import org.slf4j.LoggerFactory;
-import org.slf4j.Logger;
 import org.hamcrest.CoreMatchers;
 import org.junit.After;
 import org.junit.Assert;
@@ -125,6 +124,8 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @RunWith(Parameterized.class)
 public class Http2IntegrationTest extends InternalHttp2ServerTestBase {
@@ -1040,7 +1041,7 @@ public class Http2IntegrationTest extends InternalHttp2ServerTestBase {
             Assert.assertThat(ex.getCause(), CoreMatchers.instanceOf(ProtocolException.class));
         }
 
-        final HttpConnection eventHandler = (HttpConnection) session.getHandler();
+        final HttpConnection eventHandler = (HttpConnection) ((ProtocolIOSession) session).getHandler();
         final EndpointDetails endpointDetails = eventHandler.getEndpointDetails();
         Assert.assertThat(endpointDetails.getRequestCount(), CoreMatchers.equalTo(0L));
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TestDefaultListeningIOReactor.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TestDefaultListeningIOReactor.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TestDefaultListeningIOReactor.java
index 66b3533..d0e5c12 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TestDefaultListeningIOReactor.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/TestDefaultListeningIOReactor.java
@@ -40,7 +40,7 @@ import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOReactorStatus;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.ListenerEndpoint;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.TimeValue;
 import org.junit.After;
 import org.junit.Assert;
@@ -57,7 +57,7 @@ public class TestDefaultListeningIOReactor {
     private static class NoopIOEventHandlerFactory implements IOEventHandlerFactory {
 
         @Override
-        public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+        public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
             return new IOEventHandler() {
 
                 @Override

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
index e6aa31f..db7fedd 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
@@ -48,6 +48,7 @@ import org.apache.hc.core5.http.ContentLengthStrategy;
 import org.apache.hc.core5.http.EndpointDetails;
 import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpMessage;
 import org.apache.hc.core5.http.Message;
@@ -75,20 +76,22 @@ import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
 import org.apache.hc.core5.reactor.EventMask;
 import org.apache.hc.core5.reactor.IOEventHandler;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolLayer;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.reactor.ssl.SSLBufferManagement;
 import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
 import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
+import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.Identifiable;
 
 abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage, OutgoingMessage extends HttpMessage>
-        implements Identifiable, ResourceHolder, UpgradeableHttpConnection {
+        implements Identifiable, ResourceHolder, TransportSecurityLayer, ProtocolLayer, HttpConnection {
 
     private enum ConnectionState { READY, ACTIVE, GRACEFUL_SHUTDOWN, SHUTDOWN}
 
-    private final TlsCapableIOSession ioSession;
+    private final ProtocolIOSession ioSession;
     private final H1Config h1Config;
     private final SessionInputBufferImpl inbuf;
     private final SessionOutputBufferImpl outbuf;
@@ -105,13 +108,13 @@ abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage,
 
     private volatile Message<IncomingMessage, ContentDecoder> incomingMessage;
     private volatile Message<OutgoingMessage, ContentEncoder> outgoingMessage;
-    private volatile ConnectionState connState = ConnectionState.READY;
+    private volatile ConnectionState connState;
 
     private volatile ProtocolVersion version;
     private volatile EndpointDetails endpointDetails;
 
     AbstractHttp1StreamDuplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final H1Config h1Config,
             final CharCodingConfig charCodingConfig,
             final NHttpMessageParser<IncomingMessage> incomingMessageParser,
@@ -623,8 +626,13 @@ abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage,
     }
 
     @Override
+    public IOEventHandler getHandler() {
+        return ioSession.getHandler();
+    }
+
+    @Override
     public void upgrade(final IOEventHandler eventHandler) {
-        ioSession.setHandler(eventHandler);
+        ioSession.upgrade(eventHandler);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
index 43f0379..6d94c57 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
@@ -31,7 +31,7 @@ import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -47,7 +47,7 @@ public class ClientHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         return new ClientHttp1IOEventHandler(streamDuplexerFactory.create(ioSession));
     }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java
index 2adfd3b..67559b5 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java
@@ -64,7 +64,7 @@ import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.net.InetAddressUtils;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.Asserts;
 
@@ -81,7 +81,7 @@ public class ClientHttp1StreamDuplexer extends AbstractHttp1StreamDuplexer<HttpR
     private volatile ClientHttp1StreamHandler incoming;
 
     public ClientHttp1StreamDuplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final H1Config h1Config,
             final CharCodingConfig charCodingConfig,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java
index a99c274..0272faa 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java
@@ -41,7 +41,7 @@ import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.nio.NHttpMessageParserFactory;
 import org.apache.hc.core5.http.nio.NHttpMessageWriterFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -113,7 +113,7 @@ public final class ClientHttp1StreamDuplexerFactory {
         this(httpProcessor, h1Config, charCodingConfig, null);
     }
 
-    public ClientHttp1StreamDuplexer create(final TlsCapableIOSession ioSession) {
+    public ClientHttp1StreamDuplexer create(final ProtocolIOSession ioSession) {
         return new ClientHttp1StreamDuplexer(
                 ioSession,
                 httpProcessor,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
index c7424f7..ee84dfa 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
@@ -33,7 +33,7 @@ import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -53,7 +53,7 @@ public class ServerHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
     }
 
     @Override
-    public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
+    public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
         final boolean tlsSecured;
         if (tlsStrategy != null) {
             tlsSecured = tlsStrategy.upgrade(

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java
index c400cd0..f2fcc42 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java
@@ -63,7 +63,7 @@ import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.net.InetAddressUtils;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.Asserts;
 
@@ -82,7 +82,7 @@ public class ServerHttp1StreamDuplexer extends AbstractHttp1StreamDuplexer<HttpR
     private volatile ServerHttp1StreamHandler incoming;
 
     public ServerHttp1StreamDuplexer(
-            final TlsCapableIOSession ioSession,
+            final ProtocolIOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final String scheme,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java
index df0286e..e92cd0a 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java
@@ -43,7 +43,7 @@ import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.nio.NHttpMessageParserFactory;
 import org.apache.hc.core5.http.nio.NHttpMessageWriterFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -114,7 +114,7 @@ public final class ServerHttp1StreamDuplexerFactory {
         this(httpProcessor, exchangeHandlerFactory, h1Config, charCodingConfig, null, null ,null, streamListener);
     }
 
-    public ServerHttp1StreamDuplexer create(final String scheme, final TlsCapableIOSession ioSession) {
+    public ServerHttp1StreamDuplexer create(final String scheme, final ProtocolIOSession ioSession) {
         return new ServerHttp1StreamDuplexer(ioSession, httpProcessor, exchangeHandlerFactory,
                 scheme,
                 h1Config,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOEventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOEventHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOEventHandlerFactory.java
index 458f6e2..e7d5131 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOEventHandlerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOEventHandlerFactory.java
@@ -34,6 +34,6 @@ package org.apache.hc.core5.reactor;
  */
 public interface IOEventHandlerFactory {
 
-    IOEventHandler createHandler(TlsCapableIOSession ioSession, Object attachment);
+    IOEventHandler createHandler(ProtocolIOSession ioSession, Object attachment);
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
index 44f0c1a..7068d29 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
@@ -56,20 +56,6 @@ public interface IOSession extends GracefullyCloseable, Identifiable {
     int CLOSED       = Integer.MAX_VALUE;
 
     /**
-     * Returns the event handler for this session.
-     *
-     * @since 5.0
-     */
-    IOEventHandler getHandler();
-
-    /**
-     * Sets the event handler for this session.
-     *
-     * @since 5.0
-     */
-    void setHandler(IOEventHandler handler);
-
-    /**
      * Inserts {@link Command} at the end of the command queue.
      *
      * @since 5.0

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
index 710c118..c179f25 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
@@ -79,16 +79,6 @@ class IOSessionImpl implements IOSession {
     }
 
     @Override
-    public IOEventHandler getHandler() {
-        return this.eventHandler;
-    }
-
-    @Override
-    public void setHandler(final IOEventHandler handler) {
-        this.eventHandler = handler;
-    }
-
-    @Override
     public void addLast(final Command command) {
         commandQueue.addLast(command);
         setEvent(SelectionKey.OP_WRITE);

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
index b30f50d..b789d59 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
@@ -69,7 +69,7 @@ final class IOSessionRequest implements Future<IOSession> {
         this.closeableRef = new AtomicReference<>(null);
     }
 
-    public void completed(final TlsCapableIOSession ioSession) {
+    public void completed(final ProtocolIOSession ioSession) {
         future.completed(ioSession);
         closeableRef.set(null);
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
index 34f3ec8..5322c90 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java
@@ -48,13 +48,14 @@ import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
 import org.apache.hc.core5.reactor.ssl.TlsDetails;
 import org.apache.hc.core5.util.Asserts;
 
-final class InternalDataChannel extends InternalChannel implements TlsCapableIOSession {
+final class InternalDataChannel extends InternalChannel implements ProtocolIOSession {
 
     private final IOSession ioSession;
     private final NamedEndpoint namedEndpoint;
     private final IOSessionListener sessionListener;
     private final AtomicReference<SSLIOSession> tlsSessionRef;
     private final Queue<InternalDataChannel> closedSessions;
+    private final AtomicReference<IOEventHandler> handlerRef;
     private final AtomicBoolean connected;
     private final AtomicBoolean closed;
 
@@ -68,6 +69,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
         this.closedSessions = closedSessions;
         this.sessionListener = sessionListener;
         this.tlsSessionRef = new AtomicReference<>(null);
+        this.handlerRef = new AtomicReference<>(null);
         this.connected = new AtomicBoolean(false);
         this.closed = new AtomicBoolean(false);
     }
@@ -77,6 +79,16 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
         return ioSession.getId();
     }
 
+    @Override
+    public IOEventHandler getHandler() {
+        return handlerRef.get();
+    }
+
+    @Override
+    public void upgrade(final IOEventHandler handler) {
+        handlerRef.set(handler);
+    }
+
     private IOSession getSessionImpl() {
         final SSLIOSession tlsSession = tlsSessionRef.get();
         if (tlsSession != null) {
@@ -86,8 +98,8 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
         }
     }
 
-    private IOEventHandler getEventHandler() {
-        final IOEventHandler handler = ioSession.getHandler();
+    private IOEventHandler ensureHandler() {
+        final IOEventHandler handler = handlerRef.get();
         Asserts.notNull(handler, "IO event handler");
         return handler;
     }
@@ -113,7 +125,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                         if (sessionListener != null) {
                             sessionListener.inputReady(this);
                         }
-                        final IOEventHandler handler = getEventHandler();
+                        final IOEventHandler handler = ensureHandler();
                         handler.inputReady(this);
                     }
                     tlsSession.inboundTransport();
@@ -128,7 +140,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                     if (sessionListener != null) {
                         sessionListener.outputReady(this);
                     }
-                    final IOEventHandler handler = getEventHandler();
+                    final IOEventHandler handler = ensureHandler();
                     handler.outputReady(this);
                 }
                 tlsSession.outboundTransport();
@@ -143,7 +155,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                     if (sessionListener != null) {
                         sessionListener.connected(this);
                     }
-                    final IOEventHandler handler = getEventHandler();
+                    final IOEventHandler handler = ensureHandler();
                     handler.connected(this);
                 }
             }
@@ -152,7 +164,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                 if (sessionListener != null) {
                     sessionListener.inputReady(this);
                 }
-                final IOEventHandler handler = getEventHandler();
+                final IOEventHandler handler = ensureHandler();
                 handler.inputReady(this);
             }
             if ((readyOps & SelectionKey.OP_WRITE) != 0) {
@@ -160,7 +172,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                 if (sessionListener != null) {
                     sessionListener.outputReady(this);
                 }
-                final IOEventHandler handler = getEventHandler();
+                final IOEventHandler handler = ensureHandler();
                 handler.outputReady(this);
             }
         }
@@ -173,7 +185,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
 
     @Override
     void onTimeout() throws IOException {
-        final IOEventHandler handler = getEventHandler();
+        final IOEventHandler handler = ensureHandler();
         handler.timeout(this);
         final SSLIOSession tlsSession = tlsSessionRef.get();
         if (tlsSession != null) {
@@ -186,7 +198,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
 
     @Override
     void onException(final Exception cause) {
-        final IOEventHandler handler = getEventHandler();
+        final IOEventHandler handler = ensureHandler();
         if (sessionListener != null) {
             sessionListener.exception(this, cause);
         }
@@ -197,7 +209,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
         if (sessionListener != null) {
             sessionListener.disconnected(this);
         }
-        final IOEventHandler handler = getEventHandler();
+        final IOEventHandler handler = ensureHandler();
         handler.disconnected(this);
     }
 
@@ -220,7 +232,7 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
                     @Override
                     public void execute(final SSLIOSession sslSession) {
                         if (connected.compareAndSet(false, true)) {
-                            final IOEventHandler handler = getEventHandler();
+                            final IOEventHandler handler = ensureHandler();
                             try {
                                 if (sessionListener != null) {
                                     sessionListener.connected(InternalDataChannel.this);
@@ -279,16 +291,6 @@ final class InternalDataChannel extends InternalChannel implements TlsCapableIOS
     }
 
     @Override
-    public IOEventHandler getHandler() {
-        return ioSession.getHandler();
-    }
-
-    @Override
-    public void setHandler(final IOEventHandler eventHandler) {
-        ioSession.setHandler(eventHandler);
-    }
-
-    @Override
     public void addLast(final Command command) {
         getSessionImpl().addLast(command);
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
new file mode 100644
index 0000000..8d542de
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolIOSession.java
@@ -0,0 +1,39 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.reactor;
+
+import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
+
+/**
+ * TLS capable {@link IOSession}.
+ *
+ * @since 5.0
+ */
+public interface ProtocolIOSession extends IOSession, ProtocolLayer, TransportSecurityLayer {
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolLayer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolLayer.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolLayer.java
new file mode 100644
index 0000000..8b5c2df
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ProtocolLayer.java
@@ -0,0 +1,44 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.reactor;
+
+import org.apache.hc.core5.annotation.Internal;
+
+/**
+ * Represents application protocol layer.
+ *
+ * @since 5.0
+ */
+@Internal
+public interface ProtocolLayer {
+
+    IOEventHandler getHandler();
+
+    void upgrade(IOEventHandler handler);
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
index 27830a9..edba172 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
@@ -204,7 +204,7 @@ class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements Connect
                 ioSession = ioSessionDecorator.decorate(ioSession);
             }
             final InternalDataChannel dataChannel = new InternalDataChannel(ioSession, null, sessionListener, closedSessions);
-            dataChannel.setHandler(this.eventHandlerFactory.createHandler(dataChannel, null));
+            dataChannel.upgrade(this.eventHandlerFactory.createHandler(dataChannel, null));
             dataChannel.setSocketTimeout(this.reactorConfig.getSoTimeout().toMillisIntBound());
             key.attach(dataChannel);
             dataChannel.handleIOEvent(SelectionKey.OP_CONNECT);
@@ -330,7 +330,7 @@ class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements Connect
                     ioSession = ioSessionDecorator.decorate(ioSession);
                 }
                 final InternalDataChannel dataChannel = new InternalDataChannel(ioSession, namedEndpoint, sessionListener, closedSessions);
-                dataChannel.setHandler(eventHandlerFactory.createHandler(dataChannel, attachment));
+                dataChannel.upgrade(eventHandlerFactory.createHandler(dataChannel, attachment));
                 dataChannel.setSocketTimeout(reactorConfig.getSoTimeout().toMillisIntBound());
                 return dataChannel;
             }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/TlsCapableIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/TlsCapableIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/TlsCapableIOSession.java
deleted file mode 100644
index a6e082b..0000000
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/TlsCapableIOSession.java
+++ /dev/null
@@ -1,39 +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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.hc.core5.reactor;
-
-import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
-
-/**
- * TLS capable {@link IOSession}.
- *
- * @since 5.0
- */
-public interface TlsCapableIOSession extends IOSession, TransportSecurityLayer {
-
-}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/9188bf41/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
index a462197..8325480 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
@@ -52,7 +52,6 @@ import org.apache.hc.core5.io.ShutdownType;
 import org.apache.hc.core5.net.NamedEndpoint;
 import org.apache.hc.core5.reactor.Command;
 import org.apache.hc.core5.reactor.EventMask;
-import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.ssl.ReflectionSupport;
 import org.apache.hc.core5.util.Args;
@@ -730,16 +729,6 @@ public class SSLIOSession implements IOSession {
         return this.session.getLastWriteTime();
     }
 
-    @Override
-    public IOEventHandler getHandler() {
-        return this.session.getHandler();
-    }
-
-    @Override
-    public void setHandler(final IOEventHandler handler) {
-        this.session.setHandler(handler);
-    }
-
     private static void formatOps(final StringBuilder buffer, final int ops) {
         if ((ops & SelectionKey.OP_READ) > 0) {
             buffer.append('r');