// Copyright (c) 2015 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.

// A base class for the toy client, which connects to a specified port and sends
// QUIC request to that endpoint.

#ifndef QUICHE_QUIC_TOOLS_QUIC_SPDY_CLIENT_BASE_H_
#define QUICHE_QUIC_TOOLS_QUIC_SPDY_CLIENT_BASE_H_

#include <string>

#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/crypto_handshake.h"
#include "quiche/quic/core/http/quic_spdy_client_session.h"
#include "quiche/quic/core/http/quic_spdy_client_stream.h"
#include "quiche/quic/core/quic_config.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/quic_client_base.h"
#include "quiche/common/http/http_header_block.h"

namespace quic {

class ProofVerifier;
class QuicServerId;
class SessionCache;

class QuicSpdyClientBase : public QuicClientBase,
                           public QuicSpdyStream::Visitor {
 public:
  // A ResponseListener is notified when a complete response is received.
  class ResponseListener {
   public:
    ResponseListener() {}
    virtual ~ResponseListener() {}
    virtual void OnCompleteResponse(
        QuicStreamId id, const quiche::HttpHeaderBlock& response_headers,
        absl::string_view response_body) = 0;
  };

  QuicSpdyClientBase(const QuicServerId& server_id,
                     const ParsedQuicVersionVector& supported_versions,
                     const QuicConfig& config,
                     QuicConnectionHelperInterface* helper,
                     QuicAlarmFactory* alarm_factory,
                     std::unique_ptr<NetworkHelper> network_helper,
                     std::unique_ptr<ProofVerifier> proof_verifier,
                     std::unique_ptr<SessionCache> session_cache);
  QuicSpdyClientBase(const QuicSpdyClientBase&) = delete;
  QuicSpdyClientBase& operator=(const QuicSpdyClientBase&) = delete;

  ~QuicSpdyClientBase() override;

  // QuicSpdyStream::Visitor
  void OnClose(QuicSpdyStream* stream) override;

  // A spdy session has to call CryptoConnect on top of the regular
  // initialization.
  void InitializeSession() override;

  // Sends an HTTP request and does not wait for response before returning.
  void SendRequest(const quiche::HttpHeaderBlock& headers,
                   absl::string_view body, bool fin);

  // Sends an HTTP request and waits for response before returning.
  void SendRequestAndWaitForResponse(const quiche::HttpHeaderBlock& headers,
                                     absl::string_view body, bool fin);

  // Sends a request simple GET for each URL in |url_list|, and then waits for
  // each to complete.
  void SendRequestsAndWaitForResponse(const std::vector<std::string>& url_list);

  // Returns a newly created QuicSpdyClientStream.
  virtual QuicSpdyClientStream* CreateClientStream();

  // Returns a the session used for this client downcasted to a
  // QuicSpdyClientSession.
  QuicSpdyClientSession* client_session();
  const QuicSpdyClientSession* client_session() const;

  void set_store_response(bool val) { store_response_ = val; }

  int latest_response_code() const;
  const std::string& latest_response_headers() const;
  const std::string& preliminary_response_headers() const;
  const quiche::HttpHeaderBlock& latest_response_header_block() const;
  const std::string& latest_response_body() const;
  const std::string& latest_response_trailers() const;

  QuicTime::Delta latest_ttlb() const { return latest_ttlb_; }
  QuicTime::Delta latest_ttfb() const { return latest_ttfb_; }

  void set_response_listener(std::unique_ptr<ResponseListener> listener) {
    response_listener_ = std::move(listener);
  }

  void set_drop_response_body(bool drop_response_body) {
    drop_response_body_ = drop_response_body;
  }
  bool drop_response_body() const { return drop_response_body_; }

  void set_enable_web_transport(bool enable_web_transport) {
    enable_web_transport_ = enable_web_transport;
  }
  bool enable_web_transport() const { return enable_web_transport_; }

  // QuicClientBase methods.
  bool goaway_received() const override;
  bool EarlyDataAccepted() override;
  bool ReceivedInchoateReject() override;

  std::optional<uint64_t> last_received_http3_goaway_id();

  void set_max_inbound_header_list_size(size_t size) {
    max_inbound_header_list_size_ = size;
  }

 protected:
  int GetNumSentClientHellosFromSession() override;
  int GetNumReceivedServerConfigUpdatesFromSession() override;

  // Takes ownership of |connection|.
  std::unique_ptr<QuicSession> CreateQuicClientSession(
      const quic::ParsedQuicVersionVector& supported_versions,
      QuicConnection* connection) override;

  bool HasActiveRequests() override;

 private:
  void SendRequestInternal(quiche::HttpHeaderBlock sanitized_headers,
                           absl::string_view body, bool fin);

  // If true, store the latest response code, headers, and body.
  bool store_response_;
  // HTTP response code from most recent response.
  int latest_response_code_;
  // HTTP/2 headers from most recent response.
  std::string latest_response_headers_;
  // preliminary 100 Continue HTTP/2 headers from most recent response, if any.
  std::string preliminary_response_headers_;
  // HTTP/2 headers from most recent response.
  quiche::HttpHeaderBlock latest_response_header_block_;
  // Body of most recent response.
  std::string latest_response_body_;
  // HTTP/2 trailers from most recent response.
  std::string latest_response_trailers_;

  QuicTime::Delta latest_ttfb_ = QuicTime::Delta::Infinite();
  QuicTime::Delta latest_ttlb_ = QuicTime::Delta::Infinite();

  // Listens for full responses.
  std::unique_ptr<ResponseListener> response_listener_;

  bool drop_response_body_ = false;
  bool enable_web_transport_ = false;
  // If not zero, used to set client's max inbound header size before session
  // initialize.
  size_t max_inbound_header_list_size_ = 0;
};

}  // namespace quic

#endif  // QUICHE_QUIC_TOOLS_QUIC_SPDY_CLIENT_BASE_H_
