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 2017/05/09 19:58:03 UTC

[11/50] [abbrv] httpcomponents-core git commit: HTTP protocol version negotiation

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
index 0b5d7ba..d890360 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
@@ -30,20 +30,19 @@ import org.apache.hc.core5.http.ConnectionReuseStrategy;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
-import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
 import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.HttpProcessors;
 import org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandlerFactory;
-import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestWriterFactory;
-import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseParserFactory;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
 import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.pool.ConnPoolListener;
 import org.apache.hc.core5.pool.ConnPoolPolicy;
 import org.apache.hc.core5.pool.StrictConnPool;
+import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOReactorException;
 import org.apache.hc.core5.reactor.IOSession;
@@ -55,6 +54,7 @@ import org.apache.hc.core5.util.TimeValue;
 public class AsyncRequesterBootstrap {
 
     private IOReactorConfig ioReactorConfig;
+    private H1Config h1Config;
     private CharCodingConfig charCodingConfig;
     private HttpProcessor httpProcessor;
     private ConnectionReuseStrategy connStrategy;
@@ -84,7 +84,15 @@ public class AsyncRequesterBootstrap {
     }
 
     /**
-     * Sets connection configuration.
+     * Sets HTTP/1.1 protocol parameters
+     */
+    public final AsyncRequesterBootstrap setH1Config(final H1Config h1Config) {
+        this.h1Config = h1Config;
+        return this;
+    }
+
+    /**
+     * Sets message char coding.
      */
     public final AsyncRequesterBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
         this.charCodingConfig = charCodingConfig;
@@ -177,16 +185,14 @@ public class AsyncRequesterBootstrap {
                 timeToLive,
                 connPoolPolicy,
                 connPoolListener);
-        final ClientHttp1IOEventHandlerFactory ioEventHandlerFactory = new ClientHttp1IOEventHandlerFactory(
+        final ClientHttp1StreamDuplexerFactory streamDuplexerFactory = new ClientHttp1StreamDuplexerFactory(
                 httpProcessor != null ? httpProcessor : HttpProcessors.client(),
-                charCodingConfig,
-                connStrategy != null ? connStrategy : DefaultConnectionReuseStrategy.INSTANCE,
-                DefaultHttpResponseParserFactory.INSTANCE,
-                DefaultHttpRequestWriterFactory.INSTANCE,
-                DefaultContentLengthStrategy.INSTANCE,
-                DefaultContentLengthStrategy.INSTANCE,
+                h1Config != null ? h1Config : H1Config.DEFAULT,
+                charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
                 connectionListener,
                 streamListener);
+        final IOEventHandlerFactory ioEventHandlerFactory = new ClientHttp1IOEventHandlerFactory(
+                streamDuplexerFactory);
         try {
             return new HttpAsyncRequester(
                     ioReactorConfig,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncServerBootstrap.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncServerBootstrap.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncServerBootstrap.java
index 535bb41..7cf6cd9 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncServerBootstrap.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncServerBootstrap.java
@@ -33,6 +33,7 @@ import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.ConnectionReuseStrategy;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
@@ -41,6 +42,7 @@ import org.apache.hc.core5.http.impl.HttpProcessors;
 import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestParserFactory;
 import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseWriterFactory;
 import org.apache.hc.core5.http.impl.nio.ServerHttp1IOEventHandlerFactory;
+import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
 import org.apache.hc.core5.http.nio.ssl.BasicServerTlsStrategy;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
@@ -49,6 +51,7 @@ import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
 import org.apache.hc.core5.http.nio.support.ResponseHandler;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.net.InetAddressUtils;
+import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOReactorException;
 import org.apache.hc.core5.util.Args;
@@ -61,6 +64,7 @@ public class AsyncServerBootstrap {
     private final List<HandlerEntry> handlerList;
     private String canonicalHostName;
     private IOReactorConfig ioReactorConfig;
+    private H1Config h1Config;
     private CharCodingConfig charCodingConfig;
     private HttpProcessor httpProcessor;
     private ConnectionReuseStrategy connStrategy;
@@ -96,6 +100,14 @@ public class AsyncServerBootstrap {
     }
 
     /**
+     * Sets HTTP/1.1 protocol parameters.
+     */
+    public final AsyncServerBootstrap setH1Config(final H1Config h1Config) {
+        this.h1Config = h1Config;
+        return this;
+    }
+
+    /**
      * Sets connection configuration.
      */
     public final AsyncServerBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
@@ -205,18 +217,21 @@ public class AsyncServerBootstrap {
         for (final HandlerEntry entry: handlerList) {
             exchangeHandlerFactory.register(entry.hostname, entry.uriPattern, entry.supplier);
         }
-        final ServerHttp1IOEventHandlerFactory ioEventHandlerFactory = new ServerHttp1IOEventHandlerFactory(
+        final ServerHttp1StreamDuplexerFactory streamHandlerFactory = new ServerHttp1StreamDuplexerFactory(
                 httpProcessor != null ? httpProcessor : HttpProcessors.server(),
                 exchangeHandlerFactory,
-                charCodingConfig,
+                h1Config != null ? h1Config : H1Config.DEFAULT,
+                charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
                 connStrategy != null ? connStrategy : DefaultConnectionReuseStrategy.INSTANCE,
                 DefaultHttpRequestParserFactory.INSTANCE,
                 DefaultHttpResponseWriterFactory.INSTANCE,
                 DefaultContentLengthStrategy.INSTANCE,
                 DefaultContentLengthStrategy.INSTANCE,
-                tlsStrategy != null ? tlsStrategy : new BasicServerTlsStrategy(new int[] {443, 8443}),
                 connectionListener,
                 streamListener);
+        final IOEventHandlerFactory ioEventHandlerFactory = new ServerHttp1IOEventHandlerFactory(
+                streamHandlerFactory,
+                tlsStrategy != null ? tlsStrategy : new BasicServerTlsStrategy(new int[] {443, 8443}));
         try {
             return new HttpAsyncServer(
                     ioEventHandlerFactory,

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
index 769ac2a..f7ea9be 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
@@ -69,7 +69,7 @@ import org.apache.hc.core5.reactor.IOReactorException;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.SessionRequest;
 import org.apache.hc.core5.reactor.SessionRequestCallback;
-import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
+import org.apache.hc.core5.reactor.TlsCapableIOSession;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.TimeValue;
 
@@ -106,6 +106,15 @@ public class HttpAsyncRequester extends AsyncRequester {
     public Future<AsyncClientEndpoint> connect(
             final HttpHost host,
             final TimeValue timeout,
+            final Object attachment,
+            final FutureCallback<AsyncClientEndpoint> callback) {
+        return doConnect(host, timeout, attachment, callback);
+    }
+
+    protected Future<AsyncClientEndpoint> doConnect(
+            final HttpHost host,
+            final TimeValue timeout,
+            final Object attachment,
             final FutureCallback<AsyncClientEndpoint> callback) {
         Args.notNull(host, "Host");
         Args.notNull(timeout, "Timeout");
@@ -123,17 +132,18 @@ public class HttpAsyncRequester extends AsyncRequester {
                 if (poolEntry.hasConnection()) {
                     resultFuture.completed(endpoint);
                 } else {
-                    final SessionRequest sessionRequest = requestSession(host, timeout, new SessionRequestCallback() {
+                    final SessionRequest sessionRequest = requestSession(host, timeout, attachment, new SessionRequestCallback() {
 
                         @Override
                         public void completed(final SessionRequest request) {
-                            final IOSession session = request.getSession();
-                            if (tlsStrategy != null && session instanceof TransportSecurityLayer) {
+                            final TlsCapableIOSession session = request.getSession();
+                            if (tlsStrategy != null && "https".equalsIgnoreCase(host.getSchemeName())) {
                                 tlsStrategy.upgrade(
-                                        (TransportSecurityLayer) session,
+                                        session,
                                         host,
                                         session.getLocalAddress(),
-                                        session.getRemoteAddress());
+                                        session.getRemoteAddress(),
+                                        attachment);
                             }
                             session.setSocketTimeout(timeout.toMillisIntBound());
                             poolEntry.assignConnection(session);
@@ -188,7 +198,7 @@ public class HttpAsyncRequester extends AsyncRequester {
     }
 
     public Future<AsyncClientEndpoint> connect(final HttpHost host, final TimeValue timeout) throws InterruptedException {
-        return connect(host, timeout, null);
+        return connect(host, timeout, null, null);
     }
 
     public void execute(
@@ -211,7 +221,7 @@ public class HttpAsyncRequester extends AsyncRequester {
                         throw new ProtocolException("Request authority not specified");
                     }
                     final HttpHost target = new HttpHost(authority, scheme);
-                    connect(target, timeout, new FutureCallback<AsyncClientEndpoint>() {
+                    connect(target, timeout, null, new FutureCallback<AsyncClientEndpoint>() {
 
                         @Override
                         public void completed(final AsyncClientEndpoint endpoint) {
@@ -371,7 +381,7 @@ public class HttpAsyncRequester extends AsyncRequester {
             final PoolEntry<HttpHost, IOSession> poolEntry = poolEntryRef.getAndSet(null);
             if (poolEntry != null) {
                 final IOSession ioSession = poolEntry.getConnection();
-                connPool.release(poolEntry, ioSession != null && !ioSession.isClosed());    ;
+                connPool.release(poolEntry, ioSession != null && !ioSession.isClosed());
             }
         }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1IOEventHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1IOEventHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1IOEventHandler.java
index 667bed2..392622f 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1IOEventHandler.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1IOEventHandler.java
@@ -49,7 +49,7 @@ class AbstractHttp1IOEventHandler implements HttpConnectionEventHandler {
     @Override
     public void connected(final IOSession session) {
         try {
-            streamDuplexer.onConnect();
+            streamDuplexer.onConnect(null);
         } catch (final Exception ex) {
             streamDuplexer.onException(ex);
         }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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 bbda5c8..259de37 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
@@ -77,6 +77,7 @@ import org.apache.hc.core5.reactor.TlsCapableIOSession;
 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.util.Args;
 
 abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage, OutgoingMessage extends HttpMessage>
@@ -217,10 +218,13 @@ abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage,
         }
     }
 
-    public final void onConnect() throws HttpException, IOException {
+    public final void onConnect(final ByteBuffer prefeed) throws HttpException, IOException {
         if (connectionListener != null) {
             connectionListener.onConnect(this);
         }
+        if (prefeed != null) {
+            inbuf.put(prefeed);
+        }
         connState = ConnectionState.ACTIVE;
         processCommands();
     }
@@ -579,7 +583,13 @@ abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage,
 
     @Override
     public SSLSession getSSLSession() {
-        return ioSession.getSSLSession();
+        final TlsDetails tlsDetails = ioSession.getTlsDetails();
+        return tlsDetails != null ? tlsDetails.getSSLSession() : null;
+    }
+
+    @Override
+    public TlsDetails getTlsDetails() {
+        return ioSession.getTlsDetails();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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 55c5547..43f0379 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
@@ -29,19 +29,6 @@ package org.apache.hc.core5.http.impl.nio;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ConnectionReuseStrategy;
-import org.apache.hc.core5.http.ContentLengthStrategy;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.config.CharCodingConfig;
-import org.apache.hc.core5.http.config.H1Config;
-import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
-import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
-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.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.TlsCapableIOSession;
@@ -53,86 +40,15 @@ import org.apache.hc.core5.util.Args;
 @Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class ClientHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
-    private final HttpProcessor httpProcessor;
-    private final CharCodingConfig charCodingConfig;
-    private final ConnectionReuseStrategy connectionReuseStrategy;
-    private final NHttpMessageParserFactory<HttpResponse> responseParserFactory;
-    private final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory;
-    private final ContentLengthStrategy incomingContentStrategy;
-    private final ContentLengthStrategy outgoingContentStrategy;
-    private final ConnectionListener connectionListener;
-    private final Http1StreamListener streamListener;
+    private final ClientHttp1StreamDuplexerFactory streamDuplexerFactory;
 
-    public ClientHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final CharCodingConfig charCodingConfig,
-            final ConnectionReuseStrategy connectionReuseStrategy,
-            final NHttpMessageParserFactory<HttpResponse> responseParserFactory,
-            final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory,
-            final ContentLengthStrategy incomingContentStrategy,
-            final ContentLengthStrategy outgoingContentStrategy,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
-        this.charCodingConfig = charCodingConfig !=  null ? charCodingConfig : CharCodingConfig.DEFAULT;
-        this.connectionReuseStrategy = connectionReuseStrategy != null ? connectionReuseStrategy :
-                DefaultConnectionReuseStrategy.INSTANCE;
-        this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
-                DefaultHttpResponseParserFactory.INSTANCE;
-        this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
-                DefaultHttpRequestWriterFactory.INSTANCE;
-        this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
-                DefaultContentLengthStrategy.INSTANCE;
-        this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
-                DefaultContentLengthStrategy.INSTANCE;
-        this.connectionListener = connectionListener;
-        this.streamListener = streamListener;
-    }
-
-    public ClientHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final CharCodingConfig charCodingConfig,
-            final ConnectionReuseStrategy connectionReuseStrategy,
-            final NHttpMessageParserFactory<HttpResponse> responseParserFactory,
-            final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this(httpProcessor, charCodingConfig, connectionReuseStrategy,
-                responseParserFactory, requestWriterFactory, null ,null, connectionListener, streamListener);
-    }
-
-    public ClientHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final CharCodingConfig charCodingConfig,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this(httpProcessor, charCodingConfig, null, null, null, connectionListener, streamListener);
-    }
-
-    public ClientHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final CharCodingConfig charCodingConfig) {
-        this(httpProcessor, charCodingConfig, null, null);
+    public ClientHttp1IOEventHandlerFactory(final ClientHttp1StreamDuplexerFactory streamDuplexerFactory) {
+        this.streamDuplexerFactory = Args.notNull(streamDuplexerFactory, "Stream duplexer factory");
     }
 
     @Override
     public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
-        return new ClientHttp1IOEventHandler(createStreamDuplexer(ioSession));
-    }
-
-    protected ClientHttp1StreamDuplexer createStreamDuplexer(final TlsCapableIOSession ioSession) {
-        return new ClientHttp1StreamDuplexer(
-                ioSession,
-                httpProcessor,
-                H1Config.DEFAULT,
-                charCodingConfig,
-                connectionReuseStrategy,
-                responseParserFactory.create(),
-                requestWriterFactory.create(),
-                incomingContentStrategy,
-                outgoingContentStrategy,
-                connectionListener,
-                streamListener);
+        return new ClientHttp1IOEventHandler(streamDuplexerFactory.create(ioSession));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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
new file mode 100644
index 0000000..bb26d13
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexerFactory.java
@@ -0,0 +1,137 @@
+/*
+ * ====================================================================
+ * 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.http.impl.nio;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ConnectionReuseStrategy;
+import org.apache.hc.core5.http.ContentLengthStrategy;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+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.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public final class ClientHttp1StreamDuplexerFactory {
+
+    private final HttpProcessor httpProcessor;
+    private final H1Config h1Config;
+    private final CharCodingConfig charCodingConfig;
+    private final ConnectionReuseStrategy connectionReuseStrategy;
+    private final NHttpMessageParserFactory<HttpResponse> responseParserFactory;
+    private final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory;
+    private final ContentLengthStrategy incomingContentStrategy;
+    private final ContentLengthStrategy outgoingContentStrategy;
+    private final ConnectionListener connectionListener;
+    private final Http1StreamListener streamListener;
+
+    public ClientHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionReuseStrategy connectionReuseStrategy,
+            final NHttpMessageParserFactory<HttpResponse> responseParserFactory,
+            final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+            final ContentLengthStrategy incomingContentStrategy,
+            final ContentLengthStrategy outgoingContentStrategy,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+        this.h1Config = h1Config != null ? h1Config : H1Config.DEFAULT;
+        this.charCodingConfig = charCodingConfig !=  null ? charCodingConfig : CharCodingConfig.DEFAULT;
+        this.connectionReuseStrategy = connectionReuseStrategy != null ? connectionReuseStrategy :
+                DefaultConnectionReuseStrategy.INSTANCE;
+        this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
+                new DefaultHttpResponseParserFactory(h1Config);
+        this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
+                DefaultHttpRequestWriterFactory.INSTANCE;
+        this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
+                DefaultContentLengthStrategy.INSTANCE;
+        this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
+                DefaultContentLengthStrategy.INSTANCE;
+        this.connectionListener = connectionListener;
+        this.streamListener = streamListener;
+    }
+
+    public ClientHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionReuseStrategy connectionReuseStrategy,
+            final NHttpMessageParserFactory<HttpResponse> responseParserFactory,
+            final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this(httpProcessor, h1Config, charCodingConfig, connectionReuseStrategy,
+                responseParserFactory, requestWriterFactory, null ,null, connectionListener, streamListener);
+    }
+
+    public ClientHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this(httpProcessor, h1Config, charCodingConfig, null, null, null, connectionListener, streamListener);
+    }
+
+    public ClientHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig) {
+        this(httpProcessor, h1Config, charCodingConfig, null, null);
+    }
+
+    public ClientHttp1StreamDuplexer create(final TlsCapableIOSession ioSession) {
+        return new ClientHttp1StreamDuplexer(
+                ioSession,
+                httpProcessor,
+                h1Config,
+                charCodingConfig,
+                connectionReuseStrategy,
+                responseParserFactory.create(),
+                requestWriterFactory.create(),
+                incomingContentStrategy,
+                outgoingContentStrategy,
+                connectionListener,
+                streamListener);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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 a38517c..2f24a54 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
@@ -29,23 +29,7 @@ package org.apache.hc.core5.http.impl.nio;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ConnectionReuseStrategy;
-import org.apache.hc.core5.http.ContentLengthStrategy;
-import org.apache.hc.core5.http.ExceptionListener;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.config.CharCodingConfig;
-import org.apache.hc.core5.http.config.H1Config;
-import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
-import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
-import org.apache.hc.core5.http.impl.Http1StreamListener;
-import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
-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.nio.ssl.TlsStrategy;
-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;
@@ -57,106 +41,27 @@ import org.apache.hc.core5.util.Args;
 @Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class ServerHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
-    private final HttpProcessor httpProcessor;
-    private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
-    private final ConnectionReuseStrategy connectionReuseStrategy;
-    private final CharCodingConfig charCodingConfig;
-    private final NHttpMessageParserFactory<HttpRequest> requestParserFactory;
-    private final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory;
-    private final ContentLengthStrategy incomingContentStrategy;
-    private final ContentLengthStrategy outgoingContentStrategy;
+    private final ServerHttp1StreamDuplexerFactory streamDuplexerFactory;
     private final TlsStrategy tlsStrategy;
-    private final ConnectionListener connectionListener;
-    private final Http1StreamListener streamListener;
 
     public ServerHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
-            final CharCodingConfig charCodingConfig,
-            final ConnectionReuseStrategy connectionReuseStrategy,
-            final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
-            final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory,
-            final ContentLengthStrategy incomingContentStrategy,
-            final ContentLengthStrategy outgoingContentStrategy,
-            final TlsStrategy tlsStrategy,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
-        this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
-        this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
-        this.connectionReuseStrategy = connectionReuseStrategy != null ? connectionReuseStrategy :
-                DefaultConnectionReuseStrategy.INSTANCE;
-        this.requestParserFactory = requestParserFactory != null ? requestParserFactory :
-                DefaultHttpRequestParserFactory.INSTANCE;
-        this.responseWriterFactory = responseWriterFactory != null ? responseWriterFactory :
-                DefaultHttpResponseWriterFactory.INSTANCE;
-        this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
-                DefaultContentLengthStrategy.INSTANCE;
-        this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
-                DefaultContentLengthStrategy.INSTANCE;
+            final ServerHttp1StreamDuplexerFactory streamDuplexerFactory,
+            final TlsStrategy tlsStrategy) {
+        this.streamDuplexerFactory = Args.notNull(streamDuplexerFactory, "Stream duplexer factory");
         this.tlsStrategy = tlsStrategy;
-        this.connectionListener = connectionListener;
-        this.streamListener = streamListener;
-    }
-
-    public ServerHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
-            final CharCodingConfig charCodingConfig,
-            final ConnectionReuseStrategy connectionReuseStrategy,
-            final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
-            final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory,
-            final TlsStrategy tlsStrategy,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this(httpProcessor, exchangeHandlerFactory, charCodingConfig,
-                connectionReuseStrategy, requestParserFactory, responseWriterFactory,
-                null, null, tlsStrategy, connectionListener, streamListener);
-    }
-
-    public ServerHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
-            final CharCodingConfig charCodingConfig,
-            final TlsStrategy tlsStrategy,
-            final ConnectionListener connectionListener,
-            final Http1StreamListener streamListener) {
-        this(httpProcessor, exchangeHandlerFactory, charCodingConfig, null, null ,null,
-                tlsStrategy, connectionListener, streamListener);
-    }
-
-    public ServerHttp1IOEventHandlerFactory(
-            final HttpProcessor httpProcessor,
-            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
-            final CharCodingConfig charCodingConfig,
-            final TlsStrategy tlsStrategy,
-            final ExceptionListener errorListener) {
-        this(httpProcessor, exchangeHandlerFactory, charCodingConfig, tlsStrategy, null, null);
     }
 
     @Override
     public IOEventHandler createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
-        return new ServerHttp1IOEventHandler(createStreamDuplexer(ioSession));
-    }
-
-    protected ServerHttp1StreamDuplexer createStreamDuplexer(final TlsCapableIOSession ioSession) {
         if (tlsStrategy != null) {
             tlsStrategy.upgrade(
                     ioSession,
                     null,
                     ioSession.getLocalAddress(),
-                    ioSession.getRemoteAddress());
+                    ioSession.getRemoteAddress(),
+                    attachment);
         }
-        return new ServerHttp1StreamDuplexer(ioSession, httpProcessor, exchangeHandlerFactory,
-                H1Config.DEFAULT,
-                charCodingConfig,
-                connectionReuseStrategy,
-                requestParserFactory.create(),
-                responseWriterFactory.create(),
-                incomingContentStrategy,
-                outgoingContentStrategy,
-                connectionListener,
-                streamListener);
+        return new ServerHttp1IOEventHandler(streamDuplexerFactory.create(ioSession));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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
new file mode 100644
index 0000000..568390a
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexerFactory.java
@@ -0,0 +1,136 @@
+/*
+ * ====================================================================
+ * 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.http.impl.nio;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ConnectionReuseStrategy;
+import org.apache.hc.core5.http.ContentLengthStrategy;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+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.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public final class ServerHttp1StreamDuplexerFactory {
+
+    private final HttpProcessor httpProcessor;
+    private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
+    private final ConnectionReuseStrategy connectionReuseStrategy;
+    private final H1Config h1Config;
+    private final CharCodingConfig charCodingConfig;
+    private final NHttpMessageParserFactory<HttpRequest> requestParserFactory;
+    private final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory;
+    private final ContentLengthStrategy incomingContentStrategy;
+    private final ContentLengthStrategy outgoingContentStrategy;
+    private final ConnectionListener connectionListener;
+    private final Http1StreamListener streamListener;
+
+    public ServerHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionReuseStrategy connectionReuseStrategy,
+            final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
+            final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory,
+            final ContentLengthStrategy incomingContentStrategy,
+            final ContentLengthStrategy outgoingContentStrategy,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+        this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
+        this.h1Config = h1Config != null ? h1Config : H1Config.DEFAULT;
+        this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
+        this.connectionReuseStrategy = connectionReuseStrategy != null ? connectionReuseStrategy :
+                DefaultConnectionReuseStrategy.INSTANCE;
+        this.requestParserFactory = requestParserFactory != null ? requestParserFactory :
+                new DefaultHttpRequestParserFactory(h1Config);
+        this.responseWriterFactory = responseWriterFactory != null ? responseWriterFactory :
+                DefaultHttpResponseWriterFactory.INSTANCE;
+        this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
+                DefaultContentLengthStrategy.INSTANCE;
+        this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
+                DefaultContentLengthStrategy.INSTANCE;
+        this.connectionListener = connectionListener;
+        this.streamListener = streamListener;
+    }
+
+    public ServerHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionReuseStrategy connectionReuseStrategy,
+            final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
+            final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this(httpProcessor, exchangeHandlerFactory, h1Config, charCodingConfig,
+                connectionReuseStrategy, requestParserFactory, responseWriterFactory,
+                null, null, connectionListener, streamListener);
+    }
+
+    public ServerHttp1StreamDuplexerFactory(
+            final HttpProcessor httpProcessor,
+            final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
+            final H1Config h1Config,
+            final CharCodingConfig charCodingConfig,
+            final ConnectionListener connectionListener,
+            final Http1StreamListener streamListener) {
+        this(httpProcessor, exchangeHandlerFactory, h1Config, charCodingConfig, null, null ,null, connectionListener, streamListener);
+    }
+
+    public ServerHttp1StreamDuplexer create(final TlsCapableIOSession ioSession) {
+        return new ServerHttp1StreamDuplexer(ioSession, httpProcessor, exchangeHandlerFactory,
+                h1Config,
+                charCodingConfig,
+                connectionReuseStrategy,
+                requestParserFactory.create(),
+                responseWriterFactory.create(),
+                incomingContentStrategy,
+                outgoingContentStrategy,
+                connectionListener,
+                streamListener);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
index 6d02fb0..59d0774 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
@@ -116,6 +116,14 @@ public class SessionInputBufferImpl extends ExpandableBuffer implements SessionI
         this(buffersize, 256);
     }
 
+    public void put(final ByteBuffer src) {
+        if (src != null && src.hasRemaining()) {
+            setInputMode();
+            ensureCapacity(src.remaining());
+            buffer().put(src);
+        }
+    }
+
     @Override
     public int fill(final ReadableByteChannel channel) throws IOException {
         Args.notNull(channel, "Channel");

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategy.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategy.java
index 93176d3..9451bf8 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategy.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicClientTlsStrategy.java
@@ -90,7 +90,7 @@ public class BasicClientTlsStrategy implements TlsStrategy {
             final HttpHost host,
             final SocketAddress localAddress,
             final SocketAddress remoteAddress,
-            final String... parameters) {
+            final Object attachment) {
         final String scheme = host != null ? host.getSchemeName() : null;
         if ("https".equalsIgnoreCase(scheme)) {
             tlsSession.startTls(sslContext, sslBufferManagement, initializer, verifier);

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategy.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategy.java
index 11154cf..0936ceb 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategy.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/BasicServerTlsStrategy.java
@@ -96,7 +96,7 @@ public class BasicServerTlsStrategy implements TlsStrategy {
             final HttpHost host,
             final SocketAddress localAddress,
             final SocketAddress remoteAddress,
-            final String... parameters) {
+            final Object attachment) {
         final int port = ((InetSocketAddress) localAddress).getPort();
         for (final int securePort: securePorts) {
             if (port == securePort) {

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/TlsStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/TlsStrategy.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/TlsStrategy.java
index 47f009d..24514af 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/TlsStrategy.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/ssl/TlsStrategy.java
@@ -44,6 +44,6 @@ public interface TlsStrategy {
             HttpHost host,
             SocketAddress localAddress,
             SocketAddress remoteAddress,
-            String... parameters);
+            Object attachment);
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalIOSession.java
index f7cf3a6..6c6fce1 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalIOSession.java
@@ -35,7 +35,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
@@ -47,6 +46,7 @@ import org.apache.hc.core5.reactor.ssl.SSLIOSession;
 import org.apache.hc.core5.reactor.ssl.SSLMode;
 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.util.Asserts;
 
 /**
@@ -239,9 +239,9 @@ class InternalIOSession implements TlsCapableIOSession {
     }
 
     @Override
-    public SSLSession getSSLSession() {
+    public TlsDetails getTlsDetails() {
         final SSLIOSession sslIoSession = tlsSessionRef.get();
-        return sslIoSession != null ? sslIoSession.getSSLSession() : null;
+        return sslIoSession != null ? sslIoSession.getTlsDetails() : null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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 2edf266..64bf23d 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
@@ -41,7 +41,6 @@ import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSession;
 
 import org.apache.hc.core5.annotation.Contract;
@@ -53,6 +52,7 @@ 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;
 import org.apache.hc.core5.util.Asserts;
 
@@ -86,6 +86,7 @@ public class SSLIOSession implements IOSession {
     private volatile SSLMode sslMode;
     private volatile int status;
     private volatile boolean initialized;
+    private TlsDetails tlsDetails;
 
     /**
      * Creates new instance of {@code SSLIOSession} class with static SSL buffers.
@@ -199,7 +200,7 @@ public class SSLIOSession implements IOSession {
 
     /**
      * Initializes the session. This method invokes the {@link
-     * SSLSessionInitializer#initialize(NamedEndpoint, SSLParameters)} callback
+     * SSLSessionInitializer#initialize(NamedEndpoint, SSLEngine)} callback
      * if an instance of {@link SSLSessionInitializer} was specified at the construction time.
      *
      * @throws SSLException in case of a SSL protocol exception.
@@ -219,9 +220,7 @@ public class SSLIOSession implements IOSession {
             break;
         }
         if (this.initializer != null) {
-            final SSLParameters sslParameters = this.sslEngine.getSSLParameters();
-            this.initializer.initialize(this.targetEndpoint, sslParameters);
-            this.sslEngine.setSSLParameters(sslParameters);
+            this.initializer.initialize(this.targetEndpoint, this.sslEngine);
         }
         this.initialized = true;
         this.sslEngine.beginHandshake();
@@ -234,8 +233,8 @@ public class SSLIOSession implements IOSession {
         doHandshake();
     }
 
-    public synchronized SSLSession getSSLSession() {
-        return this.sslEngine.getSession();
+    public synchronized TlsDetails getTlsDetails() {
+        return tlsDetails;
     }
 
     // A works-around for exception handling craziness in Sun/Oracle's SSLEngine
@@ -351,7 +350,12 @@ public class SSLIOSession implements IOSession {
         // It is never generated by SSLEngine.getHandshakeStatus().
         if (result != null && result.getHandshakeStatus() == HandshakeStatus.FINISHED) {
             if (this.verifier != null) {
-                this.verifier.verify(this.targetEndpoint, this.sslEngine.getSession());
+                this.tlsDetails = this.verifier.verify(this.targetEndpoint, this.sslEngine);
+            }
+            if (this.tlsDetails == null) {
+                final SSLSession sslSession = this.sslEngine.getSession();
+                final String applicationProtocol = ReflectionSupport.callGetter(this.sslEngine, "ApplicationProtocol", String.class);
+                this.tlsDetails = new TlsDetails(sslSession, applicationProtocol);
             }
             if (this.callback != null) {
                 this.callback.execute(this);

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionInitializer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionInitializer.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionInitializer.java
index d8c83dd..d9a7f52 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionInitializer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionInitializer.java
@@ -27,7 +27,7 @@
 
 package org.apache.hc.core5.reactor.ssl;
 
-import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLEngine;
 
 import org.apache.hc.core5.net.NamedEndpoint;
 
@@ -42,13 +42,12 @@ public interface SSLSessionInitializer {
     /**
      * Triggered when the SSL connection is being initialized. Custom handlers
      * can use this callback to customize properties of the {@link javax.net.ssl.SSLEngine}
-     * used to establish the SSL session by modifying the given
-     * {@link SSLParameters}.
+     * used to establish the SSL session.
      *
      * @param endpoint the endpoint name for a client side session or {@code null}
      *                 for a server side session.
-     * @param sslParameters the actual SSL parameters.
+     * @param sslEngine the SSL engine.
      */
-    void initialize(NamedEndpoint endpoint, SSLParameters sslParameters);
+    void initialize(NamedEndpoint endpoint, SSLEngine sslEngine);
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionVerifier.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionVerifier.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionVerifier.java
index f7b8ef2..b6f98d1 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionVerifier.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLSessionVerifier.java
@@ -27,8 +27,8 @@
 
 package org.apache.hc.core5.reactor.ssl;
 
+import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
 
 import org.apache.hc.core5.net.NamedEndpoint;
 
@@ -43,15 +43,15 @@ public interface SSLSessionVerifier {
     /**
      * Triggered when the SSL connection has been established and initial SSL
      * handshake has been successfully completed. Custom handlers can use
-     * this callback to verify properties of the {@link SSLSession}.
+     * this callback to verify properties of the {@link SSLEngine}.
      * For instance this would be the right place to enforce SSL cipher
      * strength, validate certificate chain and do hostname checks.
      *
      * @param endpoint the endpoint name for a client side session or {@code null}
      *                 for a server side session.
-     * @param sslsession newly created SSL session.
+     * @param sslEngine SSL engine.
      * @throws SSLException if case of SSL protocol error.
      */
-    void verify(NamedEndpoint endpoint, SSLSession sslsession) throws SSLException;
+    TlsDetails verify(NamedEndpoint endpoint, SSLEngine sslEngine) throws SSLException;
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TlsDetails.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TlsDetails.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TlsDetails.java
new file mode 100644
index 0000000..9e41ef8
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TlsDetails.java
@@ -0,0 +1,63 @@
+/*
+ * ====================================================================
+ * 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.ssl;
+
+import javax.net.ssl.SSLSession;
+
+/**
+ * Represents details of a fully established TLS session.
+ *
+ * @since 5.0
+ */
+public final class TlsDetails {
+
+    private final SSLSession sslSession;
+    private final String applicationProtocol;
+
+    public TlsDetails(final SSLSession sslSession, final String applicationProtocol) {
+        this.sslSession = sslSession;
+        this.applicationProtocol = applicationProtocol;
+    }
+
+    public SSLSession getSSLSession() {
+        return sslSession;
+    }
+
+    public String getApplicationProtocol() {
+        return applicationProtocol;
+    }
+
+    @Override
+    public String toString() {
+        return "TlsDetails{" +
+                "sslSession=" + sslSession +
+                ", applicationProtocol='" + applicationProtocol + '\'' +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TransportSecurityLayer.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TransportSecurityLayer.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TransportSecurityLayer.java
index 0d724be..c63e255 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TransportSecurityLayer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/TransportSecurityLayer.java
@@ -28,7 +28,6 @@
 package org.apache.hc.core5.reactor.ssl;
 
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
 
 /**
  * Represents a TLS capable session layer.
@@ -43,6 +42,6 @@ public interface TransportSecurityLayer {
             SSLSessionInitializer initializer,
             SSLSessionVerifier verifier) throws UnsupportedOperationException;
 
-    SSLSession getSSLSession();
+    TlsDetails getTlsDetails();
 
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/ssl/ReflectionSupport.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/ssl/ReflectionSupport.java b/httpcore5/src/main/java/org/apache/hc/core5/ssl/ReflectionSupport.java
new file mode 100644
index 0000000..333d5f0
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/ssl/ReflectionSupport.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * 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.ssl;
+
+import java.lang.reflect.Method;
+
+public final class ReflectionSupport {
+
+    public static void callSetter(final Object object, final String setterName, final Class type, final Object value) {
+        try {
+            final Class<?> clazz = object.getClass();
+            final Method method = clazz.getMethod("set" + setterName, type);
+            method.invoke(object, value);
+        } catch (final Exception ignore) {
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T callGetter(final Object object, final String getterName, final Class<T> resultType) {
+        try {
+            final Class<?> clazz = object.getClass();
+            final Method method = clazz.getMethod("get" + getterName);
+            return resultType.cast(method.invoke(object));
+        } catch (final Exception ignore) {
+            return null;
+        }
+    }
+
+}