xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/first_flight.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/test_tools/first_flight.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "quiche/quic/core/crypto/quic_crypto_client_config.h"
11 #include "quiche/quic/core/http/quic_spdy_client_session.h"
12 #include "quiche/quic/core/quic_config.h"
13 #include "quiche/quic/core/quic_connection.h"
14 #include "quiche/quic/core/quic_connection_id.h"
15 #include "quiche/quic/core/quic_packet_writer.h"
16 #include "quiche/quic/core/quic_packets.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/core/quic_versions.h"
19 #include "quiche/quic/platform/api/quic_ip_address.h"
20 #include "quiche/quic/platform/api/quic_socket_address.h"
21 #include "quiche/quic/test_tools/crypto_test_utils.h"
22 #include "quiche/quic/test_tools/mock_connection_id_generator.h"
23 #include "quiche/quic/test_tools/quic_connection_peer.h"
24 #include "quiche/quic/test_tools/quic_test_utils.h"
25 
26 namespace quic {
27 namespace test {
28 
29 // Utility class that creates a custom HTTP/3 session and QUIC connection in
30 // order to extract the first flight of packets it sends. This is meant to only
31 // be used by GetFirstFlightOfPackets() below.
32 class FirstFlightExtractor : public DelegatedPacketWriter::Delegate {
33  public:
FirstFlightExtractor(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config)34   FirstFlightExtractor(const ParsedQuicVersion& version,
35                        const QuicConfig& config,
36                        const QuicConnectionId& server_connection_id,
37                        const QuicConnectionId& client_connection_id,
38                        std::unique_ptr<QuicCryptoClientConfig> crypto_config)
39       : version_(version),
40         server_connection_id_(server_connection_id),
41         client_connection_id_(client_connection_id),
42         writer_(this),
43         config_(config),
44         crypto_config_(std::move(crypto_config)) {
45     EXPECT_NE(version_, UnsupportedQuicVersion());
46   }
47 
FirstFlightExtractor(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id)48   FirstFlightExtractor(const ParsedQuicVersion& version,
49                        const QuicConfig& config,
50                        const QuicConnectionId& server_connection_id,
51                        const QuicConnectionId& client_connection_id)
52       : FirstFlightExtractor(
53             version, config, server_connection_id, client_connection_id,
54             std::make_unique<QuicCryptoClientConfig>(
55                 crypto_test_utils::ProofVerifierForTesting())) {}
56 
GenerateFirstFlight(QuicEcnCodepoint ecn=ECN_NOT_ECT)57   void GenerateFirstFlight(QuicEcnCodepoint ecn = ECN_NOT_ECT) {
58     crypto_config_->set_alpn(AlpnForVersion(version_));
59     connection_ = new QuicConnection(
60         server_connection_id_,
61         /*initial_self_address=*/QuicSocketAddress(),
62         QuicSocketAddress(TestPeerIPAddress(), kTestPort), &connection_helper_,
63         &alarm_factory_, &writer_,
64         /*owns_writer=*/false, Perspective::IS_CLIENT,
65         ParsedQuicVersionVector{version_}, connection_id_generator_);
66     if (ecn != ECN_NOT_ECT) {
67       QuicConnectionPeer::DisableEcnCodepointValidation(connection_);
68       connection_->set_ecn_codepoint(ecn);
69     }
70     connection_->set_client_connection_id(client_connection_id_);
71     session_ = std::make_unique<QuicSpdyClientSession>(
72         config_, ParsedQuicVersionVector{version_},
73         connection_,  // session_ takes ownership of connection_ here.
74         TestServerId(), crypto_config_.get());
75     session_->Initialize();
76     session_->CryptoConnect();
77   }
78 
OnDelegatedPacket(const char * buffer,size_t buf_len,const QuicIpAddress &,const QuicSocketAddress &,PerPacketOptions *,const QuicPacketWriterParams & params)79   void OnDelegatedPacket(const char* buffer, size_t buf_len,
80                          const QuicIpAddress& /*self_client_address*/,
81                          const QuicSocketAddress& /*peer_client_address*/,
82                          PerPacketOptions* /*options*/,
83                          const QuicPacketWriterParams& params) override {
84     packets_.emplace_back(
85         QuicReceivedPacket(buffer, buf_len,
86                            connection_helper_.GetClock()->ApproximateNow(),
87                            /*owns_buffer=*/false, /*ttl=*/0, /*ttl_valid=*/true,
88                            /*packet_headers=*/nullptr, /*headers_length=*/0,
89                            /*owns_header_buffer=*/false, params.ecn_codepoint)
90             .Clone());
91   }
92 
ConsumePackets()93   std::vector<std::unique_ptr<QuicReceivedPacket>>&& ConsumePackets() {
94     return std::move(packets_);
95   }
96 
GetCryptoStreamBytesWritten() const97   uint64_t GetCryptoStreamBytesWritten() const {
98     QUICHE_DCHECK(session_);
99     QUICHE_DCHECK(session_->GetCryptoStream());
100     return session_->GetCryptoStream()->BytesSentOnLevel(
101         EncryptionLevel::ENCRYPTION_INITIAL);
102   }
103 
104  private:
105   ParsedQuicVersion version_;
106   QuicConnectionId server_connection_id_;
107   QuicConnectionId client_connection_id_;
108   MockQuicConnectionHelper connection_helper_;
109   MockAlarmFactory alarm_factory_;
110   DelegatedPacketWriter writer_;
111   QuicConfig config_;
112   std::unique_ptr<QuicCryptoClientConfig> crypto_config_;
113   QuicConnection* connection_;  // Owned by session_.
114   std::unique_ptr<QuicSpdyClientSession> session_;
115   std::vector<std::unique_ptr<QuicReceivedPacket>> packets_;
116   MockConnectionIdGenerator connection_id_generator_;
117 };
118 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config,QuicEcnCodepoint ecn)119 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
120     const ParsedQuicVersion& version, const QuicConfig& config,
121     const QuicConnectionId& server_connection_id,
122     const QuicConnectionId& client_connection_id,
123     std::unique_ptr<QuicCryptoClientConfig> crypto_config,
124     QuicEcnCodepoint ecn) {
125   FirstFlightExtractor first_flight_extractor(
126       version, config, server_connection_id, client_connection_id,
127       std::move(crypto_config));
128   first_flight_extractor.GenerateFirstFlight(ecn);
129   return first_flight_extractor.ConsumePackets();
130 }
131 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config)132 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
133     const ParsedQuicVersion& version, const QuicConfig& config,
134     const QuicConnectionId& server_connection_id,
135     const QuicConnectionId& client_connection_id,
136     std::unique_ptr<QuicCryptoClientConfig> crypto_config) {
137   return GetFirstFlightOfPackets(version, config, server_connection_id,
138                                  client_connection_id, std::move(crypto_config),
139                                  ECN_NOT_ECT);
140 }
141 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id)142 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
143     const ParsedQuicVersion& version, const QuicConfig& config,
144     const QuicConnectionId& server_connection_id,
145     const QuicConnectionId& client_connection_id) {
146   FirstFlightExtractor first_flight_extractor(
147       version, config, server_connection_id, client_connection_id);
148   first_flight_extractor.GenerateFirstFlight();
149   return first_flight_extractor.ConsumePackets();
150 }
151 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id)152 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
153     const ParsedQuicVersion& version, const QuicConfig& config,
154     const QuicConnectionId& server_connection_id) {
155   return GetFirstFlightOfPackets(version, config, server_connection_id,
156                                  EmptyQuicConnectionId());
157 }
158 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config)159 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
160     const ParsedQuicVersion& version, const QuicConfig& config) {
161   return GetFirstFlightOfPackets(version, config, TestConnectionId());
162 }
163 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id)164 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
165     const ParsedQuicVersion& version,
166     const QuicConnectionId& server_connection_id,
167     const QuicConnectionId& client_connection_id) {
168   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
169                                  server_connection_id, client_connection_id);
170 }
171 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConnectionId & server_connection_id)172 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
173     const ParsedQuicVersion& version,
174     const QuicConnectionId& server_connection_id) {
175   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
176                                  server_connection_id, EmptyQuicConnectionId());
177 }
178 
GetFirstFlightOfPackets(const ParsedQuicVersion & version)179 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
180     const ParsedQuicVersion& version) {
181   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
182                                  TestConnectionId());
183 }
184 
GetAnnotatedFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config)185 AnnotatedPackets GetAnnotatedFirstFlightOfPackets(
186     const ParsedQuicVersion& version, const QuicConfig& config,
187     const QuicConnectionId& server_connection_id,
188     const QuicConnectionId& client_connection_id,
189     std::unique_ptr<QuicCryptoClientConfig> crypto_config) {
190   FirstFlightExtractor first_flight_extractor(
191       version, config, server_connection_id, client_connection_id,
192       std::move(crypto_config));
193   first_flight_extractor.GenerateFirstFlight();
194   return AnnotatedPackets{first_flight_extractor.ConsumePackets(),
195                           first_flight_extractor.GetCryptoStreamBytesWritten()};
196 }
197 
GetAnnotatedFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config)198 AnnotatedPackets GetAnnotatedFirstFlightOfPackets(
199     const ParsedQuicVersion& version, const QuicConfig& config) {
200   FirstFlightExtractor first_flight_extractor(
201       version, config, TestConnectionId(), EmptyQuicConnectionId());
202   first_flight_extractor.GenerateFirstFlight();
203   return AnnotatedPackets{first_flight_extractor.ConsumePackets(),
204                           first_flight_extractor.GetCryptoStreamBytesWritten()};
205 }
206 
207 }  // namespace test
208 }  // namespace quic
209