// Copyright 2025 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/masque/masque_ohttp_client.h"

#include <cstring>
#include <functional>
#include <iostream>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "openssl/base.h"
#include "quiche/quic/core/io/quic_default_event_loop.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_default_clock.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/masque/masque_connection_pool.h"
#include "quiche/quic/tools/quic_url.h"
#include "quiche/binary_http/binary_http_message.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_system_event_loop.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/common/quiche_status_utils.h"
#include "quiche/common/quiche_text_utils.h"
#include "quiche/oblivious_http/buffers/oblivious_http_request.h"
#include "quiche/oblivious_http/buffers/oblivious_http_response.h"
#include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"
#include "quiche/oblivious_http/oblivious_http_client.h"
#include <zlib.h>

#define ENDPOINT info_ << ": "

namespace quic {

using ::quic::MasqueConnectionPool;
using ::quic::QuicUrl;
using ::quiche::BinaryHttpRequest;
using ::quiche::BinaryHttpResponse;
using ::quiche::ChunkedObliviousHttpClient;
using ::quiche::ObliviousHttpClient;
using ::quiche::ObliviousHttpHeaderKeyConfig;
using ::quiche::ObliviousHttpKeyConfigs;
using ::quiche::ObliviousHttpRequest;
using ::quiche::ObliviousHttpResponse;
using RequestId = ::quic::MasqueConnectionPool::RequestId;
using Message = ::quic::MasqueConnectionPool::Message;

namespace {

static constexpr uint64_t kFixedSizeResponseFramingIndicator = 0x01;
// Buffer size for gzip decompression. 32KB chosen arbitrarily.
static constexpr size_t kGzipDecompressBufferSize = 32768;

absl::Status ParseHeadersIntoMap(
    const std::vector<std::string>& headers,
    std::vector<std::pair<std::string, std::string>>& headers_map) {
  for (const std::string& header : headers) {
    std::vector<absl::string_view> header_split =
        absl::StrSplit(header, absl::MaxSplits(':', 1));
    if (header_split.size() != 2) {
      return absl::InvalidArgumentError(
          absl::StrCat("Failed to parse header \"", header, "\""));
    }
    std::string header_name = std::string(header_split[0]);
    absl::StripAsciiWhitespace(&header_name);
    absl::AsciiStrToLower(&header_name);
    std::string header_value = std::string(header_split[1]);
    absl::StripAsciiWhitespace(&header_value);
    headers_map.push_back({std::move(header_name), std::move(header_value)});
  }
  return absl::OkStatus();
}

absl::StatusOr<std::vector<absl::string_view>> SplitIntoChunks(
    absl::string_view data, int num_chunks) {
  if (num_chunks <= 0) {
    return absl::InvalidArgumentError("num_chunks must be greater than 0");
  }
  if (data.size() < num_chunks) {
    return absl::InvalidArgumentError("data is smaller than num_chunks");
  }
  std::vector<absl::string_view> chunks;
  size_t offset = 0;
  for (size_t i = 0; i < num_chunks; ++i) {
    size_t end = (data.size() * (i + 1)) / num_chunks;
    chunks.push_back(data.substr(offset, end - offset));
    offset = end;
  }
  return chunks;
}

class PingPongResponseVisitor : public MasqueOhttpClient::ResponseVisitor {
 public:
  explicit PingPongResponseVisitor(std::vector<std::string> chunks,
                                   absl::string_view info_string)
      : chunks_(std::move(chunks)), info_(info_string) {}

  void OnRequestStarted(quic::MasqueConnectionPool::RequestId request_id,
                        MasqueOhttpClient* client) override {
    QUICHE_LOG(INFO) << ENDPOINT << "Ping-pong request " << request_id
                     << " started with " << chunks_.size() << " chunks";
    request_id_ = request_id;
    client_ = client;
    bool is_final = (chunks_.size() <= 1);
    status_ = client_->SendBodyChunk(request_id_, chunks_[0], is_final);
    if (!status_.ok()) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Ping-pong request " << request_id
                        << " failed to send first chunk: " << status_.message();
      done_ = true;
      return;
    }
    current_chunk_idx_ = 1;
    if (is_final) {
      QUICHE_LOG(INFO) << ENDPOINT << "Ping-pong request " << request_id
                       << " only had one chunk, marking as done";
      done_ = true;
    }
  }

  void OnResponseChunk(quic::MasqueConnectionPool::RequestId request_id,
                       absl::string_view chunk) override {
    QUICHE_DVLOG(1) << "Ping-pong request " << request_id
                    << " got response chunk #" << current_chunk_idx_
                    << " of length " << chunk.size();
    if (request_id != request_id_ || current_chunk_idx_ >= chunks_.size()) {
      return;
    }
    bool is_final = (current_chunk_idx_ == chunks_.size() - 1);
    status_ = client_->SendBodyChunk(request_id_, chunks_[current_chunk_idx_],
                                     is_final);
    if (!status_.ok()) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Ping-pong request " << request_id
                        << " failed to send chunk #" << current_chunk_idx_
                        << ": " << status_.message();
      done_ = true;
      return;
    }
    current_chunk_idx_++;
  }

  void OnResponseDone(quic::MasqueConnectionPool::RequestId request_id,
                      const MasqueOhttpClient::Message&) override {
    QUICHE_LOG(INFO) << ENDPOINT << "Ping-pong request done: " << request_id;
    if (request_id == request_id_) {
      done_ = true;
    }
  }

  void OnError(quic::MasqueConnectionPool::RequestId request_id,
               absl::Status status) override {
    QUICHE_LOG(ERROR) << ENDPOINT << "Ping-pong request " << request_id
                      << " got error: " << status.message();
    if (request_id == request_id_) {
      status_ = status;
      done_ = true;
    }
  }

  bool done() const { return done_; }
  absl::Status status() const { return status_; }

 private:
  MasqueOhttpClient* client_ = nullptr;
  std::vector<std::string> chunks_;
  size_t current_chunk_idx_ = 0;
  quic::MasqueConnectionPool::RequestId request_id_ = 0;
  bool done_ = false;
  absl::Status status_ = absl::OkStatus();
  const std::string info_;
};

absl::StatusOr<std::unique_ptr<PingPongResponseVisitor>>
CreateVisitorIfPingPong(const MasqueOhttpClient::Config& config,
                        absl::string_view info_string) {
  const MasqueOhttpClient::Config::PerRequestConfig* ping_pong_config = nullptr;

  for (const auto& req_config : config.per_request_configs()) {
    if (req_config.ping_pong_mode()) {
      ping_pong_config = &req_config;
      break;
    }
  }

  if (ping_pong_config == nullptr) {
    return nullptr;
  }

  if (config.per_request_configs().size() > 1) {
    return absl::InvalidArgumentError(
        "PingPong mode is exclusive and supports only one request at a time");
  }

  if (ping_pong_config->num_ohttp_chunks() <= 0) {
    return absl::InvalidArgumentError(
        "num_ohttp_chunks must be set and greater than 0 when "
        "ping_pong_mode is enabled");
  }

  std::string post_data = ping_pong_config->post_data();
  QUICHE_ASSIGN_OR_RETURN(
      std::vector<absl::string_view> chunks,
      SplitIntoChunks(post_data, ping_pong_config->num_ohttp_chunks()));

  std::vector<std::string> string_chunks;
  string_chunks.reserve(chunks.size());
  for (absl::string_view chunk : chunks) {
    string_chunks.push_back(std::string(chunk));
  }

  return std::make_unique<PingPongResponseVisitor>(std::move(string_chunks),
                                                   info_string);
}

}  // namespace

absl::StatusOr<GzipDecompressor::DecompressedData>
GzipDecompressor::InflateLoop(int flush) {
  int ret = Z_OK;
  std::string decompressed = "";
  std::vector<unsigned char> outbuffer(kGzipDecompressBufferSize);

  // Decompress the input in chunks until we reach the end of the stream or
  // need more input.
  do {
    stream_->next_out = outbuffer.data();
    stream_->avail_out = outbuffer.size();

    ret = inflate(stream_.get(), flush);

    if (ret != Z_OK && ret != Z_STREAM_END) {
      return absl::InternalError(absl::StrCat(
          "Gzip decompression failed with error code: ", ret,
          stream_->msg ? absl::StrCat(" (", stream_->msg, ")") : ""));
    }

    // Calculate how much data was placed in the buffer.
    size_t decompressed_size = outbuffer.size() - stream_->avail_out;
    decompressed.append(reinterpret_cast<char*>(outbuffer.data()),
                        decompressed_size);
  } while (stream_->avail_out == 0 && ret != Z_STREAM_END);

  return DecompressedData{ret, std::move(decompressed)};
}

absl::StatusOr<std::unique_ptr<GzipDecompressor>> GzipDecompressor::Create() {
  auto stream = std::make_unique<z_stream>();
  // z_stream fields must be explicitly initialized, as per the zlib
  // documentation.
  memset(stream.get(), 0, sizeof(z_stream));

  // Initialize zlib for gzip decompression.
  // 16 + MAX_WBITS tells zlib to expect a gzip header and trailer, which is
  // the expectation for valid HTTP responses with `Content-Encoding: gzip`.
  int inflate_result = inflateInit2(stream.get(), 16 + MAX_WBITS);
  if (inflate_result != Z_OK) {
    return absl::InternalError(
        absl::StrCat("Failed to initialize zlib for gzip decompression, error "
                     "code: ",
                     inflate_result));
  }

  return std::unique_ptr<GzipDecompressor>(
      new GzipDecompressor(std::move(stream)));
}

absl::StatusOr<std::string> GzipDecompressor::Decompress(
    absl::string_view input, bool end_stream) {
  if (stream_ == nullptr) {
    return absl::FailedPreconditionError("Decompression has already ended");
  }
  stream_->next_in =
      reinterpret_cast<unsigned char*>(const_cast<char*>(input.data()));
  stream_->avail_in = input.size();

  QUICHE_ASSIGN_OR_RETURN(DecompressedData decompressed_data,
                          InflateLoop(end_stream ? Z_FINISH : Z_NO_FLUSH));

  if (decompressed_data.status_code == Z_STREAM_END) {
    finished_ = true;
  }

  if (end_stream && !finished_) {
    return absl::InternalError(
        "Gzip decompression failed to reach end of stream");
  }
  return decompressed_data.data;
}

void GzipDecompressor::EndDecompression() {
  if (stream_ != nullptr) {
    inflateEnd(stream_.get());
    stream_.reset();
  }
}

absl::StatusOr<std::string> GzipDecompress(absl::string_view input) {
  QUICHE_ASSIGN_OR_RETURN(std::unique_ptr<GzipDecompressor> decompressor,
                          GzipDecompressor::Create());
  return decompressor->Decompress(input, /*end_stream=*/true);
}

std::string MasqueOhttpClient::Config::PerRequestConfig::method() const {
  if (method_.has_value()) {
    return *method_;
  }
  if (!post_data_.empty()) {
    return "POST";
  }
  return "GET";
}

absl::Status MasqueOhttpClient::Config::PerRequestConfig::AddHeaders(
    const std::vector<std::string>& headers) {
  return ParseHeadersIntoMap(headers, headers_);
}

absl::Status MasqueOhttpClient::Config::PerRequestConfig::AddOuterHeaders(
    const std::vector<std::string>& headers) {
  return ParseHeadersIntoMap(headers, outer_headers_);
}

absl::Status MasqueOhttpClient::Config::AddKeyFetchHeaders(
    const std::vector<std::string>& headers) {
  return ParseHeadersIntoMap(headers, key_fetch_headers_);
}

absl::Status MasqueOhttpClient::Config::PerRequestConfig::AddPrivateToken(
    const std::string& private_token) {
  // Private tokens require padded base64url and we allow any encoding for
  // convenience, so we need to unescape and re-escape.
  // https://www.rfc-editor.org/rfc/rfc9577#section-2.2.2
  std::string formatted_token;
  if (!absl::Base64Unescape(private_token, &formatted_token) &&
      !absl::WebSafeBase64Unescape(private_token, &formatted_token)) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid base64 encoding in private token: \"", private_token, "\""));
  }
  formatted_token = absl::Base64Escape(formatted_token);
  absl::StrReplaceAll({{"+", "-"}, {"/", "_"}}, &formatted_token);
  headers_.push_back({"authorization", absl::StrCat("PrivateToken token=\"",
                                                    formatted_token, "\"")});
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::Config::ConfigureKeyFetchClientCert(
    const std::string& client_cert_file,
    const std::string& client_cert_key_file) {
  QUICHE_ASSIGN_OR_RETURN(key_fetch_ssl_ctx_,
                          MasqueConnectionPool::CreateSslCtx(
                              client_cert_file, client_cert_key_file));
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::Config::ConfigureKeyFetchClientCertFromData(
    const std::string& client_cert_pem_data,
    const std::string& client_cert_key_data) {
  QUICHE_ASSIGN_OR_RETURN(key_fetch_ssl_ctx_,
                          MasqueConnectionPool::CreateSslCtxFromData(
                              client_cert_pem_data, client_cert_key_data));
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::Config::ConfigureOhttpMtls(
    const std::string& client_cert_file,
    const std::string& client_cert_key_file) {
  QUICHE_ASSIGN_OR_RETURN(
      ohttp_ssl_ctx_, MasqueConnectionPool::CreateSslCtx(client_cert_file,
                                                         client_cert_key_file));
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::Config::ConfigureOhttpMtlsFromData(
    const std::string& client_cert_pem_data,
    const std::string& client_cert_key_data) {
  QUICHE_ASSIGN_OR_RETURN(ohttp_ssl_ctx_,
                          MasqueConnectionPool::CreateSslCtxFromData(
                              client_cert_pem_data, client_cert_key_data));
  return absl::OkStatus();
}

bool MasqueOhttpClient::Config::skip_ohttp() const {
  static constexpr absl::string_view kSkip = "skip";
  return key_fetch_url_ == kSkip && relay_url_ == kSkip;
}

MasqueOhttpClient::MasqueOhttpClient(Config config,
                                     quic::QuicEventLoop* event_loop,
                                     absl::string_view info_string)
    : config_(std::move(config)),
      info_(info_string),
      connection_pool_(event_loop, config_.key_fetch_ssl_ctx(),
                       config_.disable_certificate_verification(),
                       config_.dns_config(), this, info_) {
  connection_pool_.SetMtlsSslCtx(config_.ohttp_ssl_ctx());
}

// static
absl::StatusOr<MasqueOhttpClient::RunDetails> MasqueOhttpClient::RunInner(
    Config config, absl::string_view info_string) {
  if (config.per_request_configs().empty()) {
    return absl::InvalidArgumentError("No OHTTP URLs to request");
  }
  if (config.key_fetch_ssl_ctx() == nullptr) {
    QUICHE_RETURN_IF_ERROR(config.ConfigureKeyFetchClientCert("", ""));
  }
  if (config.ohttp_ssl_ctx() == nullptr) {
    QUICHE_RETURN_IF_ERROR(config.ConfigureOhttpMtls("", ""));
  }
  QUICHE_ASSIGN_OR_RETURN(
      std::unique_ptr<PingPongResponseVisitor> ping_pong_visitor,
      CreateVisitorIfPingPong(config, info_string));

  quiche::QuicheSystemEventLoop system_event_loop("masque_ohttp_client");
  std::unique_ptr<QuicEventLoop> event_loop =
      GetDefaultEventLoop()->Create(QuicDefaultClock::Get());
  MasqueOhttpClient ohttp_client(std::move(config), event_loop.get(),
                                 info_string);
  if (ping_pong_visitor) {
    ohttp_client.set_response_visitor(ping_pong_visitor.get());
  }

  ohttp_client.Start();
  while (!ohttp_client.IsDone()) {
    if (ping_pong_visitor && ping_pong_visitor->done()) {
      if (!ping_pong_visitor->status().ok()) {
        ohttp_client.Abort(ping_pong_visitor->status());
      }
      break;
    }
    ohttp_client.connection_pool_.event_loop()->RunEventLoopOnce(
        quic::QuicTime::Delta::FromMilliseconds(50));
  }
  return std::move(ohttp_client.run_details_);
}

// static
MasqueOhttpClient::RunDetails MasqueOhttpClient::Run(
    Config config, absl::string_view info_string) {
  absl::StatusOr<MasqueOhttpClient::RunDetails> run_result =
      RunInner(std::move(config), info_string);
  if (!run_result.ok()) {
    RunDetails run_details;
    run_details.status = run_result.status();
    return run_details;
  }
  return *std::move(run_result);
}

void MasqueOhttpClient::Start() {
  absl::Status status = StartKeyFetch();
  if (!status.ok()) {
    Abort(status);
  }
}
bool MasqueOhttpClient::IsDone() {
  if (!run_details_.status.ok()) {
    return true;
  }
  if (!config_.skip_ohttp() && !ohttp_client_.has_value()) {
    // Key fetch request is still pending.
    return false;
  }
  return unstarted_requests_.empty() && pending_ohttp_requests_.empty();
}

void MasqueOhttpClient::Abort(absl::Status status) {
  QUICHE_CHECK(!status.ok());
  if (!run_details_.status.ok()) {
    QUICHE_LOG(ERROR)
        << ENDPOINT << "MasqueOhttpClient already aborted, ignoring new error: "
        << status.message();
    return;
  }
  run_details_.status = status;
  QUICHE_LOG(ERROR) << ENDPOINT
                    << "Aborting MasqueOhttpClient: " << status.message();
}

absl::StatusOr<QuicUrl> ParseUrl(const std::string& url_string) {
  QuicUrl url(url_string, "https");
  if (url.host().empty() && !absl::StrContains(url_string, "://")) {
    url = QuicUrl(absl::StrCat("https://", url_string));
  }
  if (url.host().empty()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to parse OHTTP key URL ", url_string));
  }
  return url;
}

absl::Status MasqueOhttpClient::StartKeyFetch() {
  if (config_.skip_ohttp()) {
    return HandleKeyData("");
  }
  std::string decoded_key_data;
  if (absl::HexStringToBytes(config_.key_fetch_url(), &decoded_key_data) &&
      !decoded_key_data.empty()) {
    return HandleKeyData(decoded_key_data);
  }
  QuicUrl url(config_.key_fetch_url(), "https");
  if (url.host().empty() &&
      !absl::StrContains(config_.key_fetch_url(), "://")) {
    url = QuicUrl(absl::StrCat("https://", config_.key_fetch_url()));
  }
  if (url.host().empty()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to parse OHTTP key URL \"", config_.key_fetch_url(), "\""));
  }
  Message request;
  request.headers[":method"] = "GET";
  request.headers[":scheme"] = url.scheme();
  request.headers[":authority"] = url.HostPort();
  request.headers[":path"] = url.PathParamsQuery();
  request.headers["accept"] = "application/ohttp-keys";
  for (const std::pair<std::string, std::string>& header :
       config_.key_fetch_headers()) {
    request.headers[header.first] = header.second;
  }

  absl::StatusOr<RequestId> request_id =
      connection_pool_.SendRequest(request, /*mtls=*/false);
  if (!request_id.ok()) {
    return absl::FailedPreconditionError(
        absl::StrCat("Failed to send OHTTP key fetch request: ",
                     request_id.status().message()));
  }
  key_fetch_request_id_ = *request_id;
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::CheckStatusAndContentType(
    const Message& response, const std::string& content_type,
    std::optional<uint16_t> expected_status_code) {
  int16_t status_code = MasqueConnectionPool::GetStatusCode(response);
  if (expected_status_code.has_value()) {
    if (status_code != *expected_status_code) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Unexpected status code in ", content_type,
          " response: ", status_code, ", expected: ", *expected_status_code));
    }
    if (*expected_status_code < 200 || *expected_status_code >= 300) {
      // If we expect a failure status code, skip the content-type check.
      return absl::OkStatus();
    }
  } else {
    if (status_code < 200 || status_code >= 300) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Bad status code in ", content_type, " response: ", status_code));
    }
  }
  auto content_type_it = response.headers.find("content-type");
  if (content_type_it == response.headers.end()) {
    return absl::InvalidArgumentError(
        absl::StrCat("No content-type header in ", content_type, " response."));
  }
  std::vector<absl::string_view> content_type_split =
      absl::StrSplit(content_type_it->second, absl::MaxSplits(';', 1));
  absl::string_view content_type_without_params = content_type_split[0];
  quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
      &content_type_without_params);
  if (content_type_without_params != content_type) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unexpected content-type in ", content_type,
                     " response: ", content_type_it->second));
  }
  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::CheckEncapsulatedStatus(
    const Message& response, std::optional<uint16_t> expected_status_code) {
  int16_t encapsulated_status_code =
      MasqueConnectionPool::GetStatusCode(response);
  absl::Status status = absl::OkStatus();
  if (expected_status_code.has_value()) {
    if (encapsulated_status_code != *expected_status_code) {
      status = absl::InvalidArgumentError(absl::StrCat(
          "Unexpected encapsulated status code: ", encapsulated_status_code,
          ", expected: ", *expected_status_code));
    }
  } else if (encapsulated_status_code < 200 ||
             encapsulated_status_code >= 300) {
    status = absl::InvalidArgumentError(absl::StrCat(
        "Bad encapsulated status code: ", encapsulated_status_code));
  }
  if (!status.ok() && !response.body.empty()) {
    QUICHE_LOG(INFO) << ENDPOINT << "Body:" << std::endl << response.body;
  }
  return status;
}

absl::Status MasqueOhttpClient::HandleKeyResponse(
    absl::StatusOr<Message>&& response) {
  key_fetch_request_id_ = std::nullopt;

  if (!response.ok()) {
    return absl::FailedPreconditionError(absl::StrCat(
        "Failed to fetch OHTTP keys: ", response.status().message()));
  }
  QUICHE_LOG(INFO) << ENDPOINT << "Received OHTTP keys response: "
                   << response->headers.DebugString();
  QUICHE_RETURN_IF_ERROR(CheckStatusAndContentType(
      *response, "application/ohttp-keys", std::nullopt));

  run_details_.key_fetch_response = std::move(*response);
  return HandleKeyData(run_details_.key_fetch_response.body);
}

absl::Status MasqueOhttpClient::HandleKeyData(const std::string& key_data) {
  if (config_.skip_ohttp()) {
    for (const auto& per_request_config : config_.per_request_configs()) {
      QUICHE_RETURN_IF_ERROR(SendDirectRequest(per_request_config));
    }
    return absl::OkStatus();
  }
  absl::StatusOr<ObliviousHttpKeyConfigs> key_configs =
      ObliviousHttpKeyConfigs::ParseConcatenatedKeys(key_data);
  if (!key_configs.ok()) {
    return absl::FailedPreconditionError(absl::StrCat(
        "Failed to parse OHTTP keys: ", key_configs.status().message()));
  }
  QUICHE_LOG(INFO) << ENDPOINT << "Successfully got " << key_configs->NumKeys()
                   << " OHTTP keys: " << std::endl
                   << key_configs->DebugString();
  if (config_.per_request_configs().empty()) {
    return absl::InvalidArgumentError("No OHTTP URLs to request, exiting.");
  }
  relay_url_ = QuicUrl(config_.relay_url(), "https");
  if (relay_url_.host().empty() &&
      !absl::StrContains(config_.relay_url(), "://")) {
    relay_url_ = QuicUrl(absl::StrCat("https://", config_.relay_url()));
  }
  QUICHE_LOG(INFO) << ENDPOINT << "Using relay URL: " << relay_url_.ToString();
  ObliviousHttpHeaderKeyConfig key_config = key_configs->PreferredConfig();
  if (key_configs->NumKeys() > 1) {
    QUICHE_LOG(INFO) << ENDPOINT << "Using key ID: "
                     << static_cast<int>(key_config.GetKeyId());
  }
  absl::StatusOr<absl::string_view> public_key =
      key_configs->GetPublicKeyForId(key_config.GetKeyId());
  if (!public_key.ok()) {
    return absl::InternalError(
        absl::StrCat("Failed to get OHTTP public key for key ID ",
                     static_cast<int>(key_config.GetKeyId()), ": ",
                     public_key.status().message()));
  }

  absl::StatusOr<ObliviousHttpClient> ohttp_client =
      ObliviousHttpClient::Create(*public_key, key_config);
  if (!ohttp_client.ok()) {
    return absl::InternalError(absl::StrCat("Failed to create OHTTP client: ",
                                            ohttp_client.status().message()));
  }
  ohttp_client_.emplace(std::move(*ohttp_client));

  bool first_request = true;
  for (size_t i = 0; i < config_.per_request_configs().size(); ++i) {
    if (first_request || config_.send_requests_in_parallel()) {
      QUICHE_RETURN_IF_ERROR(
          SendOhttpRequest(config_.per_request_configs()[i]));
      first_request = false;
    } else {
      unstarted_requests_.push_back(i);
    }
  }
  return absl::OkStatus();
}

void MasqueOhttpClient::MaybeStartNextRequest() {
  if (unstarted_requests_.empty()) {
    return;
  }
  absl::Status status = SendOhttpRequest(
      config_.per_request_configs()[unstarted_requests_.front()]);
  unstarted_requests_.pop_front();
  if (!status.ok()) {
    Abort(status);
  }
}

absl::Status MasqueOhttpClient::SendOhttpRequest(
    const Config::PerRequestConfig& per_request_config) {
  QuicUrl url(per_request_config.url(), "https");
  if (url.host().empty() &&
      !absl::StrContains(per_request_config.url(), "://")) {
    url = QuicUrl(absl::StrCat("https://", per_request_config.url()));
  }
  if (url.host().empty()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to parse URL ", per_request_config.url()));
  }
  BinaryHttpRequest::ControlData control_data;
  std::string post_data = per_request_config.post_data();
  control_data.method = per_request_config.method();
  control_data.scheme = url.scheme();
  control_data.authority = url.HostPort();
  control_data.path = url.PathParamsQuery();
  std::string encrypted_data;
  PendingRequest pending_request(per_request_config);
  if (!ohttp_client_.has_value()) {
    QUICHE_LOG(FATAL) << ENDPOINT
                      << "Cannot send OHTTP request without OHTTP client";
    return absl::InternalError(
        "Cannot send OHTTP request without OHTTP client");
  }
  std::string encoded_data;
  int num_bhttp_chunks = per_request_config.num_bhttp_chunks();
  if (num_bhttp_chunks < 0) {
    num_bhttp_chunks = (per_request_config.num_ohttp_chunks() > 0 ? 1 : 0);
  }
  if (num_bhttp_chunks > 0) {
    pending_request.encoder.emplace();
    QUICHE_ASSIGN_OR_RETURN(
        encoded_data, pending_request.encoder->EncodeControlData(control_data));
    std::vector<quiche::BinaryHttpMessage::FieldView> headers;
    for (const std::pair<std::string, std::string>& header :
         per_request_config.headers()) {
      headers.push_back({header.first, header.second});
    }
    if (config_.handle_gzip_response()) {
      headers.push_back({"accept-encoding", "gzip"});
    }
    QUICHE_ASSIGN_OR_RETURN(
        std::string encoded_headers,
        pending_request.encoder->EncodeHeaders(absl::MakeSpan(headers)));
    encoded_data += encoded_headers;
    if (!per_request_config.ping_pong_mode()) {
      if (!post_data.empty()) {
        QUICHE_ASSIGN_OR_RETURN(std::vector<absl::string_view> body_chunks,
                                SplitIntoChunks(post_data, num_bhttp_chunks));
        QUICHE_ASSIGN_OR_RETURN(std::string encoded_body,
                                pending_request.encoder->EncodeBodyChunks(
                                    absl::MakeSpan(body_chunks),
                                    /*body_chunks_done=*/false));
        encoded_data += encoded_body;
      }
      QUICHE_ASSIGN_OR_RETURN(std::string encoded_final_chunk,
                              pending_request.encoder->EncodeBodyChunks(
                                  {}, /*body_chunks_done=*/true));
      encoded_data += encoded_final_chunk;
      std::vector<quiche::BinaryHttpMessage::FieldView> trailers;
      QUICHE_ASSIGN_OR_RETURN(
          std::string encoded_trailers,
          pending_request.encoder->EncodeTrailers(absl::MakeSpan(trailers)));
      encoded_data += encoded_trailers;
    }
  } else {
    BinaryHttpRequest binary_request(control_data);
    for (const std::pair<std::string, std::string>& header :
         per_request_config.headers()) {
      binary_request.AddHeaderField({header.first, header.second});
    }
    if (config_.handle_gzip_response()) {
      binary_request.AddHeaderField({"accept-encoding", "gzip"});
    }
    binary_request.set_body(post_data);
    QUICHE_ASSIGN_OR_RETURN(encoded_data, binary_request.Serialize());
  }
  int num_ohttp_chunks = per_request_config.num_ohttp_chunks();
  if (num_ohttp_chunks > 0) {
    pending_request.chunk_handler =
        std::make_unique<ChunkHandler>(config_.handle_gzip_response(), info_);
    QUICHE_ASSIGN_OR_RETURN(
        ChunkedObliviousHttpClient chunked_client,
        ChunkedObliviousHttpClient::Create(
            ohttp_client_->GetPublicKey(), ohttp_client_->GetKeyConfig(),
            pending_request.chunk_handler.get()));
    QUICHE_ASSIGN_OR_RETURN(std::vector<absl::string_view> ohttp_chunks,
                            SplitIntoChunks(encoded_data, num_ohttp_chunks));

    for (size_t i = 0; i < ohttp_chunks.size(); i++) {
      bool is_final_chunk = (i == ohttp_chunks.size() - 1 &&
                             !per_request_config.ping_pong_mode());
      QUICHE_ASSIGN_OR_RETURN(
          std::string ohttp_chunk,
          chunked_client.EncryptRequestChunk(ohttp_chunks[i], is_final_chunk));
      encrypted_data += ohttp_chunk;
    }

    pending_request.chunk_handler->SetChunkedClient(std::move(chunked_client));
  } else {
    QUICHE_ASSIGN_OR_RETURN(
        ObliviousHttpRequest ohttp_request,
        ohttp_client_->CreateObliviousHttpRequest(encoded_data));
    encrypted_data = ohttp_request.EncapsulateAndSerialize();
    pending_request.context.emplace(std::move(ohttp_request).ReleaseContext());
  }
  Message request;
  request.headers[":method"] = "POST";
  request.headers[":scheme"] = relay_url_.scheme();
  request.headers[":authority"] = relay_url_.HostPort();
  request.headers[":path"] = relay_url_.PathParamsQuery();
  request.headers["content-type"] =
      num_ohttp_chunks > 0 ? "message/ohttp-chunked-req" : "message/ohttp-req";
  for (const std::pair<std::string, std::string>& header :
       per_request_config.outer_headers()) {
    request.headers[header.first] = header.second;
  }
  QUICHE_VLOG(1) << "Sending encrypted request: "
                 << absl::BytesToHexString(encrypted_data);
  request.body = encrypted_data;
  bool end_stream =
      num_ohttp_chunks <= 0 || !per_request_config.ping_pong_mode();
  bool stream_response = num_ohttp_chunks > 0;
  absl::StatusOr<RequestId> request_id = connection_pool_.SendRequest(
      request, /*mtls=*/true, end_stream, stream_response);
  if (!request_id.ok()) {
    return absl::InternalError(absl::StrCat("Failed to send OHTTP request: ",
                                            request_id.status().message()));
  }

  QUICHE_LOG(INFO) << ENDPOINT << "Sent OHTTP request for "
                   << per_request_config.url();

  if (pending_request.chunk_handler) {
    pending_request.chunk_handler->SetResponseChunkCallback(
        [this, request_id = *request_id](absl::string_view chunk) {
          if (response_visitor_) {
            response_visitor_->OnResponseChunk(request_id, chunk);
          }
        });
  }
  pending_ohttp_requests_.insert({*request_id, std::move(pending_request)});

  if (response_visitor_) {
    response_visitor_->OnRequestStarted(*request_id, this);
  }

  return absl::OkStatus();
}

absl::Status MasqueOhttpClient::SendDirectRequest(
    const Config::PerRequestConfig& per_request_config) {
  QuicUrl url(per_request_config.url(), "https");
  if (url.host().empty() &&
      !absl::StrContains(per_request_config.url(), "://")) {
    url = QuicUrl(absl::StrCat("https://", per_request_config.url()));
  }
  if (url.host().empty()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to parse URL ", per_request_config.url()));
  }
  Message request;
  std::string post_data = per_request_config.post_data();
  request.headers[":method"] = per_request_config.method();
  request.headers[":scheme"] = url.scheme();
  request.headers[":authority"] = url.HostPort();
  request.headers[":path"] = url.PathParamsQuery();
  if (config_.handle_gzip_response()) {
    request.headers["accept-encoding"] = "gzip";
  }
  for (const std::pair<std::string, std::string>& header :
       per_request_config.headers()) {
    request.headers[header.first] = header.second;
  }
  request.body = per_request_config.post_data();
  absl::StatusOr<RequestId> request_id = connection_pool_.SendRequest(
      request, /*mtls=*/true, /*end_stream=*/true, /*stream_response=*/false);
  if (!request_id.ok()) {
    return absl::InternalError(absl::StrCat("Failed to send direct request: ",
                                            request_id.status().message()));
  }

  QUICHE_LOG(INFO) << ENDPOINT << "Sent direct request for "
                   << per_request_config.url();

  pending_ohttp_requests_.insert(
      {*request_id, PendingRequest(per_request_config)});

  return absl::OkStatus();
}

absl::StatusOr<Message> MasqueOhttpClient::TryExtractEncapsulatedResponse(
    RequestId request_id, quiche::ObliviousHttpRequest::Context& context,
    const Message& response) {
  if (!ohttp_client_.has_value()) {
    QUICHE_LOG(FATAL) << "Received OHTTP response without OHTTP client";
    return absl::InternalError("Received OHTTP response without OHTTP client");
  }
  QUICHE_ASSIGN_OR_RETURN(
      ObliviousHttpResponse ohttp_response,
      ohttp_client_->DecryptObliviousHttpResponse(response.body, context));
  QUICHE_LOG(INFO) << ENDPOINT << "Received OHTTP response for " << request_id;
  QUICHE_VLOG(2) << "Decrypted unchunked response body: "
                 << absl::BytesToHexString(ohttp_response.GetPlaintextData());
  quiche::QuicheDataReader reader(ohttp_response.GetPlaintextData());
  uint64_t framing_indicator;
  if (!reader.ReadVarInt62(&framing_indicator)) {
    return absl::InvalidArgumentError(
        "Failed to read framing indicator for unchunked response");
  }
  if (framing_indicator == kFixedSizeResponseFramingIndicator) {
    absl::StatusOr<BinaryHttpResponse> binary_response =
        BinaryHttpResponse::Create(ohttp_response.GetPlaintextData());
    QUICHE_RETURN_IF_ERROR(binary_response.status());
    Message encapsulated_response;
    encapsulated_response.headers[":status"] =
        absl::StrCat(binary_response->status_code());
    for (const quiche::BinaryHttpMessage::Field& field :
         binary_response->GetHeaderFields()) {
      encapsulated_response.headers[field.name] = field.value;
    }
    encapsulated_response.body = binary_response->body();
    return encapsulated_response;
  }
  ChunkHandler chunk_handler(config_.handle_gzip_response(), info_);
  chunk_handler.SetResponseChunkCallback(
      [this, request_id](absl::string_view chunk) {
        if (response_visitor_) {
          response_visitor_->OnResponseChunk(request_id, chunk);
        }
      });
  QUICHE_RETURN_IF_ERROR(
      chunk_handler.OnDecryptedChunk(ohttp_response.GetPlaintextData()));
  QUICHE_RETURN_IF_ERROR(chunk_handler.OnChunksDone());
  QUICHE_ASSIGN_OR_RETURN(ChunkedObliviousHttpClient chunked_client,
                          ChunkedObliviousHttpClient::Create(
                              ohttp_client_->GetPublicKey(),
                              ohttp_client_->GetKeyConfig(), &chunk_handler));
  QUICHE_RETURN_IF_ERROR(
      chunked_client.DecryptResponse(ohttp_response.GetPlaintextData(),
                                     /*end_stream=*/true));
  return std::move(chunk_handler).ExtractResponse();
}

absl::Status MasqueOhttpClient::ProcessOhttpResponse(
    RequestId request_id, absl::StatusOr<Message>&& response, bool end_stream) {
  auto it = pending_ohttp_requests_.find(request_id);
  if (it == pending_ohttp_requests_.end()) {
    return absl::InternalError(absl::StrCat(
        "Received unexpected response for unknown request ", request_id));
  }
  auto cleanup = absl::MakeCleanup([this, it, end_stream]() {
    if (end_stream) {
      pending_ohttp_requests_.erase(it);
      MaybeStartNextRequest();
    }
  });
  if (!response.ok()) {
    if (it->second.per_request_config.expected_gateway_error().has_value()) {
      std::string expected_errors =
          *it->second.per_request_config.expected_gateway_error();
      std::vector<absl::string_view> expected_error_parts =
          absl::StrSplit(expected_errors, '|');
      for (const absl::string_view expected_error : expected_error_parts) {
        if (absl::StrContains(response.status().message(), expected_error)) {
          return absl::OkStatus();
        }
      }
    }
    return response.status();
  }
  run_details_.ohttp_responses.push_back(RunDetails::OhttpResponse{});
  if (config_.skip_ohttp()) {
    return ProcessEncapsulatedResponse(request_id, *response,
                                       it->second.per_request_config);
  }
  run_details_.ohttp_responses.back().gateway_response = std::move(*response);
  Message& resp = run_details_.ohttp_responses.back().gateway_response;
  std::string content_type =
      it->second.per_request_config.num_ohttp_chunks() > 0
          ? "message/ohttp-chunked-res"
          : "message/ohttp-res";
  std::optional<uint16_t> expected_gateway_status_code =
      it->second.per_request_config.expected_gateway_status_code();
  absl::Status status = CheckStatusAndContentType(resp, content_type,
                                                  expected_gateway_status_code);
  if (!status.ok()) {
    if (!resp.body.empty()) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Bad " << content_type
                        << " with body:" << std::endl
                        << resp.body;
    } else {
      QUICHE_LOG(ERROR) << ENDPOINT << "Bad " << content_type
                        << " with empty body";
    }
    return status;
  }
  if (expected_gateway_status_code.has_value() &&
      (*expected_gateway_status_code < 200 ||
       *expected_gateway_status_code >= 300)) {
    // If we expect a failure status code, skip decapsulation.
    return absl::OkStatus();
  }

  if (!end_stream) {
    // We delivered headers. For chunked OHTTP, we just wait for data chunks.
    if (it->second.per_request_config.num_ohttp_chunks() <= 0) {
      QUICHE_LOG(ERROR) << ENDPOINT
                        << "Received partial response for non-chunked OHTTP";
      return absl::InternalError(
          "Received partial response for non-chunked OHTTP");
    }
    return absl::OkStatus();
  }

  std::optional<Message> encapsulated_response;
  QUICHE_VLOG(2) << "Received encrypted response body: "
                 << absl::BytesToHexString(resp.body);
  if (it->second.per_request_config.num_ohttp_chunks() > 0) {
    absl::Status decrypt_status = it->second.chunk_handler->DecryptChunk(
        /*encrypted_chunk=*/"", /*end_stream=*/true);
    if (!decrypt_status.ok()) {
      return decrypt_status;
    }
    encapsulated_response =
        std::move(*it->second.chunk_handler).ExtractResponse();
  } else {
    if (!it->second.context.has_value()) {
      QUICHE_LOG(FATAL) << "Received OHTTP response without OHTTP context";
      return absl::InternalError(
          "Received OHTTP response without OHTTP context");
    }
    QUICHE_ASSIGN_OR_RETURN(
        encapsulated_response,
        TryExtractEncapsulatedResponse(request_id, *it->second.context, resp));
  }
  QUICHE_LOG(INFO) << ENDPOINT
                   << "Successfully decapsulated response for request ID "
                   << request_id << ". Body length is "
                   << encapsulated_response->body.size() << ". Headers:"
                   << encapsulated_response->headers.DebugString();

  return ProcessEncapsulatedResponse(request_id, *encapsulated_response,
                                     it->second.per_request_config);
}

absl::Status MasqueOhttpClient::ProcessEncapsulatedResponse(
    RequestId request_id, Message& response,
    const Config::PerRequestConfig& per_request_config) {
  run_details_.ohttp_responses.back().encapsulated_response =
      std::move(response);
  Message& resp = run_details_.ohttp_responses.back().encapsulated_response;
  if (config_.handle_gzip_response()) {
    auto content_encoding_it = resp.headers.find("content-encoding");
    if (content_encoding_it != resp.headers.end() &&
        absl::EqualsIgnoreCase(content_encoding_it->second, "gzip")) {
      size_t compressed_size = resp.body.size();
      QUICHE_ASSIGN_OR_RETURN(std::string decompressed_body,
                              GzipDecompress(resp.body));
      QUICHE_LOG(INFO) << ENDPOINT
                       << "Successfully decompressed gzip response from size "
                       << compressed_size << " to size "
                       << decompressed_body.size();
      resp.body = std::move(decompressed_body);
    }
  }
  std::cout << resp.body;
  if (!resp.body.empty() && resp.body[resp.body.size() - 1] != '\n') {
    std::cout << std::endl;
  }
  QUICHE_RETURN_IF_ERROR(CheckEncapsulatedStatus(
      resp, per_request_config.expected_encapsulated_status_code()));
  if (const auto& callback =
          per_request_config.encapsulated_response_body_callback();
      callback) {
    QUICHE_RETURN_IF_ERROR(callback(resp.body));
  }

  if (response_visitor_) {
    response_visitor_->OnResponseDone(request_id, resp);
  }

  return absl::OkStatus();
}

void MasqueOhttpClient::OnPoolResponse(MasqueConnectionPool* /*pool*/,
                                       RequestId request_id,
                                       absl::StatusOr<Message>&& response,
                                       bool end_stream) {
  if (key_fetch_request_id_.has_value() &&
      *key_fetch_request_id_ == request_id) {
    absl::Status status = HandleKeyResponse(std::move(response));
    if (!status.ok()) {
      Abort(status);
    }
  } else {
    absl::Status status =
        ProcessOhttpResponse(request_id, std::move(response), end_stream);
    if (!status.ok()) {
      Abort(status);
      if (response_visitor_) {
        response_visitor_->OnError(request_id, status);
      }
    }
  }
}

void MasqueOhttpClient::OnPoolData(MasqueConnectionPool* /*pool*/,
                                   RequestId request_id, absl::string_view data,
                                   bool end_stream) {
  if (key_fetch_request_id_.has_value() &&
      *key_fetch_request_id_ == request_id) {
    Abort(absl::InternalError(absl::StrCat(
        "Received data for non-streamed key fetch request ", request_id)));
    return;
  }
  auto it = pending_ohttp_requests_.find(request_id);
  if (it == pending_ohttp_requests_.end()) {
    Abort(absl::InternalError(absl::StrCat(
        "Received data for unknown or non-OHTTP request: ", request_id)));
    return;
  }
  PendingRequest& pending_request = it->second;

  if (!pending_request.chunk_handler) {
    Abort(absl::InternalError(
        absl::StrCat("Received data for non-streamed request ", request_id)));
    return;
  }

  auto cleanup = absl::MakeCleanup([this, it, end_stream]() {
    if (end_stream) {
      pending_ohttp_requests_.erase(it);
      MaybeStartNextRequest();
    }
  });

  absl::Status status =
      pending_request.chunk_handler->DecryptChunk(data, end_stream);
  if (!status.ok()) {
    Abort(status);
    if (response_visitor_) {
      response_visitor_->OnError(request_id, status);
    }
    return;
  }
  if (end_stream) {
    Message response =
        std::move(*pending_request.chunk_handler).ExtractResponse();
    status = CheckEncapsulatedStatus(
        response,
        pending_request.per_request_config.expected_encapsulated_status_code());
    if (!status.ok()) {
      Abort(status);
      if (response_visitor_) {
        response_visitor_->OnError(request_id, status);
      }
      return;
    }

    if (const auto& callback = pending_request.per_request_config
                                   .encapsulated_response_body_callback();
        callback) {
      status = callback(response.body);
      if (!status.ok()) {
        Abort(status);
        if (response_visitor_) {
          response_visitor_->OnError(request_id, status);
        }
        return;
      }
    }
    if (response_visitor_) {
      response_visitor_->OnResponseDone(request_id, response);
    }
  }
}

absl::Status MasqueOhttpClient::SendBodyChunk(RequestId request_id,
                                              absl::string_view chunk,
                                              bool is_final) {
  if (chunk.empty() && !is_final) {
    return absl::OkStatus();
  }
  auto it = pending_ohttp_requests_.find(request_id);
  if (it == pending_ohttp_requests_.end()) {
    return absl::NotFoundError(
        absl::StrCat("Request ", request_id, " not found"));
  }
  PendingRequest& pending_request = it->second;
  if (!pending_request.encoder.has_value()) {
    if (!chunk.empty()) {
      return absl::FailedPreconditionError(
          "Cannot send non-empty body chunks for known-length requests");
    }
    std::string encoded_data;
    auto& chunked_client = pending_request.chunk_handler->chunked_client();
    if (!chunked_client.has_value()) {
      return absl::FailedPreconditionError("Chunked client not initialized");
    }
    QUICHE_ASSIGN_OR_RETURN(
        std::string encrypted_chunk,
        chunked_client->EncryptRequestChunk(encoded_data, is_final));
    return connection_pool_.SendBodyChunk(request_id, encrypted_chunk,
                                          is_final);
  }

  std::string encoded_data;
  std::vector<absl::string_view> body_chunks;
  if (!chunk.empty()) {
    body_chunks.push_back(chunk);
  }

  QUICHE_ASSIGN_OR_RETURN(
      encoded_data,
      pending_request.encoder->EncodeBodyChunks(absl::MakeSpan(body_chunks),
                                                /*body_chunks_done=*/is_final));

  if (is_final) {
    std::vector<quiche::BinaryHttpMessage::FieldView> trailers;
    QUICHE_ASSIGN_OR_RETURN(
        std::string encoded_trailers,
        pending_request.encoder->EncodeTrailers(absl::MakeSpan(trailers)));
    encoded_data += encoded_trailers;
  }

  auto& chunked_client = pending_request.chunk_handler->chunked_client();
  if (!chunked_client.has_value()) {
    return absl::FailedPreconditionError("Chunked client not initialized");
  }

  QUICHE_ASSIGN_OR_RETURN(
      std::string encrypted_chunk,
      chunked_client->EncryptRequestChunk(encoded_data, is_final));

  return connection_pool_.SendBodyChunk(request_id, encrypted_chunk, is_final);
}

absl::Status MasqueOhttpClient::ChunkHandler::DecryptChunk(
    absl::string_view encrypted_chunk, bool end_stream) {
  if (!chunked_client_.has_value()) {
    QUICHE_LOG(FATAL) << "DecryptChunk called without a chunked client";
    return absl::InternalError("DecryptChunk called without a chunked client");
  }
  return chunked_client_->DecryptResponse(encrypted_chunk, end_stream);
}

absl::Status MasqueOhttpClient::ChunkHandler::OnDecryptedChunk(
    absl::string_view decrypted_chunk) {
  decrypted_chunk_count_++;
  QUICHE_LOG(INFO) << ENDPOINT << "Received decrypted chunk #"
                   << decrypted_chunk_count_ << " of size "
                   << decrypted_chunk.size();
  absl::StrAppend(&buffered_binary_response_, decrypted_chunk);
  if (!is_chunked_response_.has_value()) {
    quiche::QuicheDataReader reader(buffered_binary_response_);
    uint64_t framing_indicator;
    if (!reader.ReadVarInt62(&framing_indicator)) {
      // Not enough data to read the framing indicator yet.
      return absl::OkStatus();
    }
    is_chunked_response_ =
        framing_indicator != kFixedSizeResponseFramingIndicator;
  }
  if (*is_chunked_response_) {
    return decoder_.Decode(decrypted_chunk, /*end_stream=*/false);
  } else {
    // Buffer and wait for OnChunksDone().
    return absl::OkStatus();
  }
}
absl::Status MasqueOhttpClient::ChunkHandler::OnChunksDone() {
  QUICHE_VLOG(2) << "Decrypted chunked response body: "
                 << absl::BytesToHexString(buffered_binary_response_);
  if (!is_chunked_response_.has_value()) {
    return absl::InvalidArgumentError(
        "OnChunksDone called without framing indicator");
  }
  if (*is_chunked_response_) {
    return decoder_.Decode("", /*end_stream=*/true);
  } else {
    absl::StatusOr<BinaryHttpResponse> binary_response =
        BinaryHttpResponse::Create(buffered_binary_response_);
    QUICHE_RETURN_IF_ERROR(binary_response.status());
    response_.headers[":status"] = absl::StrCat(binary_response->status_code());
    for (const quiche::BinaryHttpMessage::Field& field :
         binary_response->GetHeaderFields()) {
      response_.headers[field.name] = field.value;
    }
    response_.body = binary_response->body();
    return absl::OkStatus();
  }
}

absl::Status MasqueOhttpClient::ChunkHandler::OnInformationalResponseStatusCode(
    uint16_t status_code) {
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnInformationalResponseHeader(
    absl::string_view name, absl::string_view value) {
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnInformationalResponseDone() {
  return absl::OkStatus();
}
absl::Status
MasqueOhttpClient::ChunkHandler::OnInformationalResponsesSectionDone() {
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnFinalResponseStatusCode(
    uint16_t status_code) {
  response_.headers[":status"] = absl::StrCat(status_code);
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnFinalResponseHeader(
    absl::string_view name, absl::string_view value) {
  response_.headers[name] = value;
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnFinalResponseHeadersDone() {
  QUICHE_LOG(INFO) << ENDPOINT << "Received chunked OHTTP response headers: "
                   << response_.headers.DebugString();
  if (handle_gzip_response_) {
    auto it = response_.headers.find("content-encoding");
    if (it != response_.headers.end() &&
        absl::EqualsIgnoreCase(it->second, "gzip")) {
      is_gzipped_ = true;
    }
  }
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnBodyChunk(
    absl::string_view body_chunk) {
  body_chunk_count_++;
  QUICHE_LOG(INFO) << ENDPOINT << "Received body chunk #" << body_chunk_count_
                   << " of size " << body_chunk.size();

  if (body_chunk.empty()) {
    return absl::OkStatus();
  }

  std::string decompressed = "";
  absl::string_view processed_chunk = body_chunk;
  if (is_gzipped_) {
    if (!decompressor_) {
      QUICHE_ASSIGN_OR_RETURN(decompressor_, GzipDecompressor::Create());
    }
    QUICHE_ASSIGN_OR_RETURN(
        decompressed,
        decompressor_->Decompress(body_chunk, /*end_stream=*/false));
    processed_chunk = decompressed;
    QUICHE_LOG(INFO) << ENDPOINT << "Decompressed chunk to size "
                     << processed_chunk.size();
    if (processed_chunk.empty()) {
      return absl::OkStatus();
    }
  }

  std::cout << processed_chunk << std::flush;
  last_chunk_ended_without_newline_ =
      !processed_chunk.empty() &&
      processed_chunk[processed_chunk.size() - 1] != '\n';

  response_.body += processed_chunk;

  if (response_chunk_callback_) {
    response_chunk_callback_(processed_chunk);
  }

  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnBodyChunksDone() {
  if (decompressor_ != nullptr) {
    if (!decompressor_->IsFinished()) {
      return absl::InternalError("Gzip stream truncated");
    }
    decompressor_->EndDecompression();
  }
  if (last_chunk_ended_without_newline_) {
    std::cout << std::endl;
  }
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnTrailer(
    absl::string_view name, absl::string_view value) {
  return absl::OkStatus();
}
absl::Status MasqueOhttpClient::ChunkHandler::OnTrailersDone() {
  return absl::OkStatus();
}

}  // namespace quic

#undef ENDPOINT
