Adds Http2VisitorInterface::OnErrorDebug(), a method that conveys error messages for debugging purposes.

PiperOrigin-RevId: 381094999
diff --git a/http2/adapter/callback_visitor.cc b/http2/adapter/callback_visitor.cc
index e953d46..fa1e0f7 100644
--- a/http2/adapter/callback_visitor.cc
+++ b/http2/adapter/callback_visitor.cc
@@ -300,6 +300,13 @@
   QUICHE_LOG(FATAL) << "Not implemented";
 }
 
+void CallbackVisitor::OnErrorDebug(absl::string_view message) {
+  if (callbacks_->error_callback2) {
+    callbacks_->error_callback2(nullptr, -1, message.data(), message.size(),
+                                user_data_);
+  }
+}
+
 CallbackVisitor::StreamInfoMap::iterator CallbackVisitor::GetStreamInfo(
     Http2StreamId stream_id) {
   auto it = stream_map_.find(stream_id);
diff --git a/http2/adapter/callback_visitor.h b/http2/adapter/callback_visitor.h
index 07b3608..fe728ba 100644
--- a/http2/adapter/callback_visitor.h
+++ b/http2/adapter/callback_visitor.h
@@ -71,6 +71,7 @@
   void OnMetadataForStream(Http2StreamId stream_id,
                            absl::string_view metadata) override;
   void OnMetadataEndForStream(Http2StreamId stream_id) override;
+  void OnErrorDebug(absl::string_view message) override;
 
  private:
   struct StreamInfo {
diff --git a/http2/adapter/http2_visitor_interface.h b/http2/adapter/http2_visitor_interface.h
index f174329..4250a5f 100644
--- a/http2/adapter/http2_visitor_interface.h
+++ b/http2/adapter/http2_visitor_interface.h
@@ -186,6 +186,9 @@
   // for a stream. Note that there may be multiple metadata blocks for a stream.
   virtual void OnMetadataEndForStream(Http2StreamId stream_id) = 0;
 
+  // Invoked with an error message from the application.
+  virtual void OnErrorDebug(absl::string_view message) = 0;
+
  protected:
   Http2VisitorInterface() = default;
 };
diff --git a/http2/adapter/mock_http2_visitor.h b/http2/adapter/mock_http2_visitor.h
index bacdd4f..f3ab9ec 100644
--- a/http2/adapter/mock_http2_visitor.h
+++ b/http2/adapter/mock_http2_visitor.h
@@ -131,6 +131,8 @@
               OnMetadataEndForStream,
               (Http2StreamId stream_id),
               (override));
+
+  MOCK_METHOD(void, OnErrorDebug, (absl::string_view message), (override));
 };
 
 }  // namespace test
diff --git a/http2/adapter/nghttp2_adapter_test.cc b/http2/adapter/nghttp2_adapter_test.cc
index 11f3921..4ca1fab 100644
--- a/http2/adapter/nghttp2_adapter_test.cc
+++ b/http2/adapter/nghttp2_adapter_test.cc
@@ -393,6 +393,10 @@
   EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
   EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
   EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+  EXPECT_CALL(
+      visitor,
+      OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
+                   "stream: 1, name: [:bad-status], value: [9000]"));
 
   // Bad status trailer will cause a PROTOCOL_ERROR. The header is never
   // delivered in an OnHeaderForStream callback.
diff --git a/http2/adapter/nghttp2_callbacks.cc b/http2/adapter/nghttp2_callbacks.cc
index d2c7e6d..c88dd8b 100644
--- a/http2/adapter/nghttp2_callbacks.cc
+++ b/http2/adapter/nghttp2_callbacks.cc
@@ -211,6 +211,14 @@
   return 0;
 }
 
+int OnError(nghttp2_session* session, int lib_error_code, const char* msg,
+            size_t len, void* user_data) {
+  QUICHE_CHECK_NE(user_data, nullptr);
+  auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+  visitor->OnErrorDebug(absl::string_view(msg, len));
+  return 0;
+}
+
 nghttp2_session_callbacks_unique_ptr Create() {
   nghttp2_session_callbacks* callbacks;
   nghttp2_session_callbacks_new(&callbacks);
@@ -230,6 +238,7 @@
   nghttp2_session_callbacks_set_before_frame_send_callback(callbacks,
                                                            &OnBeforeFrameSent);
   nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, &OnFrameSent);
+  nghttp2_session_callbacks_set_error_callback2(callbacks, &OnError);
   nghttp2_session_callbacks_set_send_data_callback(
       callbacks, &DataFrameSourceSendCallback);
   return MakeCallbacksPtr(callbacks);
diff --git a/http2/adapter/nghttp2_callbacks.h b/http2/adapter/nghttp2_callbacks.h
index 8f026fa..faa8f9a 100644
--- a/http2/adapter/nghttp2_callbacks.h
+++ b/http2/adapter/nghttp2_callbacks.h
@@ -55,6 +55,9 @@
 int OnStreamClosed(nghttp2_session* session, Http2StreamId stream_id,
                    uint32_t error_code, void* user_data);
 
+// Invoked when the library has an error message to deliver.
+int OnError(nghttp2_session* session, int lib_error_code, const char* msg,
+            size_t len, void* user_data);
 
 nghttp2_session_callbacks_unique_ptr Create();
 
diff --git a/http2/adapter/oghttp2_adapter_test.cc b/http2/adapter/oghttp2_adapter_test.cc
index 3ba26e4..82b70b0 100644
--- a/http2/adapter/oghttp2_adapter_test.cc
+++ b/http2/adapter/oghttp2_adapter_test.cc
@@ -133,7 +133,8 @@
   EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
 }
 
-// TODO(birenroy): Validate headers and re-enable this test.
+// TODO(birenroy): Validate headers and re-enable this test. The library should
+// invoke OnErrorDebug() with an error message for the invalid header.
 TEST(OgHttp2AdapterClientTest, DISABLED_ClientHandlesInvalidTrailers) {
   DataSavingVisitor visitor;
   OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
diff --git a/http2/adapter/recording_http2_visitor.cc b/http2/adapter/recording_http2_visitor.cc
index 15dce0c..a752e52 100644
--- a/http2/adapter/recording_http2_visitor.cc
+++ b/http2/adapter/recording_http2_visitor.cc
@@ -172,6 +172,10 @@
   events_.push_back(absl::StrFormat("OnMetadataEndForStream %d", stream_id));
 }
 
+void RecordingHttp2Visitor::OnErrorDebug(absl::string_view message) {
+  events_.push_back(absl::StrFormat("OnErrorDebug %s", message));
+}
+
 }  // namespace test
 }  // namespace adapter
 }  // namespace http2
diff --git a/http2/adapter/recording_http2_visitor.h b/http2/adapter/recording_http2_visitor.h
index 17c5c52..d286112 100644
--- a/http2/adapter/recording_http2_visitor.h
+++ b/http2/adapter/recording_http2_visitor.h
@@ -69,6 +69,7 @@
   void OnMetadataForStream(Http2StreamId stream_id,
                            absl::string_view metadata) override;
   void OnMetadataEndForStream(Http2StreamId stream_id) override;
+  void OnErrorDebug(absl::string_view message) override;
 
   const EventSequence& GetEventSequence() const { return events_; }
   void Clear() { events_.clear(); }