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 2016/10/31 17:33:33 UTC

svn commit: r1767339 [2/14] - in /httpcomponents/httpcore/trunk: ./ httpcore5-ab/src/main/java/org/apache/hc/core5/http/benchmark/ httpcore5-ab/src/test/java/org/apache/hc/core5/http/benchmark/ httpcore5-h2/src/main/java/org/apache/hc/core5/http2/boots...

Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java?rev=1767339&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java Mon Oct 31 17:33:27 2016
@@ -0,0 +1,91 @@
+/*
+ * ====================================================================
+ * 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.http2.bootstrap;
+
+import org.apache.hc.core5.http.impl.HttpProcessors;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
+import org.apache.hc.core5.http.protocol.RequestExpectContinue;
+import org.apache.hc.core5.http.protocol.RequestUserAgent;
+import org.apache.hc.core5.http.protocol.ResponseDate;
+import org.apache.hc.core5.http.protocol.ResponseServer;
+import org.apache.hc.core5.http2.protocol.H2RequestConnControl;
+import org.apache.hc.core5.http2.protocol.H2RequestContent;
+import org.apache.hc.core5.http2.protocol.H2RequestTargetHost;
+import org.apache.hc.core5.http2.protocol.H2RequestValidateHost;
+import org.apache.hc.core5.http2.protocol.H2ResponseConnControl;
+import org.apache.hc.core5.http2.protocol.H2ResponseContent;
+import org.apache.hc.core5.util.TextUtils;
+import org.apache.hc.core5.util.VersionInfo;
+
+/**
+ * @since 5.0
+ */
+public final class Http2Processors {
+
+    private final static String SOFTWARE = "Apache-HttpCore";
+
+    public static HttpProcessorBuilder customServer(final String serverInfo) {
+        return HttpProcessorBuilder.create()
+                .addAll(
+                        new ResponseDate(),
+                        new ResponseServer(!TextUtils.isBlank(serverInfo) ? serverInfo :
+                                VersionInfo.getSoftwareInfo(SOFTWARE, "org.apache.hc.core5", Http2Processors.class)),
+                        new H2ResponseContent(),
+                        new H2ResponseConnControl())
+                .addAll(
+                        new H2RequestValidateHost());
+    }
+
+    public static HttpProcessor server(final String serverInfo) {
+        return customServer(serverInfo).build();
+    }
+
+    public static HttpProcessor server() {
+        return customServer(null).build();
+    }
+
+    public static HttpProcessorBuilder customClient(final String agentInfo) {
+        return HttpProcessorBuilder.create()
+                .addAll(
+                        new H2RequestContent(),
+                        new H2RequestTargetHost(),
+                        new H2RequestConnControl(),
+                        new RequestUserAgent(!TextUtils.isBlank(agentInfo) ? agentInfo :
+                                VersionInfo.getSoftwareInfo(SOFTWARE, "org.apache.hc.core5", HttpProcessors.class)),
+                        new RequestExpectContinue());
+    };
+
+    public static HttpProcessor client(final String agentInfo) {
+        return customClient(agentInfo).build();
+    }
+
+    public static HttpProcessor client() {
+        return customClient(null).build();
+    }
+
+}

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java Mon Oct 31 17:33:27 2016
@@ -27,19 +27,21 @@
 
 package org.apache.hc.core5.http2.impl.nio;
 
-import org.apache.hc.core5.http.ExceptionListener;
-import org.apache.hc.core5.reactor.IOEventHandler;
+import java.io.IOException;
+import java.net.SocketAddress;
+
+import org.apache.hc.core5.http.HttpConnectionMetrics;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
 
-class AbstractHttp2IOEventHandler implements IOEventHandler {
+class AbstractHttp2IOEventHandler implements HttpConnectionEventHandler {
 
     private final AbstractHttp2StreamMultiplexer streamMultiplexer;
-    private final ExceptionListener errorListener;
 
-    AbstractHttp2IOEventHandler(final AbstractHttp2StreamMultiplexer streamMultiplexer, final ExceptionListener errorListener) {
+    AbstractHttp2IOEventHandler(final AbstractHttp2StreamMultiplexer streamMultiplexer) {
         this.streamMultiplexer = Args.notNull(streamMultiplexer, "Stream multiplexer");
-        this.errorListener = errorListener;
     }
 
     @Override
@@ -48,9 +50,6 @@ class AbstractHttp2IOEventHandler implem
             streamMultiplexer.onConnect(null);
         } catch (final Exception ex) {
             streamMultiplexer.onException(ex);
-            if (errorListener != null) {
-                errorListener.onError(ex);
-            }
         }
     }
 
@@ -60,9 +59,6 @@ class AbstractHttp2IOEventHandler implem
             streamMultiplexer.onInput();
         } catch (final Exception ex) {
             streamMultiplexer.onException(ex);
-            if (errorListener != null) {
-                errorListener.onError(ex);
-            }
         }
     }
 
@@ -72,9 +68,6 @@ class AbstractHttp2IOEventHandler implem
             streamMultiplexer.onOutput();
         } catch (final Exception ex) {
             streamMultiplexer.onException(ex);
-            if (errorListener != null) {
-                errorListener.onError(ex);
-            }
         }
     }
 
@@ -84,14 +77,61 @@ class AbstractHttp2IOEventHandler implem
             streamMultiplexer.onTimeout();
         } catch (final Exception ex) {
             streamMultiplexer.onException(ex);
-            if (errorListener != null) {
-                errorListener.onError(ex);
-            }
         }
     }
 
     @Override
     public void disconnected(final IOSession session) {
+        streamMultiplexer.onDisconnect();
+    }
+
+    @Override
+    public void close() throws IOException {
+        streamMultiplexer.close();
+    }
+
+    @Override
+    public void shutdown() throws IOException {
+        streamMultiplexer.shutdown();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return streamMultiplexer.isOpen();
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        streamMultiplexer.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public HttpConnectionMetrics getMetrics() {
+        return streamMultiplexer.getMetrics();
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return streamMultiplexer.getSocketTimeout();
     }
 
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        return streamMultiplexer.getProtocolVersion();
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return streamMultiplexer.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return streamMultiplexer.getLocalAddress();
+    }
+
+    @Override
+    public String toString() {
+        return streamMultiplexer.toString();
+    }
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java Mon Oct 31 17:33:27 2016
@@ -52,6 +52,11 @@ import org.apache.hc.core5.http.HttpVers
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.ProtocolVersion;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.command.ExecutionCommand;
+import org.apache.hc.core5.http.nio.command.ShutdownCommand;
+import org.apache.hc.core5.http.nio.command.ShutdownType;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
@@ -67,10 +72,6 @@ import org.apache.hc.core5.http2.frame.S
 import org.apache.hc.core5.http2.hpack.HPackDecoder;
 import org.apache.hc.core5.http2.hpack.HPackEncoder;
 import org.apache.hc.core5.http2.impl.BasicH2TransportMetrics;
-import org.apache.hc.core5.http2.nio.AsyncPushProducer;
-import org.apache.hc.core5.http2.nio.command.ExecutionCommand;
-import org.apache.hc.core5.http2.nio.command.ShutdownCommand;
-import org.apache.hc.core5.http2.nio.command.ShutdownType;
 import org.apache.hc.core5.reactor.Command;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
@@ -105,7 +106,8 @@ abstract class AbstractHttp2StreamMultip
     private final Lock outputLock;
     private final AtomicInteger outputRequests;
     private final AtomicInteger lastStreamId;
-    private final Http2StreamListener callback;
+    private final ConnectionListener connectionListener;
+    private final Http2StreamListener streamListener;
 
     private ConnectionHandshake connState = ConnectionHandshake.READY;
     private SettingsHandshake localSettingState = SettingsHandshake.READY;
@@ -125,7 +127,8 @@ abstract class AbstractHttp2StreamMultip
             final HttpProcessor httpProcessor,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener callback) {
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
         this.mode = Args.notNull(mode, "Mode");
         this.ioSession = Args.notNull(ioSession, "IO session");
         this.frameFactory = Args.notNull(frameFactory, "Frame factory");
@@ -152,7 +155,8 @@ abstract class AbstractHttp2StreamMultip
 
         this.remoteConfig = H2Config.DEFAULT;
         this.lowMark = this.remoteConfig.getInitialWindowSize() / 2;
-        this.callback = callback;
+        this.connectionListener = connectionListener;
+        this.streamListener = streamListener;
     }
 
     abstract Http2StreamHandler createRemotelyInitiatedStream(
@@ -174,8 +178,8 @@ abstract class AbstractHttp2StreamMultip
     private int updateInputWindow(
             final int streamId, final AtomicInteger window, final int delta) throws ArithmeticException {
         final int newSize = updateWindow(window, delta);
-        if (callback != null) {
-            callback.onInputFlowControl(streamId, delta, newSize);
+        if (streamListener != null) {
+            streamListener.onInputFlowControl(streamId, delta, newSize);
         }
         return newSize;
     }
@@ -183,16 +187,16 @@ abstract class AbstractHttp2StreamMultip
     private int updateOutputWindow(
             final int streamId, final AtomicInteger window, final int delta) throws ArithmeticException {
         final int newSize = updateWindow(window, delta);
-        if (callback != null) {
-            callback.onOutputFlowControl(streamId, delta, newSize);
+        if (streamListener != null) {
+            streamListener.onOutputFlowControl(streamId, delta, newSize);
         }
         return newSize;
     }
 
     private void commitFrameInternal(final RawFrame frame) throws IOException {
         if (outputBuffer.isEmpty() && outputQueue.isEmpty()) {
-            if (callback != null) {
-                callback.onFrameOutput(frame);
+            if (streamListener != null) {
+                streamListener.onFrameOutput(frame);
             }
             outputBuffer.write(frame, ioSession.channel());
         } else {
@@ -216,8 +220,8 @@ abstract class AbstractHttp2StreamMultip
         if (headers == null || headers.isEmpty()) {
             throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Message headers are missing");
         }
-        if (callback != null) {
-            callback.onHeaderOutput(headers);
+        if (streamListener != null) {
+            streamListener.onHeaderOutput(headers);
         }
         final ByteArrayBuffer buf = new ByteArrayBuffer(512);
         hPackEncoder.encodeHeaders(buf, headers);
@@ -250,8 +254,8 @@ abstract class AbstractHttp2StreamMultip
         if (headers == null || headers.isEmpty()) {
             throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Message headers are missing");
         }
-        if (callback != null) {
-            callback.onHeaderOutput(headers);
+        if (streamListener != null) {
+            streamListener.onHeaderOutput(headers);
         }
         final ByteArrayBuffer buf = new ByteArrayBuffer(512);
         buf.append((byte)(promisedStreamId >> 24));
@@ -297,8 +301,8 @@ abstract class AbstractHttp2StreamMultip
             if (payload.remaining() <= maxPayloadSize) {
                 chunk = payload.remaining();
                 final RawFrame dataFrame = frameFactory.createData(streamId, payload, false);
-                if (callback != null) {
-                    callback.onFrameOutput(dataFrame);
+                if (streamListener != null) {
+                    streamListener.onFrameOutput(dataFrame);
                 }
                 outputBuffer.write(dataFrame, ioSession.channel());
             } else {
@@ -307,8 +311,8 @@ abstract class AbstractHttp2StreamMultip
                 try {
                     payload.limit(payload.position() + chunk);
                     final RawFrame dataFrame = frameFactory.createData(streamId, payload, false);
-                    if (callback != null) {
-                        callback.onFrameOutput(dataFrame);
+                    if (streamListener != null) {
+                        streamListener.onFrameOutput(dataFrame);
                     }
                     outputBuffer.write(dataFrame, ioSession.channel());
                 } finally {
@@ -361,6 +365,9 @@ abstract class AbstractHttp2StreamMultip
     }
 
     public final void onConnect(final ByteBuffer prefeed) throws HttpException, IOException {
+        if (connectionListener != null) {
+            connectionListener.onConnect(this);
+        }
         if (prefeed != null) {
             inputBuffer.put(prefeed);
         }
@@ -383,8 +390,8 @@ abstract class AbstractHttp2StreamMultip
         } else {
             RawFrame frame;
             while ((frame = inputBuffer.read(ioSession.channel())) != null) {
-                if (callback != null) {
-                    callback.onFrameInput(frame);
+                if (streamListener != null) {
+                    streamListener.onFrameInput(frame);
                 }
                 consumeFrame(frame);
             }
@@ -400,8 +407,8 @@ abstract class AbstractHttp2StreamMultip
             while (outputBuffer.isEmpty()) {
                 final RawFrame frame = outputQueue.poll();
                 if (frame != null) {
-                    if (callback != null) {
-                        callback.onFrameOutput(frame);
+                    if (streamListener != null) {
+                        streamListener.onFrameOutput(frame);
                     }
                     outputBuffer.write(frame, ioSession.channel());
                 } else {
@@ -412,16 +419,6 @@ abstract class AbstractHttp2StreamMultip
             outputLock.unlock();
         }
 
-        switch (connState) {
-            case ACTIVE:
-                processPendingCommands();
-                break;
-            case GRACEFUL_SHUTDOWN:
-            case SHUTDOWN:
-                cancelPendingCommands();
-                break;
-        }
-
         final int connWinSize = connInputWindow.get();
         if (connWinSize < lowMark) {
             final int delta = this.remoteConfig.getInitialWindowSize() - connWinSize;
@@ -468,11 +465,14 @@ abstract class AbstractHttp2StreamMultip
             }
         }
 
-        if (connState == ConnectionHandshake.SHUTDOWN) {
+        if (connState == ConnectionHandshake.ACTIVE) {
+            processPendingCommands();
+        } else if (connState == ConnectionHandshake.SHUTDOWN) {
             outputLock.lock();
             try {
                 if (outputBuffer.isEmpty() && outputQueue.isEmpty()) {
                     ioSession.close();
+                    cancelPendingCommands();
                 }
             } finally {
                 outputLock.unlock();
@@ -498,6 +498,13 @@ abstract class AbstractHttp2StreamMultip
         streamMap.clear();
     }
 
+    public final void onDisconnect() {
+        cancelPendingCommands();
+        if (connectionListener != null) {
+            connectionListener.onConnect(this);
+        }
+    }
+
     private void processPendingCommands() throws IOException, HttpException {
         final Queue<Command> commandQueue = ioSession.getCommandQueue();
         while (!commandQueue.isEmpty() && streamMap.size() < remoteConfig.getMaxConcurrentStreams()) {
@@ -531,6 +538,7 @@ abstract class AbstractHttp2StreamMultip
                         localConfig.getInitialWindowSize(),
                         remoteConfig.getInitialWindowSize());
                 final Http2StreamHandler streamHandler = new ClientHttp2StreamHandler(
+                        this,
                         channel,
                         httpProcessor,
                         connMetrics,
@@ -550,14 +558,21 @@ abstract class AbstractHttp2StreamMultip
     }
 
     private void cancelPendingCommands() {
-        final Queue<Command> commandQueue = ioSession.getCommandQueue();
-        while (!commandQueue.isEmpty()) {
-            final Command command = commandQueue.remove();
-            command.cancel();
+        final Deque<Command> commandQueue = ioSession.getCommandQueue();
+        for (;;) {
+            final Command command = commandQueue.poll();
+            if (command != null) {
+                command.cancel();
+            } else {
+                break;
+            }
         }
     }
 
     public final void onException(final Exception cause) {
+        if (connectionListener != null) {
+            connectionListener.onError(this, cause);
+        }
         try {
             if (!(cause instanceof ConnectionClosedException)) {
                 final H2Error errorCode;
@@ -577,7 +592,6 @@ abstract class AbstractHttp2StreamMultip
                 stream.reset(cause);
             }
             streamMap.clear();
-            cancelPendingCommands();
             connState = ConnectionHandshake.SHUTDOWN;
         } catch (IOException ignore) {
         } finally {
@@ -895,8 +909,8 @@ abstract class AbstractHttp2StreamMultip
             if (promisedStreamId > processedRemoteStreamId) {
                 processedRemoteStreamId = promisedStreamId;
             }
-            if (callback != null) {
-                callback.onHeaderInput(headers);
+            if (streamListener != null) {
+                streamListener.onHeaderInput(headers);
             }
             if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
                 throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
@@ -923,8 +937,8 @@ abstract class AbstractHttp2StreamMultip
             if (stream.isRemoteInitiated() && streamId > processedRemoteStreamId) {
                 processedRemoteStreamId = streamId;
             }
-            if (callback != null) {
-                callback.onHeaderInput(headers);
+            if (streamListener != null) {
+                streamListener.onHeaderInput(headers);
             }
             if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
                 throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, "Stream refused");
@@ -953,8 +967,8 @@ abstract class AbstractHttp2StreamMultip
             if (stream.isRemoteInitiated() && streamId > processedRemoteStreamId) {
                 processedRemoteStreamId = streamId;
             }
-            if (callback != null) {
-                callback.onHeaderInput(headers);
+            if (streamListener != null) {
+                streamListener.onHeaderInput(headers);
             }
             if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
                 throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, "Stream refused");
@@ -1189,7 +1203,7 @@ abstract class AbstractHttp2StreamMultip
                     localConfig.getInitialWindowSize(),
                     remoteConfig.getInitialWindowSize());
             final Http2StreamHandler streamHandler = new ServerPushHttp2StreamHandler(
-                    channel, httpProcessor, connMetrics, pushProducer);
+                    AbstractHttp2StreamMultiplexer.this, channel, httpProcessor, connMetrics, pushProducer);
             final Http2Stream stream = new Http2Stream(channel, streamHandler, false);
             streamMap.put(promisedStreamId, stream);
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2IOEventHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2IOEventHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2IOEventHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2IOEventHandler.java Mon Oct 31 17:33:27 2016
@@ -29,7 +29,6 @@ package org.apache.hc.core5.http2.impl.n
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
 
 /**
  * {@link org.apache.hc.core5.reactor.IOEventHandler} that implements client side HTTP/2 messaging protocol.
@@ -39,12 +38,8 @@ import org.apache.hc.core5.http.Exceptio
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
 public class ClientHttp2IOEventHandler extends AbstractHttp2IOEventHandler {
 
-    public ClientHttp2IOEventHandler(final ClientHttp2StreamMultiplexer streamMultiplexer, final ExceptionListener errorListener) {
-        super(streamMultiplexer, errorListener);
-    }
-
     public ClientHttp2IOEventHandler(final ClientHttp2StreamMultiplexer streamMultiplexer) {
-        this(streamMultiplexer, null);
+        super(streamMultiplexer);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java Mon Oct 31 17:33:27 2016
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.Atomi
 
 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.HttpRequest;
@@ -41,6 +42,10 @@ import org.apache.hc.core5.http.HttpStat
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.nio.MessageState;
+import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
+import org.apache.hc.core5.http.nio.RequestChannel;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
@@ -48,13 +53,11 @@ import org.apache.hc.core5.http2.H2Conne
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
-import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
-import org.apache.hc.core5.http2.nio.AsyncClientExchangeHandler;
-import org.apache.hc.core5.http2.nio.DataStreamChannel;
-import org.apache.hc.core5.http2.nio.RequestChannel;
+import org.apache.hc.core5.http.impl.LazyEntityDetails;
 
 class ClientHttp2StreamHandler implements Http2StreamHandler {
 
+    private final HttpConnection connection;
     private final Http2StreamChannel outputChannel;
     private final DataStreamChannel dataChannel;
     private final HttpProcessor httpProcessor;
@@ -68,11 +71,13 @@ class ClientHttp2StreamHandler implement
     private volatile MessageState responseState;
 
     ClientHttp2StreamHandler(
+            final HttpConnection connection,
             final Http2StreamChannel outputChannel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics,
             final AsyncClientExchangeHandler exchangeHandler,
             final HttpContext context) {
+        this.connection = connection;
         this.outputChannel = outputChannel;
         this.dataChannel = new DataStreamChannel() {
 
@@ -102,7 +107,7 @@ class ClientHttp2StreamHandler implement
         this.httpProcessor = httpProcessor;
         this.connMetrics = connMetrics;
         this.exchangeHandler = exchangeHandler;
-        this.context = HttpCoreContext.adapt(context);
+        this.context = context != null ? HttpCoreContext.adapt(context) : HttpCoreContext.create();
         this.requestCommitted = new AtomicBoolean(false);
         this.done = new AtomicBoolean(false);
         this.requestState = MessageState.HEADERS;
@@ -125,7 +130,7 @@ class ClientHttp2StreamHandler implement
         if (requestCommitted.compareAndSet(false, true)) {
             context.setProtocolVersion(HttpVersion.HTTP_2);
             context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
-            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, connection);
             httpProcessor.process(request, entityDetails, context);
             connMetrics.incrementRequestCount();
 
@@ -148,7 +153,7 @@ class ClientHttp2StreamHandler implement
     public void produceOutput() throws HttpException, IOException {
         switch (requestState) {
             case HEADERS:
-                exchangeHandler.submitRequest(new RequestChannel() {
+                exchangeHandler.produceRequest(new RequestChannel() {
 
                     @Override
                     public void sendRequest(
@@ -175,7 +180,7 @@ class ClientHttp2StreamHandler implement
             throw new ProtocolException("Unexpected message headers");
         }
         final HttpResponse response = DefaultH2ResponseConverter.INSTANCE.convert(headers);
-        final EntityDetails entityDetails = endStream ? null : new IncomingEntityDetails(response);
+        final EntityDetails entityDetails = endStream ? null : new LazyEntityDetails(response);
 
         if (response.getCode() < 200) {
             if (response.getCode() == HttpStatus.SC_CONTINUE && requestState == MessageState.ACK) {

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java Mon Oct 31 17:33:27 2016
@@ -30,13 +30,14 @@ import java.io.IOException;
 import java.nio.charset.Charset;
 
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+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.http2.frame.FrameFactory;
 import org.apache.hc.core5.http2.frame.StreamIdGenerator;
-import org.apache.hc.core5.http2.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOSession;
 
 /**
@@ -55,8 +56,10 @@ public class ClientHttp2StreamMultiplexe
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
+            final ConnectionListener connectionListener,
             final Http2StreamListener streamListener) {
-        super(Mode.CLIENT, ioSession, frameFactory, StreamIdGenerator.ODD, httpProcessor, charset, h2Config, streamListener);
+        super(Mode.CLIENT, ioSession, frameFactory, StreamIdGenerator.ODD, httpProcessor, charset,
+                h2Config, connectionListener, streamListener);
         this.pushHandlerFactory = pushHandlerFactory;
     }
 
@@ -66,7 +69,8 @@ public class ClientHttp2StreamMultiplexe
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config) {
-        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory, charset, h2Config, null);
+        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory, charset,
+                h2Config, null, null);
     }
 
     public ClientHttp2StreamMultiplexer(
@@ -82,7 +86,7 @@ public class ClientHttp2StreamMultiplexe
             final Http2StreamChannel channel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics) throws IOException {
-        return new ClientPushHttp2StreamHandler(channel, httpProcessor, connMetrics, pushHandlerFactory);
+        return new ClientPushHttp2StreamHandler(this, channel, httpProcessor, connMetrics, pushHandlerFactory);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java Mon Oct 31 17:33:27 2016
@@ -28,6 +28,7 @@
 package org.apache.hc.core5.http2.impl.nio;
 
 import java.io.IOException;
+import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.charset.Charset;
@@ -35,14 +36,17 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.HttpConnectionMetrics;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
-import org.apache.hc.core5.http2.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
@@ -51,7 +55,7 @@ import org.apache.hc.core5.util.Args;
  * @since 5.0
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
-public class ClientHttpProtocolNegotiator implements IOEventHandler {
+public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler {
 
     // PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n
     final static byte[] PREFACE = new byte[] {
@@ -59,31 +63,34 @@ public class ClientHttpProtocolNegotiato
             0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d,
             0x0d, 0x0a, 0x0d, 0x0a};
 
+    private final IOSession ioSession;
     private final HttpProcessor httpProcessor;
     private final Charset charset;
     private final H2Config h2Config;
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
+    private final ConnectionListener connectionListener;
     private final Http2StreamListener streamListener;
-    private final ExceptionListener errorListener;
 
     public ClientHttpProtocolNegotiator(
+            final IOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        this.ioSession = Args.notNull(ioSession, "I/O session");
         this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.pushHandlerFactory = pushHandlerFactory;
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
         this.streamListener = streamListener;
-        this.errorListener = errorListener;
+        this.connectionListener = connectionListener;
     }
 
     protected ClientHttp2StreamMultiplexer createStreamMultiplexer(final IOSession ioSession) {
         return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
-                pushHandlerFactory, charset, h2Config, streamListener);
+                pushHandlerFactory, charset, h2Config, connectionListener, streamListener);
     }
 
     @Override
@@ -97,13 +104,13 @@ public class ClientHttpProtocolNegotiato
             }
         } catch (IOException ex) {
             ioSession.shutdown();
-            if (errorListener != null) {
-                errorListener.onError(ex);
+            if (connectionListener != null) {
+                connectionListener.onError(this, ex);
             }
             return;
         }
         final ClientHttp2StreamMultiplexer streamMultiplexer = createStreamMultiplexer(ioSession);
-        final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer, errorListener);
+        final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
         newHandler.connected(ioSession);
         ioSession.setHandler(newHandler);
     }
@@ -124,4 +131,49 @@ public class ClientHttpProtocolNegotiato
     public void disconnected(final IOSession session) {
     }
 
+    @Override
+    public HttpConnectionMetrics getMetrics() {
+        return null;
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        ioSession.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return ioSession.getSocketTimeout();
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        return null;
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return ioSession.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return ioSession.getLocalAddress();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return !ioSession.isClosed();
+    }
+
+    @Override
+    public void close() throws IOException {
+        ioSession.close();
+    }
+
+    @Override
+    public void shutdown() throws IOException {
+        ioSession.shutdown();
+    }
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java Mon Oct 31 17:33:27 2016
@@ -32,11 +32,11 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+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.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
@@ -51,42 +51,43 @@ public class ClientHttpProtocolNegotiato
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
+    private final ConnectionListener connectionListener;
     private final Http2StreamListener streamListener;
-    private final ExceptionListener errorListener;
 
     public ClientHttpProtocolNegotiatorFactory(
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
         this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.pushHandlerFactory = pushHandlerFactory;
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+        this.connectionListener = connectionListener;
         this.streamListener = streamListener;
-        this.errorListener = errorListener;
     }
 
     public ClientHttpProtocolNegotiatorFactory(
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
-        this(httpProcessor, pushHandlerFactory, null, null, streamListener, errorListener);
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        this(httpProcessor, pushHandlerFactory, null, null, connectionListener, streamListener);
     }
 
     public ClientHttpProtocolNegotiatorFactory(
             final HttpProcessor httpProcessor,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
-        this(httpProcessor, null, streamListener, errorListener);
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        this(httpProcessor, null, connectionListener, streamListener);
     }
 
     @Override
     public ClientHttpProtocolNegotiator createHandler(final IOSession ioSession) {
-        return new ClientHttpProtocolNegotiator(httpProcessor, pushHandlerFactory, charset, h2Config, streamListener, errorListener);
+        return new ClientHttpProtocolNegotiator(ioSession, httpProcessor, pushHandlerFactory,
+                charset, h2Config, connectionListener, streamListener);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java Mon Oct 31 17:33:27 2016
@@ -33,25 +33,29 @@ import java.util.concurrent.atomic.Atomi
 
 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.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.LazyEntityDetails;
+import org.apache.hc.core5.http.impl.nio.MessageState;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.H2StreamResetException;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
-import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
-import org.apache.hc.core5.http2.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.util.Asserts;
 
 class ClientPushHttp2StreamHandler implements Http2StreamHandler {
 
+    private final HttpConnection connection;
     private final Http2StreamChannel internalOutputChannel;
     private final HttpProcessor httpProcessor;
     private final BasicHttpConnectionMetrics connMetrics;
@@ -65,10 +69,12 @@ class ClientPushHttp2StreamHandler imple
     private volatile MessageState responseState;
 
     ClientPushHttp2StreamHandler(
+            final HttpConnection connection,
             final Http2StreamChannel outputChannel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) {
+        this.connection = connection;
         this.internalOutputChannel = outputChannel;
         this.httpProcessor = httpProcessor;
         this.connMetrics = connMetrics;
@@ -94,19 +100,25 @@ class ClientPushHttp2StreamHandler imple
 
             request = DefaultH2RequestConverter.INSTANCE.convert(headers);
 
+            final AsyncPushConsumer handler;
+            try {
+                handler = pushHandlerFactory != null ? pushHandlerFactory.create(request) : null;
+            } catch (ProtocolException ex) {
+                throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, ex.getMessage());
+            }
+            if (handler == null) {
+                throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
+            }
+            exchangeHandler = handler;
+
             context.setProtocolVersion(HttpVersion.HTTP_2);
             context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
-            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, connection);
             httpProcessor.process(request, null, context);
             connMetrics.incrementRequestCount();
 
-            exchangeHandler = pushHandlerFactory != null ? pushHandlerFactory.create(request, context) : null;
-            if (exchangeHandler == null) {
-                releaseResources();
-                throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
-            }
         } else {
-            throw new ProtocolException("Unexpected promise");
+            throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Unexpected promise");
         }
     }
 
@@ -117,7 +129,7 @@ class ClientPushHttp2StreamHandler imple
             Asserts.notNull(exchangeHandler, "Exchange handler");
 
             final HttpResponse response = DefaultH2ResponseConverter.INSTANCE.convert(headers);
-            final EntityDetails entityDetails = endStream ? null : new IncomingEntityDetails(request);
+            final EntityDetails entityDetails = endStream ? null : new LazyEntityDetails(request);
 
             context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
             httpProcessor.process(response, entityDetails, context);

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamChannel.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamChannel.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamChannel.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamChannel.java Mon Oct 31 17:33:27 2016
@@ -32,9 +32,9 @@ import java.util.List;
 
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http2.nio.AsyncPushProducer;
-import org.apache.hc.core5.http2.nio.CapacityChannel;
-import org.apache.hc.core5.http2.nio.DataStreamChannel;
+import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.CapacityChannel;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
 
 interface Http2StreamChannel extends DataStreamChannel, CapacityChannel {
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamHandler.java Mon Oct 31 17:33:27 2016
@@ -32,7 +32,7 @@ import java.util.List;
 
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http2.nio.ResourceHolder;
+import org.apache.hc.core5.http.nio.ResourceHolder;
 
 interface Http2StreamHandler extends ResourceHolder {
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2IOEventHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2IOEventHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2IOEventHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2IOEventHandler.java Mon Oct 31 17:33:27 2016
@@ -29,7 +29,6 @@ package org.apache.hc.core5.http2.impl.n
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
 
 /**
  * {@link org.apache.hc.core5.reactor.IOEventHandler} that implements server side HTTP/2 messaging protocol.
@@ -39,12 +38,8 @@ import org.apache.hc.core5.http.Exceptio
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
 public class ServerHttp2IOEventHandler extends AbstractHttp2IOEventHandler{
 
-    public ServerHttp2IOEventHandler(final ServerHttp2StreamMultiplexer streamMultiplexer, final ExceptionListener errorListener) {
-        super(streamMultiplexer, errorListener);
-    }
-
     public ServerHttp2IOEventHandler(final ServerHttp2StreamMultiplexer streamMultiplexer) {
-        this(streamMultiplexer, null);
+        super(streamMultiplexer);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java Mon Oct 31 17:33:27 2016
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.Atomi
 
 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.HttpRequest;
@@ -41,24 +42,27 @@ import org.apache.hc.core5.http.HttpStat
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.LazyEntityDetails;
+import org.apache.hc.core5.http.impl.nio.MessageState;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
+import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
+import org.apache.hc.core5.http.nio.ExpectationChannel;
+import org.apache.hc.core5.http.nio.HandlerFactory;
+import org.apache.hc.core5.http.nio.ResponseChannel;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
+import org.apache.hc.core5.http2.H2StreamResetException;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
-import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
-import org.apache.hc.core5.http2.nio.AsyncPushProducer;
-import org.apache.hc.core5.http2.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http2.nio.DataStreamChannel;
-import org.apache.hc.core5.http2.nio.ExpectationChannel;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
-import org.apache.hc.core5.http2.nio.ResponseChannel;
 import org.apache.hc.core5.util.Asserts;
 
 public class ServerHttp2StreamHandler implements Http2StreamHandler {
 
+    private final HttpConnection connection;
     private final Http2StreamChannel outputChannel;
     private final DataStreamChannel dataChannel;
     private final HttpProcessor httpProcessor;
@@ -73,10 +77,12 @@ public class ServerHttp2StreamHandler im
     private volatile MessageState responseState;
 
     ServerHttp2StreamHandler(
+            final HttpConnection connection,
             final Http2StreamChannel outputChannel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory) {
+        this.connection = connection;
         this.outputChannel = outputChannel;
         this.dataChannel = new DataStreamChannel() {
 
@@ -167,24 +173,35 @@ public class ServerHttp2StreamHandler im
         requestState = requestEndStream ? MessageState.COMPLETE : MessageState.BODY;
 
         final HttpRequest request = DefaultH2RequestConverter.INSTANCE.convert(requestHeaders);
-        final EntityDetails requestEntityDetails = requestEndStream ? null : new IncomingEntityDetails(request);
+        final EntityDetails requestEntityDetails = requestEndStream ? null : new LazyEntityDetails(request);
+
+        final AsyncServerExchangeHandler handler;
+        try {
+            handler = exchangeHandlerFactory != null ? exchangeHandlerFactory.create(request) : null;
+        } catch (ProtocolException ex) {
+            throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, ex.getMessage());
+        }
+        if (handler == null) {
+            throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
+        }
+        if (handler == null) {
+            throw new H2ConnectionException(H2Error.INTERNAL_ERROR,
+                    "Unable to handle " + request.getMethod() + " " + request.getPath());
+        }
+        exchangeHandler = handler;
 
         context.setProtocolVersion(HttpVersion.HTTP_2);
         context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
-        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, connection);
+        exchangeHandler.setContext(context);
+
         httpProcessor.process(request, requestEntityDetails, context);
         connMetrics.incrementRequestCount();
 
-        exchangeHandler = exchangeHandlerFactory.create(request, context);
-        if (exchangeHandler == null) {
-            throw new H2ConnectionException(H2Error.INTERNAL_ERROR,
-                    "Unable to handle " + request.getMethod() + " " + request.getPath());
-        }
-
         boolean expectContinue = false;
         if (requestEntityDetails != null) {
             final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
-            if ("100-continue".equalsIgnoreCase(h.getValue())) {
+            if (h != null && "100-continue".equalsIgnoreCase(h.getValue())) {
                 expectContinue = true;
             }
         }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java Mon Oct 31 17:33:27 2016
@@ -30,13 +30,14 @@ import java.io.IOException;
 import java.nio.charset.Charset;
 
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+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.http2.frame.FrameFactory;
 import org.apache.hc.core5.http2.frame.StreamIdGenerator;
-import org.apache.hc.core5.http2.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
 
@@ -56,8 +57,10 @@ public class ServerHttp2StreamMultiplexe
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener callback) {
-        super(Mode.SERVER, ioSession, frameFactory, StreamIdGenerator.EVEN, httpProcessor, charset, h2Config, callback);
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        super(Mode.SERVER, ioSession, frameFactory, StreamIdGenerator.EVEN, httpProcessor, charset,
+                h2Config, connectionListener, streamListener);
         this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Handler factory");
     }
 
@@ -67,7 +70,8 @@ public class ServerHttp2StreamMultiplexe
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config) {
-        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, exchangeHandlerFactory, charset, h2Config, null);
+        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, exchangeHandlerFactory, charset,
+                h2Config, null, null);
     }
 
     @Override
@@ -75,7 +79,7 @@ public class ServerHttp2StreamMultiplexe
             final Http2StreamChannel channel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics) throws IOException {
-        return new ServerHttp2StreamHandler(channel, httpProcessor, connMetrics, exchangeHandlerFactory);
+        return new ServerHttp2StreamHandler(this, channel, httpProcessor, connMetrics, exchangeHandlerFactory);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java Mon Oct 31 17:33:27 2016
@@ -27,6 +27,8 @@
 
 package org.apache.hc.core5.http2.impl.nio;
 
+import java.io.IOException;
+import java.net.SocketAddress;
 import java.net.SocketTimeoutException;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
@@ -34,15 +36,17 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.HttpConnectionMetrics;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
-import org.apache.hc.core5.http2.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
-import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
 
@@ -50,37 +54,40 @@ import org.apache.hc.core5.util.Args;
  * @since 5.0
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
-public class ServerHttpProtocolNegotiator implements IOEventHandler {
+public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler {
 
     final static byte[] PREFACE = ClientHttpProtocolNegotiator.PREFACE;
 
+    private final IOSession ioSession;
     private final HttpProcessor httpProcessor;
     private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
-    private final Http2StreamListener streamListener;
-    private final ExceptionListener errorListener;
     private final ByteBuffer bytebuf;
+    private final ConnectionListener connectionListener;
+    private final Http2StreamListener streamListener;
 
     public ServerHttpProtocolNegotiator(
+            final IOSession ioSession,
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        this.ioSession = Args.notNull(ioSession, "I/O session");
         this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
-        this.streamListener = streamListener;
-        this.errorListener = errorListener;
         this.bytebuf = ByteBuffer.allocate(1024);
+        this.connectionListener = connectionListener;
+        this.streamListener = streamListener;
     }
 
     protected ServerHttp2StreamMultiplexer createStreamMultiplexer(final IOSession ioSession) {
         return new ServerHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
-                exchangeHandlerFactory, charset, h2Config, streamListener);
+                exchangeHandlerFactory, charset, h2Config, connectionListener, streamListener);
     }
 
     @Override
@@ -103,12 +110,12 @@ public class ServerHttpProtocolNegotiato
                 final ServerHttp2StreamMultiplexer streamMultiplexer = createStreamMultiplexer(session);
                 streamMultiplexer.onConnect(bytebuf.hasRemaining() ? bytebuf : null);
                 streamMultiplexer.onInput();
-                session.setHandler(new ServerHttp2IOEventHandler(streamMultiplexer, errorListener));
+                session.setHandler(new ServerHttp2IOEventHandler(streamMultiplexer));
             }
         } catch (Exception ex) {
             session.close();
-            if (errorListener != null) {
-                errorListener.onError(ex);
+            if (connectionListener != null) {
+                connectionListener.onError(this, ex);
             }
         }
     }
@@ -120,8 +127,8 @@ public class ServerHttpProtocolNegotiato
     @Override
     public void timeout(final IOSession session) {
         session.close();
-        if (errorListener != null) {
-            errorListener.onError(new SocketTimeoutException());
+        if (connectionListener != null) {
+            connectionListener.onError(this, new SocketTimeoutException());
         }
     }
 
@@ -129,4 +136,49 @@ public class ServerHttpProtocolNegotiato
     public void disconnected(final IOSession session) {
     }
 
+    @Override
+    public HttpConnectionMetrics getMetrics() {
+        return null;
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        ioSession.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return ioSession.getSocketTimeout();
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        return null;
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return ioSession.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return ioSession.getLocalAddress();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return !ioSession.isClosed();
+    }
+
+    @Override
+    public void close() throws IOException {
+        ioSession.close();
+    }
+
+    @Override
+    public void shutdown() throws IOException {
+        ioSession.shutdown();
+    }
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java Mon Oct 31 17:33:27 2016
@@ -32,11 +32,11 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.impl.nio.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+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.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.util.Args;
@@ -51,35 +51,36 @@ public class ServerHttpProtocolNegotiato
     private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
+    private final ConnectionListener connectionListener;
     private final Http2StreamListener streamListener;
-    private final ExceptionListener errorListener;
 
     public ServerHttpProtocolNegotiatorFactory(
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
         this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+        this.connectionListener = connectionListener;
         this.streamListener = streamListener;
-        this.errorListener = errorListener;
     }
 
     public ServerHttpProtocolNegotiatorFactory(
             final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
-            final Http2StreamListener streamListener,
-            final ExceptionListener errorListener) {
-        this(httpProcessor, exchangeHandlerFactory, null, null, streamListener, errorListener);
+            final ConnectionListener connectionListener,
+            final Http2StreamListener streamListener) {
+        this(httpProcessor, exchangeHandlerFactory, null, null, connectionListener, streamListener);
     }
 
     @Override
     public ServerHttpProtocolNegotiator createHandler(final IOSession ioSession) {
-        return new ServerHttpProtocolNegotiator(httpProcessor, exchangeHandlerFactory, charset, h2Config, streamListener, errorListener);
+        return new ServerHttpProtocolNegotiator(ioSession, httpProcessor, exchangeHandlerFactory,
+                charset, h2Config, connectionListener, streamListener);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java Mon Oct 31 17:33:27 2016
@@ -33,22 +33,25 @@ import java.util.concurrent.atomic.Atomi
 
 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.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.impl.nio.MessageState;
+import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
+import org.apache.hc.core5.http.nio.ResponseChannel;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
-import org.apache.hc.core5.http2.nio.AsyncPushProducer;
-import org.apache.hc.core5.http2.nio.DataStreamChannel;
-import org.apache.hc.core5.http2.nio.ResponseChannel;
 
 class ServerPushHttp2StreamHandler implements Http2StreamHandler {
 
+    private final HttpConnection connection;
     private final Http2StreamChannel outputChannel;
     private final DataStreamChannel dataChannel;
     private final HttpProcessor httpProcessor;
@@ -61,10 +64,12 @@ class ServerPushHttp2StreamHandler imple
     private volatile MessageState responseState;
 
     ServerPushHttp2StreamHandler(
+            final HttpConnection connection,
             final Http2StreamChannel outputChannel,
             final HttpProcessor httpProcessor,
             final BasicHttpConnectionMetrics connMetrics,
             final AsyncPushProducer pushProducer) {
+        this.connection = connection;
         this.outputChannel = outputChannel;
         this.dataChannel = new DataStreamChannel() {
 
@@ -146,7 +151,7 @@ class ServerPushHttp2StreamHandler imple
                         if (responseCommitted.compareAndSet(false, true)) {
 
                             context.setProtocolVersion(HttpVersion.HTTP_2);
-                            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+                            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, connection);
                             context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
                             httpProcessor.process(response, entityDetails, context);
 
@@ -162,8 +167,8 @@ class ServerPushHttp2StreamHandler imple
                             final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
 
                         context.setProtocolVersion(HttpVersion.HTTP_2);
+                        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, connection);
                         context.setAttribute(HttpCoreContext.HTTP_REQUEST, promise);
-                        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
                         httpProcessor.process(promise, null, context);
 
                         final List<Header> headers = DefaultH2RequestConverter.INSTANCE.convert(promise);

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedInputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedInputBuffer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedInputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedInputBuffer.java Mon Oct 31 17:33:27 2016
@@ -37,7 +37,8 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.hc.core5.http2.nio.CapacityChannel;
+import org.apache.hc.core5.http.impl.nio.entity.SharedInputBuffer;
+import org.apache.hc.core5.http.nio.CapacityChannel;
 import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -199,7 +200,7 @@ public class TestSharedInputBuffer {
 
         Assert.assertEquals(Boolean.TRUE, task1.get(5, TimeUnit.SECONDS));
         Assert.assertEquals("12345678901234567890123456789012345678901234567890", task2.get(5, TimeUnit.SECONDS));
-        Mockito.verify(capacityChannel, Mockito.atLeast(1)).update(10);
+        Mockito.verify(capacityChannel, Mockito.atLeast(1)).update(Mockito.anyInt());
     }
 
     @Test

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedOutputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedOutputBuffer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedOutputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/entity/TestSharedOutputBuffer.java Mon Oct 31 17:33:27 2016
@@ -41,8 +41,9 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.impl.nio.entity.SharedOutputBuffer;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
 import org.apache.hc.core5.http2.WritableByteChannelMock;
-import org.apache.hc.core5.http2.nio.DataStreamChannel;
 import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -97,7 +98,7 @@ public class TestSharedOutputBuffer {
         Mockito.verifyZeroInteractions(dataStreamChannel);
 
         Assert.assertEquals(0, outputBuffer.length());
-        Assert.assertEquals(30, outputBuffer.available());
+        Assert.assertEquals(30, outputBuffer.capacity());
 
         final byte[] tmp = "1234567890".getBytes(charset);
         outputBuffer.write(tmp, 0, tmp.length);
@@ -106,7 +107,7 @@ public class TestSharedOutputBuffer {
         outputBuffer.write('2');
 
         Assert.assertEquals(22, outputBuffer.length());
-        Assert.assertEquals(8, outputBuffer.available());
+        Assert.assertEquals(8, outputBuffer.capacity());
 
         Mockito.verifyZeroInteractions(dataStreamChannel);
     }
@@ -122,7 +123,7 @@ public class TestSharedOutputBuffer {
         outputBuffer.flush(dataStreamChannel);
 
         Assert.assertEquals(0, outputBuffer.length());
-        Assert.assertEquals(30, outputBuffer.available());
+        Assert.assertEquals(30, outputBuffer.capacity());
 
         final byte[] tmp = "1234567890".getBytes(charset);
         outputBuffer.write(tmp, 0, tmp.length);
@@ -133,7 +134,7 @@ public class TestSharedOutputBuffer {
         outputBuffer.flush(dataStreamChannel);
 
         Assert.assertEquals(0, outputBuffer.length());
-        Assert.assertEquals(30, outputBuffer.available());
+        Assert.assertEquals(30, outputBuffer.capacity());
     }
 
     @Test

Modified: httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/ActuallyConnectIT.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/ActuallyConnectIT.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/ActuallyConnectIT.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/ActuallyConnectIT.java Mon Oct 31 17:33:27 2016
@@ -33,10 +33,10 @@ import org.apache.hc.core5.http.ClassicH
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHost;
-import org.apache.hc.core5.http.entity.EntityUtils;
-import org.apache.hc.core5.http.entity.StringEntity;
 import org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection;
 import org.apache.hc.core5.http.io.HttpRequestHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.testing.classic.ClassicTestClient;

Modified: httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/Common.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/Common.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/Common.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-osgi/src/test/java/org/apache/hc/core5/http/osgi/Common.java Mon Oct 31 17:33:27 2016
@@ -88,7 +88,7 @@ public class Common {
                         "org.apache.hc.core5.concurrent",
                         "org.apache.hc.core5.http",
                         "org.apache.hc.core5.http.config",
-                        "org.apache.hc.core5.http.entity",
+                        "org.apache.hc.core5.http.io.entity",
                         "org.apache.hc.core5.http.message",
                         "org.apache.hc.core5.http.protocol",
                         "org.apache.hc.core5.http.impl",

Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/ClassicTestServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/ClassicTestServer.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/ClassicTestServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/ClassicTestServer.java Mon Oct 31 17:33:27 2016
@@ -37,12 +37,13 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hc.core5.http.ConnectionClosedException;
 import org.apache.hc.core5.http.ExceptionListener;
-import org.apache.hc.core5.http.bootstrap.io.ServerBootstrap;
 import org.apache.hc.core5.http.config.SocketConfig;
+import org.apache.hc.core5.http.impl.io.bootstrap.HttpServer;
+import org.apache.hc.core5.http.impl.io.bootstrap.ServerBootstrap;
 import org.apache.hc.core5.http.io.HttpConnectionFactory;
+import org.apache.hc.core5.http.io.HttpExpectationVerifier;
 import org.apache.hc.core5.http.io.HttpRequestHandler;
 import org.apache.hc.core5.http.io.UriHttpRequestHandlerMapper;
-import org.apache.hc.core5.http.io.HttpExpectationVerifier;
 import org.apache.hc.core5.util.Asserts;
 
 public class ClassicTestServer {
@@ -51,7 +52,7 @@ public class ClassicTestServer {
     private volatile HttpExpectationVerifier expectationVerifier;
     private volatile int timeout;
 
-    private volatile org.apache.hc.core5.http.bootstrap.io.HttpServer server;
+    private volatile HttpServer server;
 
     public ClassicTestServer() throws IOException {
         super();
@@ -77,7 +78,7 @@ public class ClassicTestServer {
     }
 
     public int getPort() {
-        final org.apache.hc.core5.http.bootstrap.io.HttpServer local = this.server;
+        final HttpServer local = this.server;
         if (local != null) {
             return this.server.getLocalPort();
         } else {
@@ -86,7 +87,7 @@ public class ClassicTestServer {
     }
 
     public InetAddress getInetAddress() {
-        final org.apache.hc.core5.http.bootstrap.io.HttpServer local = this.server;
+        final HttpServer local = this.server;
         if (local != null) {
             return local.getInetAddress();
         } else {
@@ -100,7 +101,6 @@ public class ClassicTestServer {
                 .setSocketConfig(SocketConfig.custom()
                         .setSoTimeout(this.timeout)
                         .build())
-                .setServerInfo("TEST-SERVER/1.1")
                 .setConnectionFactory(new LoggingConnFactory())
                 .setExceptionListener(new SimpleExceptionListener())
                 .setExpectationVerifier(this.expectationVerifier)
@@ -114,7 +114,7 @@ public class ClassicTestServer {
     }
 
     public void shutdown(final long gracePeriod, final TimeUnit timeUnit) {
-        final org.apache.hc.core5.http.bootstrap.io.HttpServer local = this.server;
+        final HttpServer local = this.server;
         this.server = null;
         if (local != null) {
             local.shutdown(gracePeriod, timeUnit);

Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/LoggingBHttpClientConnection.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/LoggingBHttpClientConnection.java?rev=1767339&r1=1767338&r2=1767339&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/LoggingBHttpClientConnection.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/classic/LoggingBHttpClientConnection.java Mon Oct 31 17:33:27 2016
@@ -43,7 +43,7 @@ import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpVersion;
-import org.apache.hc.core5.http.config.MessageConstraints;
+import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection;
 import org.apache.hc.core5.http.io.HttpMessageParserFactory;
 import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
@@ -64,7 +64,7 @@ public class LoggingBHttpClientConnectio
             final int fragmentSizeHint,
             final CharsetDecoder chardecoder,
             final CharsetEncoder charencoder,
-            final MessageConstraints constraints,
+            final H1Config constraints,
             final ContentLengthStrategy incomingContentStrategy,
             final ContentLengthStrategy outgoingContentStrategy,
             final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,