Fix oghttp2 to reject 204 responses with a body, even with no content-length header.

This CL updates OgHttp2Session::CanReceiveBody() to return false for responses
with :status 204. This change aligns oghttp2 further with nghttp2 and GFE2:
http://google3/third_party/quiche/common/balsa/balsa_headers.cc;l=1093;rcl=436357765.
PiperOrigin-RevId: 436844954
diff --git a/http2/adapter/nghttp2_adapter_test.cc b/http2/adapter/nghttp2_adapter_test.cc
index fe4e32c..645575e 100644
--- a/http2/adapter/nghttp2_adapter_test.cc
+++ b/http2/adapter/nghttp2_adapter_test.cc
@@ -579,8 +579,19 @@
   const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
   ASSERT_GT(stream_id1, 0);
 
+  const std::vector<Header> headers2 =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/two"}});
+
+  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  ASSERT_GT(stream_id2, stream_id1);
+
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
 
   int result = adapter->Send();
   EXPECT_EQ(0, result);
@@ -592,6 +603,8 @@
           .Headers(1, {{":status", "204"}, {"content-length", "2"}},
                    /*fin=*/false)
           .Data(1, "hi")
+          .Headers(3, {{":status", "204"}}, /*fin=*/false)
+          .Data(3, "hi")
           .Serialize();
 
   // Server preface (empty SETTINGS)
@@ -609,6 +622,12 @@
   EXPECT_CALL(
       visitor,
       OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
+  EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
+  EXPECT_CALL(visitor, OnHeaderForStream(3, ":status", "204"));
+  EXPECT_CALL(visitor, OnEndHeadersForStream(3));
+  EXPECT_CALL(visitor, OnFrameHeader(3, _, DATA, 0));
+  EXPECT_CALL(visitor, OnBeginDataForStream(3, 2));
 
   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
   EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
@@ -620,12 +639,18 @@
               OnFrameSent(RST_STREAM, 1, _, 0x0,
                           static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
   EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
+  EXPECT_CALL(visitor,
+              OnFrameSent(RST_STREAM, 3, _, 0x0,
+                          static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
+  EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
 
   EXPECT_TRUE(adapter->want_write());
   result = adapter->Send();
   EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
-                                            SpdyFrameType::RST_STREAM}));
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
+                            SpdyFrameType::RST_STREAM}));
 }
 
 TEST(NgHttp2AdapterTest, ClientHandles304WithContent) {
diff --git a/http2/adapter/oghttp2_adapter_test.cc b/http2/adapter/oghttp2_adapter_test.cc
index 2aa0255..775609a 100644
--- a/http2/adapter/oghttp2_adapter_test.cc
+++ b/http2/adapter/oghttp2_adapter_test.cc
@@ -671,10 +671,21 @@
   const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
   ASSERT_GT(stream_id1, 0);
 
+  const std::vector<Header> headers2 =
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/two"}});
+
+  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  ASSERT_GT(stream_id2, stream_id1);
+
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
+  EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
 
   int result = adapter->Send();
   EXPECT_EQ(0, result);
@@ -686,6 +697,8 @@
           .Headers(1, {{":status", "204"}, {"content-length", "2"}},
                    /*fin=*/false)
           .Data(1, "hi")
+          .Headers(3, {{":status", "204"}}, /*fin=*/false)
+          .Data(3, "hi")
           .Serialize();
 
   // Server preface (empty SETTINGS)
@@ -699,6 +712,12 @@
   EXPECT_CALL(
       visitor,
       OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
+  EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
+  EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
+  EXPECT_CALL(visitor, OnHeaderForStream(3, ":status", "204"));
+  EXPECT_CALL(visitor, OnEndHeadersForStream(3));
+  EXPECT_CALL(visitor, OnFrameHeader(3, _, DATA, 0));
+  EXPECT_CALL(visitor, OnBeginDataForStream(3, 2));
 
   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
   EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
@@ -710,12 +729,18 @@
               OnFrameSent(RST_STREAM, 1, _, 0x0,
                           static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
   EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
+  EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
+  EXPECT_CALL(visitor,
+              OnFrameSent(RST_STREAM, 3, _, 0x0,
+                          static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
+  EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::HTTP2_NO_ERROR));
 
   EXPECT_TRUE(adapter->want_write());
   result = adapter->Send();
   EXPECT_EQ(0, result);
-  EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
-                                            SpdyFrameType::RST_STREAM}));
+  EXPECT_THAT(visitor.data(),
+              EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
+                            SpdyFrameType::RST_STREAM}));
 }
 
 TEST(OgHttp2AdapterTest, ClientHandles304WithContent) {
diff --git a/http2/adapter/oghttp2_session.cc b/http2/adapter/oghttp2_session.cc
index 25cd0e9..d8431dd 100644
--- a/http2/adapter/oghttp2_session.cc
+++ b/http2/adapter/oghttp2_session.cc
@@ -284,7 +284,7 @@
   frame_contains_fin_ = false;
 }
 
-// TODO(diannahu): Add checks for other response codes and request methods.
+// TODO(diannahu): Add checks for request methods.
 bool OgHttp2Session::PassthroughHeadersHandler::CanReceiveBody() const {
   switch (header_type()) {
     case HeaderType::REQUEST_TRAILER:
@@ -294,7 +294,9 @@
     case HeaderType::RESPONSE:
       // 304 responses should not have a body:
       // https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.2
-      return status_header() != "304";
+      // Neither should 204 responses:
+      // https://httpwg.org/specs/rfc7231.html#rfc.section.6.3.5
+      return status_header() != "304" && status_header() != "204";
     case HeaderType::REQUEST:
       return true;
   }