From 38ef1f624aaf045458b6fe055742fa680a96a9e1 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Thu, 7 Mar 2019 10:50:05 +0000
Subject: [PATCH 2/5] Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63223

---
 java/org/apache/coyote/http2/Http2UpgradeHandler.java | 8 ++++++++
 java/org/apache/coyote/http2/Stream.java              | 5 +++++
 java/org/apache/coyote/http2/StreamStateMachine.java  | 8 +++++++-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index da724652aa..2330d12e09 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -555,6 +555,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
         synchronized (socketWrapper) {
             doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize);
         }
+        stream.sentHeaders();
         if (endOfStream) {
             stream.sentEndOfStream();
         }
@@ -1178,6 +1179,13 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
 
 
     void push(Request request, Stream associatedStream) throws IOException {
+        if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) {
+            // If there are too many open streams, simply ignore the push
+            // request.
+            activeRemoteStreamCount.decrementAndGet();
+            return;
+        }
+
         Stream pushStream;
 
         // Synchronized since PUSH_PROMISE frames have to be sent in order. Once
diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index 43aee9d656..629d0210b4 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -561,6 +561,11 @@ class Stream extends AbstractStream implements HeaderEmitter {
     }
 
 
+    final void sentHeaders() {
+        state.sentHeaders();
+    }
+
+
     final void sentEndOfStream() {
         streamOutputBuffer.endOfStreamSent = true;
         state.sentEndOfStream();
diff --git a/java/org/apache/coyote/http2/StreamStateMachine.java b/java/org/apache/coyote/http2/StreamStateMachine.java
index 3b67f865d3..d19bb0a255 100644
--- a/java/org/apache/coyote/http2/StreamStateMachine.java
+++ b/java/org/apache/coyote/http2/StreamStateMachine.java
@@ -53,6 +53,12 @@ class StreamStateMachine {
     }
 
 
+    final synchronized void sentHeaders() {
+        // No change if currently OPEN
+        stateChange(State.RESERVED_LOCAL, State.HALF_CLOSED_REMOTE);
+    }
+
+
     final synchronized void receivedStartOfHeaders() {
         stateChange(State.IDLE, State.OPEN);
         stateChange(State.RESERVED_REMOTE, State.HALF_CLOSED_LOCAL);
@@ -170,7 +176,7 @@ class StreamStateMachine {
                             Http2Error.PROTOCOL_ERROR, FrameType.PRIORITY,
                                                        FrameType.RST,
                                                        FrameType.WINDOW_UPDATE),
-        RESERVED_REMOTE    (false, false, true,  true,
+        RESERVED_REMOTE    (false,  true, true,  true,
                             Http2Error.PROTOCOL_ERROR, FrameType.HEADERS,
                                                        FrameType.PRIORITY,
                                                        FrameType.RST),
-- 
2.23.0

