|  | // 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_ |