Refactors error handling in PassthroughHeadersHandler.
Protected by refactoring, no functional change expected.
PiperOrigin-RevId: 611471355
diff --git a/quiche/http2/adapter/oghttp2_session.cc b/quiche/http2/adapter/oghttp2_session.cc
index 8f36e85..e12c9a4 100644
--- a/quiche/http2/adapter/oghttp2_session.cc
+++ b/quiche/http2/adapter/oghttp2_session.cc
@@ -216,12 +216,13 @@
}
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockStart() {
+ error_encountered_ = false;
result_ = Http2VisitorInterface::HEADER_OK;
const bool status = visitor_.OnBeginHeadersForStream(stream_id_);
if (!status) {
QUICHE_VLOG(1)
<< "Visitor rejected header block, returning HEADER_CONNECTION_ERROR";
- result_ = Http2VisitorInterface::HEADER_CONNECTION_ERROR;
+ SetResult(Http2VisitorInterface::HEADER_CONNECTION_ERROR);
}
validator_->StartHeaderBlock();
}
@@ -242,7 +243,7 @@
void OgHttp2Session::PassthroughHeadersHandler::OnHeader(
absl::string_view key, absl::string_view value) {
- if (result_ != Http2VisitorInterface::HEADER_OK) {
+ if (error_encountered_) {
QUICHE_VLOG(2) << "Early return; status not HEADER_OK";
return;
}
@@ -254,28 +255,31 @@
if (validation_result != HeaderValidator::HEADER_OK) {
QUICHE_VLOG(2) << "Header validation failed with result "
<< static_cast<int>(validation_result);
- result_ = InterpretHeaderStatus(validation_result);
+ SetResult(InterpretHeaderStatus(validation_result));
return;
}
- result_ = visitor_.OnHeaderForStream(stream_id_, key, value);
+ const Http2VisitorInterface::OnHeaderResult result =
+ visitor_.OnHeaderForStream(stream_id_, key, value);
+ SetResult(result);
}
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockEnd(
size_t /* uncompressed_header_bytes */,
size_t /* compressed_header_bytes */) {
- if (result_ == Http2VisitorInterface::HEADER_OK) {
+ const bool frame_contains_fin = frame_contains_fin_;
+ frame_contains_fin_ = false;
+ if (!error_encountered_) {
if (!validator_->FinishHeaderBlock(type_)) {
QUICHE_VLOG(1) << "FinishHeaderBlock returned false; returning "
- "HEADER_HTTP_MESSAGING";
- result_ = Http2VisitorInterface::HEADER_HTTP_MESSAGING;
+ << "HEADER_HTTP_MESSAGING";
+ SetResult(Http2VisitorInterface::HEADER_HTTP_MESSAGING);
}
}
- if (frame_contains_fin_ && IsResponse(type_) &&
- StatusIs1xx(status_header())) {
+ if (frame_contains_fin && IsResponse(type_) && StatusIs1xx(status_header())) {
QUICHE_VLOG(1) << "Unexpected end of stream without final headers";
- result_ = Http2VisitorInterface::HEADER_HTTP_MESSAGING;
+ SetResult(Http2VisitorInterface::HEADER_HTTP_MESSAGING);
}
- if (result_ == Http2VisitorInterface::HEADER_OK) {
+ if (!error_encountered_) {
const bool result = visitor_.OnEndHeadersForStream(stream_id_);
if (!result) {
session_.fatal_visitor_callback_failure_ = true;
@@ -284,7 +288,6 @@
} else {
session_.OnHeaderStatus(stream_id_, result_);
}
- frame_contains_fin_ = false;
}
// TODO(diannahu): Add checks for request methods.
@@ -306,6 +309,14 @@
return true;
}
+void OgHttp2Session::PassthroughHeadersHandler::SetResult(
+ Http2VisitorInterface::OnHeaderResult result) {
+ if (result != Http2VisitorInterface::HEADER_OK) {
+ error_encountered_ = true;
+ result_ = result;
+ }
+}
+
// A visitor that extracts an int64_t from each type of a ProcessBytesResult.
struct OgHttp2Session::ProcessBytesResultVisitor {
int64_t operator()(const int64_t bytes) const { return bytes; }
diff --git a/quiche/http2/adapter/oghttp2_session.h b/quiche/http2/adapter/oghttp2_session.h
index da88c68..25d3f9a 100644
--- a/quiche/http2/adapter/oghttp2_session.h
+++ b/quiche/http2/adapter/oghttp2_session.h
@@ -266,6 +266,7 @@
void set_stream_id(Http2StreamId stream_id) {
stream_id_ = stream_id;
+ error_encountered_ = false;
result_ = Http2VisitorInterface::HEADER_OK;
}
@@ -296,6 +297,8 @@
bool CanReceiveBody() const;
private:
+ void SetResult(Http2VisitorInterface::OnHeaderResult result);
+
OgHttp2Session& session_;
Http2VisitorInterface& visitor_;
Http2StreamId stream_id_ = 0;
@@ -305,6 +308,7 @@
std::unique_ptr<HeaderValidatorBase> validator_;
HeaderType type_ = HeaderType::RESPONSE;
bool frame_contains_fin_ = false;
+ bool error_encountered_ = false;
};
struct QUICHE_EXPORT ProcessBytesResultVisitor;