This is an automated email from the ASF dual-hosted git repository.

chenBright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new a80df6fa Read GOAWAY fields before additional debug data (#3395)
a80df6fa is described below

commit a80df6fa2ab760a004403a4c91b29e773ae6f167
Author: UB <[email protected]>
AuthorDate: Tue Jul 21 08:02:01 2026 +0530

    Read GOAWAY fields before additional debug data (#3395)
    
    Signed-off-by: ubeddulla khan <[email protected]>
---
 src/brpc/policy/http2_rpc_protocol.cpp   |  6 ++++--
 test/brpc_http_rpc_protocol_unittest.cpp | 30 ++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/brpc/policy/http2_rpc_protocol.cpp 
b/src/brpc/policy/http2_rpc_protocol.cpp
index b2de496c..d527a055 100644
--- a/src/brpc/policy/http2_rpc_protocol.cpp
+++ b/src/brpc/policy/http2_rpc_protocol.cpp
@@ -977,10 +977,12 @@ H2ParseResult H2Context::OnGoAway(
         LOG(ERROR) << "Invalid flags=" << h.flags;
         return MakeH2Error(H2_PROTOCOL_ERROR);
     }
+    // Last-Stream-ID and Error Code precede the Additional Debug Data.
+    // The reserved bit of Last-Stream-ID is ignored on receipt.
+    const int last_stream_id = static_cast<int>(LoadUint32(it) & 0x7FFFFFFF);
+    const H2Error ALLOW_UNUSED h2_error = static_cast<H2Error>(LoadUint32(it));
     // Skip Additional Debug Data
     it.forward(h.payload_size - 8);
-    const int last_stream_id = static_cast<int>(LoadUint32(it));
-    const H2Error ALLOW_UNUSED h2_error = static_cast<H2Error>(LoadUint32(it));
     // TODO(zhujiashun): client and server should unify the code.
     // Server Push is not supported so it works fine now.
     if (is_client_side()) {
diff --git a/test/brpc_http_rpc_protocol_unittest.cpp 
b/test/brpc_http_rpc_protocol_unittest.cpp
index a75a1225..87837abf 100644
--- a/test/brpc_http_rpc_protocol_unittest.cpp
+++ b/test/brpc_http_rpc_protocol_unittest.cpp
@@ -1598,6 +1598,36 @@ TEST_F(HttpTest, http2_settings) {
     ASSERT_TRUE(ctx->_remote_settings.stream_window_size == (1u << 29) - 1);
 }
 
+TEST_F(HttpTest, http2_goaway_with_debug_data) {
+    // GOAWAY payload is Last-Stream-ID(4) | Error Code(4) | Debug Data(*).
+    const uint32_t payload_size = 16;
+    char goawaybuf[brpc::policy::FRAME_HEAD_SIZE + payload_size];
+    brpc::policy::SerializeFrameHead(goawaybuf, payload_size,
+                                     brpc::policy::H2_FRAME_GOAWAY, 0, 0);
+    char* p = goawaybuf + brpc::policy::FRAME_HEAD_SIZE;
+    // Last-Stream-ID=1, with the reserved bit set so it must be masked off.
+    p[0] = (char)0x80; p[1] = 0; p[2] = 0; p[3] = 1;
+    // Error Code = H2_NO_ERROR
+    p[4] = 0; p[5] = 0; p[6] = 0; p[7] = 0;
+    // Debug Data whose last 8 bytes would be read as the two fields above.
+    p[8] = (char)0xff; p[9] = (char)0xff; p[10] = (char)0xff; p[11] = 
(char)0xff;
+    p[12] = 0; p[13] = 0; p[14] = 0; p[15] = 0;
+
+    butil::IOBuf buf;
+    buf.append(goawaybuf, brpc::policy::FRAME_HEAD_SIZE + payload_size);
+
+    brpc::policy::H2Context* ctx =
+        new brpc::policy::H2Context(_h2_client_sock.get(), NULL);
+    CHECK_EQ(ctx->Init(), 0);
+    _h2_client_sock->initialize_parsing_context(&ctx);
+    ctx->_conn_state = brpc::policy::H2_CONNECTION_READY;
+    brpc::policy::ParseH2Message(&buf, _h2_client_sock.get(), false, NULL);
+
+    // Reading the debug data instead would leave -1 here, which disables the
+    // `_goaway_stream_id >= 0' check in TryToInsertStream.
+    ASSERT_EQ(1, ctx->_goaway_stream_id);
+}
+
 TEST_F(HttpTest, http2_invalid_settings) {
     {
         brpc::Server server;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to