1 // Copyright (c) 2019 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 <memory>
6 #include <utility>
7
8 #include "absl/strings/string_view.h"
9 #include "quiche/quic/core/io/quic_default_event_loop.h"
10 #include "quiche/quic/core/io/quic_event_loop.h"
11 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
12 #include "quiche/quic/core/quic_alarm_factory.h"
13 #include "quiche/quic/core/quic_default_clock.h"
14 #include "quiche/quic/platform/api/quic_expect_bug.h"
15 #include "quiche/quic/platform/api/quic_test.h"
16 #include "quiche/quic/platform/api/quic_test_loopback.h"
17 #include "quiche/quic/qbone/platform/icmp_packet.h"
18 #include "quiche/quic/qbone/qbone_client_session.h"
19 #include "quiche/quic/qbone/qbone_constants.h"
20 #include "quiche/quic/qbone/qbone_control_placeholder.pb.h"
21 #include "quiche/quic/qbone/qbone_packet_processor_test_tools.h"
22 #include "quiche/quic/qbone/qbone_server_session.h"
23 #include "quiche/quic/test_tools/crypto_test_utils.h"
24 #include "quiche/quic/test_tools/mock_clock.h"
25 #include "quiche/quic/test_tools/mock_connection_id_generator.h"
26 #include "quiche/quic/test_tools/quic_connection_peer.h"
27 #include "quiche/quic/test_tools/quic_session_peer.h"
28 #include "quiche/quic/test_tools/quic_test_utils.h"
29 #include "quiche/common/quiche_callbacks.h"
30
31 namespace quic {
32 namespace test {
33 namespace {
34
35 using ::testing::_;
36 using ::testing::Contains;
37 using ::testing::ElementsAre;
38 using ::testing::Eq;
39 using ::testing::Invoke;
40 using ::testing::NiceMock;
41 using ::testing::Not;
42
TestPacketIn(const std::string & body)43 std::string TestPacketIn(const std::string& body) {
44 return PrependIPv6HeaderForTest(body, 5);
45 }
46
TestPacketOut(const std::string & body)47 std::string TestPacketOut(const std::string& body) {
48 return PrependIPv6HeaderForTest(body, 4);
49 }
50
GetTestParams()51 ParsedQuicVersionVector GetTestParams() {
52 SetQuicReloadableFlag(quic_disable_version_q046, false);
53 return CurrentSupportedVersionsWithQuicCrypto();
54 }
55
56 // Used by QuicCryptoServerConfig to provide server credentials, passes
57 // everything through to ProofSourceForTesting if success is true,
58 // and fails otherwise.
59 class IndirectionProofSource : public ProofSource {
60 public:
IndirectionProofSource(bool success)61 explicit IndirectionProofSource(bool success) {
62 if (success) {
63 proof_source_ = crypto_test_utils::ProofSourceForTesting();
64 }
65 }
66
67 // ProofSource override.
GetProof(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,const std::string & server_config,QuicTransportVersion transport_version,absl::string_view chlo_hash,std::unique_ptr<Callback> callback)68 void GetProof(const QuicSocketAddress& server_address,
69 const QuicSocketAddress& client_address,
70 const std::string& hostname, const std::string& server_config,
71 QuicTransportVersion transport_version,
72 absl::string_view chlo_hash,
73 std::unique_ptr<Callback> callback) override {
74 if (!proof_source_) {
75 QuicCryptoProof proof;
76 quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain =
77 GetCertChain(server_address, client_address, hostname,
78 &proof.cert_matched_sni);
79 callback->Run(/*ok=*/false, chain, proof, /*details=*/nullptr);
80 return;
81 }
82 proof_source_->GetProof(server_address, client_address, hostname,
83 server_config, transport_version, chlo_hash,
84 std::move(callback));
85 }
86
GetCertChain(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,bool * cert_matched_sni)87 quiche::QuicheReferenceCountedPointer<Chain> GetCertChain(
88 const QuicSocketAddress& server_address,
89 const QuicSocketAddress& client_address, const std::string& hostname,
90 bool* cert_matched_sni) override {
91 if (!proof_source_) {
92 return quiche::QuicheReferenceCountedPointer<Chain>();
93 }
94 return proof_source_->GetCertChain(server_address, client_address, hostname,
95 cert_matched_sni);
96 }
97
ComputeTlsSignature(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,uint16_t signature_algorithm,absl::string_view in,std::unique_ptr<SignatureCallback> callback)98 void ComputeTlsSignature(
99 const QuicSocketAddress& server_address,
100 const QuicSocketAddress& client_address, const std::string& hostname,
101 uint16_t signature_algorithm, absl::string_view in,
102 std::unique_ptr<SignatureCallback> callback) override {
103 if (!proof_source_) {
104 callback->Run(/*ok=*/true, "Signature", /*details=*/nullptr);
105 return;
106 }
107 proof_source_->ComputeTlsSignature(server_address, client_address, hostname,
108 signature_algorithm, in,
109 std::move(callback));
110 }
111
SupportedTlsSignatureAlgorithms() const112 absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
113 const override {
114 if (!proof_source_) {
115 return {};
116 }
117 return proof_source_->SupportedTlsSignatureAlgorithms();
118 }
119
GetTicketCrypter()120 TicketCrypter* GetTicketCrypter() override { return nullptr; }
121
122 private:
123 std::unique_ptr<ProofSource> proof_source_;
124 };
125
126 // Used by QuicCryptoClientConfig to verify server credentials, passes
127 // everything through to ProofVerifierForTesting is success is true,
128 // otherwise returns a canned response of QUIC_FAILURE.
129 class IndirectionProofVerifier : public ProofVerifier {
130 public:
IndirectionProofVerifier(bool success)131 explicit IndirectionProofVerifier(bool success) {
132 if (success) {
133 proof_verifier_ = crypto_test_utils::ProofVerifierForTesting();
134 }
135 }
136
137 // ProofVerifier override
VerifyProof(const std::string & hostname,const uint16_t port,const std::string & server_config,QuicTransportVersion transport_version,absl::string_view chlo_hash,const std::vector<std::string> & certs,const std::string & cert_sct,const std::string & signature,const ProofVerifyContext * context,std::string * error_details,std::unique_ptr<ProofVerifyDetails> * verify_details,std::unique_ptr<ProofVerifierCallback> callback)138 QuicAsyncStatus VerifyProof(
139 const std::string& hostname, const uint16_t port,
140 const std::string& server_config, QuicTransportVersion transport_version,
141 absl::string_view chlo_hash, const std::vector<std::string>& certs,
142 const std::string& cert_sct, const std::string& signature,
143 const ProofVerifyContext* context, std::string* error_details,
144 std::unique_ptr<ProofVerifyDetails>* verify_details,
145 std::unique_ptr<ProofVerifierCallback> callback) override {
146 if (!proof_verifier_) {
147 return QUIC_FAILURE;
148 }
149 return proof_verifier_->VerifyProof(
150 hostname, port, server_config, transport_version, chlo_hash, certs,
151 cert_sct, signature, context, error_details, verify_details,
152 std::move(callback));
153 }
154
VerifyCertChain(const std::string & hostname,const uint16_t port,const std::vector<std::string> & certs,const std::string & ocsp_response,const std::string & cert_sct,const ProofVerifyContext * context,std::string * error_details,std::unique_ptr<ProofVerifyDetails> * details,uint8_t * out_alert,std::unique_ptr<ProofVerifierCallback> callback)155 QuicAsyncStatus VerifyCertChain(
156 const std::string& hostname, const uint16_t port,
157 const std::vector<std::string>& certs, const std::string& ocsp_response,
158 const std::string& cert_sct, const ProofVerifyContext* context,
159 std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details,
160 uint8_t* out_alert,
161 std::unique_ptr<ProofVerifierCallback> callback) override {
162 if (!proof_verifier_) {
163 return QUIC_FAILURE;
164 }
165 return proof_verifier_->VerifyCertChain(
166 hostname, port, certs, ocsp_response, cert_sct, context, error_details,
167 details, out_alert, std::move(callback));
168 }
169
CreateDefaultContext()170 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
171 if (!proof_verifier_) {
172 return nullptr;
173 }
174 return proof_verifier_->CreateDefaultContext();
175 }
176
177 private:
178 std::unique_ptr<ProofVerifier> proof_verifier_;
179 };
180
181 class DataSavingQbonePacketWriter : public QbonePacketWriter {
182 public:
WritePacketToNetwork(const char * packet,size_t size)183 void WritePacketToNetwork(const char* packet, size_t size) override {
184 data_.push_back(std::string(packet, size));
185 }
186
data()187 const std::vector<std::string>& data() { return data_; }
188
189 private:
190 std::vector<std::string> data_;
191 };
192
193 template <class T>
194 class DataSavingQboneControlHandler : public QboneControlHandler<T> {
195 public:
OnControlRequest(const T & request)196 void OnControlRequest(const T& request) override { data_.push_back(request); }
197
OnControlError()198 void OnControlError() override { error_ = true; }
199
data()200 const std::vector<T>& data() { return data_; }
error()201 bool error() { return error_; }
202
203 private:
204 std::vector<T> data_;
205 bool error_ = false;
206 };
207
208 // Single-threaded scheduled task runner based on a MockClock.
209 //
210 // Simulates asynchronous execution on a single thread by holding scheduled
211 // tasks until Run() is called. Performs no synchronization, assumes that
212 // Schedule() and Run() are called on the same thread.
213 class FakeTaskRunner {
214 public:
FakeTaskRunner(MockQuicConnectionHelper * helper)215 explicit FakeTaskRunner(MockQuicConnectionHelper* helper)
216 : tasks_([](const TaskType& l, const TaskType& r) {
217 // Items at a later time should run after items at an earlier time.
218 // Priority queue comparisons should return true if l appears after r.
219 return l->time() > r->time();
220 }),
221 helper_(helper) {}
222
223 // Runs all tasks in time order. Executes tasks scheduled at
224 // the same in an arbitrary order.
Run()225 void Run() {
226 while (!tasks_.empty()) {
227 tasks_.top()->Run();
228 tasks_.pop();
229 }
230 }
231
232 private:
233 class InnerTask {
234 public:
InnerTask(std::function<void ()> task,QuicTime time)235 InnerTask(std::function<void()> task, QuicTime time)
236 : task_(std::move(task)), time_(time) {}
237
Cancel()238 void Cancel() { cancelled_ = true; }
239
Run()240 void Run() {
241 if (!cancelled_) {
242 std::move(task_)();
243 }
244 }
245
time() const246 QuicTime time() const { return time_; }
247
248 private:
249 bool cancelled_ = false;
250 quiche::SingleUseCallback<void()> task_;
251 QuicTime time_;
252 };
253
254 public:
255 // Schedules a function to run immediately and advances the time.
Schedule(std::function<void ()> task)256 void Schedule(std::function<void()> task) {
257 tasks_.push(std::shared_ptr<InnerTask>(
258 new InnerTask(std::move(task), helper_->GetClock()->Now())));
259 helper_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
260 }
261
262 private:
263 using TaskType = std::shared_ptr<InnerTask>;
264 std::priority_queue<
265 TaskType, std::vector<TaskType>,
266 quiche::UnretainedCallback<bool(const TaskType&, const TaskType&)>>
267 tasks_;
268 MockQuicConnectionHelper* helper_;
269 };
270
271 class QboneSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
272 public:
QboneSessionTest()273 QboneSessionTest()
274 : supported_versions_({GetParam()}),
275 runner_(&helper_),
276 compressed_certs_cache_(100) {}
277
~QboneSessionTest()278 ~QboneSessionTest() override {
279 delete client_connection_;
280 delete server_connection_;
281 }
282
GetClock() const283 const MockClock* GetClock() const {
284 return static_cast<const MockClock*>(helper_.GetClock());
285 }
286
287 // The parameters are used to control whether the handshake will success or
288 // not.
CreateClientAndServerSessions(bool client_handshake_success=true,bool server_handshake_success=true,bool send_qbone_alpn=true)289 void CreateClientAndServerSessions(bool client_handshake_success = true,
290 bool server_handshake_success = true,
291 bool send_qbone_alpn = true) {
292 // Quic crashes if packets are sent at time 0, and the clock defaults to 0.
293 helper_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
294 event_loop_ = GetDefaultEventLoop()->Create(QuicDefaultClock::Get());
295 alarm_factory_ = event_loop_->CreateAlarmFactory();
296 client_writer_ = std::make_unique<DataSavingQbonePacketWriter>();
297 server_writer_ = std::make_unique<DataSavingQbonePacketWriter>();
298 client_handler_ =
299 std::make_unique<DataSavingQboneControlHandler<QboneClientRequest>>();
300 server_handler_ =
301 std::make_unique<DataSavingQboneControlHandler<QboneServerRequest>>();
302 QuicSocketAddress server_address(TestLoopback(), 0);
303 QuicSocketAddress client_address;
304 if (server_address.host().address_family() == IpAddressFamily::IP_V4) {
305 client_address = QuicSocketAddress(QuicIpAddress::Any4(), 0);
306 } else {
307 client_address = QuicSocketAddress(QuicIpAddress::Any6(), 0);
308 }
309
310 {
311 client_connection_ = new QuicConnection(
312 TestConnectionId(), client_address, server_address, &helper_,
313 alarm_factory_.get(), new NiceMock<MockPacketWriter>(), true,
314 Perspective::IS_CLIENT, supported_versions_,
315 connection_id_generator_);
316 client_connection_->SetSelfAddress(client_address);
317 QuicConfig config;
318 client_crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
319 std::make_unique<IndirectionProofVerifier>(client_handshake_success));
320 if (send_qbone_alpn) {
321 client_crypto_config_->set_alpn("qbone");
322 }
323 client_peer_ = std::make_unique<QboneClientSession>(
324 client_connection_, client_crypto_config_.get(),
325 /*owner=*/nullptr, config, supported_versions_,
326 QuicServerId("test.example.com", 1234, false), client_writer_.get(),
327 client_handler_.get());
328 }
329
330 {
331 server_connection_ = new QuicConnection(
332 TestConnectionId(), server_address, client_address, &helper_,
333 alarm_factory_.get(), new NiceMock<MockPacketWriter>(), true,
334 Perspective::IS_SERVER, supported_versions_,
335 connection_id_generator_);
336 server_connection_->SetSelfAddress(server_address);
337 QuicConfig config;
338 server_crypto_config_ = std::make_unique<QuicCryptoServerConfig>(
339 QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
340 std::make_unique<IndirectionProofSource>(server_handshake_success),
341 KeyExchangeSource::Default());
342 QuicCryptoServerConfig::ConfigOptions options;
343 QuicServerConfigProtobuf primary_config =
344 server_crypto_config_->GenerateConfig(QuicRandom::GetInstance(),
345 GetClock(), options);
346 std::unique_ptr<CryptoHandshakeMessage> message(
347 server_crypto_config_->AddConfig(primary_config,
348 GetClock()->WallNow()));
349
350 server_peer_ = std::make_unique<QboneServerSession>(
351 supported_versions_, server_connection_, nullptr, config,
352 server_crypto_config_.get(), &compressed_certs_cache_,
353 server_writer_.get(), TestLoopback6(), TestLoopback6(), 64,
354 server_handler_.get());
355 }
356
357 // Hook everything up!
358 MockPacketWriter* client_writer = static_cast<MockPacketWriter*>(
359 QuicConnectionPeer::GetWriter(client_peer_->connection()));
360 ON_CALL(*client_writer, WritePacket(_, _, _, _, _, _))
361 .WillByDefault(Invoke([this](const char* buffer, size_t buf_len,
362 const QuicIpAddress& self_address,
363 const QuicSocketAddress& peer_address,
364 PerPacketOptions* option,
365 const QuicPacketWriterParams& params) {
366 char* copy = new char[1024 * 1024];
367 memcpy(copy, buffer, buf_len);
368 runner_.Schedule([this, copy, buf_len] {
369 QuicReceivedPacket packet(copy, buf_len, GetClock()->Now());
370 server_peer_->ProcessUdpPacket(server_connection_->self_address(),
371 client_connection_->self_address(),
372 packet);
373 delete[] copy;
374 });
375 return WriteResult(WRITE_STATUS_OK, buf_len);
376 }));
377 MockPacketWriter* server_writer = static_cast<MockPacketWriter*>(
378 QuicConnectionPeer::GetWriter(server_peer_->connection()));
379 ON_CALL(*server_writer, WritePacket(_, _, _, _, _, _))
380 .WillByDefault(Invoke([this](const char* buffer, size_t buf_len,
381 const QuicIpAddress& self_address,
382 const QuicSocketAddress& peer_address,
383 PerPacketOptions* options,
384 const QuicPacketWriterParams& params) {
385 char* copy = new char[1024 * 1024];
386 memcpy(copy, buffer, buf_len);
387 runner_.Schedule([this, copy, buf_len] {
388 QuicReceivedPacket packet(copy, buf_len, GetClock()->Now());
389 client_peer_->ProcessUdpPacket(client_connection_->self_address(),
390 server_connection_->self_address(),
391 packet);
392 delete[] copy;
393 });
394 return WriteResult(WRITE_STATUS_OK, buf_len);
395 }));
396 }
397
StartHandshake()398 void StartHandshake() {
399 server_peer_->Initialize();
400 client_peer_->Initialize();
401 runner_.Run();
402 }
403
ExpectICMPTooBigResponse(const std::vector<std::string> & written_packets,const int mtu,const std::string & packet)404 void ExpectICMPTooBigResponse(const std::vector<std::string>& written_packets,
405 const int mtu, const std::string& packet) {
406 auto* header = reinterpret_cast<const ip6_hdr*>(packet.data());
407 icmp6_hdr icmp_header{};
408 icmp_header.icmp6_type = ICMP6_PACKET_TOO_BIG;
409 icmp_header.icmp6_mtu = mtu;
410
411 std::string expected;
412 CreateIcmpPacket(header->ip6_dst, header->ip6_src, icmp_header, packet,
413 [&expected](absl::string_view icmp_packet) {
414 expected = std::string(icmp_packet);
415 });
416
417 EXPECT_THAT(written_packets, Contains(expected));
418 }
419
420 // Test handshake establishment and sending/receiving of data for two
421 // directions.
TestStreamConnection(bool use_messages)422 void TestStreamConnection(bool use_messages) {
423 ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
424 ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
425 ASSERT_TRUE(server_peer_->IsEncryptionEstablished());
426 ASSERT_TRUE(client_peer_->IsEncryptionEstablished());
427
428 // Create an outgoing stream from the client and say hello.
429 QUIC_LOG(INFO) << "Sending client -> server";
430 client_peer_->ProcessPacketFromNetwork(TestPacketIn("hello"));
431 client_peer_->ProcessPacketFromNetwork(TestPacketIn("world"));
432 runner_.Run();
433 // The server should see the data, the client hasn't received
434 // anything yet.
435 EXPECT_THAT(server_writer_->data(),
436 ElementsAre(TestPacketOut("hello"), TestPacketOut("world")));
437 EXPECT_TRUE(client_writer_->data().empty());
438 EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
439 EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
440
441 // Let's pretend some service responds.
442 QUIC_LOG(INFO) << "Sending server -> client";
443 server_peer_->ProcessPacketFromNetwork(TestPacketIn("Hello Again"));
444 server_peer_->ProcessPacketFromNetwork(TestPacketIn("Again"));
445 runner_.Run();
446 EXPECT_THAT(server_writer_->data(),
447 ElementsAre(TestPacketOut("hello"), TestPacketOut("world")));
448 EXPECT_THAT(
449 client_writer_->data(),
450 ElementsAre(TestPacketOut("Hello Again"), TestPacketOut("Again")));
451 EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
452 EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
453
454 // Try to send long payloads that are larger than the QUIC MTU but
455 // smaller than the QBONE max size.
456 // This should trigger the non-ephemeral stream code path.
457 std::string long_data(
458 QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1, 'A');
459 QUIC_LOG(INFO) << "Sending server -> client long data";
460 server_peer_->ProcessPacketFromNetwork(TestPacketIn(long_data));
461 runner_.Run();
462 if (use_messages) {
463 ExpectICMPTooBigResponse(
464 server_writer_->data(),
465 server_peer_->connection()->GetGuaranteedLargestMessagePayload(),
466 TestPacketOut(long_data));
467 } else {
468 EXPECT_THAT(client_writer_->data(), Contains(TestPacketOut(long_data)));
469 }
470 EXPECT_THAT(server_writer_->data(),
471 Not(Contains(TestPacketOut(long_data))));
472 EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
473 EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
474
475 QUIC_LOG(INFO) << "Sending client -> server long data";
476 client_peer_->ProcessPacketFromNetwork(TestPacketIn(long_data));
477 runner_.Run();
478 if (use_messages) {
479 ExpectICMPTooBigResponse(
480 client_writer_->data(),
481 client_peer_->connection()->GetGuaranteedLargestMessagePayload(),
482 TestPacketIn(long_data));
483 } else {
484 EXPECT_THAT(server_writer_->data(), Contains(TestPacketOut(long_data)));
485 }
486 EXPECT_FALSE(client_peer_->EarlyDataAccepted());
487 EXPECT_FALSE(client_peer_->ReceivedInchoateReject());
488 EXPECT_THAT(client_peer_->GetNumReceivedServerConfigUpdates(), Eq(0));
489
490 if (!use_messages) {
491 EXPECT_THAT(client_peer_->GetNumStreamedPackets(), Eq(1));
492 EXPECT_THAT(server_peer_->GetNumStreamedPackets(), Eq(1));
493 }
494
495 if (use_messages) {
496 EXPECT_THAT(client_peer_->GetNumEphemeralPackets(), Eq(0));
497 EXPECT_THAT(server_peer_->GetNumEphemeralPackets(), Eq(0));
498 EXPECT_THAT(client_peer_->GetNumMessagePackets(), Eq(2));
499 EXPECT_THAT(server_peer_->GetNumMessagePackets(), Eq(2));
500 } else {
501 EXPECT_THAT(client_peer_->GetNumEphemeralPackets(), Eq(2));
502 EXPECT_THAT(server_peer_->GetNumEphemeralPackets(), Eq(2));
503 EXPECT_THAT(client_peer_->GetNumMessagePackets(), Eq(0));
504 EXPECT_THAT(server_peer_->GetNumMessagePackets(), Eq(0));
505 }
506
507 // All streams are ephemeral and should be gone.
508 EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
509 EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
510 }
511
512 // Test that client and server are not connected after handshake failure.
TestDisconnectAfterFailedHandshake()513 void TestDisconnectAfterFailedHandshake() {
514 EXPECT_FALSE(client_peer_->IsEncryptionEstablished());
515 EXPECT_FALSE(client_peer_->OneRttKeysAvailable());
516
517 EXPECT_FALSE(server_peer_->IsEncryptionEstablished());
518 EXPECT_FALSE(server_peer_->OneRttKeysAvailable());
519 }
520
521 protected:
522 const ParsedQuicVersionVector supported_versions_;
523 std::unique_ptr<QuicEventLoop> event_loop_;
524 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
525 FakeTaskRunner runner_;
526 MockQuicConnectionHelper helper_;
527 QuicConnection* client_connection_;
528 QuicConnection* server_connection_;
529 QuicCompressedCertsCache compressed_certs_cache_;
530
531 std::unique_ptr<QuicCryptoClientConfig> client_crypto_config_;
532 std::unique_ptr<QuicCryptoServerConfig> server_crypto_config_;
533 std::unique_ptr<DataSavingQbonePacketWriter> client_writer_;
534 std::unique_ptr<DataSavingQbonePacketWriter> server_writer_;
535 std::unique_ptr<DataSavingQboneControlHandler<QboneClientRequest>>
536 client_handler_;
537 std::unique_ptr<DataSavingQboneControlHandler<QboneServerRequest>>
538 server_handler_;
539
540 std::unique_ptr<QboneServerSession> server_peer_;
541 std::unique_ptr<QboneClientSession> client_peer_;
542 MockConnectionIdGenerator connection_id_generator_;
543 };
544
545 INSTANTIATE_TEST_SUITE_P(Tests, QboneSessionTest,
546 ::testing::ValuesIn(GetTestParams()),
547 ::testing::PrintToStringParamName());
548
TEST_P(QboneSessionTest,StreamConnection)549 TEST_P(QboneSessionTest, StreamConnection) {
550 CreateClientAndServerSessions();
551 client_peer_->set_send_packets_as_messages(false);
552 server_peer_->set_send_packets_as_messages(false);
553 StartHandshake();
554 TestStreamConnection(false);
555 }
556
TEST_P(QboneSessionTest,Messages)557 TEST_P(QboneSessionTest, Messages) {
558 CreateClientAndServerSessions();
559 client_peer_->set_send_packets_as_messages(true);
560 server_peer_->set_send_packets_as_messages(true);
561 StartHandshake();
562 TestStreamConnection(true);
563 }
564
TEST_P(QboneSessionTest,ClientRejection)565 TEST_P(QboneSessionTest, ClientRejection) {
566 CreateClientAndServerSessions(false /*client_handshake_success*/,
567 true /*server_handshake_success*/,
568 true /*send_qbone_alpn*/);
569 StartHandshake();
570 TestDisconnectAfterFailedHandshake();
571 }
572
TEST_P(QboneSessionTest,BadAlpn)573 TEST_P(QboneSessionTest, BadAlpn) {
574 CreateClientAndServerSessions(true /*client_handshake_success*/,
575 true /*server_handshake_success*/,
576 false /*send_qbone_alpn*/);
577 StartHandshake();
578 TestDisconnectAfterFailedHandshake();
579 }
580
TEST_P(QboneSessionTest,ServerRejection)581 TEST_P(QboneSessionTest, ServerRejection) {
582 CreateClientAndServerSessions(true /*client_handshake_success*/,
583 false /*server_handshake_success*/,
584 true /*send_qbone_alpn*/);
585 StartHandshake();
586 TestDisconnectAfterFailedHandshake();
587 }
588
589 // Test that data streams are not created before handshake.
TEST_P(QboneSessionTest,CannotCreateDataStreamBeforeHandshake)590 TEST_P(QboneSessionTest, CannotCreateDataStreamBeforeHandshake) {
591 CreateClientAndServerSessions();
592 EXPECT_QUIC_BUG(client_peer_->ProcessPacketFromNetwork(TestPacketIn("hello")),
593 "Attempting to send packet before encryption established");
594 EXPECT_QUIC_BUG(server_peer_->ProcessPacketFromNetwork(TestPacketIn("hello")),
595 "Attempting to send packet before encryption established");
596 EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
597 EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
598 }
599
TEST_P(QboneSessionTest,ControlRequests)600 TEST_P(QboneSessionTest, ControlRequests) {
601 CreateClientAndServerSessions();
602 StartHandshake();
603 EXPECT_TRUE(client_handler_->data().empty());
604 EXPECT_FALSE(client_handler_->error());
605 EXPECT_TRUE(server_handler_->data().empty());
606 EXPECT_FALSE(server_handler_->error());
607
608 QboneClientRequest client_request;
609 client_request.SetExtension(client_placeholder, "hello from the server");
610 EXPECT_TRUE(server_peer_->SendClientRequest(client_request));
611 runner_.Run();
612 ASSERT_FALSE(client_handler_->data().empty());
613 EXPECT_THAT(client_handler_->data()[0].GetExtension(client_placeholder),
614 Eq("hello from the server"));
615 EXPECT_FALSE(client_handler_->error());
616
617 QboneServerRequest server_request;
618 server_request.SetExtension(server_placeholder, "hello from the client");
619 EXPECT_TRUE(client_peer_->SendServerRequest(server_request));
620 runner_.Run();
621 ASSERT_FALSE(server_handler_->data().empty());
622 EXPECT_THAT(server_handler_->data()[0].GetExtension(server_placeholder),
623 Eq("hello from the client"));
624 EXPECT_FALSE(server_handler_->error());
625 }
626
627 } // namespace
628 } // namespace test
629 } // namespace quic
630