• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_client_push_promise_index.h"
12 #include "quiche/quic/core/http/quic_spdy_client_session.h"
13 #include "quiche/quic/core/quic_config.h"
14 #include "quiche/quic/core/quic_connection.h"
15 #include "quiche/quic/core/quic_connection_id.h"
16 #include "quiche/quic/core/quic_packet_writer.h"
17 #include "quiche/quic/core/quic_packets.h"
18 #include "quiche/quic/core/quic_types.h"
19 #include "quiche/quic/core/quic_versions.h"
20 #include "quiche/quic/platform/api/quic_ip_address.h"
21 #include "quiche/quic/platform/api/quic_socket_address.h"
22 #include "quiche/quic/test_tools/crypto_test_utils.h"
23 #include "quiche/quic/test_tools/mock_connection_id_generator.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()57   void GenerateFirstFlight() {
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     connection_->set_client_connection_id(client_connection_id_);
67     session_ = std::make_unique<QuicSpdyClientSession>(
68         config_, ParsedQuicVersionVector{version_},
69         connection_,  // session_ takes ownership of connection_ here.
70         TestServerId(), crypto_config_.get(), &push_promise_index_);
71     session_->Initialize();
72     session_->CryptoConnect();
73   }
74 
OnDelegatedPacket(const char * buffer,size_t buf_len,const QuicIpAddress &,const QuicSocketAddress &,PerPacketOptions *)75   void OnDelegatedPacket(const char* buffer, size_t buf_len,
76                          const QuicIpAddress& /*self_client_address*/,
77                          const QuicSocketAddress& /*peer_client_address*/,
78                          PerPacketOptions* /*options*/) override {
79     packets_.emplace_back(
80         QuicReceivedPacket(buffer, buf_len,
81                            connection_helper_.GetClock()->ApproximateNow(),
82                            /*owns_buffer=*/false)
83             .Clone());
84   }
85 
ConsumePackets()86   std::vector<std::unique_ptr<QuicReceivedPacket>>&& ConsumePackets() {
87     return std::move(packets_);
88   }
89 
GetCryptoStreamBytesWritten() const90   uint64_t GetCryptoStreamBytesWritten() const {
91     QUICHE_DCHECK(session_);
92     QUICHE_DCHECK(session_->GetCryptoStream());
93     return session_->GetCryptoStream()->BytesSentOnLevel(
94         EncryptionLevel::ENCRYPTION_INITIAL);
95   }
96 
97  private:
98   ParsedQuicVersion version_;
99   QuicConnectionId server_connection_id_;
100   QuicConnectionId client_connection_id_;
101   MockQuicConnectionHelper connection_helper_;
102   MockAlarmFactory alarm_factory_;
103   DelegatedPacketWriter writer_;
104   QuicConfig config_;
105   std::unique_ptr<QuicCryptoClientConfig> crypto_config_;
106   QuicClientPushPromiseIndex push_promise_index_;
107   QuicConnection* connection_;  // Owned by session_.
108   std::unique_ptr<QuicSpdyClientSession> session_;
109   std::vector<std::unique_ptr<QuicReceivedPacket>> packets_;
110   MockConnectionIdGenerator connection_id_generator_;
111 };
112 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config)113 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
114     const ParsedQuicVersion& version, const QuicConfig& config,
115     const QuicConnectionId& server_connection_id,
116     const QuicConnectionId& client_connection_id,
117     std::unique_ptr<QuicCryptoClientConfig> crypto_config) {
118   FirstFlightExtractor first_flight_extractor(
119       version, config, server_connection_id, client_connection_id,
120       std::move(crypto_config));
121   first_flight_extractor.GenerateFirstFlight();
122   return first_flight_extractor.ConsumePackets();
123 }
124 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id)125 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
126     const ParsedQuicVersion& version, const QuicConfig& config,
127     const QuicConnectionId& server_connection_id,
128     const QuicConnectionId& client_connection_id) {
129   FirstFlightExtractor first_flight_extractor(
130       version, config, server_connection_id, client_connection_id);
131   first_flight_extractor.GenerateFirstFlight();
132   return first_flight_extractor.ConsumePackets();
133 }
134 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id)135 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
136     const ParsedQuicVersion& version, const QuicConfig& config,
137     const QuicConnectionId& server_connection_id) {
138   return GetFirstFlightOfPackets(version, config, server_connection_id,
139                                  EmptyQuicConnectionId());
140 }
141 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config)142 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
143     const ParsedQuicVersion& version, const QuicConfig& config) {
144   return GetFirstFlightOfPackets(version, config, TestConnectionId());
145 }
146 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id)147 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
148     const ParsedQuicVersion& version,
149     const QuicConnectionId& server_connection_id,
150     const QuicConnectionId& client_connection_id) {
151   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
152                                  server_connection_id, client_connection_id);
153 }
154 
GetFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConnectionId & server_connection_id)155 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
156     const ParsedQuicVersion& version,
157     const QuicConnectionId& server_connection_id) {
158   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
159                                  server_connection_id, EmptyQuicConnectionId());
160 }
161 
GetFirstFlightOfPackets(const ParsedQuicVersion & version)162 std::vector<std::unique_ptr<QuicReceivedPacket>> GetFirstFlightOfPackets(
163     const ParsedQuicVersion& version) {
164   return GetFirstFlightOfPackets(version, DefaultQuicConfig(),
165                                  TestConnectionId());
166 }
167 
GetAnnotatedFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config,const QuicConnectionId & server_connection_id,const QuicConnectionId & client_connection_id,std::unique_ptr<QuicCryptoClientConfig> crypto_config)168 AnnotatedPackets GetAnnotatedFirstFlightOfPackets(
169     const ParsedQuicVersion& version, const QuicConfig& config,
170     const QuicConnectionId& server_connection_id,
171     const QuicConnectionId& client_connection_id,
172     std::unique_ptr<QuicCryptoClientConfig> crypto_config) {
173   FirstFlightExtractor first_flight_extractor(
174       version, config, server_connection_id, client_connection_id,
175       std::move(crypto_config));
176   first_flight_extractor.GenerateFirstFlight();
177   return AnnotatedPackets{first_flight_extractor.ConsumePackets(),
178                           first_flight_extractor.GetCryptoStreamBytesWritten()};
179 }
180 
GetAnnotatedFirstFlightOfPackets(const ParsedQuicVersion & version,const QuicConfig & config)181 AnnotatedPackets GetAnnotatedFirstFlightOfPackets(
182     const ParsedQuicVersion& version, const QuicConfig& config) {
183   FirstFlightExtractor first_flight_extractor(
184       version, config, TestConnectionId(), EmptyQuicConnectionId());
185   first_flight_extractor.GenerateFirstFlight();
186   return AnnotatedPackets{first_flight_extractor.ConsumePackets(),
187                           first_flight_extractor.GetCryptoStreamBytesWritten()};
188 }
189 
190 }  // namespace test
191 }  // namespace quic
192